From a3e3683650578b09fdeccba13445db195b72257c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 6 Jan 2020 17:08:18 +0100 Subject: [PATCH 001/479] add scrollbar scale interface, and linear and logarithmic implementations (closes #2226) --- src/game/client/components/menus.cpp | 4 +-- src/game/client/components/menus.h | 33 ++++++++++++++++++- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_callback.cpp | 6 ++-- src/game/client/components/menus_settings.cpp | 8 ++--- 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index aa9a1993..353be29b 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -634,7 +634,7 @@ void CMenus::DoEditBoxOption(void *pID, char *pOption, int OptionLength, const C DoEditBox(pID, &EditBox, pOption, OptionLength, pRect->h*ms_FontmodHeight*0.8f, pOffset, Hidden); } -void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, bool Infinite) +void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale, bool Infinite) { int Value = *pOption; if(Infinite) @@ -665,7 +665,7 @@ void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, co UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); ScrollBar.VMargin(4.0f, &ScrollBar); - Value = round_to_int(DoScrollbarH(pID, &ScrollBar, (float)(Value - Min) / (float)(Max - Min))*(float)(Max - Min) + (float)Min + 0.1f); + Value = pScale->ToAbsolute(DoScrollbarH(pID, &ScrollBar, pScale->ToRelative(Value, Min, Max)), Min, Max); if(Infinite && Value == Max) Value = 0; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 6ec3c8ca..76db43ac 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -30,6 +30,37 @@ class CMenusKeyBinder : public CComponent virtual bool OnInput(IInput::CEvent Event); }; +class IScrollbarScale +{ +public: + virtual float ToRelative(int AbsoluteValue, int Min, int Max) = 0; + virtual int ToAbsolute(float RelativeValue, int Min, int Max) = 0; +}; +static class : public IScrollbarScale +{ +public: + float ToRelative(int AbsoluteValue, int Min, int Max) + { + return (AbsoluteValue - Min) / (float)(Max - Min); + } + int ToAbsolute(float RelativeValue, int Min, int Max) + { + return round_to_int(RelativeValue*(Max - Min) + Min + 0.1f); + } +} LinearScrollbarScale; +static class : public IScrollbarScale +{ +public: + float ToRelative(int AbsoluteValue, int Min, int Max) + { + return (log(AbsoluteValue) - log(Min)) / (float)(log(Max) - log(Min)); + } + int ToAbsolute(float RelativeValue, int Min, int Max) + { + return round_to_int(exp(RelativeValue*(log(Max) - log(Min)) + log(Min))); + } +} LogarithmicScrollbarScale; + class CMenus : public CComponent { public: @@ -84,7 +115,7 @@ class CMenus : public CComponent */ int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false); - void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, bool Infinite=false); + void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite=false); float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive); void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 5549dd94..5dc180a3 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1771,7 +1771,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); Button.VMargin(4.0f, &Button); static int s_BrFilterPing = 0; - Value = round_to_int(DoScrollbarH(&s_BrFilterPing, &Button, (float)(Value - Min) / (float)(Max - Min))*(float)(Max - Min) + (float)Min + 0.1f); + Value = LogarithmicScrollbarScale.ToAbsolute(DoScrollbarH(&s_BrFilterPing, &Button, LogarithmicScrollbarScale.ToRelative(Value, Min, Max)), Min, Max); if(Value != FilterInfo.m_Ping) { FilterInfo.m_Ping = Value; pFilter->SetFilter(&FilterInfo); diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 554c35b1..7bcab6a7 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -146,10 +146,10 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View, void *pUser) } View.HSplitTop(Spaceing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500); + pSelf->DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spaceing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500); + pSelf->DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); return BackgroundHeight; } @@ -182,7 +182,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) { View.HSplitTop(Spaceing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500); + pSelf->DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spaceing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 17414de9..2cab9889 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1086,7 +1086,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); - DoScrollbarOption(&g_Config.m_ClMenuAlpha, &g_Config.m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75, false); + DoScrollbarOption(&g_Config.m_ClMenuAlpha, &g_Config.m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); @@ -1099,7 +1099,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&g_Config.m_ClAutoDemoMax, &g_Config.m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, true); + DoScrollbarOption(&g_Config.m_ClAutoDemoMax, &g_Config.m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } Client.HSplitTop(Spacing, 0, &Client); @@ -1113,7 +1113,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&g_Config.m_ClAutoScreenshotMax, &g_Config.m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, true); + DoScrollbarOption(&g_Config.m_ClAutoScreenshotMax, &g_Config.m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -2108,7 +2108,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) } Right.HSplitTop(ButtonHeight, &Button, &Right); - DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Volume"), 0, 100); + DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Volume"), 0, 100, &LogarithmicScrollbarScale); } else { From 6b034c8df97ce290064c53d74a697ebcfb6883b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 7 Jan 2020 00:35:26 +0100 Subject: [PATCH 002/479] match quick search against game type (#2275), minor refactorings --- src/engine/client/serverbrowser_filter.cpp | 7 +++ src/engine/serverbrowser.h | 1 + src/game/client/components/menus_browser.cpp | 58 +++++++++++++------- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/engine/client/serverbrowser_filter.cpp b/src/engine/client/serverbrowser_filter.cpp index 72cef727..31a49c22 100644 --- a/src/engine/client/serverbrowser_filter.cpp +++ b/src/engine/client/serverbrowser_filter.cpp @@ -189,6 +189,13 @@ void CServerBrowserFilter::CServerFilter::Filter() m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME; } + // match against game type + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterString)) + { + MatchFound = 1; + m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_GAMETYPE; + } + if(!MatchFound) Filtered = 1; } diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 7ba73162..31acc50a 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -122,6 +122,7 @@ class IServerBrowser : public IInterface QUICK_SERVERNAME=1, QUICK_PLAYER=2, QUICK_MAPNAME=4, + QUICK_GAMETYPE=8, TYPE_INTERNET=0, TYPE_LAN, diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 5549dd94..4e4f2afa 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -36,6 +36,7 @@ CServerFilterInfo CMenus::CBrowserFilter::ms_FilterStandard = {IServerBrowser::F CServerFilterInfo CMenus::CBrowserFilter::ms_FilterFavorites = {IServerBrowser::FILTER_COMPAT_VERSION|IServerBrowser::FILTER_FAVORITE, 999, -1, 0, {{0}}, {0}}; CServerFilterInfo CMenus::CBrowserFilter::ms_FilterAll = {IServerBrowser::FILTER_COMPAT_VERSION, 999, -1, 0, {{0}}, {0}}; +vec3 TextHighlightColor = vec3(0.4f, 0.4f, 1.0f); // filters CMenus::CBrowserFilter::CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser) @@ -461,12 +462,12 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { - // highlight the parts that matches + // highlight the part that matches const char *pStr = str_find_nocase(pEntry->m_aName, g_Config.m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aName, (int)(pStr-pEntry->m_aName)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, TextAlpha); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); @@ -493,12 +494,12 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) { - // highlight the parts that matches + // highlight the part that matches const char *pStr = str_find_nocase(pEntry->m_aMap, g_Config.m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aMap, (int)(pStr-pEntry->m_aMap)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, TextAlpha); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); @@ -543,7 +544,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max); if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) - TextRender()->TextColor(0.4f, 0.4f, 1.0f, TextAlpha); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); Button.y += 2.0f; if(Num < 100) @@ -602,13 +603,27 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn // gametype text CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = Button.w; + TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + + if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) { - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Button.w; + // highlight the part that matches + const char *pStr = str_find_nocase(pEntry->m_aGameType, g_Config.m_BrFilterString); + if(pStr) + { + TextRender()->TextEx(&Cursor, pEntry->m_aGameType, (int)(pStr-pEntry->m_aGameType)); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); + TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); + TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); + } + else + TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); } - - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); + else + TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); } } @@ -795,9 +810,10 @@ void CMenus::RenderServerbrowserOverlay() CUIRect Screen = *UI()->Screen(); float ButtonHeight = 20.0f; + vec4 TextColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); if(pInfo && pInfo->m_NumClients) { @@ -859,14 +875,14 @@ void CMenus::RenderServerbrowserOverlay() const char *pName = pInfo->m_aClients[i].m_aName; if(g_Config.m_BrFilterString[0]) { - // highlight the parts that matches + // highlight the part that matches const char *s = str_find_nocase(pName, g_Config.m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); } else @@ -881,14 +897,14 @@ void CMenus::RenderServerbrowserOverlay() const char *pClan = pInfo->m_aClients[i].m_aClan; if(g_Config.m_BrFilterString[0]) { - // highlight the parts that matches + // highlight the part that matches const char *s = str_find_nocase(pClan, g_Config.m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); } else @@ -2046,12 +2062,12 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int const char *pName = pInfo->m_aClients[i].m_aName; if(g_Config.m_BrFilterString[0]) { - // highlight the parts that matches + // highlight the part that matches const char *s = str_find_nocase(pName, g_Config.m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s + str_length(g_Config.m_BrFilterString), -1); @@ -2068,12 +2084,12 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int const char *pClan = pInfo->m_aClients[i].m_aClan; if(g_Config.m_BrFilterString[0]) { - // highlight the parts that matches + // highlight the part that matches const char *s = str_find_nocase(pClan, g_Config.m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); TextRender()->TextEx(&Cursor, s + str_length(g_Config.m_BrFilterString), -1); From d38f9e026d29f343859d31b20d421808c1aad5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 8 Jan 2020 01:15:22 +0100 Subject: [PATCH 003/479] fix statboard not closing with esc (closes #2377) --- src/game/client/components/stats.cpp | 29 ++++++++++++++++++++++++---- src/game/client/components/stats.h | 3 +++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/stats.cpp b/src/game/client/components/stats.cpp index 2971dfe6..0d151607 100644 --- a/src/game/client/components/stats.cpp +++ b/src/game/client/components/stats.cpp @@ -11,9 +11,7 @@ CStats::CStats() { - m_Active = false; - m_ScreenshotTaken = false; - m_ScreenshotTime = -1; + OnReset(); } void CStats::CPlayerStats::Reset() @@ -40,7 +38,10 @@ void CStats::OnReset() { for(int i = 0; i < MAX_CLIENTS; i++) m_aStats[i].Reset(); + m_Active = false; + m_Activate = false; + m_ScreenshotTaken = false; m_ScreenshotTime = -1; } @@ -54,9 +55,22 @@ bool CStats::IsActive() const return m_Active; } +void CStats::OnRelease() +{ + m_Active = false; +} + void CStats::ConKeyStats(IConsole::IResult *pResult, void *pUserData) { - ((CStats *)pUserData)->m_Active = pResult->GetInteger(0) != 0; + CStats *pStats = (CStats *)pUserData; + int Result = pResult->GetInteger(0); + if(!Result) + { + pStats->m_Activate = false; + pStats->m_Active = false; + } + else if(!pStats->m_Active) + pStats->m_Activate = true; } void CStats::OnConsoleInit() @@ -117,6 +131,13 @@ void CStats::OnRender() if(m_pClient->m_pMenus->IsActive()) return; + // postpone the active state till the render area gets updated during the rendering + if(m_Activate) + { + m_Active = true; + m_Activate = false; + } + if(!IsActive()) return; diff --git a/src/game/client/components/stats.h b/src/game/client/components/stats.h index 71d0b8dd..b4f09c8d 100644 --- a/src/game/client/components/stats.h +++ b/src/game/client/components/stats.h @@ -49,6 +49,8 @@ class CStats: public CComponent CPlayerStats m_aStats[MAX_CLIENTS]; bool m_Active; + bool m_Activate; + bool m_ScreenshotTaken; int64 m_ScreenshotTime; static void ConKeyStats(IConsole::IResult *pResult, void *pUserData); @@ -61,6 +63,7 @@ class CStats: public CComponent void OnStartGame(); virtual void OnConsoleInit(); virtual void OnRender(); + virtual void OnRelease(); virtual void OnMessage(int MsgType, void *pRawMsg); void UpdatePlayTime(int Ticks); From e5f94b3310af9a4ec8cb650690339b63ed1b0a9b Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 8 Jan 2020 10:42:45 +0100 Subject: [PATCH 004/479] fixed server browser entries ending up in the wrong list. closes #2379 --- src/engine/client/serverbrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index d62b0dca..df4ff3f2 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -267,7 +267,7 @@ void CServerBrowser::SetType(int Type) void CServerBrowser::Refresh(int RefreshFlags) { - m_RefreshFlags = RefreshFlags; + m_RefreshFlags |= RefreshFlags; if(RefreshFlags&IServerBrowser::REFRESHFLAG_LAN) { From aa0bf33ad9149b7d86f9aa634c592c1a5712f3dc Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 8 Jan 2020 11:34:32 +0100 Subject: [PATCH 005/479] updated teeworlds-lib version --- scripts/download.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/download.py b/scripts/download.py index a9f055dc..7b30ab51 100644 --- a/scripts/download.py +++ b/scripts/download.py @@ -16,7 +16,7 @@ def unzip(filename, where): return z.namelist()[0] def downloadAll(targets): - version = "4bf6dbc8c9f9b2fa89b2b5be1928f5e85bca01e6" + version = "9e78876d7a7ebb66807b2f09207d4211d2265de8" url = "https://github.com/teeworlds/teeworlds-libs/archive/{}.zip".format(version) # download and unzip From 6ac12cd030f99ec27a46d92e3a2560eeeda3ae59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 8 Jan 2020 12:50:51 +0100 Subject: [PATCH 006/479] fix logarithmic scrollbar to support minimum of 0 --- src/game/client/components/menus.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 76db43ac..c8789e62 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -53,10 +53,18 @@ static class : public IScrollbarScale public: float ToRelative(int AbsoluteValue, int Min, int Max) { + if(Min == 0) + { + return ToRelative(AbsoluteValue+1, Min+1, Max+1); + } return (log(AbsoluteValue) - log(Min)) / (float)(log(Max) - log(Min)); } int ToAbsolute(float RelativeValue, int Min, int Max) { + if(Min == 0) + { + return ToAbsolute(RelativeValue, Min+1, Max+1)-1; + } return round_to_int(exp(RelativeValue*(log(Max) - log(Min)) + log(Min))); } } LogarithmicScrollbarScale; From d37f886944eda1e94d783f0758d53da3f2a7af62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 9 Jan 2020 00:10:55 +0100 Subject: [PATCH 007/479] make lower values on log scrollbar scale more smooth --- src/game/client/components/menus.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index c8789e62..a65d9ce3 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -36,7 +36,7 @@ class IScrollbarScale virtual float ToRelative(int AbsoluteValue, int Min, int Max) = 0; virtual int ToAbsolute(float RelativeValue, int Min, int Max) = 0; }; -static class : public IScrollbarScale +static class CLinearScrollbarScale : public IScrollbarScale { public: float ToRelative(int AbsoluteValue, int Min, int Max) @@ -48,26 +48,32 @@ static class : public IScrollbarScale return round_to_int(RelativeValue*(Max - Min) + Min + 0.1f); } } LinearScrollbarScale; -static class : public IScrollbarScale +static class CLogarithmicScrollbarScale : public IScrollbarScale { +private: + int m_MinAdjustment; public: + CLogarithmicScrollbarScale(int MinAdjustment) + { + m_MinAdjustment = max(MinAdjustment, 1); // must be at least 1 to support Min == 0 with logarithm + } float ToRelative(int AbsoluteValue, int Min, int Max) { - if(Min == 0) + if(Min < m_MinAdjustment) { - return ToRelative(AbsoluteValue+1, Min+1, Max+1); + return ToRelative(AbsoluteValue+m_MinAdjustment, Min+m_MinAdjustment, Max+m_MinAdjustment); } return (log(AbsoluteValue) - log(Min)) / (float)(log(Max) - log(Min)); } int ToAbsolute(float RelativeValue, int Min, int Max) { - if(Min == 0) + if(Min < m_MinAdjustment) { - return ToAbsolute(RelativeValue, Min+1, Max+1)-1; + return ToAbsolute(RelativeValue, Min+m_MinAdjustment, Max+m_MinAdjustment)-m_MinAdjustment; } return round_to_int(exp(RelativeValue*(log(Max) - log(Min)) + log(Min))); } -} LogarithmicScrollbarScale; +} LogarithmicScrollbarScale(25); class CMenus : public CComponent { From d20a1e1429e03425252b65a48a6c1718d36f59fe Mon Sep 17 00:00:00 2001 From: AssassinTee Date: Wed, 8 Jan 2020 17:40:12 +0100 Subject: [PATCH 008/479] fix issue #2372 this commit will be crushed --- src/game/client/components/binds.cpp | 34 ++++++++++++++++++++-------- src/game/client/components/binds.h | 2 ++ src/game/client/components/chat.cpp | 19 +++++++++++----- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 0df27649..4887c2b0 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -205,27 +205,43 @@ const char *CBinds::Get(int KeyID, int Modifier) return ""; } -void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize) +void CBinds::GetKeyID(const char *pBindStr, int& KeyID, int& Modifier) { - aKey[0] = 0; - for(int KeyID = 0; KeyID < KEY_LAST; KeyID++) + for(KeyID = 0; KeyID < KEY_LAST; KeyID++) { - for(int m = 0; m < MODIFIER_COUNT; m++) + for(Modifier = 0; Modifier < MODIFIER_COUNT; Modifier++) { - const char *pBind = Get(KeyID, m); + const char *pBind = Get(KeyID, Modifier); if(!pBind[0]) continue; - if(str_comp(pBind, pBindStr) == 0) - { - str_format(aKey, BufSize, "%s%s", GetModifierName(m), Input()->KeyName(KeyID)); + if(str_find(pBind, pBindStr) != 0) return; - } } } + + //this is already given by the loops above + KeyID = KEY_LAST; + Modifier = MODIFIER_COUNT; +} + +void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize, int KeyID, int Modifier) +{ + aKey[0] = 0; + if(KeyID < KEY_LAST){ + str_format(aKey, BufSize, "%s%s", GetModifierName(Modifier), Input()->KeyName(KeyID)); + return; + } str_copy(aKey, "key not found", BufSize); } +void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize) +{ + int KeyID, Modifier; + GetKeyID(pBindStr, KeyID, Modifier); + GetKey(pBindStr, aKey, BufSize, KeyID, Modifier); +} + void CBinds::SetDefaults() { // set default key bindings diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index d1df5ba6..df7a27b8 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -42,6 +42,8 @@ class CBinds : public CComponent void SetDefaults(); void UnbindAll(); const char *Get(int KeyID, int Modifier); + void GetKeyID(const char *pBindStr, int& KeyID, int& Modifier); + void GetKey(const char *pBindStr, char aKey[64], unsigned BufSize, int KeyID, int Modifier); void GetKey(const char *pBindStr, char aKey[64], unsigned BufSize); static const char *GetModifierName(int m); static int GetModifierMask(IInput *i); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 7c7dd80a..5620e82b 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -908,13 +908,20 @@ void CChat::OnRender() CTextCursor InfoCursor; TextRender()->SetCursor(&InfoCursor, 2.0f, y+12.0f, CategoryFontSize*0.75, TEXTFLAG_RENDER); - //find keyname and format text - char aKeyName[64]; - m_pClient->m_pBinds->GetKey(GetCommandName(m_ChatBufferMode), aKeyName, sizeof(aKeyName)); + //Check if key exists with bind + int KeyID, Modifier; + m_pClient->m_pBinds->GetKeyID(GetCommandName(m_ChatBufferMode), KeyID, Modifier); + + if(KeyID < KEY_LAST) + { + //find keyname and format text + char aKeyName[64]; + m_pClient->m_pBinds->GetKey(GetCommandName(m_ChatBufferMode), aKeyName, sizeof(aKeyName), KeyID, Modifier); - char aInfoText[128]; - str_format(aInfoText, sizeof(aInfoText), Localize("Press %s to resume chatting"), aKeyName); - TextRender()->TextEx(&InfoCursor, aInfoText, -1); + char aInfoText[128]; + str_format(aInfoText, sizeof(aInfoText), Localize("Press %s to resume chatting"), aKeyName); + TextRender()->TextEx(&InfoCursor, aInfoText, -1); + } } else { From 21d85f186282f8924c3f8b2d28b9c030ee0ff691 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 9 Jan 2020 18:30:57 +0100 Subject: [PATCH 009/479] trigger workflow on pull request --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 94c31827..ca51cb72 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,6 +1,6 @@ name: Build -on: [push] +on: [push, pull_request] jobs: build-cmake: From c89077bcc57e5a7966aec657bf7de6fa99b71e7c Mon Sep 17 00:00:00 2001 From: Sonix- Date: Thu, 9 Jan 2020 20:38:39 +0100 Subject: [PATCH 010/479] Improve friend boxes --- src/game/client/components/menus_browser.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 19cdf580..2e232c21 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1457,22 +1457,21 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) { View.HSplitTop(20.0f + GetListHeaderHeight(), &Rect, &View); ScrollRegionAddRect(&s_ScrollRegion, Rect); - - RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 0.5f, 0.5f, 0.5f), CUI::CORNER_ALL, 5.0f); + if(i == FRIEND_PLAYER_ON) + RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 1.0f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); + else if(i == FRIEND_CLAN_ON) + RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 0.5f, 1.5f, 0.30f), CUI::CORNER_ALL, 5.0f); + else + RenderTools()->DrawUIRect(&Rect, vec4(1.0f, 0.5f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); Rect.VMargin(2.0f, &Rect); Rect.VSplitRight(45.0f, &Rect, &Icon); Rect.HSplitTop(20.0f, &Button, 0); // name Rect.HSplitTop(10.0f, &Button, &Rect); - vec4 Colour = (i == FRIEND_PLAYER_ON) ? vec4(0.5f, 1.0f, 0.5f, 0.15f) : - (i == FRIEND_CLAN_ON || !m_lFriendList[i][f].m_aName[0]) ? vec4(0.0f, 0.0f, 0.0f, 0.15f) : vec4(1.0f, 0.5f, 0.5f, 0.15f); - RenderTools()->DrawUIRect(&Button, Colour, CUI::CORNER_T, 4.0f); Button.VSplitLeft(2.0f, 0, &Button); UI()->DoLabel(&Button, m_lFriendList[i][f].m_aName, FontSize - 2, CUI::ALIGN_LEFT); // clan Rect.HSplitTop(10.0f, &Button, &Rect); - Colour = (i != FRIEND_OFF) ? vec4(0.5f, 1.0f, 0.5f, 0.15f) : vec4(1.0f, 0.5f, 0.5f, 0.15f); - RenderTools()->DrawUIRect(&Button, Colour, CUI::CORNER_B, 4.0f); Button.VSplitLeft(2.0f, 0, &Button); UI()->DoLabel(&Button, m_lFriendList[i][f].m_aClan, FontSize - 2, CUI::ALIGN_LEFT); // info From 3c48afa873198fa6b43c8a987fe11b2c608c1b35 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Jan 2020 15:47:20 +0100 Subject: [PATCH 011/479] fixed warnings --- src/game/client/components/menus.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index a65d9ce3..1da7eb13 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -61,17 +61,22 @@ static class CLogarithmicScrollbarScale : public IScrollbarScale { if(Min < m_MinAdjustment) { - return ToRelative(AbsoluteValue+m_MinAdjustment, Min+m_MinAdjustment, Max+m_MinAdjustment); + AbsoluteValue += m_MinAdjustment; + Min += m_MinAdjustment; + Max += m_MinAdjustment; } return (log(AbsoluteValue) - log(Min)) / (float)(log(Max) - log(Min)); } int ToAbsolute(float RelativeValue, int Min, int Max) { + int ResultAdjustment = 0; if(Min < m_MinAdjustment) { - return ToAbsolute(RelativeValue, Min+m_MinAdjustment, Max+m_MinAdjustment)-m_MinAdjustment; + Min += m_MinAdjustment; + Max += m_MinAdjustment; + ResultAdjustment = -m_MinAdjustment; } - return round_to_int(exp(RelativeValue*(log(Max) - log(Min)) + log(Min))); + return round_to_int(exp(RelativeValue*(log(Max) - log(Min)) + log(Min))) + ResultAdjustment; } } LogarithmicScrollbarScale(25); From eff937c9b876a48f9156baece0a55cd2baab1cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 9 Jan 2020 19:02:23 +0100 Subject: [PATCH 012/479] add UiDoListboxFilter, add filter to skin selection --- src/game/client/components/menus.cpp | 36 ++++++++++++++++--- src/game/client/components/menus.h | 15 ++++++-- src/game/client/components/menus_settings.cpp | 24 ++++++------- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 353be29b..93a21ee1 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -450,10 +450,10 @@ int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) return Inside; } -int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners) +bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners) { int Inside = UI()->MouseInside(pRect); - bool ReturnValue = false; + bool Changed = false; bool UpdateOffset = false; static int s_AtIndex = 0; static bool s_DoScroll = false; @@ -516,7 +516,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS { Len = str_length(pStr); int NumChars = Len; - ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars, Input()); + Changed |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars, Input()); } } } @@ -616,7 +616,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS } UI()->ClipDisable(); - return ReturnValue; + return Changed; } void CMenus::DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden) @@ -949,6 +949,34 @@ void CMenus::UiDoListboxHeader(CListBoxState* pState, const CUIRect *pRect, cons pState->m_ListBoxView = View; } +bool CMenus::UiDoListboxFilter(CListBoxState* pState, float FilterHeight, float Spacing) +{ + CUIRect Filter; + CUIRect View = pState->m_ListBoxView; + + // background + View.HSplitTop(FilterHeight+Spacing, &Filter, 0); + RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); + + // draw filter + View.HSplitTop(FilterHeight, &Filter, &View); + Filter.Margin(Spacing, &Filter); + + float FontSize = Filter.h*ms_FontmodHeight*0.8f; + + CUIRect Label, EditBox; + Filter.VSplitLeft(Filter.w/5.0f, &Label, &EditBox); + Label.y += Spacing; + UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); + bool Changed = DoEditBox(pState->m_aFilterString, &EditBox, pState->m_aFilterString, sizeof(pState->m_aFilterString), FontSize, &pState->m_OffsetFilter); + + View.HSplitTop(Spacing, &Filter, &View); + + pState->m_ListBoxView = View; + + return Changed; +} + void CMenus::UiDoListboxStart(CListBoxState* pState, const void *pID, float RowHeight, const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect, bool Background, bool *pActive) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 1da7eb13..9409c633 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -132,7 +132,7 @@ class CMenus : public CComponent static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); */ - int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); + bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false); void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite=false); float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); @@ -256,8 +256,9 @@ class CMenus : public CComponent CUIRect m_Rect; }; - struct CListBoxState + class CListBoxState { + public: CUIRect m_ListBoxView; float m_ListBoxRowHeight; int m_ListBoxItemIndex; @@ -271,15 +272,25 @@ class CMenus : public CComponent bool m_ListBoxItemActivated; CScrollRegion m_ScrollRegion; vec2 m_ScrollOffset; + char m_aFilterString[64]; + float m_OffsetFilter; CListBoxState() { m_ScrollOffset = vec2(0,0); m_ListBoxUpdateScroll = false; + m_aFilterString[0] = '\0'; + m_OffsetFilter = 0.0f; + } + + bool FilterMatches(const char *pNeedle) + { + return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); } }; void UiDoListboxHeader(CListBoxState* pState, const CUIRect *pRect, const char *pTitle, float HeaderHeight, float Spacing); + bool UiDoListboxFilter(CListBoxState* pState, float FilterHeight, float Spacing); void UiDoListboxStart(CListBoxState* pState, const void *pID, float RowHeight, const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect=0, bool Background=true, bool *pActive = 0); CListboxItem UiDoListboxNextItem(CListBoxState* pState, const void *pID, bool Selected = false, bool *pActive = 0); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 2cab9889..45b01b68 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -417,8 +417,10 @@ void CMenus::RenderSkinSelection(CUIRect MainView) { const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i); // no special skins - if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0) + if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0 && s_ListBoxState.FilterMatches(s->m_aName)) + { s_paSkinList.add(s); + } } m_RefreshSkinSelector = false; } @@ -426,6 +428,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) m_pSelectedSkin = 0; int OldSelected = -1; UiDoListboxHeader(&s_ListBoxState, &MainView, Localize("Skins"), 20.0f, 2.0f); + m_RefreshSkinSelector = UiDoListboxFilter(&s_ListBoxState, 20.0f, 2.0f); UiDoListboxStart(&s_ListBoxState, &m_RefreshSkinSelector, 50.0f, 0, s_paSkinList.size(), 10, OldSelected); for(int i = 0; i < s_paSkinList.size(); ++i) @@ -464,20 +467,17 @@ void CMenus::RenderSkinSelection(CUIRect MainView) } const int NewSelected = UiDoListboxEnd(&s_ListBoxState, 0); - if(NewSelected != -1) + if(NewSelected != -1 && NewSelected != OldSelected) { - if(NewSelected != OldSelected) + m_pSelectedSkin = s_paSkinList[NewSelected]; + mem_copy(g_Config.m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(g_Config.m_PlayerSkin)); + for(int p = 0; p < NUM_SKINPARTS; p++) { - m_pSelectedSkin = s_paSkinList[NewSelected]; - mem_copy(g_Config.m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(g_Config.m_PlayerSkin)); - for(int p = 0; p < NUM_SKINPARTS; p++) - { - mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, 24); - *CSkins::ms_apUCCVariables[p] = m_pSelectedSkin->m_aUseCustomColors[p]; - *CSkins::ms_apColorVariables[p] = m_pSelectedSkin->m_aPartColors[p]; - } - m_SkinModified = true; + mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, 24); + *CSkins::ms_apUCCVariables[p] = m_pSelectedSkin->m_aUseCustomColors[p]; + *CSkins::ms_apColorVariables[p] = m_pSelectedSkin->m_aPartColors[p]; } + m_SkinModified = true; } OldSelected = NewSelected; } From da2acb32874238ac8fb985e6fa84f637d6a446eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 9 Jan 2020 20:18:28 +0100 Subject: [PATCH 013/479] refactor CListBoxState to CListBox --- src/game/client/components/menus.cpp | 160 ++++++++++-------- src/game/client/components/menus.h | 38 ++--- src/game/client/components/menus_demo.cpp | 10 +- src/game/client/components/menus_ingame.cpp | 25 ++- src/game/client/components/menus_settings.cpp | 75 ++++---- 5 files changed, 157 insertions(+), 151 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 93a21ee1..b9105c88 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -927,36 +927,46 @@ void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, RenderTools()->DrawUIRect(&Slider, Color, CUI::CORNER_ALL, Slider.h/2.0f); } -void CMenus::UiDoListboxHeader(CListBoxState* pState, const CUIRect *pRect, const char *pTitle, + +CMenus::CListBox::CListBox(CMenus *pMenus) +{ + m_pMenus = pMenus; + m_ScrollOffset = vec2(0,0); + m_ListBoxUpdateScroll = false; + m_aFilterString[0] = '\0'; + m_OffsetFilter = 0.0f; +} + +void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight, float Spacing) { CUIRect Header; CUIRect View = *pRect; // background - const float Height = GetListHeaderHeight(); + const float Height = m_pMenus->GetListHeaderHeight(); View.HSplitTop(Height+Spacing, &Header, 0); - RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); + m_pMenus->RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); // draw header View.HSplitTop(Height, &Header, &View); Header.y += 2.0f; - UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + m_pMenus->UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); View.HSplitTop(Spacing, &Header, &View); // setup the variables - pState->m_ListBoxView = View; + m_ListBoxView = View; } -bool CMenus::UiDoListboxFilter(CListBoxState* pState, float FilterHeight, float Spacing) +bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) { CUIRect Filter; - CUIRect View = pState->m_ListBoxView; + CUIRect View = m_ListBoxView; // background View.HSplitTop(FilterHeight+Spacing, &Filter, 0); - RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); + m_pMenus->RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); // draw filter View.HSplitTop(FilterHeight, &Filter, &View); @@ -967,17 +977,17 @@ bool CMenus::UiDoListboxFilter(CListBoxState* pState, float FilterHeight, float CUIRect Label, EditBox; Filter.VSplitLeft(Filter.w/5.0f, &Label, &EditBox); Label.y += Spacing; - UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); - bool Changed = DoEditBox(pState->m_aFilterString, &EditBox, pState->m_aFilterString, sizeof(pState->m_aFilterString), FontSize, &pState->m_OffsetFilter); + m_pMenus->UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); + bool Changed = m_pMenus->DoEditBox(m_aFilterString, &EditBox, m_aFilterString, sizeof(m_aFilterString), FontSize, &m_OffsetFilter); View.HSplitTop(Spacing, &Filter, &View); - pState->m_ListBoxView = View; + m_ListBoxView = View; return Changed; } -void CMenus::UiDoListboxStart(CListBoxState* pState, const void *pID, float RowHeight, +void CMenus::CListBox::DoStart(float RowHeight, const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect, bool Background, bool *pActive) { @@ -985,92 +995,92 @@ void CMenus::UiDoListboxStart(CListBoxState* pState, const void *pID, float RowH if(pRect) View = *pRect; else - View = pState->m_ListBoxView; + View = m_ListBoxView; CUIRect Footer; // background if(Background) - RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + m_pMenus->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); // draw footers if(pBottomText) { - const float Height = GetListHeaderHeight(); + const float Height = m_pMenus->GetListHeaderHeight(); View.HSplitBottom(Height, &View, &Footer); Footer.VSplitLeft(10.0f, 0, &Footer); Footer.y += 2.0f; - UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + m_pMenus->UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } // setup the variables - pState->m_ListBoxView = View; - pState->m_ListBoxSelectedIndex = SelectedIndex; - pState->m_ListBoxNewSelected = SelectedIndex; - pState->m_ListBoxNewSelOffset = 0; - pState->m_ListBoxItemIndex = 0; - pState->m_ListBoxRowHeight = RowHeight; - pState->m_ListBoxNumItems = NumItems; - pState->m_ListBoxItemsPerRow = ItemsPerRow; - pState->m_ListBoxDoneEvents = 0; - pState->m_ListBoxItemActivated = false; + m_ListBoxView = View; + m_ListBoxSelectedIndex = SelectedIndex; + m_ListBoxNewSelected = SelectedIndex; + m_ListBoxNewSelOffset = 0; + m_ListBoxItemIndex = 0; + m_ListBoxRowHeight = RowHeight; + m_ListBoxNumItems = NumItems; + m_ListBoxItemsPerRow = ItemsPerRow; + m_ListBoxDoneEvents = 0; + m_ListBoxItemActivated = false; // handle input if(!pActive || *pActive) { - if(m_DownArrowPressed) - pState->m_ListBoxNewSelOffset += 1; - if(m_UpArrowPressed) - pState->m_ListBoxNewSelOffset -= 1; + if(m_pMenus->m_DownArrowPressed) + m_ListBoxNewSelOffset += 1; + if(m_pMenus->m_UpArrowPressed) + m_ListBoxNewSelOffset -= 1; } // setup the scrollbar - pState->m_ScrollOffset = vec2(0, 0); - BeginScrollRegion(&pState->m_ScrollRegion, &pState->m_ListBoxView, &pState->m_ScrollOffset); - pState->m_ListBoxView.y += pState->m_ScrollOffset.y; + m_ScrollOffset = vec2(0, 0); + m_pMenus->BeginScrollRegion(&m_ScrollRegion, &m_ListBoxView, &m_ScrollOffset); + m_ListBoxView.y += m_ScrollOffset.y; } -CMenus::CListboxItem CMenus::UiDoListboxNextRow(CListBoxState* pState) +CMenus::CListboxItem CMenus::CListBox::DoNextRow() { static CUIRect s_RowView; CListboxItem Item = {0}; - if(pState->m_ListBoxItemIndex%pState->m_ListBoxItemsPerRow == 0) - pState->m_ListBoxView.HSplitTop(pState->m_ListBoxRowHeight /*-2.0f*/, &s_RowView, &pState->m_ListBoxView); - ScrollRegionAddRect(&pState->m_ScrollRegion, s_RowView); - if(pState->m_ListBoxUpdateScroll && pState->m_ListBoxSelectedIndex == pState->m_ListBoxItemIndex) + if(m_ListBoxItemIndex%m_ListBoxItemsPerRow == 0) + m_ListBoxView.HSplitTop(m_ListBoxRowHeight /*-2.0f*/, &s_RowView, &m_ListBoxView); + m_pMenus->ScrollRegionAddRect(&m_ScrollRegion, s_RowView); + if(m_ListBoxUpdateScroll && m_ListBoxSelectedIndex == m_ListBoxItemIndex) { - ScrollRegionScrollHere(&pState->m_ScrollRegion, CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); - pState->m_ListBoxUpdateScroll = false; + m_pMenus->ScrollRegionScrollHere(&m_ScrollRegion, CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + m_ListBoxUpdateScroll = false; } - s_RowView.VSplitLeft(s_RowView.w/(pState->m_ListBoxItemsPerRow-pState->m_ListBoxItemIndex%pState->m_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); + s_RowView.VSplitLeft(s_RowView.w/(m_ListBoxItemsPerRow-m_ListBoxItemIndex%m_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); - if(pState->m_ListBoxSelectedIndex == pState->m_ListBoxItemIndex) + if(m_ListBoxSelectedIndex == m_ListBoxItemIndex) Item.m_Selected = 1; - Item.m_Visible = !ScrollRegionIsRectClipped(&pState->m_ScrollRegion, Item.m_Rect); + Item.m_Visible = !m_pMenus->ScrollRegionIsRectClipped(&m_ScrollRegion, Item.m_Rect); - pState->m_ListBoxItemIndex++; + m_ListBoxItemIndex++; return Item; } -CMenus::CListboxItem CMenus::UiDoListboxNextItem(CListBoxState* pState, const void *pId, bool Selected, bool *pActive) +CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) { - int ThisItemIndex = pState->m_ListBoxItemIndex; + int ThisItemIndex = m_ListBoxItemIndex; if(Selected) { - if(pState->m_ListBoxSelectedIndex == pState->m_ListBoxNewSelected) - pState->m_ListBoxNewSelected = ThisItemIndex; - pState->m_ListBoxSelectedIndex = ThisItemIndex; + if(m_ListBoxSelectedIndex == m_ListBoxNewSelected) + m_ListBoxNewSelected = ThisItemIndex; + m_ListBoxSelectedIndex = ThisItemIndex; } - CListboxItem Item = UiDoListboxNextRow(pState); + CListboxItem Item = DoNextRow(); static bool s_ItemClicked = false; - if(Item.m_Visible && UI()->DoButtonLogic(pId, "", pState->m_ListBoxSelectedIndex == pState->m_ListBoxItemIndex, &Item.m_Rect)) + if(Item.m_Visible && m_pMenus->UI()->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) { s_ItemClicked = true; - pState->m_ListBoxNewSelected = ThisItemIndex; + m_ListBoxNewSelected = ThisItemIndex; if(pActive) *pActive = true; } @@ -1080,44 +1090,50 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(CListBoxState* pState, const vo const bool ProcessInput = !pActive || *pActive; // process input, regard selected index - if(pState->m_ListBoxSelectedIndex == ThisItemIndex) + if(m_ListBoxSelectedIndex == ThisItemIndex) { - if(ProcessInput && !pState->m_ListBoxDoneEvents) + if(ProcessInput && !m_ListBoxDoneEvents) { - pState->m_ListBoxDoneEvents = 1; + m_ListBoxDoneEvents = 1; - if(m_EnterPressed || (s_ItemClicked && Input()->MouseDoubleClick())) + if(m_pMenus->m_EnterPressed || (s_ItemClicked && m_pMenus->Input()->MouseDoubleClick())) { - pState->m_ListBoxItemActivated = true; - UI()->SetActiveItem(0); + m_ListBoxItemActivated = true; + m_pMenus->UI()->SetActiveItem(0); } } CUIRect r = Item.m_Rect; - RenderTools()->DrawUIRect(&r, vec4(1,1,1,ProcessInput?0.5f:0.33f), CUI::CORNER_ALL, 5.0f); + m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); } - /*else*/ if(UI()->HotItem() == pId) + /*else*/ if(m_pMenus->UI()->HotItem() == pId) { CUIRect r = Item.m_Rect; - RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.33f), CUI::CORNER_ALL, 5.0f); + m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); } return Item; } -int CMenus::UiDoListboxEnd(CListBoxState* pState, bool *pItemActivated) +int CMenus::CListBox::DoEnd(bool *pItemActivated) { - EndScrollRegion(&pState->m_ScrollRegion); - if(pState->m_ListBoxNewSelOffset != 0 && pState->m_ListBoxSelectedIndex != -1 && pState->m_ListBoxSelectedIndex == pState->m_ListBoxNewSelected) + m_pMenus->EndScrollRegion(&m_ScrollRegion); + if(m_ListBoxNewSelOffset != 0 && m_ListBoxSelectedIndex != -1 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) { - pState->m_ListBoxNewSelected = clamp(pState->m_ListBoxNewSelected + pState->m_ListBoxNewSelOffset, 0, pState->m_ListBoxNumItems - 1); - pState->m_ListBoxUpdateScroll = true; + m_ListBoxNewSelected = clamp(m_ListBoxNewSelected + m_ListBoxNewSelOffset, 0, m_ListBoxNumItems - 1); + m_ListBoxUpdateScroll = true; } if(pItemActivated) - *pItemActivated = pState->m_ListBoxItemActivated; - return pState->m_ListBoxNewSelected; + *pItemActivated = m_ListBoxItemActivated; + return m_ListBoxNewSelected; } +bool CMenus::CListBox::FilterMatches(const char *pNeedle) +{ + return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); +} + + int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier) { // process @@ -2162,9 +2178,9 @@ int CMenus::Render() static int ActSelection = -2; if(ActSelection == -2) ActSelection = FilterInfo.m_Country; - static CListBoxState s_ListBoxState; + static CListBox s_ListBox(this); int OldSelected = -1; - UiDoListboxStart(&s_ListBoxState, &s_ListBoxState, 40.0f, 0, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); + s_ListBox.DoStart(40.0f, 0, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -2174,7 +2190,7 @@ int CMenus::Render() if(pEntry->m_CountryCode == ActSelection) OldSelected = i; - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &pEntry->m_CountryCode, OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected == i); if(Item.m_Visible) { CUIRect Label; @@ -2202,7 +2218,7 @@ int CMenus::Render() } } - const int NewSelected = UiDoListboxEnd(&s_ListBoxState, 0); + const int NewSelected = s_ListBox.DoEnd(0); if(OldSelected != NewSelected) ActSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 9409c633..4f986485 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -256,9 +256,10 @@ class CMenus : public CComponent CUIRect m_Rect; }; - class CListBoxState + class CListBox { - public: + private: + CMenus *m_pMenus; CUIRect m_ListBoxView; float m_ListBoxRowHeight; int m_ListBoxItemIndex; @@ -275,28 +276,19 @@ class CMenus : public CComponent char m_aFilterString[64]; float m_OffsetFilter; - CListBoxState() - { - m_ScrollOffset = vec2(0,0); - m_ListBoxUpdateScroll = false; - m_aFilterString[0] = '\0'; - m_OffsetFilter = 0.0f; - } - - bool FilterMatches(const char *pNeedle) - { - return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); - } + public: + CListBox(CMenus *pMenus); + + void DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight = 20.0f, float Spacing = 2.0f); + bool DoFilter(float FilterHeight = 20.0f, float Spacing = 2.0f); + void DoStart(float RowHeight, const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, + const CUIRect *pRect = 0, bool Background = true, bool *pActive = 0); + CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = 0); + CListboxItem DoNextRow(); + int DoEnd(bool *pItemActivated); + bool FilterMatches(const char *pNeedle); }; - void UiDoListboxHeader(CListBoxState* pState, const CUIRect *pRect, const char *pTitle, float HeaderHeight, float Spacing); - bool UiDoListboxFilter(CListBoxState* pState, float FilterHeight, float Spacing); - void UiDoListboxStart(CListBoxState* pState, const void *pID, float RowHeight, const char *pBottomText, int NumItems, - int ItemsPerRow, int SelectedIndex, const CUIRect *pRect=0, bool Background=true, bool *pActive = 0); - CListboxItem UiDoListboxNextItem(CListBoxState* pState, const void *pID, bool Selected = false, bool *pActive = 0); - CListboxItem UiDoListboxNextRow(CListBoxState* pState); - int UiDoListboxEnd(CListBoxState* pState, bool *pItemActivated); - enum { POPUP_NONE=0, @@ -744,7 +736,7 @@ class CMenus : public CComponent void RenderSettingsSound(CUIRect MainView); void RenderSettings(CUIRect MainView); - bool DoResolutionList(CUIRect* pRect, CListBoxState* pListBoxState, + bool DoResolutionList(CUIRect* pRect, CListBox* pListBox, const sorted_array& lModes); // found in menu_callback.cpp diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index c4b07e62..6a23fddb 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -376,12 +376,12 @@ void CMenus::RenderDemoList(CUIRect MainView) CUIRect ListBox, Button, FileIcon; MainView.HSplitTop(MainView.h - BackgroundHeight - 2 * HMargin, &ListBox, &MainView); - static CListBoxState s_ListBoxState; - UiDoListboxHeader(&s_ListBoxState, &ListBox, Localize("Recorded"), 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &s_ListBoxState, 20.0f, 0, m_lDemos.size(), 1, m_DemolistSelectedIndex); + static CListBox s_ListBox(this); + s_ListBox.DoHeader(&ListBox, Localize("Recorded"), 20.0f, 2.0f); + s_ListBox.DoStart(20.0f, 0, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, (void*)(&r.front())); + CListboxItem Item = s_ListBox.DoNextItem((void*)(&r.front())); // marker count const CDemoItem& DemoItem = r.front(); int DemoMarkerCount = 0; @@ -421,7 +421,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } } bool Activated = false; - m_DemolistSelectedIndex = UiDoListboxEnd(&s_ListBoxState, &Activated); + m_DemolistSelectedIndex = s_ListBox.DoEnd(&Activated); DemolistOnUpdate(false); MainView.HSplitTop(HMargin, 0, &MainView); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index a0c9940b..0a42a1b5 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -503,19 +503,17 @@ void CMenus::RenderServerInfo(CUIRect MainView) bool CMenus::RenderServerControlServer(CUIRect MainView) { - bool doCallVote = false; - static int s_VoteList = 0; - static CListBoxState s_ListBoxState; + static CListBox s_ListBox(this); CUIRect List = MainView; - UiDoListboxHeader(&s_ListBoxState, &List, Localize("Option"), 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &s_VoteList, 20.0f, 0, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); + s_ListBox.DoHeader(&List, Localize("Option")); + s_ListBox.DoStart(20.0f, 0, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { if(m_aFilterString[0] && !str_find_nocase(pOption->m_aDescription, m_aFilterString)) continue; // no match found - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, pOption); + CListboxItem Item = s_ListBox.DoNextItem(pOption); if(Item.m_Visible) { @@ -525,7 +523,8 @@ bool CMenus::RenderServerControlServer(CUIRect MainView) } } - m_CallvoteSelectedOption = UiDoListboxEnd(&s_ListBoxState, &doCallVote); + bool doCallVote = false; + m_CallvoteSelectedOption = s_ListBox.DoEnd(&doCallVote); return doCallVote; } @@ -552,15 +551,15 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) const float Spacing = 2.0f; const float NameWidth = 250.0f; const float ClanWidth = 250.0f; - static int s_VoteList = 0; - static CListBoxState s_ListBoxState; + + static CListBox s_ListBox(this); CUIRect List = MainView; - UiDoListboxHeader(&s_ListBoxState, &List, Localize("Player"), 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &s_VoteList, 20.0f, 0, NumOptions, 1, Selected, 0, true); + s_ListBox.DoHeader(&List, Localize("Player")); + s_ListBox.DoStart(20.0f, 0, NumOptions, 1, Selected, 0, true); for(int i = 0; i < NumOptions; i++) { - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &aPlayerIDs[i]); + CListboxItem Item = s_ListBox.DoNextItem(&aPlayerIDs[i]); if(Item.m_Visible) { @@ -598,7 +597,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) } } - Selected = UiDoListboxEnd(&s_ListBoxState, 0); + Selected = s_ListBox.DoEnd(0); m_CallvoteSelectedPlayer = Selected != -1 ? aPlayerIDs[Selected] : -1; } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 45b01b68..40bc17b5 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -409,7 +409,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) void CMenus::RenderSkinSelection(CUIRect MainView) { static sorted_array s_paSkinList; - static CListBoxState s_ListBoxState; + static CListBox s_ListBox(this); if(m_RefreshSkinSelector) { s_paSkinList.clear(); @@ -417,7 +417,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) { const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i); // no special skins - if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0 && s_ListBoxState.FilterMatches(s->m_aName)) + if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0 && s_ListBox.FilterMatches(s->m_aName)) { s_paSkinList.add(s); } @@ -427,9 +427,9 @@ void CMenus::RenderSkinSelection(CUIRect MainView) m_pSelectedSkin = 0; int OldSelected = -1; - UiDoListboxHeader(&s_ListBoxState, &MainView, Localize("Skins"), 20.0f, 2.0f); - m_RefreshSkinSelector = UiDoListboxFilter(&s_ListBoxState, 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &m_RefreshSkinSelector, 50.0f, 0, s_paSkinList.size(), 10, OldSelected); + s_ListBox.DoHeader(&MainView, Localize("Skins")); + m_RefreshSkinSelector = s_ListBox.DoFilter(); + s_ListBox.DoStart(50.0f, 0, s_paSkinList.size(), 10, OldSelected); for(int i = 0; i < s_paSkinList.size(); ++i) { @@ -442,7 +442,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) OldSelected = i; } - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &s_paSkinList[i], OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(&s_paSkinList[i], OldSelected == i); if(Item.m_Visible) { CTeeRenderInfo Info; @@ -466,7 +466,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) } } - const int NewSelected = UiDoListboxEnd(&s_ListBoxState, 0); + const int NewSelected = s_ListBox.DoEnd(0); if(NewSelected != -1 && NewSelected != OldSelected) { m_pSelectedSkin = s_paSkinList[NewSelected]; @@ -503,9 +503,9 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } static int OldSelected = -1; - static CListBoxState s_ListBoxState; - UiDoListboxHeader(&s_ListBoxState, &MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected]), 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &s_InitSkinPartList, 50.0f, 0, s_paList[m_TeePartSelected].size(), 5, OldSelected); + static CListBox s_ListBox(this); + s_ListBox.DoHeader(&MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected])); + s_ListBox.DoStart(50.0f, 0, s_paList[m_TeePartSelected].size(), 5, OldSelected); for(int i = 0; i < s_paList[m_TeePartSelected].size(); ++i) { @@ -515,7 +515,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) if(!str_comp(s->m_aName, CSkins::ms_apSkinVariables[m_TeePartSelected])) OldSelected = i; - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &s_paList[m_TeePartSelected][i], OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(&s_paList[m_TeePartSelected][i], OldSelected == i); if(Item.m_Visible) { CTeeRenderInfo Info; @@ -552,7 +552,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } } - const int NewSelected = UiDoListboxEnd(&s_ListBoxState, 0); + const int NewSelected = s_ListBox.DoEnd(0); if(NewSelected != -1) { if(NewSelected != OldSelected) @@ -760,33 +760,34 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) { - static int s_LanguageList = 0; static int s_SelectedLanguage = -1; static sorted_array s_Languages; - static CListBoxState s_ListBoxState; + static CListBox s_ListBox(this); if(s_Languages.size() == 0) { s_Languages.add(CLanguage("English", "", 826)); LoadLanguageIndexfile(Storage(), Console(), &s_Languages); for(int i = 0; i < s_Languages.size(); i++) + { if(str_comp(s_Languages[i].m_FileName, g_Config.m_ClLanguagefile) == 0) { s_SelectedLanguage = i; break; } + } } int OldSelected = s_SelectedLanguage; if(Header) - UiDoListboxHeader(&s_ListBoxState, &MainView, Localize("Language"), 20.0f, 2.0f); + s_ListBox.DoHeader(&MainView, Localize("Language")); bool IsActive = m_ActiveListBox == ACTLB_LANG; - UiDoListboxStart(&s_ListBoxState, &s_LanguageList, 20.0f, 0, s_Languages.size(), 1, s_SelectedLanguage, Header?0:&MainView, Header?true:false, &IsActive); + s_ListBox.DoStart(20.0f, 0, s_Languages.size(), 1, s_SelectedLanguage, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &r.front(), false, &IsActive); + CListboxItem Item = s_ListBox.DoNextItem(&r.front(), false, &IsActive); if(IsActive) m_ActiveListBox = ACTLB_LANG; @@ -812,7 +813,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) } } - s_SelectedLanguage = UiDoListboxEnd(&s_ListBoxState, 0); + s_SelectedLanguage = s_ListBox.DoEnd(0); if(OldSelected != s_SelectedLanguage) { @@ -824,9 +825,8 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) { - static int s_ThemeList = 0; static int s_SelectedTheme = -1; - static CListBoxState s_ListBoxState_Theme; + static CListBox s_ListBox(this); if(m_lThemes.size() == 0) // not loaded yet { @@ -846,13 +846,13 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) int OldSelected = s_SelectedTheme; if(Header) - UiDoListboxHeader(&s_ListBoxState_Theme, &MainView, Localize("Theme"), 20.0f, 2.0f); + s_ListBox.DoHeader(&MainView, Localize("Theme")); bool IsActive = m_ActiveListBox == ACTLB_THEME; - UiDoListboxStart(&s_ListBoxState_Theme, &s_ThemeList, 20.0f, 0, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header?true:false, &IsActive); + s_ListBox.DoStart(20.0f, 0, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = m_lThemes.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState_Theme, &r.front(), false, &IsActive); + CListboxItem Item = s_ListBox.DoNextItem(&r.front(), false, &IsActive); if(IsActive) m_ActiveListBox = ACTLB_THEME; @@ -904,7 +904,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) } } - s_SelectedTheme = UiDoListboxEnd(&s_ListBoxState_Theme, 0); + s_SelectedTheme = s_ListBox.DoEnd(0); if(OldSelected != s_SelectedTheme) { @@ -1207,10 +1207,10 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) // country flag selector MainView.HSplitTop(10.0f, 0, &MainView); - static CListBoxState s_ListBoxState; + static CListBox s_ListBox(this); int OldSelected = -1; - UiDoListboxHeader(&s_ListBoxState, &MainView, Localize("Country"), 20.0f, 2.0f); - UiDoListboxStart(&s_ListBoxState, &s_ListBoxState, 40.0f, 0, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); + s_ListBox.DoHeader(&MainView, Localize("Country")); + s_ListBox.DoStart(40.0f, 0, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -1220,7 +1220,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) if(pEntry->m_CountryCode == g_Config.m_PlayerCountry) OldSelected = i; - CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, &pEntry->m_CountryCode, OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected == i); if(Item.m_Visible) { CUIRect Label; @@ -1248,7 +1248,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) } } - const int NewSelected = UiDoListboxEnd(&s_ListBoxState, 0); + const int NewSelected = s_ListBox.DoEnd(0); if(OldSelected != NewSelected) g_Config.m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; @@ -1662,14 +1662,13 @@ float CMenus::RenderSettingsControlsStats(CUIRect View, void *pUser) return 11*20.0f; } -bool CMenus::DoResolutionList(CUIRect* pRect, CListBoxState* pListBoxState, +bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, const sorted_array& lModes) { int OldSelected = -1; char aBuf[32]; - UiDoListboxStart(pListBoxState, pListBoxState, 20.0f, 0, lModes.size(), 1, - OldSelected, pRect); + pListBox->DoStart(20.0f, 0, lModes.size(), 1, OldSelected, pRect); for(int i = 0; i < lModes.size(); ++i) { @@ -1679,7 +1678,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBoxState* pListBoxState, OldSelected = i; } - CListboxItem Item = UiDoListboxNextItem(pListBoxState, &lModes[i], OldSelected == i); + CListboxItem Item = pListBox->DoNextItem(&lModes[i], OldSelected == i); if(Item.m_Visible) { int G = gcd(lModes[i].m_Width, lModes[i].m_Height); @@ -1709,7 +1708,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBoxState* pListBoxState, } } - const int NewSelected = UiDoListboxEnd(pListBoxState, 0); + const int NewSelected = pListBox->DoEnd(0); if(OldSelected != NewSelected) { g_Config.m_GfxScreenWidth = lModes[NewSelected].m_Width; @@ -1945,10 +1944,10 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ListRec.VSplitRight(1.5f, &ListRec, 0); ListOth.VSplitLeft(1.5f, 0, &ListOth); - static CListBoxState s_RecListBoxState; - static CListBoxState s_OthListBoxState; - CheckSettings |= DoResolutionList(&ListRec, &s_RecListBoxState, m_lRecommendedVideoModes); - CheckSettings |= DoResolutionList(&ListOth, &s_OthListBoxState, m_lOtherVideoModes); + static CListBox s_RecListBox(this); + static CListBox s_OthListBox(this); + CheckSettings |= DoResolutionList(&ListRec, &s_RecListBox, m_lRecommendedVideoModes); + CheckSettings |= DoResolutionList(&ListOth, &s_OthListBox, m_lOtherVideoModes); } // reset button From 7d21beae3141ae84a0330bf4b2fd8a4a6f00a506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 9 Jan 2020 20:50:27 +0100 Subject: [PATCH 014/479] add filter to skin part selection lists --- src/game/client/components/menus_settings.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 40bc17b5..e409f4f5 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -486,6 +486,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { static bool s_InitSkinPartList = true; static sorted_array s_paList[6]; + static CListBox s_ListBox(this); if(s_InitSkinPartList) { for(int p = 0; p < NUM_SKINPARTS; p++) @@ -495,16 +496,18 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { const CSkins::CSkinPart *s = m_pClient->m_pSkins->GetSkinPart(p, i); // no special skins - if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0) + if((s->m_Flags&CSkins::SKINFLAG_SPECIAL) == 0 && s_ListBox.FilterMatches(s->m_aName)) + { s_paList[p].add(s); + } } } s_InitSkinPartList = false; } static int OldSelected = -1; - static CListBox s_ListBox(this); s_ListBox.DoHeader(&MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected])); + s_InitSkinPartList = s_ListBox.DoFilter(); s_ListBox.DoStart(50.0f, 0, s_paList[m_TeePartSelected].size(), 5, OldSelected); for(int i = 0; i < s_paList[m_TeePartSelected].size(); ++i) From c4144a718c9748f930c9361dc2bde791fe2b70eb Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Jan 2020 18:47:48 +0100 Subject: [PATCH 015/479] updated lib version --- scripts/download.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/download.py b/scripts/download.py index 7b30ab51..81cf7ede 100644 --- a/scripts/download.py +++ b/scripts/download.py @@ -16,7 +16,7 @@ def unzip(filename, where): return z.namelist()[0] def downloadAll(targets): - version = "9e78876d7a7ebb66807b2f09207d4211d2265de8" + version = "6c4af62b8c9853bfca1166d672a16abdbf9f0d26" url = "https://github.com/teeworlds/teeworlds-libs/archive/{}.zip".format(version) # download and unzip From 51e1a680d285e26ef3cf98026707dd0c4e04576a Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 11 Jan 2020 00:24:58 +0000 Subject: [PATCH 016/479] Hide killmessages when cl_show_hud is off --- src/game/client/components/infomessages.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index 8d2f9777..ea90e7e6 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -137,6 +137,9 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) void CInfoMessages::OnRender() { + if(!g_Config.m_ClShowhud) + return; + float Width = 400*3.0f*Graphics()->ScreenAspect(); float Height = 400*3.0f; From d70ac6ceff7a0eac12f7efe7ab79f8f60a6f2dbf Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 15:16:56 +0100 Subject: [PATCH 017/479] when building for x64 check if gcc supports it. helps with auto-detection of cl when mingw and vs are installed. use cl as default then --- configure.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.lua b/configure.lua index 8060bbe7..aec5443c 100644 --- a/configure.lua +++ b/configure.lua @@ -359,7 +359,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc) -- no need todo anything if we have a driver -- TODO: test if we can find the compiler else - if ExecuteSilent("g++ -v") == 0 then + if (ExecuteSilent("g++ -v") and ((arch ~= "amd64" and arch ~= "ia64") or CTestCompile(settings, "int main(){return 0;}", "-m64"))) then option.driver = "gcc" elseif ExecuteSilent("cl") == 0 then option.driver = "cl" From 78240979018f523a086143b0a5a88fbbb6b364fb Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 17:18:57 +0100 Subject: [PATCH 018/479] fixed scrollable are for the motd in the ingame server info. closes #2374 --- src/game/client/components/menus_ingame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 0a42a1b5..70584622 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -495,7 +495,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) // define the MOTD text area and make it scrollable CUIRect MotdTextArea; - Motd.HSplitTop(Cursor.m_Y-Motd.y+5.0f, &MotdTextArea, &Motd); + Motd.HSplitTop(Cursor.m_Y-Motd.y+ButtonHeight*ms_FontmodHeight*0.8f+5.0f, &MotdTextArea, &Motd); ScrollRegionAddRect(&s_ScrollRegion, MotdTextArea); EndScrollRegion(&s_ScrollRegion); From 763935eea0543e6fa79805f4959e2c85732a9a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 11 Jan 2020 18:11:44 +0100 Subject: [PATCH 019/479] add support for multiple joysticks, some refactoring --- src/engine/client/input.cpp | 120 +++++++++++++++--- src/engine/client/input.h | 20 ++- src/engine/input.h | 11 +- src/engine/shared/config_variables.h | 5 +- src/game/client/components/menus.cpp | 8 +- src/game/client/components/menus_callback.cpp | 118 ++++++++++------- src/game/client/components/menus_settings.cpp | 6 +- 7 files changed, 208 insertions(+), 80 deletions(-) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 5c2c3c71..680b94b6 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -42,12 +42,13 @@ CInput::CInput() mem_zero(m_aInputCount, sizeof(m_aInputCount)); mem_zero(m_aInputState, sizeof(m_aInputState)); - m_pJoystick = 0; - m_InputCounter = 1; m_InputGrabbed = 0; m_pClipboardText = 0; + m_SelectedJoystickIndex = -1; + m_aSelectedJoystickGUID[0] = '\0'; + m_PreviousHat = 0; m_MouseDoubleClick = false; @@ -61,6 +62,7 @@ CInput::~CInput() { SDL_free(m_pClipboardText); } + CloseJoysticks(); } void CInput::Init() @@ -71,6 +73,11 @@ void CInput::Init() MouseModeRelative(); + InitJoysticks(); +} + +void CInput::InitJoysticks() +{ if(!SDL_WasInit(SDL_INIT_JOYSTICK)) { if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) @@ -80,20 +87,27 @@ void CInput::Init() } } - if(SDL_NumJoysticks() > 0) + int NumJoysticks = SDL_NumJoysticks(); + if(NumJoysticks > 0) { - m_pJoystick = SDL_JoystickOpen(0); + dbg_msg("joystick", "%d joystick(s) found", NumJoysticks); - if(!m_pJoystick) { - dbg_msg("joystick", "Could not open 0th joystick: %s", SDL_GetError()); - return; - } + for(int i = 0; i < NumJoysticks; i++) + { + SDL_Joystick *pJoystick = SDL_JoystickOpen(i); - dbg_msg("joystick", "Opened Joystick 0"); - dbg_msg("joystick", "Name: %s", SDL_JoystickNameForIndex(0)); - dbg_msg("joystick", "Number of Axes: %d", SDL_JoystickNumAxes(m_pJoystick)); - dbg_msg("joystick", "Number of Buttons: %d", SDL_JoystickNumButtons(m_pJoystick)); - dbg_msg("joystick", "Number of Balls: %d", SDL_JoystickNumBalls(m_pJoystick)); + if(!pJoystick) { + dbg_msg("joystick", "Could not open joystick %d: %s", i, SDL_GetError()); + return; + } + m_apJoysticks.add(pJoystick); + + dbg_msg("joystick", "Opened Joystick %d", i); + dbg_msg("joystick", "Name: %s", SDL_JoystickNameForIndex(i)); + dbg_msg("joystick", "Number of Axes: %d", SDL_JoystickNumAxes(pJoystick)); + dbg_msg("joystick", "Number of Buttons: %d", SDL_JoystickNumButtons(pJoystick)); + dbg_msg("joystick", "Number of Balls: %d", SDL_JoystickNumBalls(pJoystick)); + } } else { @@ -101,10 +115,82 @@ void CInput::Init() } } -float CInput::GetJoystickAxisValue(int Axis) const +SDL_Joystick* CInput::GetActiveJoystick() +{ + if(m_apJoysticks.size() == 0) + { + return NULL; + } + if(m_aSelectedJoystickGUID[0] && str_comp(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID) != 0) + { + // Refresh if cached GUID differs from configured GUID + m_SelectedJoystickIndex = -1; + } + if(m_SelectedJoystickIndex == -1) + { + for(int i = 0; i < m_apJoysticks.size(); i++) + { + char aGUID[sizeof(m_aSelectedJoystickGUID)]; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[i]), aGUID, sizeof(aGUID)); + if(str_comp(g_Config.m_JoystickGUID, aGUID) == 0) + { + m_SelectedJoystickIndex = i; + str_copy(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + break; + } + } + // could not find configured joystick, falling back to first available + if(m_SelectedJoystickIndex == -1) + { + m_SelectedJoystickIndex = 0; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[0]), g_Config.m_JoystickGUID, sizeof(g_Config.m_JoystickGUID)); + str_copy(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + } + } + return m_apJoysticks[m_SelectedJoystickIndex]; +} + +void CInput::CloseJoysticks() +{ + for(sorted_array::range r = m_apJoysticks.all(); !r.empty(); r.pop_front()) + { + if (SDL_JoystickGetAttached(r.front())) + { + SDL_JoystickClose(r.front()); + } + } + m_apJoysticks.clear(); +} + +void CInput::SelectNextJoystick() +{ + const int Num = m_apJoysticks.size(); + if(Num > 1) + { + const int NextIndex = (m_SelectedJoystickIndex + 1) % Num; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[NextIndex]), g_Config.m_JoystickGUID, sizeof(g_Config.m_JoystickGUID)); + } +} + +const char* CInput::GetJoystickName() +{ + SDL_Joystick* pJoystick = GetActiveJoystick(); + dbg_assert((bool)pJoystick, "Requesting joystick name, but no joysticks were initialized"); + return SDL_JoystickName(pJoystick); +} + +float CInput::GetJoystickAxisValue(int Axis) +{ + SDL_Joystick* pJoystick = GetActiveJoystick(); + dbg_assert((bool)pJoystick, "Requesting joystick axis value, but no joysticks were initialized"); + return static_cast(SDL_JoystickGetAxis(pJoystick, Axis)) / (float)(SDL_JOYSTICK_AXIS_MAX+1); +} + +int CInput::GetJoystickNumAxes() { - dbg_assert((bool)m_pJoystick, "Requesting joystic axis value, but no joysticks were initialized"); - return static_cast(SDL_JoystickGetAxis(m_pJoystick, Axis)) / (float)(SDL_JOYSTICK_AXIS_MAX+1); + SDL_Joystick* pJoystick = GetActiveJoystick(); + dbg_assert((bool)pJoystick, "Requesting joystick axes count, but no joysticks were initialized"); + return SDL_JoystickNumAxes(pJoystick); } void CInput::MouseRelative(float *x, float *y) @@ -120,7 +206,7 @@ void CInput::MouseRelative(float *x, float *y) vec2 j = vec2(0.0f, 0.0f); - if(g_Config.m_JoystickEnable && m_pJoystick) + if(g_Config.m_JoystickEnable && GetActiveJoystick()) { const float Max = 50.0f; j = vec2(GetJoystickAxisValue(g_Config.m_JoystickX), GetJoystickAxisValue(g_Config.m_JoystickY)) * Max; diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 1d4cec60..4b226b22 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -3,11 +3,19 @@ #ifndef ENGINE_CLIENT_INPUT_H #define ENGINE_CLIENT_INPUT_H +#include + class CInput : public IEngineInput { IEngineGraphics *m_pGraphics; IConsole *m_pConsole; - SDL_Joystick *m_pJoystick; + + sorted_array m_apJoysticks; + int m_SelectedJoystickIndex; + char m_aSelectedJoystickGUID[34]; + SDL_Joystick* GetActiveJoystick(); + void InitJoysticks(); + void CloseJoysticks(); int m_InputGrabbed; char *m_pClipboardText; @@ -38,9 +46,13 @@ class CInput : public IEngineInput bool KeyIsPressed(int Key) const { return KeyState(Key); } bool KeyPress(int Key, bool CheckCounter) const { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; } - - bool HasJoystick() const { return m_pJoystick; } - float GetJoystickAxisValue(int Axis) const; + + int NumJoysticks() const { return m_apJoysticks.size(); } + int GetJoystickIndex() const { return m_SelectedJoystickIndex; }; + void SelectNextJoystick(); + const char* GetJoystickName(); + int GetJoystickNumAxes(); + float GetJoystickAxisValue(int Axis); virtual void MouseRelative(float *x, float *y); virtual void MouseModeAbsolute(); diff --git a/src/engine/input.h b/src/engine/input.h index 4f689d73..118073c5 100644 --- a/src/engine/input.h +++ b/src/engine/input.h @@ -7,6 +7,7 @@ const int g_MaxKeys = 512; extern const char g_aaKeyStrings[g_MaxKeys][20]; +const int g_MaxJoystickAxes = 12; class IInput : public IInterface { @@ -58,10 +59,14 @@ class IInput : public IInterface virtual bool KeyPress(int Key, bool CheckCounter=false) const = 0; const char *KeyName(int Key) const { return (Key >= 0 && Key < g_MaxKeys) ? g_aaKeyStrings[Key] : g_aaKeyStrings[0]; } virtual void Clear() = 0; - + // joystick - virtual bool HasJoystick() const = 0; - virtual float GetJoystickAxisValue(int Axis) const = 0; + virtual int NumJoysticks() const = 0; + virtual int GetJoystickIndex() const = 0; + virtual void SelectNextJoystick() = 0; + virtual const char* GetJoystickName() = 0; + virtual int GetJoystickNumAxes() = 0; + virtual float GetJoystickAxisValue(int Axis) = 0; // mouse virtual void MouseModeRelative() = 0; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 4edf2597..c4bcfc9d 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -69,9 +69,10 @@ MACRO_CONFIG_INT(InpGrab, inp_grab, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Disab MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ingame mouse sensitivity") MACRO_CONFIG_INT(JoystickEnable , joystick_enable, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable joystick") +MACRO_CONFIG_STR(JoystickGUID, joystick_guid, 34, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick GUID which uniquely identifies the active joystick") MACRO_CONFIG_INT(JoystickSens, joystick_sens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick sensitivity") -MACRO_CONFIG_INT(JoystickX, joystick_x, 0, 0, 6, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls X axis of cursor") -MACRO_CONFIG_INT(JoystickY, joystick_y, 1, 0, 6, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls Y axis of cursor") +MACRO_CONFIG_INT(JoystickX, joystick_x, 0, 0, 12, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls X axis of cursor") +MACRO_CONFIG_INT(JoystickY, joystick_y, 1, 0, 12, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls Y axis of cursor") MACRO_CONFIG_INT(JoystickTolerance, joystick_tolerance, 5, 0, 50, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick Axis tolerance to account for jitter") MACRO_CONFIG_STR(SvName, sv_name, 128, "unnamed server", CFGFLAG_SAVE|CFGFLAG_SERVER, "Server name") diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index b9105c88..86900499 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -918,13 +918,13 @@ void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, CUIRect ToleranceArea = Rail; ToleranceArea.w *= Tolerance; ToleranceArea.x += (Rail.w-ToleranceArea.w)/2.0f; - vec4 Color = Active ? vec4(0.8f, 0.35f, 0.35f, 1.0f) : vec4(0.7f, 0.5f, 0.5f, 1.0f); - RenderTools()->DrawUIRect(&ToleranceArea, Color, CUI::CORNER_ALL, ToleranceArea.h/2.0f); + vec4 ToleranceColor = Active ? vec4(0.8f, 0.35f, 0.35f, 1.0f) : vec4(0.7f, 0.5f, 0.5f, 1.0f); + RenderTools()->DrawUIRect(&ToleranceArea, ToleranceColor, CUI::CORNER_ALL, ToleranceArea.h/2.0f); CUIRect Slider = Handle; Slider.HMargin(4.0f, &Slider); - Color = Active ? vec4(0.95f, 0.95f, 0.95f, 1.0f) : vec4(0.8f, 0.8f, 0.8f, 1.0f); - RenderTools()->DrawUIRect(&Slider, Color, CUI::CORNER_ALL, Slider.h/2.0f); + vec4 SliderColor = Active ? vec4(0.95f, 0.95f, 0.95f, 1.0f) : vec4(0.8f, 0.8f, 0.8f, 1.0f); + RenderTools()->DrawUIRect(&Slider, SliderColor, CUI::CORNER_ALL, Slider.h/2.0f); } diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 7bcab6a7..f0787fd1 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -65,11 +65,11 @@ static CKeyInfo gs_aKeys[] = const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); -void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spaceing) +void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing) { for (int i = Start; i < Stop; i++) { - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); CKeyInfo &Key = gs_aKeys[i]; CUIRect Button, Label; @@ -130,24 +130,24 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View, void *pUser) int NumOptions = 3; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); CUIRect Button; - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonInpGrab = 0; if(pSelf->DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !g_Config.m_InpGrab, &Button)) { g_Config.m_InpGrab ^= 1; } - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); pSelf->DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); pSelf->DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); @@ -160,40 +160,64 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) UpdateBindKeys(pSelf->m_pClient->m_pBinds); bool JoystickEnabled = g_Config.m_JoystickEnable; - int NumOptions = JoystickEnabled ? 2+2+6 : 2; + int NumJoysticks = pSelf->m_pClient->Input()->NumJoysticks(); + int NumOptions = 2; // expandable header & message + if(JoystickEnabled) + { + if(NumJoysticks > 1) + { + NumOptions++; // joystick selection + } + NumOptions += 2; // sensitivity & tolerance + NumOptions += pSelf->m_pClient->Input()->GetJoystickNumAxes(); // axis selection + } float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing+Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing+Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); CUIRect Button; - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - static int s_ButtonJoystickEnable = 0; - if(pSelf->DoButton_CheckBox(&s_ButtonJoystickEnable , Localize("Enable joystick"), g_Config.m_JoystickEnable, &Button)) + static int s_ButtonJoystickEnable = 0; + if(pSelf->DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), g_Config.m_JoystickEnable, &Button)) { g_Config.m_JoystickEnable ^= 1; } if(JoystickEnabled) { - if(pSelf->m_pClient->Input()->HasJoystick()) + if(NumJoysticks > 0) { - View.HSplitTop(Spaceing, 0, &View); + // show joystick device selection if more than one available + if(NumJoysticks > 1) + { + View.HSplitTop(Spacing, 0, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + static CButtonContainer s_ButtonJoystickId; + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "Joystick %d: %s", pSelf->m_pClient->Input()->GetJoystickIndex(), pSelf->m_pClient->Input()->GetJoystickName()); + if(pSelf->DoButton_Menu(&s_ButtonJoystickId, aBuf, 0, &Button)) + { + pSelf->m_pClient->Input()->SelectNextJoystick(); + } + } + + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); pSelf->DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); pSelf->DoScrollbarOption(&g_Config.m_JoystickTolerance, &g_Config.m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); // shrink view and draw background - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.VSplitLeft(View.w/6, 0, &View); View.VSplitRight(View.w/5, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.125f), CUI::CORNER_ALL, 5.0f); - + pSelf->DoJoystickAxisPicker(View); } else @@ -214,13 +238,13 @@ float CMenus::RenderSettingsControlsMovement(CUIRect View, void *pUser) int NumOptions = 5; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(0, 5, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(0, 5, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -232,13 +256,13 @@ float CMenus::RenderSettingsControlsWeapon(CUIRect View, void *pUser) int NumOptions = 7; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(5, 12, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(5, 12, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -250,13 +274,13 @@ float CMenus::RenderSettingsControlsVoting(CUIRect View, void *pUser) int NumOptions = 2; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(12, 14, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(12, 14, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -268,13 +292,13 @@ float CMenus::RenderSettingsControlsChat(CUIRect View, void *pUser) int NumOptions = 4; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(14, 18, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(14, 18, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -311,15 +335,15 @@ float CMenus::RenderSettingsControlsScoreboard(CUIRect View, void *pUser) int NumOptions = 2; int StartOption = 18; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); - View.HSplitTop(ButtonHeight*2+Spaceing*3, 0, &View); + View.HSplitTop(ButtonHeight*2+Spacing*3, 0, &View); View.VSplitLeft(View.w/3, 0, &View); View.VSplitRight(View.w/2, &View, 0); static int s_StatboardConfigDropdown = 0; @@ -337,13 +361,13 @@ float CMenus::RenderSettingsControlsMisc(CUIRect View, void *pUser) int NumOptions = 12; int StartOption = 20; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + float Spacing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spaceing); + pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -352,13 +376,13 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) { CUIRect Row, Button; float ButtonHeight = 20.0f; - float Spaceing = 2.0f; + float Spacing = 2.0f; float DeviceLabelWidth = View.w*0.30f; float StatusWidth = View.w*0.30f; float BindWidth = View.w*0.1f; float StatusMargin = View.w*0.05f; - View.HSplitTop(Spaceing, 0, &View); // ? + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Row, &View); Row.VSplitLeft(StatusWidth, &Button, &Row); m_pClient->UI()->DoLabel(&Button, Localize("Device"), 13.0f, CUI::ALIGN_CENTER); @@ -369,12 +393,12 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) Row.VSplitLeft(2*BindWidth, &Button, &Row); m_pClient->UI()->DoLabel(&Button, Localize("Aim bind"), 13.0f, CUI::ALIGN_CENTER); - static int aActive[6][2]; - for(int i = 0; i < 6; i++) + static int s_aActive[g_MaxJoystickAxes][2]; + for(int i = 0; i < min(m_pClient->Input()->GetJoystickNumAxes(), g_MaxJoystickAxes); i++) { bool Active = g_Config.m_JoystickX == i || g_Config.m_JoystickY == i; - View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Row, &View); RenderTools()->DrawUIRect(&Row, vec4(0.0f, 0.0f, 0.0f, 0.125f), CUI::CORNER_ALL, 5.0f); @@ -387,20 +411,20 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) else m_pClient->TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); m_pClient->UI()->DoLabel(&Button, aBuf, 13.0f, CUI::ALIGN_CENTER); - + // Device status Row.VSplitLeft(StatusMargin, 0, &Row); Row.VSplitLeft(StatusWidth, &Button, &Row); - Button.HSplitTop(14.0f, &Button, 0); + Button.HMargin((ButtonHeight-14.0f)/2.0f, &Button); DoJoystickBar(&Button, (m_pClient->Input()->GetJoystickAxisValue(i)+1.0f)/2.0f, g_Config.m_JoystickTolerance/50.0f, Active); - + // Bind to X,Y Row.VSplitLeft(2*StatusMargin, 0, &Row); Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&aActive[i][0], "X", g_Config.m_JoystickX == i, &Button, g_Config.m_JoystickY == i)) + if(DoButton_CheckBox(&s_aActive[i][0], "X", g_Config.m_JoystickX == i, &Button, g_Config.m_JoystickY == i)) g_Config.m_JoystickX = i; Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&aActive[i][1], "Y", g_Config.m_JoystickY == i, &Button, g_Config.m_JoystickX == i)) + if(DoButton_CheckBox(&s_aActive[i][1], "Y", g_Config.m_JoystickY == i, &Button, g_Config.m_JoystickX == i)) g_Config.m_JoystickY = i; Row.VSplitLeft(StatusMargin, 0, &Row); } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index e409f4f5..1508a9a4 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1550,13 +1550,13 @@ void CMenus::RenderSettingsControls(CUIRect MainView) static int s_MouseDropdown = 0; static bool s_MouseActive = true; float Split = DoIndependentDropdownMenu(&s_MouseDropdown, &MainView, Localize("Mouse"), HeaderHeight, RenderSettingsControlsMouse, &s_MouseActive); - + MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); static int s_JoystickDropdown = 0; - static bool s_JoystickActive = m_pClient->Input()->HasJoystick(); // hide by default if no joystick found + static bool s_JoystickActive = m_pClient->Input()->NumJoysticks() > 0; // hide by default if no joystick found Split = DoIndependentDropdownMenu(&s_JoystickDropdown, &MainView, Localize("Joystick"), HeaderHeight, RenderSettingsControlsJoystick, &s_JoystickActive); - + MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); static int s_MovementDropdown = 0; From f4c4fc0c162902751f61b7c019294e402e33bc91 Mon Sep 17 00:00:00 2001 From: Sonix- Date: Sat, 11 Jan 2020 18:36:17 +0100 Subject: [PATCH 020/479] Make the offline friends box smaller and add some margin on top inside the boxes --- src/game/client/components/menus_browser.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 2e232c21..3295f84e 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1455,7 +1455,10 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // entries for(int f = 0; f < m_lFriendList[i].size(); ++f, ++ButtonId) { - View.HSplitTop(20.0f + GetListHeaderHeight(), &Rect, &View); + if(i == FRIEND_OFF) + View.HSplitTop(8.0f + GetListHeaderHeight(), &Rect, &View); + else + View.HSplitTop(20.0f + GetListHeaderHeight(), &Rect, &View); ScrollRegionAddRect(&s_ScrollRegion, Rect); if(i == FRIEND_PLAYER_ON) RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 1.0f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); @@ -1464,6 +1467,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) else RenderTools()->DrawUIRect(&Rect, vec4(1.0f, 0.5f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); Rect.VMargin(2.0f, &Rect); + Rect.HMargin(2.0f, &Rect); Rect.VSplitRight(45.0f, &Rect, &Icon); Rect.HSplitTop(20.0f, &Button, 0); // name From 8be930173ffce3c93a70021cf3a51685d2175d4f Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 19:42:29 +0100 Subject: [PATCH 021/479] fixed a crash when there no joysticks --- src/game/client/components/menus_callback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index f0787fd1..4ba86707 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -162,7 +162,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) bool JoystickEnabled = g_Config.m_JoystickEnable; int NumJoysticks = pSelf->m_pClient->Input()->NumJoysticks(); int NumOptions = 2; // expandable header & message - if(JoystickEnabled) + if(JoystickEnabled && NumJoysticks > 0) { if(NumJoysticks > 1) { From 86bdecf4a696a4a072d6ee4f432f5ea770b7d8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 11 Jan 2020 20:13:21 +0100 Subject: [PATCH 022/479] consolidate ban/ban_range and unban/unban_range, closes #1127 --- src/engine/server/server.cpp | 2 +- src/engine/shared/netban.cpp | 87 ++++++++++++++++++------------------ src/engine/shared/netban.h | 2 - 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 79c283ad..a1984e69 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -151,7 +151,7 @@ void CServerBan::InitServerBan(IConsole *pConsole, IStorage *pStorage, CServer* 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"); + Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with IP/IP range/client id for x minutes for any reason"); } template diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index ed58b38b..e4610b7b 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -364,10 +364,8 @@ void CNetBan::Init(IConsole *pConsole, IStorage *pStorage) 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("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBan, this, "Ban IP (or IP range) for x minutes for any reason"); + Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnban, this, "Unban IP/IP range/banlist entry"); 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"); @@ -491,62 +489,63 @@ 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); + char aBuf[256]; + str_copy(aBuf, pResult->GetString(0), sizeof(aBuf)); + const char *pSeparator = str_find(aBuf, "-"); - 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"; + const int Minutes = pResult->NumArguments() > 1 ? clamp(pResult->GetInteger(1), 0, 31*24*60) : 30; + const char *pReason = pResult->NumArguments() > 2 ? pResult->GetString(2) : "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); + if(pSeparator == NULL || pSeparator[1] == '\0') + { + NETADDR Addr; + if(net_addr_from_str(&Addr, aBuf) == 0) + pThis->BanAddr(&Addr, Minutes*60, pReason); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid network address)"); + } else - pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid range)"); + { + aBuf[pSeparator-&aBuf[0]] = '\0'; + + CNetRange Range; + if(net_addr_from_str(&Range.m_LB, aBuf) == 0 && net_addr_from_str(&Range.m_UB, pSeparator+1) == 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 + char aBuf[256]; + str_copy(aBuf, pResult->GetString(0), sizeof(aBuf)); + const char *pSeparator = str_find(aBuf, "-"); + + if(StrAllnum(aBuf)) + { + pThis->UnbanByIndex(str_toint(aBuf)); + } + else if(pSeparator == NULL || pSeparator[1] == '\0') { NETADDR Addr; - if(net_addr_from_str(&Addr, pStr) == 0) + if(net_addr_from_str(&Addr, aBuf) == 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)"); + { + aBuf[pSeparator-&aBuf[0]] = '\0'; + + CNetRange Range; + if(net_addr_from_str(&Range.m_LB, aBuf) == 0 && net_addr_from_str(&Range.m_UB, pSeparator+1) == 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) diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h index 1c1d7a02..14586e02 100644 --- a/src/engine/shared/netban.h +++ b/src/engine/shared/netban.h @@ -183,9 +183,7 @@ class CNetBan bool IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize, int *pLastInfoQuery); 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); From 7f1f52669931bafb490645683ad919cc0618be7f Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 21:03:28 +0100 Subject: [PATCH 023/479] fixed position of the "no joystick found"-notice in the settings menu --- src/game/client/components/menus_callback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 4ba86707..715c45cb 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -222,7 +222,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) } else { - View.HSplitTop((View.y-2*ButtonHeight)/2.0f, 0, &View); + View.HSplitTop((View.h-ButtonHeight)/2.0f, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); pSelf->m_pClient->UI()->DoLabel(&Button, Localize("No joysticks found. Plug in a joystick and restart the game."), 13.0f, CUI::ALIGN_CENTER); } From 7a999665ad59f9fd6b9ab5a51e341b28a922822a Mon Sep 17 00:00:00 2001 From: Sonix- Date: Sat, 11 Jan 2020 21:18:46 +0100 Subject: [PATCH 024/479] Make the delete button bigger And adjust some margins --- src/game/client/components/menus_browser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 3295f84e..71af4781 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1491,14 +1491,15 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) UI()->DoLabel(&Button, aBuf, FontSize - 2, CUI::ALIGN_LEFT); } // delete button - Icon.HSplitTop(20.0f, &Rect, 0); - Rect.VSplitRight(10.0f, &Button, &Icon); + Icon.HSplitTop(14.0f, &Rect, 0); + Rect.VSplitRight(12.0f, 0, &Icon); Icon.HMargin((Icon.h - Icon.w) / 2, &Icon); if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &Icon)) { m_pDeleteFriend = &m_lFriendList[i][f]; } // join button + Rect.VSplitRight(15.0f, &Button, 0); if(m_lFriendList[i][f].m_pServerInfo) { Button.Margin((Button.h - GetListHeaderHeight() + 2.0f) / 2, &Button); From 160bfa8b0da8944f927d66b7d146254c48007000 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 21:22:11 +0100 Subject: [PATCH 025/479] don't process menu hot keys when a modifier is pressed --- src/game/client/components/menus.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 86900499..aec2d61f 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2777,7 +2777,9 @@ void CMenus::OnRender() bool CMenus::CheckHotKey(int Key) { - return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); + return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && + !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier + Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } void CMenus::RenderBackground() From f6a6c06467e3cecae6933ea3ee72230607e60ad6 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 22:30:59 +0100 Subject: [PATCH 026/479] don't check/count rcon authentication tries when you can't get banned. closes #2286 --- src/engine/server/server.cpp | 2 +- src/engine/shared/netban.cpp | 13 ++++++++++++- src/engine/shared/netban.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index a1984e69..a2e15420 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1048,7 +1048,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } - else if(g_Config.m_SvRconMaxTries) + else if(g_Config.m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) { m_aClients[ClientID].m_AuthTries++; char aBuf[128]; diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index e4610b7b..353ddd35 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -294,7 +294,7 @@ 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)) + if(!IsBannable(pData)) { Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (localhost)"); return -1; @@ -456,6 +456,17 @@ void CNetBan::UnbanAll() m_BanRangePool.Reset(); } +template +bool CNetBan::IsBannable(const T *pData) +{ + // do not ban localhost + if(NetMatch(pData, &m_LocalhostIPV4) || NetMatch(pData, &m_LocalhostIPV6)) + { + return false; + } + return true; +} + bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize, int *pLastInfoQuery) { CNetHash aHash[17]; diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h index 14586e02..31e9b0da 100644 --- a/src/engine/shared/netban.h +++ b/src/engine/shared/netban.h @@ -180,6 +180,7 @@ class CNetBan int UnbanByRange(const CNetRange *pRange); int UnbanByIndex(int Index); void UnbanAll(); + template bool IsBannable(const T *pData); bool IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize, int *pLastInfoQuery); static void ConBan(class IConsole::IResult *pResult, void *pUser); From efa7ab37b617dbee9cde54e4461fd750d8efbb90 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 11 Jan 2020 22:52:02 +0100 Subject: [PATCH 027/479] fixed linker problem in release mode --- src/engine/shared/netban.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index 353ddd35..a82440d9 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -633,3 +633,5 @@ template void CNetBan::MakeBanInfo(CBan *pBan, char *pBuf, template void CNetBan::MakeBanInfo(CBan *pBan, char *pBuf, unsigned BufferSize, int Type, int *pLastInfoQuery); template int CNetBan::Ban >(CNetBan::CBanPool *pBanPool, const NETADDR *pData, int Seconds, const char *pReason); template int CNetBan::Ban >(CNetBan::CBanPool *pBanPool, const CNetRange *pData, int Seconds, const char *pReason); +template bool CNetBan::IsBannable(const NETADDR *pData); +template bool CNetBan::IsBannable(const CNetRange *pData); From 8c77b4d3e4a5a5c1ebbe32fdceb33abc240e6b6b Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 12 Jan 2020 17:39:08 +0100 Subject: [PATCH 028/479] updated year --- license.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/license.txt b/license.txt index 73866f06..1be4a824 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright (C) 2007-2018 Magnus Auvinen +Copyright (C) 2007-2020 Magnus Auvinen This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages From d7152310514687e51f53e1832a00d10bf49691f4 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 12 Jan 2020 17:52:03 +0100 Subject: [PATCH 029/479] removed old debug messages --- src/engine/client/serverbrowser_fav.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index c9a0bea7..012fd95d 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -172,10 +172,8 @@ const NETADDR *CServerBrowserFavorites::UpdateFavorites() { str_copy(pEntry->m_aHostname, m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_aHostname, sizeof(pEntry->m_aHostname)); pEntry->m_State = FAVSTATE_HOST; - dbg_msg("test", "fav aquired hostname, %s", m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_aHostname); } RemoveFavoriteEntry(m_FavLookup.m_FavoriteIndex); - dbg_msg("test", "fav removed multiple entry"); } else { @@ -186,12 +184,10 @@ const NETADDR *CServerBrowserFavorites::UpdateFavorites() m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_Addr = m_FavLookup.m_HostLookup.m_Addr; m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_State = FAVSTATE_HOST; pResult = &m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_Addr; - dbg_msg("test", "fav added, %s", m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_aHostname); } else { RemoveFavoriteEntry(m_FavLookup.m_FavoriteIndex); - dbg_msg("test", "fav removed entry that failed hostname-address check"); } } } @@ -201,12 +197,10 @@ const NETADDR *CServerBrowserFavorites::UpdateFavorites() if(m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_State == FAVSTATE_LOOKUP) { m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_State = FAVSTATE_INVALID; - dbg_msg("test", "fav invalid, %s", m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_aHostname); } else { RemoveFavoriteEntry(m_FavLookup.m_FavoriteIndex); - dbg_msg("test", "fav removed invalid check-based entry"); } } } From 419878c9f0ffcccbb7c7bffc998062c70b297bcd Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 12 Jan 2020 18:11:04 +0100 Subject: [PATCH 030/479] when looking for binds search for explicit binds first and use double binds as a fallback --- src/game/client/components/binds.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 4887c2b0..5b905919 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -207,22 +207,30 @@ const char *CBinds::Get(int KeyID, int Modifier) void CBinds::GetKeyID(const char *pBindStr, int& KeyID, int& Modifier) { - for(KeyID = 0; KeyID < KEY_LAST; KeyID++) + KeyID = KEY_LAST; + Modifier = MODIFIER_COUNT; + + for(int LocalKeyID = 0; LocalKeyID < KEY_LAST; LocalKeyID++) { - for(Modifier = 0; Modifier < MODIFIER_COUNT; Modifier++) + for(int LocalModifier = 0; LocalModifier < MODIFIER_COUNT; LocalModifier++) { - const char *pBind = Get(KeyID, Modifier); + const char *pBind = Get(LocalKeyID, LocalModifier); if(!pBind[0]) continue; - if(str_find(pBind, pBindStr) != 0) + if(str_comp(pBind, pBindStr) == 0) + { + KeyID = LocalKeyID; + Modifier = LocalModifier; return; + } + if(str_find(pBind, pBindStr) != 0) + { + KeyID = LocalKeyID; + Modifier = LocalModifier; + } } } - - //this is already given by the loops above - KeyID = KEY_LAST; - Modifier = MODIFIER_COUNT; } void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize, int KeyID, int Modifier) From 1e2c364356c42866339b56da2fa8513613e1374a Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 12 Jan 2020 18:16:22 +0100 Subject: [PATCH 031/479] added localization and fixed style --- src/game/client/components/binds.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 5b905919..4782ea43 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -236,11 +236,12 @@ void CBinds::GetKeyID(const char *pBindStr, int& KeyID, int& Modifier) void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize, int KeyID, int Modifier) { aKey[0] = 0; - if(KeyID < KEY_LAST){ + if(KeyID < KEY_LAST) + { str_format(aKey, BufSize, "%s%s", GetModifierName(Modifier), Input()->KeyName(KeyID)); return; } - str_copy(aKey, "key not found", BufSize); + str_copy(aKey, Localize("key not found"), BufSize); } void CBinds::GetKey(const char *pBindStr, char aKey[64], unsigned BufSize) From b7e76314023664658b9f119bb80c9bf3d7c26361 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 12 Jan 2020 18:45:01 +0100 Subject: [PATCH 032/479] reset checkpoint time on own death in race gametype. closes #2351 --- src/game/client/components/hud.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index aa97f7e6..b685b45c 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -784,6 +784,13 @@ void CHud::OnMessage(int MsgType, void *pRawMsg) m_CheckpointDiff = pMsg->m_Diff; m_CheckpointTime = time_get(); } + else if(MsgType == NETMSGTYPE_SV_KILLMSG && (m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_RACE)) + { + // reset checkpoint time on death + CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg; + if(pMsg->m_Victim == m_pClient->m_LocalClientID) + m_CheckpointTime = 0; + } } void CHud::OnRender() From 0ca641fb0c3b7f60b58bf2bc670e07c89dde863a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 13:40:21 +0100 Subject: [PATCH 033/479] add say_self command, reorder parameters and add defaults --- src/game/client/components/chat.cpp | 22 ++++++++----- src/game/client/components/chat.h | 34 ++++++++++----------- src/game/client/components/infomessages.cpp | 4 +-- src/game/client/components/voting.cpp | 22 +++++-------- src/game/client/gameclient.cpp | 19 ++++++------ 5 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 5620e82b..3b65c636 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -89,7 +89,7 @@ void CChat::OnMapLoad() // display map rotation marker in chat char aBuf[256]; str_format(aBuf, sizeof(aBuf), Localize("Map changed to '%s'"), Client()->GetCurrentMapName()); - AddLine(CLIENT_MSG, CHAT_ALL, aBuf); + AddLine(aBuf, CLIENT_MSG, CHAT_ALL); } } } @@ -122,6 +122,11 @@ void CChat::ConSayTeam(IConsole::IResult *pResult, void *pUserData) ((CChat*)pUserData)->Say(CHAT_TEAM, pResult->GetString(0)); } +void CChat::ConSaySelf(IConsole::IResult *pResult, void *pUserData) +{ + ((CChat*)pUserData)->AddLine(pResult->GetString(0), CLIENT_MSG); +} + void CChat::ConWhisper(IConsole::IResult *pResult, void *pUserData) { CChat *pChat = (CChat *)pUserData; @@ -192,6 +197,7 @@ void CChat::OnConsoleInit() { Console()->Register("say", "r", CFGFLAG_CLIENT, ConSay, this, "Say in chat"); Console()->Register("say_team", "r", CFGFLAG_CLIENT, ConSayTeam, this, "Say in team chat"); + Console()->Register("say_self", "r", CFGFLAG_CLIENT, ConSaySelf, this, "Say message just for yourself"); Console()->Register("whisper", "ir", CFGFLAG_CLIENT, ConWhisper, this, "Whisper to a client in chat"); Console()->Register("chat", "s?i", CFGFLAG_CLIENT, ConChat, this, "Enable chat with all/team/whisper mode"); Console()->Register("+show_chat", "", CFGFLAG_CLIENT, ConShowChat, this, "Show chat"); @@ -502,7 +508,7 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) if(MsgType == NETMSGTYPE_SV_CHAT) { CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg; - AddLine(pMsg->m_ClientID, pMsg->m_Mode, pMsg->m_pMessage, pMsg->m_TargetID); + AddLine(pMsg->m_pMessage, pMsg->m_ClientID, pMsg->m_Mode, pMsg->m_TargetID); } else if(MsgType == NETMSGTYPE_SV_COMMANDINFO) { @@ -527,13 +533,14 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) } } -void CChat::AddLine(int ClientID, int Mode, const char *pLine, int TargetID) +void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) { if(*pLine == 0 || (ClientID >= 0 && (!g_Config.m_ClShowsocial || !m_pClient->m_aClients[ClientID].m_Active || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore || g_Config.m_ClFilterchat == 2 || (m_pClient->m_LocalClientID != ClientID && g_Config.m_ClFilterchat == 1 && !m_pClient->m_aClients[ClientID].m_Friend)))) return; + if(Mode == CHAT_WHISPER) { // unknown client @@ -696,16 +703,15 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine, int TargetID) } } -const char* CChat::GetCommandName(int Mode) +const char* CChat::GetCommandName(int Mode) const { switch(Mode) { case CHAT_ALL: return "chat all"; case CHAT_WHISPER: return "chat whisper"; case CHAT_TEAM: return "chat team"; - default: break; + default: return ""; } - return ""; } void CChat::OnRender() @@ -1522,7 +1528,7 @@ void CChat::Com_Mute(CChat *pChatData, const char* pCommand) char aMsg[128]; str_format(aMsg, sizeof(aMsg), !isMuted ? Localize("'%s' was muted") : Localize("'%s' was unmuted"), pChatData->m_pClient->m_aClients[TargetID].m_aName); - pChatData->AddLine(CLIENT_MSG, CHAT_ALL, aMsg, -1); + pChatData->AddLine(aMsg, CLIENT_MSG, CHAT_ALL); } pChatData->m_Mode = CHAT_NONE; pChatData->m_pClient->OnRelease(); @@ -1544,7 +1550,7 @@ void CChat::Com_Befriend(CChat *pChatData, const char* pCommand) char aMsg[128]; str_format(aMsg, sizeof(aMsg), !isFriend ? Localize("'%s' was added as a friend") : Localize("'%s' was removed as a friend"), pChatData->m_pClient->m_aClients[TargetID].m_aName); - pChatData->AddLine(CLIENT_MSG, CHAT_ALL, aMsg, -1); + pChatData->AddLine(aMsg, CLIENT_MSG, CHAT_ALL); } pChatData->m_Mode = CHAT_NONE; pChatData->m_pClient->OnRelease(); diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 476a0168..031e9d40 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -16,6 +16,7 @@ class CChat : public CComponent { MAX_LINES = 250, MAX_CHAT_PAGES = 10, + MAX_LINE_LENGTH = 512, }; struct CLine @@ -27,17 +28,10 @@ class CChat : public CComponent int m_Mode; int m_NameColor; char m_aName[MAX_NAME_LENGTH]; - char m_aText[512]; + char m_aText[MAX_LINE_LENGTH]; bool m_Highlighted; }; - // client IDs for special messages - enum - { - CLIENT_MSG = -2, - SERVER_MSG = -1, - }; - CLine m_aLines[MAX_LINES]; int m_CurrentLine; @@ -68,7 +62,7 @@ class CChat : public CComponent float m_CurrentLineWidth; int m_ChatBufferMode; - char m_ChatBuffer[512]; + char m_ChatBuffer[MAX_LINE_LENGTH]; char m_ChatCmdBuffer[1024]; struct CHistoryEntry @@ -143,22 +137,26 @@ class CChat : public CComponent static void ConSay(IConsole::IResult *pResult, void *pUserData); static void ConSayTeam(IConsole::IResult *pResult, void *pUserData); + static void ConSaySelf(IConsole::IResult *pResult, void *pUserData); static void ConWhisper(IConsole::IResult *pResult, void *pUserData); static void ConChat(IConsole::IResult *pResult, void *pUserData); static void ConShowChat(IConsole::IResult *pResult, void *pUserData); public: - bool IsActive() const { return m_Mode != CHAT_NONE; } - - void AddLine(int ClientID, int Team, const char *pLine, int TargetID = -1); - - void EnableMode(int Team, const char* pText = NULL); - - void Say(int Team, const char *pLine); + // client IDs for special messages + enum + { + CLIENT_MSG = -2, + SERVER_MSG = -1, + }; + // Mode defined by the CHAT_* constants in protocol.h + bool IsActive() const { return m_Mode != CHAT_NONE; } + void AddLine(const char *pLine, int ClientID = SERVER_MSG, int Mode = CHAT_NONE, int TargetID = -1); + void EnableMode(int Mode, const char* pText = NULL); + void Say(int Mode, const char *pLine); void ClearChatBuffer(); - - const char* GetCommandName(int Mode); + const char* GetCommandName(int Mode) const; virtual void OnInit(); virtual void OnReset(); diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index ea90e7e6..9db0687f 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -108,7 +108,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) str_append(aBuf, aImprovement, sizeof(aBuf)); } - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); } if(m_pClient->m_Snap.m_pGameDataRace && m_pClient->m_Snap.m_pGameDataRace->m_RaceFlags&RACEFLAG_FINISHMSG_AS_CHAT) @@ -116,7 +116,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) if(!pMsg->m_NewRecord) // don't print the time twice { str_format(aBuf, sizeof(aBuf), Localize("'%s' finished in: %s"), aLabel, aTime); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); } } else diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index 3aa9ae72..b5a7f280 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -186,7 +186,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) case VOTE_START_OP: str_format(aBuf, sizeof(aBuf), Localize("'%s' called vote to change server option '%s' (%s)"), aLabel, pMsg->m_pDescription, pMsg->m_pReason); str_copy(m_aDescription, pMsg->m_pDescription, sizeof(m_aDescription)); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); break; case VOTE_START_KICK: { @@ -195,7 +195,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to kick '%s' (%s)"), aLabel, g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); str_format(m_aDescription, sizeof(m_aDescription), "Kick '%s'", g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); break; } case VOTE_START_SPEC: @@ -205,7 +205,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to move '%s' to spectators (%s)"), aLabel, g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); str_format(m_aDescription, sizeof(m_aDescription), "Move '%s' to spectators", g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); } } if(pMsg->m_ClientID == m_pClient->m_LocalClientID) @@ -218,29 +218,23 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) { case VOTE_START_OP: str_format(aBuf, sizeof(aBuf), Localize("Admin forced server option '%s' (%s)"), pMsg->m_pDescription, pMsg->m_pReason); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); break; case VOTE_START_SPEC: str_format(aBuf, sizeof(aBuf), Localize("Admin moved '%s' to spectator (%s)"), pMsg->m_pDescription, pMsg->m_pReason); - m_pClient->m_pChat->AddLine(-1, 0, aBuf); + m_pClient->m_pChat->AddLine(aBuf); break; case VOTE_END_ABORT: OnReset(); - m_pClient->m_pChat->AddLine(-1, 0, Localize("Vote aborted")); + m_pClient->m_pChat->AddLine(Localize("Vote aborted")); break; case VOTE_END_PASS: OnReset(); - if(pMsg->m_ClientID == -1) - m_pClient->m_pChat->AddLine(-1, 0, Localize("Admin forced vote yes")); - else - m_pClient->m_pChat->AddLine(-1, 0, Localize("Vote passed")); + m_pClient->m_pChat->AddLine(pMsg->m_ClientID == -1 ? Localize("Admin forced vote yes") : Localize("Vote passed")); break; case VOTE_END_FAIL: OnReset(); - if(pMsg->m_ClientID == -1) - m_pClient->m_pChat->AddLine(-1, 0, Localize("Admin forced vote no")); - else - m_pClient->m_pChat->AddLine(-1, 0, Localize("Vote failed")); + m_pClient->m_pChat->AddLine(pMsg->m_ClientID == -1 ? Localize("Admin forced vote no") : Localize("Vote failed")); m_CallvoteBlockTick = BlockTick; } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d2bd95bf..f6a5bcbf 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -681,7 +681,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) char aLabel[64]; GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, m_aClients[ClientID].m_aName); str_format(aBuf, sizeof(aBuf), Localize("'%s' initiated a pause"), aLabel); - m_pChat->AddLine(-1, 0, aBuf); + m_pChat->AddLine(aBuf); } break; case GAMEMSG_CTF_CAPTURE: @@ -714,7 +714,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) str_format(aBuf, sizeof(aBuf), Localize("The red flag was captured by '%s'"), aLabel); } } - m_pChat->AddLine(-1, 0, aBuf); + m_pChat->AddLine(aBuf); } return; } @@ -730,7 +730,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) switch(gs_GameMsgList[GameMsgID].m_Action) { case DO_CHAT: - m_pChat->AddLine(-1, 0, pText); + m_pChat->AddLine(pText); break; case DO_BROADCAST: m_pBroadcast->DoBroadcast(pText); @@ -813,7 +813,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) char aLabel[64]; GetPlayerLabel(aLabel, sizeof(aLabel), pMsg->m_ClientID, m_aClients[pMsg->m_ClientID].m_aName); str_format(aBuf, sizeof(aBuf), Localize("%s is muted by you"), aLabel); - m_pChat->AddLine(-2, 0, aBuf); + m_pChat->AddLine(aBuf, CChat::CLIENT_MSG); } m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, true); @@ -893,9 +893,10 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) CNetMsg_Sv_ServerSettings *pMsg = (CNetMsg_Sv_ServerSettings *)pRawMsg; if(!m_ServerSettings.m_TeamLock && pMsg->m_TeamLock) - m_pChat->AddLine(-1, 0, Localize("Teams were locked")); + m_pChat->AddLine(Localize("Teams were locked")); else if(m_ServerSettings.m_TeamLock && !pMsg->m_TeamLock) - m_pChat->AddLine(-1, 0, Localize("Teams were unlocked")); + m_pChat->AddLine(Localize("Teams were unlocked")); + m_ServerSettings.m_KickVote = pMsg->m_KickVote; m_ServerSettings.m_KickMin = pMsg->m_KickMin; m_ServerSettings.m_SpecVote = pMsg->m_SpecVote; @@ -1701,7 +1702,7 @@ void CGameClient::DoEnterMessage(const char *pName, int ClientID, int Team) case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the blue team"), aLabel); break; case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the spectators"), aLabel); break; } - m_pChat->AddLine(-1, 0, aBuf); + m_pChat->AddLine(aBuf); } void CGameClient::DoLeaveMessage(const char *pName, int ClientID, const char *pReason) @@ -1712,7 +1713,7 @@ void CGameClient::DoLeaveMessage(const char *pName, int ClientID, const char *pR str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game (%s)"), aLabel, pReason); else str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game"), aLabel); - m_pChat->AddLine(-1, 0, aBuf); + m_pChat->AddLine(aBuf); } void CGameClient::DoTeamChangeMessage(const char *pName, int ClientID, int Team) @@ -1727,7 +1728,7 @@ void CGameClient::DoTeamChangeMessage(const char *pName, int ClientID, int Team) case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the blue team"), aLabel); break; case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the spectators"), aLabel); break; } - m_pChat->AddLine(-1, 0, aBuf); + m_pChat->AddLine(aBuf); } void CGameClient::SendSwitchTeam(int Team) From c4f5740a71111af257bd647e0fef24e96694d9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 17 Jan 2020 14:54:58 +0100 Subject: [PATCH 034/479] move sliders in direction of mouse when clicking/holding on rail (closes #2000) --- src/game/client/components/menus.cpp | 87 +++++++++++++++++----------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index aec2d61f..191ff0be 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -791,28 +791,27 @@ void CMenus::DoInfoBox(const CUIRect *pRect, const char *pLabel, const char *pVa float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) { + // layout CUIRect Handle; - static float OffsetY; pRect->HSplitTop(min(pRect->h/8.0f, 33.0f), &Handle, 0); - Handle.y += (pRect->h-Handle.h)*Current; + Handle.VMargin(5.0f, &Handle); + + CUIRect Rail; + pRect->VMargin(5.0f, &Rail); // logic + static float OffsetY; + const bool InsideHandle = UI()->MouseInside(&Handle); + const bool InsideRail = UI()->MouseInside(&Rail); float ReturnValue = Current; - bool Inside = UI()->MouseInside(&Handle); - bool Grabbed = false; + bool Grabbed = false; // whether to apply the offset if(UI()->CheckActiveItem(pID)) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - float Min = pRect->y; - float Max = pRect->h-Handle.h; - float Cur = UI()->MouseY()-OffsetY; - ReturnValue = (Cur-Min)/Max; - if(ReturnValue < 0.0f) ReturnValue = 0.0f; - if(ReturnValue > 1.0f) ReturnValue = 1.0f; Grabbed = true; } else if(UI()->HotItem() == pID) @@ -823,53 +822,61 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) OffsetY = UI()->MouseY()-Handle.y; } } + else if(UI()->MouseButton(0) && !InsideHandle && InsideRail) + { + bool Up = UI()->MouseY() < Handle.y + Handle.h/2; + OffsetY = UI()->MouseY() - Handle.y + 8 * (Up ? 1 : -1); + Grabbed = true; + } - if(Inside) + if(Grabbed) + { + const float Min = pRect->y; + const float Max = pRect->h-Handle.h; + const float Cur = UI()->MouseY()-OffsetY; + ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f); + } + + if(InsideHandle) UI()->SetHotItem(pID); // render - CUIRect Rail; - pRect->VMargin(5.0f, &Rail); RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.w/2.0f); - CUIRect Slider = Handle; - Slider.VMargin(5.0f, &Slider); vec4 Color; if(Grabbed) Color = vec4(0.9f, 0.9f, 0.9f, 1.0f); - else if(Inside) + else if(InsideHandle) Color = vec4(1.0f, 1.0f, 1.0f, 1.0f); else Color = vec4(0.8f, 0.8f, 0.8f, 1.0f); - RenderTools()->DrawUIRect(&Slider, Color, CUI::CORNER_ALL, Slider.w/2.0f); + RenderTools()->DrawUIRect(&Handle, Color, CUI::CORNER_ALL, Handle.w/2.0f); return ReturnValue; } float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) { + // layout CUIRect Handle; - static float OffsetX; pRect->VSplitLeft(min(pRect->w/8.0f, 33.0f), &Handle, 0); - Handle.x += (pRect->w-Handle.w)*Current; + Handle.HMargin(5.0f, &Handle); + + CUIRect Rail; + pRect->HMargin(5.0f, &Rail); // logic + static float OffsetX; + const bool InsideHandle = UI()->MouseInside(&Handle); + const bool InsideRail = UI()->MouseInside(&Rail); float ReturnValue = Current; - bool Inside = UI()->MouseInside(&Handle); - bool Grabbed = false; + bool Grabbed = false; // whether to apply the offset if(UI()->CheckActiveItem(pID)) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - - float Min = pRect->x; - float Max = pRect->w-Handle.w; - float Cur = UI()->MouseX()-OffsetX; - ReturnValue = (Cur-Min)/Max; - if(ReturnValue < 0.0f) ReturnValue = 0.0f; - if(ReturnValue > 1.0f) ReturnValue = 1.0f; Grabbed = true; } else if(UI()->HotItem() == pID) @@ -880,25 +887,35 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) OffsetX = UI()->MouseX()-Handle.x; } } + else if(UI()->MouseButton(0) && !InsideHandle && InsideRail) + { + bool Left = UI()->MouseX() < Handle.x + Handle.w/2; + OffsetX = UI()->MouseX() - Handle.x + 8 * (Left ? 1 : -1); + Grabbed = true; + } - if(Inside) + if(Grabbed) + { + const float Min = pRect->x; + const float Max = pRect->w-Handle.w; + const float Cur = UI()->MouseX()-OffsetX; + ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f); + } + + if(InsideHandle) UI()->SetHotItem(pID); // render - CUIRect Rail; - pRect->HMargin(5.0f, &Rail); RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.h/2.0f); - CUIRect Slider = Handle; - Slider.HMargin(5.0f, &Slider); vec4 Color; if(Grabbed) Color = vec4(0.9f, 0.9f, 0.9f, 1.0f); - else if(Inside) + else if(InsideHandle) Color = vec4(1.0f, 1.0f, 1.0f, 1.0f); else Color = vec4(0.8f, 0.8f, 0.8f, 1.0f); - RenderTools()->DrawUIRect(&Slider, Color, CUI::CORNER_ALL, Slider.h/2.0f); + RenderTools()->DrawUIRect(&Handle, Color, CUI::CORNER_ALL, Handle.h/2.0f); return ReturnValue; } From 76cb2de18335fcf79db2a6d75c4516a7b2f298fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Jan 2020 11:30:13 +0100 Subject: [PATCH 035/479] use Compress/Decompress of CNetBase --- src/engine/shared/network.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index ac8212cf..d354f624 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -133,7 +133,7 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons // compress if not ctrl msg if(!(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)) - CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); + CompressedSize = Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); // check if the compression was enabled, successful and good enough if(CompressedSize > 0 && CompressedSize < pPacket->m_DataSize) @@ -249,7 +249,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct pPacket->m_ResponseToken = NET_TOKEN_NONE; if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION) - pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); + pPacket->m_DataSize = Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); else mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize); } From 542a5409a42fe9c28b75cd2ab41e49b65fc12275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Jan 2020 11:33:26 +0100 Subject: [PATCH 036/479] fix incomplete deletion of CNetTokenCache linked list --- src/engine/shared/network_token.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index 073e979b..e2fe8891 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -150,8 +150,8 @@ CNetTokenCache::~CNetTokenCache() CConnlessPacketInfo *pTemp = m_pConnlessPacketList->m_pNext; delete m_pConnlessPacketList; m_pConnlessPacketList = pTemp; - m_pConnlessPacketList = 0; } + m_pConnlessPacketList = 0; } void CNetTokenCache::Init(NETSOCKET Socket, const CNetTokenManager *pTokenManager) @@ -327,8 +327,7 @@ void CNetTokenCache::Update() // drop expired packets while(m_pConnlessPacketList && m_pConnlessPacketList->m_Expiry <= Now) { - CConnlessPacketInfo *pNewList; - pNewList = m_pConnlessPacketList->m_pNext; + CConnlessPacketInfo *pNewList = m_pConnlessPacketList->m_pNext; delete m_pConnlessPacketList; m_pConnlessPacketList = pNewList; } From 44a0260372d170cdd51b78418708e506567f5513 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 18 Jan 2020 16:50:54 +0100 Subject: [PATCH 037/479] added some initializations --- src/mastersrv/mastersrv.cpp | 1 + src/versionsrv/versionsrv.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 66b4a79d..2395d65e 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -288,6 +288,7 @@ int main(int argc, const char **argv) // ignore_convention dbg_logger_stdout(); net_init(); + CNetBase::Init(); mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index efbfb1fd..be14743f 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -80,6 +80,7 @@ int main(int argc, char **argv) // ignore_convention dbg_logger_stdout(); net_init(); + CNetBase::Init(); mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; From f72b6fa84322eb65c862668f1c2e2840d294a716 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sun, 19 Jan 2020 12:48:52 +0000 Subject: [PATCH 038/479] Chat commands: show the current autocomplete option in gray text --- src/game/client/components/chat.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 5620e82b..e80028f4 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -934,6 +934,15 @@ void CChat::OnRender() TextRender()->TextEx(&Marker, "|", -1); TextRender()->TextEx(&Cursor, m_Input.GetString()+m_Input.GetCursorOffset(), -1); + //Render command autocomplete option hint + if(IsTypingCommand() && m_Commands.CountActiveCommands()) + if(const CChat::CChatCommand* pCommand = m_Commands.GetSelectedCommand()) + if(str_length(pCommand->m_aName)+1 > str_length(m_Input.GetString())) + { + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextEx(&Cursor, pCommand->m_aName + str_length(m_Input.GetString())-1, -1); + } + if(ChatMode == CHAT_WHISPER) { //render helper annotation From db851d514860002a9f5020cb7accf7e5fdcb45e0 Mon Sep 17 00:00:00 2001 From: LordSk Date: Sun, 19 Jan 2020 14:50:57 +0100 Subject: [PATCH 039/479] Fix cl detection --- configure.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.lua b/configure.lua index aec5443c..b4d0a067 100644 --- a/configure.lua +++ b/configure.lua @@ -359,7 +359,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc) -- no need todo anything if we have a driver -- TODO: test if we can find the compiler else - if (ExecuteSilent("g++ -v") and ((arch ~= "amd64" and arch ~= "ia64") or CTestCompile(settings, "int main(){return 0;}", "-m64"))) then + if ExecuteSilent("g++ -v") == 0 and ((arch ~= "amd64" and arch ~= "ia64") or CTestCompile(settings, "int main(){return 0;}", "-m64")) then option.driver = "gcc" elseif ExecuteSilent("cl") == 0 then option.driver = "cl" From 0f8d2473808c9b68d0704249e469af5c71b1bc0b Mon Sep 17 00:00:00 2001 From: fokkonaut <35420825+fokkonaut@users.noreply.github.com> Date: Sun, 19 Jan 2020 16:03:30 +0100 Subject: [PATCH 040/479] Fix pause behaviour --- src/game/client/gameclient.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d2bd95bf..26f37c1d 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1311,9 +1311,12 @@ void CGameClient::OnNewSnapshot() CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_LocalClientID]; if(c->m_Active) { - m_Snap.m_pLocalCharacter = &c->m_Cur; - m_Snap.m_pLocalPrevCharacter = &c->m_Prev; - m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); + if (!m_Snap.m_SpecInfo.m_Active) + { + m_Snap.m_pLocalCharacter = &c->m_Cur; + m_Snap.m_pLocalPrevCharacter = &c->m_Prev; + m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); + } } else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_LocalClientID)) { From 62ee875fc78b29527a5f0564e5aff1a46234b406 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 23 Jan 2016 21:44:45 +0100 Subject: [PATCH 041/479] Style cleanup (cherry picked from commit https://github.com/ddnet/ddnet/commit/52224875b4bae020f36a311f02346ea74b157636) --- src/engine/client/client.cpp | 20 ++++++++++---------- src/engine/client/client.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 53c5afb6..b47e12c7 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -302,7 +302,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD mem_zero(m_aSnapshots, sizeof(m_aSnapshots)); m_SnapshotStorage.Init(); - m_RecivedSnapshots = 0; + m_ReceivedSnapshots = 0; m_VersionInfo.m_State = CVersionInfo::STATE_INIT; } @@ -470,7 +470,7 @@ void CClient::OnEnterGame() m_aSnapshots[SNAP_CURRENT] = 0; m_aSnapshots[SNAP_PREV] = 0; m_SnapshotStorage.PurgeAll(); - m_RecivedSnapshots = 0; + m_ReceivedSnapshots = 0; m_SnapshotParts = 0; m_PredTick = 0; m_CurrentRecvTick = 0; @@ -562,7 +562,7 @@ void CClient::DisconnectWithReason(const char *pReason) // clear snapshots m_aSnapshots[SNAP_CURRENT] = 0; m_aSnapshots[SNAP_PREV] = 0; - m_RecivedSnapshots = 0; + m_ReceivedSnapshots = 0; } void CClient::Disconnect() @@ -796,7 +796,7 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, const SHA char aBuf[256]; str_format(aBuf, sizeof(aBuf), "loaded map '%s'", pFilename); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); - m_RecivedSnapshots = 0; + m_ReceivedSnapshots = 0; str_copy(m_aCurrentMap, pName, sizeof(m_aCurrentMap)); str_copy(m_aCurrentMapPath, pFilename, sizeof(m_aCurrentMapPath)); @@ -1340,7 +1340,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } // TODO: clean this up abit - mem_copy((char*)m_aSnapshotIncommingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize); + mem_copy((char*)m_aSnapshotIncomingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize); m_SnapshotParts |= 1< 2) + if(m_ReceivedSnapshots > 2) { int64 Now = m_GameTime.Get(time_get()); int64 TickStart = GameTick*time_freq()/50; @@ -1634,7 +1634,7 @@ void CClient::Update() Disconnect(); } } - else if(State() == IClient::STATE_ONLINE && m_RecivedSnapshots >= 3) + else if(State() == IClient::STATE_ONLINE && m_ReceivedSnapshots >= 3) { // switch snapshot int Repredict = 0; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 3260505e..6fcd3975 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -162,8 +162,8 @@ class CClient : public IClient, public CDemoPlayer::IListner class CSnapshotStorage m_SnapshotStorage; CSnapshotStorage::CHolder *m_aSnapshots[NUM_SNAPSHOT_TYPES]; - int m_RecivedSnapshots; - char m_aSnapshotIncommingData[CSnapshot::MAX_SIZE]; + int m_ReceivedSnapshots; + char m_aSnapshotIncomingData[CSnapshot::MAX_SIZE]; class CSnapshotStorage::CHolder m_aDemorecSnapshotHolders[NUM_SNAPSHOT_TYPES]; char *m_aDemorecSnapshotData[NUM_SNAPSHOT_TYPES][2][CSnapshot::MAX_SIZE]; From f5b8deca8942471901dd9bbbfc84ec00b26c6a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 19 Jan 2020 19:54:52 +0100 Subject: [PATCH 042/479] minor refactorings and style fixes in HUD --- src/game/client/components/hud.cpp | 59 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index b685b45c..f5d147f2 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -39,7 +39,6 @@ void CHud::RenderGameTimer() if(!(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH)) { - char Buf[32]; int Time = 0; if(m_pClient->m_GameInfo.m_TimeLimit && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) { @@ -53,16 +52,17 @@ void CHud::RenderGameTimer() else Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameData->m_GameStartTick)/Client()->GameTickSpeed(); - str_format(Buf, sizeof(Buf), "%d:%02d", Time/60, Time%60); + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%d:%02d", Time/60, Time%60); float FontSize = 10.0f; - float w = TextRender()->TextWidth(0, FontSize, Buf, -1, -1.0f); + float w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); // last 60 sec red, last 10 sec blink if(m_pClient->m_GameInfo.m_TimeLimit && Time <= 60 && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) { float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f; TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha); } - TextRender()->Text(0, Half-w/2, 2, FontSize, Buf, -1.0f); + TextRender()->Text(0, Half-w/2, 2, FontSize, aBuf, -1.0f); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } } @@ -75,7 +75,7 @@ void CHud::RenderPauseTimer() const char *pText = Localize("Game paused"); float FontSize = 20.0f; float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 50, FontSize, pText, -1.0f); FontSize = 16.0f; if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) @@ -97,7 +97,7 @@ void CHud::RenderPauseTimer() str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds)); } w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 75, FontSize, aBuf, -1.0f); } } @@ -108,7 +108,7 @@ void CHud::RenderStartCountdown() const char *pText = Localize("Game starts in"); float FontSize = 20.0f; float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 50, FontSize, pText, -1.0f); if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) return; @@ -118,7 +118,7 @@ void CHud::RenderStartCountdown() int Seconds = (m_pClient->m_Snap.m_pGameData->m_GameStateEndTick-Client()->GameTick()+SERVER_TICK_SPEED-1)/SERVER_TICK_SPEED; str_format(aBuf, sizeof(aBuf), "%d", Seconds); w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 75, FontSize, aBuf, -1.0f); } } @@ -130,7 +130,7 @@ void CHud::RenderDeadNotification() const char *pText = Localize("Wait for next round"); float FontSize = 16.0f; float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 50, FontSize, pText, -1.0f); } } @@ -154,6 +154,7 @@ void CHud::RenderScoreHud() int GameFlags = m_pClient->m_GameInfo.m_GameFlags; float Whole = 300*Graphics()->ScreenAspect(); float StartY = 229.0f; + const float TeamOffset = 20.0f; if(GameFlags&GAMEFLAG_TEAMS && m_pClient->m_Snap.m_pGameDataTeam && !(GameFlags&GAMEFLAG_RACE)) { @@ -168,12 +169,12 @@ void CHud::RenderScoreHud() for(int t = 0; t < NUM_TEAMS; t++) { // draw box - CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split, StartY+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f}; + CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split, StartY+t*TeamOffset, ScoreWidthMax+ImageSize+2*Split, 18.0f}; Graphics()->BlendNormal(); RenderTools()->DrawUIRect(&Rect, t == 0 ? vec4(1.0f, 0.0f, 0.0f, 0.25f) : vec4(0.0f, 0.0f, 1.0f, 0.25f), CUI::CORNER_L, 5.0f); // draw score - TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, StartY+t*20, 14.0f, aScoreTeam[t], -1.0f); + TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, StartY+t*TeamOffset, 14.0f, aScoreTeam[t], -1.0f); if(GameFlags&GAMEFLAG_SURVIVAL) { @@ -182,7 +183,7 @@ void CHud::RenderScoreHud() str_format(aBuf, sizeof(aBuf), m_pClient->m_Snap.m_AliveCount[t]==1 ? Localize("%d player left") : Localize("%d players left"), m_pClient->m_Snap.m_AliveCount[t]); float w = TextRender()->TextWidth(0, 8.0f, aBuf, -1, -1.0f); - TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*20.0f-3.0f, 8.0f, aBuf, -1.0f); + TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*TeamOffset-3.0f, 8.0f, aBuf, -1.0f); } StartY += 8.0f; } @@ -203,7 +204,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, StartY+1.0f+t*20, ImageSize/2, ImageSize); + IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, StartY+1.0f+t*TeamOffset, ImageSize/2, ImageSize); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } @@ -217,7 +218,7 @@ void CHud::RenderScoreHud() CTextCursor Cursor; float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split); - float y = StartY+(t+1)*20.0f-3.0f; + float y = StartY+(t+1)*TeamOffset-3.0f; TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, ID); @@ -227,7 +228,7 @@ void CHud::RenderScoreHud() 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, StartY+1.0f+Info.m_Size/2+t*20)); + vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*TeamOffset)); } StartY += 8.0f; } @@ -298,13 +299,13 @@ void CHud::RenderScoreHud() for(int t = 0; t < 2; t++) { // draw box - CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, StartY+t*20, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f}; + CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, StartY+t*TeamOffset, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f}; Graphics()->BlendNormal(); RenderTools()->DrawUIRect(&Rect, t == Local ? vec4(1.0f, 1.0f, 1.0f, 0.25f) : vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_L, 5.0f); // draw score float Spacing = (GameFlags&GAMEFLAG_RACE) ? 2.f : 0.f; - TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*20+Spacing, FontSize, aScore[t], -1.0f); + TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*TeamOffset+Spacing, FontSize, aScore[t], -1.0f); if(aPlayerInfo[t].m_pPlayerInfo) { @@ -316,7 +317,7 @@ void CHud::RenderScoreHud() CTextCursor Cursor; float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split-PosSize); - float y = StartY+(t+1)*20.0f-3.0f; + float y = StartY+(t+1)*TeamOffset-3.0f; TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, ID); @@ -326,13 +327,13 @@ void CHud::RenderScoreHud() 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, StartY+1.0f+Info.m_Size/2+t*20)); + vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*TeamOffset)); } // draw position char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%d.", aPos[t]); - TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, StartY+2.0f+t*20, 10.0f, aBuf, -1.0f); + TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, StartY+2.0f+t*TeamOffset, 10.0f, aBuf, -1.0f); StartY += 8.0f; } @@ -353,7 +354,7 @@ void CHud::RenderWarmupTimer() if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 50, FontSize, pText, -1.0f); } else { @@ -393,7 +394,7 @@ void CHud::RenderWarmupTimer() if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 75, FontSize, aBuf, -1.0f); } else { @@ -412,9 +413,9 @@ void CHud::RenderFps() // calculate avg. fps 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); - TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,Buf,-1, -1.0f), 5, 12, Buf, -1.0f); + char aBuf[32]; + str_format(aBuf, sizeof(Buf), "%d", (int)m_AverageFPS); + TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,aBuf,-1, -1.0f), 5, 12, aBuf, -1.0f); } } @@ -705,7 +706,7 @@ void CHud::RenderSpectatorNotification() const char *pText = Localize("Click on a player or a flag to follow it"); float FontSize = 16.0f; float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150 * Graphics()->ScreenAspect() + -w / 2, 30, FontSize, pText, -1.0f); + TextRender()->Text(0, 150 * Graphics()->ScreenAspect() - w / 2, 30, FontSize, pText, -1.0f); } } } @@ -719,7 +720,7 @@ void CHud::RenderReadyUpNotification() str_format(aText, sizeof(aText), Localize("When ready, press <%s>"), aKey); float FontSize = 16.0f; float w = TextRender()->TextWidth(0, FontSize, aText, -1, -1.0f); - TextRender()->Text(0, 150 * Graphics()->ScreenAspect() + -w / 2, 30, FontSize, aText, -1.0f); + TextRender()->Text(0, 150 * Graphics()->ScreenAspect() - w / 2, 30, FontSize, aText, -1.0f); } } @@ -752,7 +753,7 @@ void CHud::RenderCheckpoint() { char aBuf[64]; FormatTimeDiff(aBuf, sizeof(aBuf), m_CheckpointDiff, 2); - + // calculate alpha (2 sec 1 than get lower the next 2 sec) float a = 1.0f; if(TimeSinceCheckpoint > time_freq() * 2) @@ -760,7 +761,7 @@ void CHud::RenderCheckpoint() // lower the alpha slowly to blend text out a = (time_freq() * 4 - TimeSinceCheckpoint) / (float)(time_freq() * 2); } - + if(m_CheckpointDiff > 0) TextRender()->TextColor(1.0f,0.5f,0.5f,a); // red else if(m_CheckpointDiff < 0) From 904ca59a497d2ea9ac83b85cda005702b040b6ca Mon Sep 17 00:00:00 2001 From: def Date: Thu, 21 Aug 2014 00:56:35 +0200 Subject: [PATCH 043/479] Show current quad when pressing space in editor (cherry picked from commit https://github.com/ddnet/ddnet/commit/a5ec9e3240562e1b8e0e6899d44eca4bbc011c23) --- src/game/editor/editor.cpp | 32 ++++++++++++++++++++++++++++++-- src/game/editor/editor.h | 3 ++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index f242544a..d662c70a 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -1856,10 +1856,10 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) float y = -(View.y/Screen.h)*h; wx = x+w*mx/Screen.w; wy = y+h*my/Screen.h; - Graphics()->MapScreen(x, y, x+w, y+h); CLayerTiles *t = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); if(t) { + Graphics()->MapScreen(x, y, x+w, y+h); m_TilesetPicker.m_Image = t->m_Image; m_TilesetPicker.m_Texture = t->m_Texture; m_TilesetPicker.m_Game = t->m_Game; @@ -1867,17 +1867,41 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) if(m_ShowTileInfo) m_TilesetPicker.ShowInfo(); } + else + { + CLayerQuads *t = (CLayerQuads *)GetSelectedLayerType(0, LAYERTYPE_QUADS); + if(t) + { + m_QuadsetPicker.m_Image = t->m_Image; + m_QuadsetPicker.m_lQuads[0].m_aPoints[0].x = (int) View.x << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[0].y = (int) View.y << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[1].x = (int) (View.x+View.w) << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[1].y = (int) View.y << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[2].x = (int) View.x << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[2].y = (int) (View.y+View.h) << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[3].x = (int) (View.x+View.w) << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[3].y = (int) (View.y+View.h) << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[4].x = (int) (View.x+View.w/2) << 10; + m_QuadsetPicker.m_lQuads[0].m_aPoints[4].y = (int) (View.y+View.h/2) << 10; + m_QuadsetPicker.Render(); + } + } } // draw layer borders CLayer *pEditLayers[16]; int NumEditLayers = 0; - if(m_ShowTilePicker) + if(m_ShowTilePicker && GetSelectedLayer(0)->m_Type == LAYERTYPE_TILES) { pEditLayers[0] = &m_TilesetPicker; NumEditLayers++; } + else if(m_ShowTilePicker) + { + pEditLayers[0] = &m_QuadsetPicker; + NumEditLayers++; + } else { pEditLayers[0] = GetSelectedLayer(0); @@ -4610,6 +4634,10 @@ void CEditor::Init() m_TilesetPicker.MakePalette(); m_TilesetPicker.m_Readonly = true; + m_QuadsetPicker.m_pEditor = this; + m_QuadsetPicker.NewQuad(); + m_QuadsetPicker.m_Readonly = true; + m_Brush.m_pMap = &m_Map; Reset(); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index eac91ddf..1cc7568e 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -732,7 +732,7 @@ class CEditor : public IEditor int m_SelectedPoints; int m_SelectedEnvelope; int m_SelectedEnvelopePoint; - int m_SelectedQuadEnvelope; + int m_SelectedQuadEnvelope; int m_SelectedImage; vec4 m_SelectedColor; @@ -746,6 +746,7 @@ class CEditor : public IEditor CLayerGroup m_Brush; CLayerTiles m_TilesetPicker; + CLayerQuads m_QuadsetPicker; static const void *ms_pUiGotContext; From 993bd3fd8dbda5eaa7597356e84cdba3385bec38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 19 Jan 2020 20:12:40 +0100 Subject: [PATCH 044/479] add missing change --- src/game/client/components/hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index f5d147f2..d16d7f5b 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -414,7 +414,7 @@ void CHud::RenderFps() float FPS = 1.0f / Client()->RenderFrameTime(); m_AverageFPS = (m_AverageFPS*(1.0f-(1.0f/m_AverageFPS))) + (FPS*(1.0f/m_AverageFPS)); char aBuf[32]; - str_format(aBuf, sizeof(Buf), "%d", (int)m_AverageFPS); + str_format(aBuf, sizeof(aBuf), "%d", (int)m_AverageFPS); TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,aBuf,-1, -1.0f), 5, 12, aBuf, -1.0f); } } From 543864fc59e51d3159255ff1211134a9432d0cf9 Mon Sep 17 00:00:00 2001 From: def Date: Sun, 24 Aug 2014 13:38:46 +0200 Subject: [PATCH 045/479] Fix client crash when holding space and adding a group in editor (cherry picked from commit https://github.com/ddnet/ddnet/commit/3edd1bb53f52acaabdab05ad84e4f447c723e34e) --- src/game/editor/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index d662c70a..19b1ea0d 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -1892,7 +1892,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) CLayer *pEditLayers[16]; int NumEditLayers = 0; - if(m_ShowTilePicker && GetSelectedLayer(0)->m_Type == LAYERTYPE_TILES) + if(m_ShowTilePicker && GetSelectedLayer(0) && GetSelectedLayer(0)->m_Type == LAYERTYPE_TILES) { pEditLayers[0] = &m_TilesetPicker; NumEditLayers++; From 470ef300c8bb6c27dbee0597e94e8afd616086d3 Mon Sep 17 00:00:00 2001 From: jupeyy Date: Wed, 22 Jan 2020 13:23:32 +0100 Subject: [PATCH 046/479] Fix laser bounce delay, when server ticks are high --- src/game/server/entities/laser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 2fcd0e38..ecc06149 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -88,7 +88,7 @@ void CLaser::Reset() void CLaser::Tick() { - if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f) + if((Server()->Tick() - m_EvalTick) > (Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f) DoBounce(); } From d3d63175bb21fbdc86dcfdba38653d22ff74fe6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 22 Jan 2020 17:56:24 +0100 Subject: [PATCH 047/479] store server password for favorites (closes #1196), replace IsFavorite --- src/engine/client.h | 2 +- src/engine/client/client.cpp | 3 +- src/engine/client/client.h | 2 +- src/engine/client/serverbrowser.cpp | 52 ++++++++++++++++++--- src/engine/client/serverbrowser.h | 8 ++-- src/engine/client/serverbrowser_fav.cpp | 31 +++++++++--- src/engine/client/serverbrowser_fav.h | 3 +- src/engine/serverbrowser.h | 10 ++-- src/engine/shared/config_variables.h | 2 + src/game/client/components/menus.cpp | 34 ++++++++++++-- src/game/client/components/menus_ingame.cpp | 2 +- 11 files changed, 119 insertions(+), 30 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index 9dca8a43..cd9f684e 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -115,7 +115,7 @@ class IClient : public IInterface virtual void Rcon(const char *pLine) = 0; // server info - virtual void GetServerInfo(class CServerInfo *pServerInfo) const = 0; + virtual void GetServerInfo(class CServerInfo *pServerInfo) = 0; // snapshot interface diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b47e12c7..a7728d06 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -571,9 +571,10 @@ void CClient::Disconnect() } -void CClient::GetServerInfo(CServerInfo *pServerInfo) const +void CClient::GetServerInfo(CServerInfo *pServerInfo) { mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo)); + m_ServerBrowser.UpdateFavoriteState(pServerInfo); } int CClient::LoadData() diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 6fcd3975..afd3739f 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -240,7 +240,7 @@ class CClient : public IClient, public CDemoPlayer::IListner virtual void Disconnect(); - virtual void GetServerInfo(CServerInfo *pServerInfo) const; + virtual void GetServerInfo(CServerInfo *pServerInfo); int LoadData(); diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index df4ff3f2..9f44b7d5 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -245,7 +245,7 @@ void CServerBrowser::Update(bool ForceResort) { CServerEntry *pEntry = Find(i, *pFavAddr); if(pEntry) - pEntry->m_Info.m_Favorite = 1; + pEntry->m_Info.m_Favorite = true; if(i == m_ActServerlistType) ForceResort = true; @@ -344,7 +344,7 @@ void CServerBrowser::AddFavorite(const CServerInfo *pInfo) CServerEntry *pEntry = Find(i, pInfo->m_NetAddr); if(pEntry) { - pEntry->m_Info.m_Favorite = 1; + pEntry->m_Info.m_Favorite = true; // refresh servers in all filters where favorites are filtered if(i == m_ActServerlistType) @@ -363,7 +363,7 @@ void CServerBrowser::RemoveFavorite(const CServerInfo *pInfo) CServerEntry *pEntry = Find(i, pInfo->m_NetAddr); if(pEntry) { - pEntry->m_Info.m_Favorite = 0; + pEntry->m_Info.m_Favorite = false; // refresh servers in all filters where favorites are filtered if(i == m_ActServerlistType) @@ -373,6 +373,46 @@ void CServerBrowser::RemoveFavorite(const CServerInfo *pInfo) } } +void CServerBrowser::UpdateFavoriteState(CServerInfo *pInfo) +{ + pInfo->m_Favorite = m_ServerBrowserFavorites.FindFavoriteByAddr(pInfo->m_NetAddr, 0) != 0; +} + +void CServerBrowser::SetFavoritePassword(const char *pAddress, const char *pPassword) +{ + if(m_ServerBrowserFavorites.AddFavoriteEx(pAddress, 0, false, pPassword)) + { + NETADDR Addr = {0}; + if(net_addr_from_str(&Addr, pAddress)) + return; + for(int i = 0; i < NUM_TYPES; ++i) + { + CServerEntry *pEntry = Find(i, Addr); + if(pEntry) + { + pEntry->m_Info.m_Favorite = true; + + // refresh servers in all filters where favorites are filtered + if(i == m_ActServerlistType) + m_ServerBrowserFilter.Sort(m_aServerlist[m_ActServerlistType].m_ppServerlist, m_aServerlist[m_ActServerlistType].m_NumServers, CServerBrowserFilter::RESORT_FLAG_FAV); + } + } + } +} + +const char *CServerBrowser::GetFavoritePassword(const char *pAddress) +{ + NETADDR Addr = {0}; + if(net_addr_from_str(&Addr, pAddress)) + return 0; + CServerBrowserFavorites::CFavoriteServer *pFavorite = m_ServerBrowserFavorites.FindFavoriteByAddr(Addr, 0); + if(!pFavorite) + return 0; + if(!pFavorite->m_aPassword[0]) + return 0; + return pFavorite->m_aPassword; +} + // manipulate entries CServerEntry *CServerBrowser::Add(int ServerlistType, const NETADDR &Addr) { @@ -391,9 +431,7 @@ CServerEntry *CServerBrowser::Add(int ServerlistType, const NETADDR &Addr) str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName)); str_copy(pEntry->m_Info.m_aHostname, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aHostname)); - // check if it's a favorite - if(m_ServerBrowserFavorites.FindFavoriteByAddr(Addr, 0)) - pEntry->m_Info.m_Favorite = 1; + UpdateFavoriteState(&pEntry->m_Info); // add to the hash list int Hash = AddrHash(&Addr); @@ -529,7 +567,7 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) void CServerBrowser::SetInfo(int ServerlistType, CServerEntry *pEntry, const CServerInfo &Info) { - int Fav = pEntry->m_Info.m_Favorite; + bool Fav = pEntry->m_Info.m_Favorite; pEntry->m_Info = Info; pEntry->m_Info.m_Flags &= FLAG_PASSWORD|FLAG_TIMESCORE; if(str_comp(pEntry->m_Info.m_aGameType, "DM") == 0 || str_comp(pEntry->m_Info.m_aGameType, "TDM") == 0 || str_comp(pEntry->m_Info.m_aGameType, "CTF") == 0 || diff --git a/src/engine/client/serverbrowser.h b/src/engine/client/serverbrowser.h index 1b336645..3e893b30 100644 --- a/src/engine/client/serverbrowser.h +++ b/src/engine/client/serverbrowser.h @@ -41,9 +41,11 @@ class CServerBrowser : public IServerBrowser const CServerInfo *SortedGet(int FilterIndex, int Index) const { return &m_aServerlist[m_ActServerlistType].m_ppServerlist[m_ServerBrowserFilter.GetIndex(FilterIndex, Index)]->m_Info; }; const void *GetID(int FilterIndex, int Index) const { return m_ServerBrowserFilter.GetID(FilterIndex, Index); }; - bool IsFavorite(const NETADDR &Addr) { return m_ServerBrowserFavorites.FindFavoriteByAddr(Addr, 0) != 0; } - void AddFavorite(const CServerInfo *pEntry); - void RemoveFavorite(const CServerInfo *pEntry); + void AddFavorite(const CServerInfo *pInfo); + void RemoveFavorite(const CServerInfo *pInfo); + void UpdateFavoriteState(CServerInfo *pInfo); + void SetFavoritePassword(const char *pAddress, const char *pPassword); + const char *GetFavoritePassword(const char *pAddress); int AddFilter(const CServerFilterInfo *pFilterInfo) { return m_ServerBrowserFilter.AddFilter(pFilterInfo); }; void SetFilter(int Index, const CServerFilterInfo *pFilterInfo) { m_ServerBrowserFilter.SetFilter(Index, pFilterInfo); }; diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index 012fd95d..f66b7c68 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -34,15 +34,25 @@ void CServerBrowserFavorites::Init(CNetClient *pNetClient, IConsole *pConsole, I if(pConfig) pConfig->RegisterCallback(ConfigSaveCallback, this); - m_pConsole->Register("add_favorite", "s", CFGFLAG_CLIENT, ConAddFavorite, this, "Add a server as a favorite"); + m_pConsole->Register("add_favorite", "s?s", CFGFLAG_CLIENT, ConAddFavorite, this, "Add a server (optionally with password) as a favorite. Also updates password of existing favorite."); m_pConsole->Register("remove_favorite", "s", CFGFLAG_CLIENT, ConRemoveFavorite, this, "Remove a server from favorites"); } -bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck) +bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck, const char *pPassword) { - if(m_NumFavoriteServers == MAX_FAVORITES || FindFavoriteByHostname(pHostname, 0)) + if(m_NumFavoriteServers == MAX_FAVORITES) return false; + CFavoriteServer *pExistingFavorite = FindFavoriteByHostname(pHostname, 0); + if(pExistingFavorite) + { + if(pPassword) + str_copy(pExistingFavorite->m_aPassword, pPassword, sizeof(pExistingFavorite->m_aPassword)); + else + pExistingFavorite->m_aPassword[0] = '\0'; + return false; + } + bool Result = false; // check if hostname is a net address string if(net_addr_from_str(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, pHostname) == 0) @@ -73,6 +83,12 @@ bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR } str_copy(m_aFavoriteServers[m_NumFavoriteServers].m_aHostname, pHostname, sizeof(m_aFavoriteServers[m_NumFavoriteServers].m_aHostname)); + + if(pPassword) + str_copy(m_aFavoriteServers[m_NumFavoriteServers].m_aPassword, pPassword, sizeof(m_aFavoriteServers[m_NumFavoriteServers].m_aPassword)); + else + m_aFavoriteServers[m_NumFavoriteServers].m_aPassword[0] = '\0'; + ++m_NumFavoriteServers; if(g_Config.m_Debug) @@ -229,7 +245,7 @@ const NETADDR *CServerBrowserFavorites::UpdateFavorites() void CServerBrowserFavorites::ConAddFavorite(IConsole::IResult *pResult, void *pUserData) { CServerBrowserFavorites *pSelf = static_cast(pUserData); - pSelf->AddFavoriteEx(pResult->GetString(0), 0, false); + pSelf->AddFavoriteEx(pResult->GetString(0), 0, false, pResult->NumArguments() > 1 ? pResult->GetString(1) : 0); } void CServerBrowserFavorites::ConRemoveFavorite(IConsole::IResult *pResult, void *pUserData) @@ -242,10 +258,13 @@ void CServerBrowserFavorites::ConfigSaveCallback(IConfig *pConfig, void *pUserDa { CServerBrowserFavorites *pSelf = (CServerBrowserFavorites *)pUserData; - char aBuffer[256]; + char aBuffer[320]; for(int i = 0; i < pSelf->m_NumFavoriteServers; i++) { - str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", pSelf->m_aFavoriteServers[i].m_aHostname); + if(pSelf->m_aFavoriteServers[i].m_aPassword[0]) + str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\" \"%s\"", pSelf->m_aFavoriteServers[i].m_aHostname, pSelf->m_aFavoriteServers[i].m_aPassword); + else + str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\"", pSelf->m_aFavoriteServers[i].m_aHostname); pConfig->WriteLine(aBuffer); } } diff --git a/src/engine/client/serverbrowser_fav.h b/src/engine/client/serverbrowser_fav.h index edbce6fb..55eabfe4 100644 --- a/src/engine/client/serverbrowser_fav.h +++ b/src/engine/client/serverbrowser_fav.h @@ -24,6 +24,7 @@ class CServerBrowserFavorites struct CFavoriteServer { char m_aHostname[128]; + char m_aPassword[sizeof(g_Config.m_Password)]; NETADDR m_Addr; int m_State; } m_aFavoriteServers[MAX_FAVORITES]; @@ -45,7 +46,7 @@ class CServerBrowserFavorites CServerBrowserFavorites(); void Init(class CNetClient *pNetClient, class IConsole *pConsole, class IEngine *pEngine, class IConfig *pConfig); - bool AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck); + bool AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck, const char *pPassword = 0); CFavoriteServer *FindFavoriteByAddr(const NETADDR &Addr, int *Index); CFavoriteServer *FindFavoriteByHostname(const char *pHostname, int *Index); void RemoveFavoriteEntry(int Index); diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 31acc50a..bfe6d81b 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -59,7 +59,7 @@ class CServerInfo int m_NumBotSpectators; int m_Flags; int m_ServerLevel; - int m_Favorite; + bool m_Favorite; int m_Latency; // in ms char m_aGameType[16]; char m_aName[64]; @@ -166,9 +166,11 @@ class IServerBrowser : public IInterface virtual const CServerInfo *SortedGet(int FilterIndex, int Index) const = 0; virtual const void *GetID(int FilterIndex, int Index) const = 0; - virtual bool IsFavorite(const NETADDR &Addr) = 0; // todo: remove this - virtual void AddFavorite(const CServerInfo *pEntry) = 0; - virtual void RemoveFavorite(const CServerInfo *pEntry) = 0; + virtual void AddFavorite(const CServerInfo *pInfo) = 0; + virtual void RemoveFavorite(const CServerInfo *pInfo) = 0; + virtual void UpdateFavoriteState(CServerInfo *pInfo) = 0; + virtual void SetFavoritePassword(const char *pAddress, const char *pPassword) = 0; + virtual const char *GetFavoritePassword(const char *pAddress) = 0; virtual int AddFilter(const CServerFilterInfo *pFilterInfo) = 0; virtual void SetFilter(int Index, const CServerFilterInfo *pFilterInfo) = 0; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index c4bcfc9d..72cffe9d 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -30,6 +30,8 @@ MACRO_CONFIG_INT(ClAutoScreenshotMax, cl_auto_screenshot_max, 10, 0, 1000, CFGFL MACRO_CONFIG_INT(ClShowServerBroadcast, cl_show_server_broadcast, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show server broadcast") MACRO_CONFIG_INT(ClColoredBroadcast, cl_colored_broadcast, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable colored server broadcasts") +MACRO_CONFIG_INT(ClSaveServerPasswords, cl_save_server_passwords, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Save passwords of servers you successfully connect to as favorites") + MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string") MACRO_CONFIG_INT(BrSort, br_sort, 4, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sort criterion for the server browser") diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 191ff0be..e0730224 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2085,17 +2085,23 @@ int CMenus::Render() } else if(m_Popup == POPUP_PASSWORD) { - CUIRect EditBox, TryAgain, Abort; + CUIRect Label, EditBox, Save, TryAgain, Abort; - Box.HSplitTop(12.0f, 0, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + Box.HMargin(4.0f, &Box); + + Box.HSplitTop(20.0f, &Label, &Box); + UI()->DoLabel(&Label, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); - Box.HSplitBottom(ButtonHeight*1.7f, 0, &Box); Box.HSplitTop(20.0f, &EditBox, &Box); static float s_OffsetPassword = 0.0f; DoEditBoxOption(g_Config.m_Password, g_Config.m_Password, sizeof(g_Config.m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); + Box.HSplitTop(2.0f, 0, &Box); + Box.HSplitTop(20.0f, &Save, &Box); + if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, Localize("Save password and server as favorite"), g_Config.m_ClSaveServerPasswords, &Save)) + g_Config.m_ClSaveServerPasswords ^= 1; + // buttons BottomBar.VSplitMid(&Abort, &TryAgain); Abort.VSplitRight(SpacingW/2.0f, &Abort, 0); @@ -2670,6 +2676,11 @@ void CMenus::OnStateChange(int NewState, int OldState) m_Popup = POPUP_PASSWORD; UI()->SetHotItem(&g_Config.m_Password); UI()->SetActiveItem(&g_Config.m_Password); + + // reset password stored in favorites if it's invalid + const char *pPassword = ServerBrowser()->GetFavoritePassword(g_Config.m_UiServerAddress); + if(pPassword && str_comp(pPassword, g_Config.m_Password) == 0) + ServerBrowser()->SetFavoritePassword(g_Config.m_UiServerAddress, 0); } else m_Popup = POPUP_DISCONNECTED; @@ -2681,12 +2692,25 @@ void CMenus::OnStateChange(int NewState, int OldState) m_DownloadLastCheckTime = time_get(); m_DownloadLastCheckSize = 0; m_DownloadSpeed = 0.0f; - //client_serverinfo_request(); + + // restore password from favorites + const char *pPassword = ServerBrowser()->GetFavoritePassword(g_Config.m_UiServerAddress); + if(pPassword) + str_copy(g_Config.m_Password, pPassword, sizeof(g_Config.m_Password)); } else if(NewState == IClient::STATE_CONNECTING) m_Popup = POPUP_CONNECTING; else if (NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK) { + if(NewState == IClient::STATE_ONLINE && g_Config.m_ClSaveServerPasswords && g_Config.m_Password[0]) + { + // store password and server as favorite, but only if the server was actually password protected + CServerInfo ServerInfo = {0}; + Client()->GetServerInfo(&ServerInfo); + if(ServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD) + ServerBrowser()->SetFavoritePassword(g_Config.m_UiServerAddress, g_Config.m_Password); + } + m_Popup = POPUP_NONE; SetActive(false); } diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 70584622..29a12dc7 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -398,7 +398,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Password"), CurrentServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD ? Localize("Yes", "With") : Localize("No", "Without/None")); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - const bool IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr); + const bool IsFavorite = CurrentServerInfo.m_Favorite; ServerInfo.HSplitBottom(ButtonHeight, &ServerInfo, &Label); static int s_AddFavButton = 0; if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Label)) From ca333d3625827a65589db52a63dc99074d1c43b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 24 Jan 2020 12:21:12 +0100 Subject: [PATCH 048/479] change message to 'save password' if already favorite --- src/engine/client/serverbrowser.cpp | 3 ++- src/game/client/components/menus.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 9f44b7d5..51a3ff9d 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -375,7 +375,8 @@ void CServerBrowser::RemoveFavorite(const CServerInfo *pInfo) void CServerBrowser::UpdateFavoriteState(CServerInfo *pInfo) { - pInfo->m_Favorite = m_ServerBrowserFavorites.FindFavoriteByAddr(pInfo->m_NetAddr, 0) != 0; + pInfo->m_Favorite = m_ServerBrowserFavorites.FindFavoriteByAddr(pInfo->m_NetAddr, 0) != 0 + || m_ServerBrowserFavorites.FindFavoriteByHostname(pInfo->m_aHostname, 0) != 0; } void CServerBrowser::SetFavoritePassword(const char *pAddress, const char *pPassword) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index e0730224..1e295b37 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2093,13 +2093,16 @@ int CMenus::Render() UI()->DoLabel(&Label, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); Box.HSplitTop(20.0f, &EditBox, &Box); - static float s_OffsetPassword = 0.0f; DoEditBoxOption(g_Config.m_Password, g_Config.m_Password, sizeof(g_Config.m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); Box.HSplitTop(2.0f, 0, &Box); Box.HSplitTop(20.0f, &Save, &Box); - if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, Localize("Save password and server as favorite"), g_Config.m_ClSaveServerPasswords, &Save)) + CServerInfo ServerInfo = {0}; + str_copy(ServerInfo.m_aHostname, g_Config.m_UiServerAddress, sizeof(ServerInfo.m_aHostname)); + ServerBrowser()->UpdateFavoriteState(&ServerInfo); + const char *pSaveText = ServerInfo.m_Favorite ? Localize("Save password") : Localize("Save password and server as favorite"); + if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, pSaveText, g_Config.m_ClSaveServerPasswords, &Save)) g_Config.m_ClSaveServerPasswords ^= 1; // buttons From eb6aee75f1e515d879377f51357e4969036917a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 24 Jan 2020 12:23:01 +0100 Subject: [PATCH 049/479] simplify boolean assignment if statement --- src/game/client/components/menus.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 1e295b37..c3db568a 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2726,10 +2726,7 @@ void CMenus::OnRender() UI()->StartCheck(); // reset cursor - if(m_CursorActive) - m_PrevCursorActive = true; - else - m_PrevCursorActive = false; + m_PrevCursorActive = m_CursorActive; m_CursorActive = false; if(m_KeyReaderIsActive) From 73fd801e81e0a1f3d7af73307b689b166541e790 Mon Sep 17 00:00:00 2001 From: def Date: Fri, 28 Mar 2014 22:47:57 +0100 Subject: [PATCH 050/479] Preview when loading PNGs in editor (cherry picked from commit https://github.com/ddnet/ddnet/commit/f2dccafd4e5880f918d4f9e9702b2ac17edc49e3) --- src/game/editor/editor.cpp | 41 ++++++++++++++++++++++++++++++++++++++ src/game/editor/editor.h | 3 +++ 2 files changed, 44 insertions(+) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index d662c70a..649808a3 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3127,6 +3127,7 @@ void CEditor::AddFileDialogEntry(int Index, CUIRect *pView) else m_aFileDialogFileName[0] = 0; m_FilesSelectedIndex = Index; + m_FilePreviewImage = 0; if(Input()->MouseDoubleClick()) m_aFileDialogActivate = true; @@ -3138,6 +3139,7 @@ void CEditor::RenderFileDialog() // GUI coordsys Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); CUIRect View = *UI()->Screen(); + CUIRect Preview; float Width = View.w, Height = View.h; RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.25f), 0, 0); @@ -3156,6 +3158,8 @@ void CEditor::RenderFileDialog() View.HSplitBottom(14.0f, &View, &FileBox); FileBox.VSplitLeft(55.0f, &FileBoxLabel, &FileBox); View.HSplitBottom(10.0f, &View, 0); // some spacing + if (m_FileDialogFileType == CEditor::FILETYPE_IMG) + View.VSplitMid(&View, &Preview); View.VSplitRight(15.0f, &View, &Scroll); // title @@ -3253,8 +3257,43 @@ void CEditor::RenderFileDialog() else m_aFileDialogFileName[0] = 0; m_FilesSelectedIndex = NewIndex; + m_FilePreviewImage = 0; } } + + if (m_FileDialogFileType == CEditor::FILETYPE_IMG && m_FilePreviewImage == 0 && m_FilesSelectedIndex > -1) + { + char aBuffer[1024]; + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_FileList[m_FilesSelectedIndex].m_aFilename); + + if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, IStorage::TYPE_ALL)) + { + m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, m_FilePreviewImageInfo.m_Format, IGraphics::TEXLOAD_NORESAMPLE); + mem_free(m_FilePreviewImageInfo.m_pData); + } + } + if (m_FilePreviewImage) + { + int w = m_FilePreviewImageInfo.m_Width; + int h = m_FilePreviewImageInfo.m_Height; + if (m_FilePreviewImageInfo.m_Width > Preview.w) + { + h = m_FilePreviewImageInfo.m_Height * Preview.w / m_FilePreviewImageInfo.m_Width; + w = Preview.w; + } + if (h > Preview.h) + { + w = w * Preview.h / h, + h = Preview.h; + } + + Graphics()->TextureSet(m_FilePreviewImage); + Graphics()->BlendNormal(); + Graphics()->QuadsBegin(); + IGraphics::CQuadItem QuadItem(Preview.x, Preview.y, w, h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } } for(int i = 0; i < Input()->NumEvents(); i++) @@ -3399,6 +3438,7 @@ void CEditor::FilelistPopulate(int StorageType) } Storage()->ListDirectory(StorageType, m_pFileDialogPath, EditorListdirCallback, this); m_FilesSelectedIndex = m_FileList.size() ? 0 : -1; + m_FilePreviewImage = 0; m_aFileDialogActivate = false; } @@ -3420,6 +3460,7 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle m_FileDialogScrollValue = 0.0f; m_FilesSearchBoxID = 0; UI()->SetActiveItem(&m_FilesSearchBoxID); + m_FilePreviewImage = 0; if(pDefaultName) str_copy(m_aFileDialogFileName, pDefaultName, sizeof(m_aFileDialogFileName)); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 1cc7568e..46c50b55 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -675,6 +675,9 @@ class CEditor : public IEditor char m_FileDialogNewFolderName[64]; char m_FileDialogErrString[64]; float m_FilesSearchBoxID; + int m_FilePreviewImage; + CImageInfo m_FilePreviewImageInfo; + struct CFilelistItem { From 19c6395f41f0239d349289a0b61d8a4df769b347 Mon Sep 17 00:00:00 2001 From: def Date: Tue, 28 Oct 2014 22:54:24 +0100 Subject: [PATCH 051/479] Don't try to load preview images of directories (cherry picked from commit https://github.com/ddnet/ddnet/commit/0b1118938d411c752da8defbc5e6d68f10bfc723) --- src/game/editor/editor.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 649808a3..7a630e23 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3263,13 +3263,17 @@ void CEditor::RenderFileDialog() if (m_FileDialogFileType == CEditor::FILETYPE_IMG && m_FilePreviewImage == 0 && m_FilesSelectedIndex > -1) { - char aBuffer[1024]; - str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_FileList[m_FilesSelectedIndex].m_aFilename); - - if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, IStorage::TYPE_ALL)) + int Length = str_length(m_FileList[m_FilesSelectedIndex].m_aFilename); + if (Length >= 4 && !str_comp(m_FileList[m_FilesSelectedIndex].m_aFilename+Length-4, ".png")) { - m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, m_FilePreviewImageInfo.m_Format, IGraphics::TEXLOAD_NORESAMPLE); - mem_free(m_FilePreviewImageInfo.m_pData); + char aBuffer[1024]; + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_FileList[m_FilesSelectedIndex].m_aFilename); + + if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, IStorage::TYPE_ALL)) + { + m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, m_FilePreviewImageInfo.m_Format, IGraphics::TEXLOAD_NORESAMPLE); + mem_free(m_FilePreviewImageInfo.m_pData); + } } } if (m_FilePreviewImage) From 9980ef0d776287b6d4df975cf8963ec9a42102f6 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 24 Jan 2020 21:01:25 +0100 Subject: [PATCH 052/479] Use texture handle for mapres preview https://github.com/ddnet/ddnet/commit/6a6a5f00c9ad632def305f6418efbe5a029d6fce#diff-84a9f7becf198e6130d1b6d2710123dcL4156-R4520 --- src/game/editor/editor.cpp | 13 +++++++------ src/game/editor/editor.h | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 7a630e23..f0c5df76 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3127,7 +3127,7 @@ void CEditor::AddFileDialogEntry(int Index, CUIRect *pView) else m_aFileDialogFileName[0] = 0; m_FilesSelectedIndex = Index; - m_FilePreviewImage = 0; + m_PreviewImageIsLoaded = false; if(Input()->MouseDoubleClick()) m_aFileDialogActivate = true; @@ -3257,11 +3257,11 @@ void CEditor::RenderFileDialog() else m_aFileDialogFileName[0] = 0; m_FilesSelectedIndex = NewIndex; - m_FilePreviewImage = 0; + m_PreviewImageIsLoaded = false; } } - if (m_FileDialogFileType == CEditor::FILETYPE_IMG && m_FilePreviewImage == 0 && m_FilesSelectedIndex > -1) + if (m_FileDialogFileType == CEditor::FILETYPE_IMG && !m_PreviewImageIsLoaded && m_FilesSelectedIndex > -1) { int Length = str_length(m_FileList[m_FilesSelectedIndex].m_aFilename); if (Length >= 4 && !str_comp(m_FileList[m_FilesSelectedIndex].m_aFilename+Length-4, ".png")) @@ -3273,10 +3273,11 @@ void CEditor::RenderFileDialog() { m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, m_FilePreviewImageInfo.m_Format, IGraphics::TEXLOAD_NORESAMPLE); mem_free(m_FilePreviewImageInfo.m_pData); + m_PreviewImageIsLoaded = true; } } } - if (m_FilePreviewImage) + if (m_PreviewImageIsLoaded) { int w = m_FilePreviewImageInfo.m_Width; int h = m_FilePreviewImageInfo.m_Height; @@ -3442,7 +3443,7 @@ void CEditor::FilelistPopulate(int StorageType) } Storage()->ListDirectory(StorageType, m_pFileDialogPath, EditorListdirCallback, this); m_FilesSelectedIndex = m_FileList.size() ? 0 : -1; - m_FilePreviewImage = 0; + m_PreviewImageIsLoaded = false; m_aFileDialogActivate = false; } @@ -3464,7 +3465,7 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle m_FileDialogScrollValue = 0.0f; m_FilesSearchBoxID = 0; UI()->SetActiveItem(&m_FilesSearchBoxID); - m_FilePreviewImage = 0; + m_PreviewImageIsLoaded = false; if(pDefaultName) str_copy(m_aFileDialogFileName, pDefaultName, sizeof(m_aFileDialogFileName)); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 46c50b55..f7433677 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -675,7 +675,8 @@ class CEditor : public IEditor char m_FileDialogNewFolderName[64]; char m_FileDialogErrString[64]; float m_FilesSearchBoxID; - int m_FilePreviewImage; + IGraphics::CTextureHandle m_FilePreviewImage; + bool m_PreviewImageIsLoaded; CImageInfo m_FilePreviewImageInfo; From 77b9fcc2bd2c035463eb40fedac667da67bfe06a Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 24 Jan 2020 20:49:19 +0100 Subject: [PATCH 053/479] Add automapper for jungle_deathtiles --- CMakeLists.txt | 1 + datasrc/editor/automap/jungle_deathtiles.json | 308 ++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100644 datasrc/editor/automap/jungle_deathtiles.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 90799032..34f9c8a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -884,6 +884,7 @@ set(EXPECTED_DATA editor/automap/desert_main.json editor/automap/grass_doodads.json editor/automap/grass_main.json + editor/automap/jungle_deathtiles.json editor/automap/jungle_main.json editor/automap/winter_main.json editor/background.png diff --git a/datasrc/editor/automap/jungle_deathtiles.json b/datasrc/editor/automap/jungle_deathtiles.json new file mode 100644 index 00000000..a990dab4 --- /dev/null +++ b/datasrc/editor/automap/jungle_deathtiles.json @@ -0,0 +1,308 @@ +{"tileset": [ + {"single horizontal": + { + "comment": "| vertical", + "basetile": 17, + + "rules": [ + { + "comment": "| reset flags", + "index": 17, + "condition": [ + {"x": 0, "y": 0, "value": "full"} + ], + "rotate": 0, + "hflip": 0, + "vflip": 0 + }, + { + "comment": "^ top spike", + "index": 1, + "condition": [ + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"} + ] + }, + { + "comment": "v bottom spike", + "index": 1, + "condition": [ + {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"} + ], + "vflip": 1 + }, + { + "comment": "- horizontal", + "index": 34, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "full"} + ] + }, + { + "comment": "> right spike", + "index": 33, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "empty"} + ], + "hflip": 1 + }, + { + "comment": "< left spike", + "index": 33, + "condition": [ + {"x": -1, "y": 0, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"} + ] + }, + { + "comment": "+ connector cross", + "index": 16, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "full"}, + {"x": 1, "y": -1, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 1, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"}, + {"x": -1, "y": 1, "value": "empty"} + ] + }] + } + },{"single vertical": + { + "comment": "| vertical", + "basetile": 17, + + "rules": [ + { + "comment": "| reset flags", + "index": 17, + "condition": [ + {"x": 0, "y": 0, "value": "full"} + ], + "rotate": 0, + "hflip": 0, + "vflip": 0 + }, + { + "comment": "> right spike", + "index": 33, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} + ], + "hflip": 1 + }, + { + "comment": "< left spike", + "index": 33, + "condition": [ + {"x": -1, "y": 0, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} + ] + }, + { + "comment": "^ top spike", + "index": 1, + "condition": [ + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"} + ] + }, + { + "comment": "bottom spike", + "index": 1, + "condition": [ + {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"} + ], + "vflip": 1 + }, + { + "comment": "- horizontal", + "index": 34, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} + ] + }, + { + "comment": "+ connector cross", + "index": 16, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "full"}, + {"x": 1, "y": -1, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 1, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"}, + {"x": -1, "y": 1, "value": "empty"} + ] + }] + } + }, + {"double horizontal": + { + "comment": "||", + "basetile": 21, + + "rules": [ + { + "comment": "|| reset flags", + "index": 21, + "condition": [ + {"x": 0, "y": 0, "value": "full"} + ], + "rotate": 0, + "hflip": 0, + "vflip": 0 + }, + { + "comment": "^ top spike", + "index": 5, + "condition": [ + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"} + ] + }, + { + "comment": "v bottom spike", + "index": 5, + "condition": [ + {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"} + ], + "vflip": 1 + }, + { + "comment": "= horizontal", + "index": 38, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "full"} + ] + }, + { + "comment": "> right spike", + "index": 37, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "empty"} + ], + "hflip": 1 + }, + { + "comment": "< left spike", + "index": 37, + "condition": [ + {"x": -1, "y": 0, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"} + ] + }, + { + "comment": "# connector cross", + "index": 32, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "full"}, + {"x": 1, "y": -1, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 1, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"}, + {"x": -1, "y": 1, "value": "empty"} + ] + }] + } + },{"double vertical": + { + "comment": "||", + "basetile": 21, + + "rules": [ + { + "comment": "= reset flags", + "index": 21, + "condition": [ + {"x": 0, "y": 0, "value": "full"} + ], + "rotate": 0, + "hflip": 0, + "vflip": 0 + }, + { + "comment": "> right spike", + "index": 37, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} + ], + "hflip": 1 + }, + { + "comment": "< left spike", + "index": 37, + "condition": [ + {"x": -1, "y": 0, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} + ] + }, + { + "comment": "^ top spike", + "index": 5, + "condition": [ + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"} + ] + }, + { + "comment": "v bottom spike", + "index": 5, + "condition": [ + {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": 1, "value": "empty"} + ], + "vflip": 1 + }, + { + "comment": "= horizontal", + "index": 38, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} + ] + }, + { + "comment": "# connector cross", + "index": 32, + "condition": [ + {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "full"}, + {"x": 1, "y": -1, "value": "empty"}, + {"x": 1, "y": 0, "value": "full"}, + {"x": 1, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "full"}, + {"x": -1, "y": 1, "value": "empty"} + ] + }] + } + }] +} From 414bfaf2e1492100af5f9a8366fb78567e04f965 Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 25 Jan 2020 08:21:27 +0100 Subject: [PATCH 054/479] Remove unused z-coordinate from vertex --- src/engine/client/backend_sdl.cpp | 8 ++++---- src/engine/client/graphics_threaded.cpp | 5 ----- src/engine/client/graphics_threaded.h | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 9f472a7d..90a6ebe0 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -246,7 +246,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St // 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); + glOrtho(State.m_ScreenTL.x, State.m_ScreenBR.x, State.m_ScreenBR.y, State.m_ScreenTL.y, -1.0f, 1.0f); } void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand) @@ -445,9 +445,9 @@ void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand { SetState(pCommand->m_State); - glVertexPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices); - glTexCoordPointer(3, 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)*6); + glVertexPointer(2, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices); + glTexCoordPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*2); + 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); diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 412a3498..40591230 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -640,7 +640,6 @@ void CGraphics_Threaded::QuadsDraw(CQuadItem *pArray, int 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"); @@ -793,10 +792,6 @@ int CGraphics_Threaded::Init() 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-1; i++) diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index c4c4b16f..bb035d05 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -118,7 +118,7 @@ class CCommandBuffer BLEND_ADDITIVE, }; - struct SPoint { float x, y, z; }; + struct SPoint { float x, y; }; struct STexCoord { float u, v, i; }; struct SColor { float r, g, b, a; }; From 6d5e85b929a6960054ac5c414231ef72c8cdf358 Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 25 Jan 2020 08:38:23 +0100 Subject: [PATCH 055/479] Fix texture memory usage info --- src/engine/client/backend_sdl.cpp | 19 ++++++++++++------- src/engine/client/graphics_threaded.cpp | 3 +++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 9f472a7d..91e04838 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -252,6 +252,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand) { m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage; + *m_pTextureMemoryUsage = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize); glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_Max3DTexSize); dbg_msg("render", "opengl max texture sizes: %d, %d(3D)", m_MaxTexSize, m_Max3DTexSize); @@ -357,10 +358,11 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer:: // 2D texture if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE2D) { + bool Mipmaps = !(pCommand->m_Flags&CCommandBuffer::TEXFLAG_NOMIPMAPS); glGenTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex2D); m_aTextures[pCommand->m_Slot].m_State |= CTexture::STATE_TEX2D; glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot].m_Tex2D); - if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_NOMIPMAPS) + if(!Mipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -378,13 +380,16 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer:: // calculate memory usage m_aTextures[pCommand->m_Slot].m_MemSize = Width*Height*pCommand->m_PixelSize; - int TexWidth = Width; - int TexHeight = Height; - while(TexWidth > 2 && TexHeight > 2) + if(Mipmaps) { - TexWidth>>=1; - TexHeight>>=1; - m_aTextures[pCommand->m_Slot].m_MemSize += TexWidth*TexHeight*pCommand->m_PixelSize; + int TexWidth = Width; + int TexHeight = Height; + while(TexWidth > 2 && TexHeight > 2) + { + TexWidth>>=1; + TexHeight>>=1; + m_aTextures[pCommand->m_Slot].m_MemSize += TexWidth*TexHeight*pCommand->m_PixelSize; + } } } diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 412a3498..a0994c92 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -305,6 +305,9 @@ static int ImageFormatToPixelSize(int Format) int CGraphics_Threaded::LoadTextureRawSub(CTextureHandle TextureID, int x, int y, int Width, int Height, int Format, const void *pData) { + if(!TextureID.IsValid()) + return 0; + CCommandBuffer::SCommand_Texture_Update Cmd; Cmd.m_Slot = TextureID.Id(); Cmd.m_X = x; From e71315e42dc0e6a15908bf583057e8d6965ccf77 Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 25 Jan 2020 09:07:55 +0100 Subject: [PATCH 056/479] Fix clipping in nested scroll-regions --- src/game/client/components/menus.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 191ff0be..86b0a35a 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2929,7 +2929,18 @@ void CMenus::BeginScrollRegion(CScrollRegion* pSr, CUIRect* pClipRect, vec2* pOu if(pSr->m_Params.m_ClipBgColor.a > 0) RenderTools()->DrawRoundRect(pClipRect, pSr->m_Params.m_ClipBgColor, 4.0f); - UI()->ClipEnable(pClipRect); + CUIRect ClipRect = *pClipRect; + if(pSr->m_WasClipped) + { + CUIRect Intersection; + Intersection.x = max(ClipRect.x, pSr->m_OldClipRect.x); + Intersection.y = max(ClipRect.y, pSr->m_OldClipRect.y); + Intersection.w = min(ClipRect.x+ClipRect.w, pSr->m_OldClipRect.x+pSr->m_OldClipRect.w) - ClipRect.x; + Intersection.h = min(ClipRect.y+ClipRect.h, pSr->m_OldClipRect.y+pSr->m_OldClipRect.h) - ClipRect.y; + ClipRect = Intersection; + } + + UI()->ClipEnable(&ClipRect); pSr->m_ClipRect = *pClipRect; pSr->m_ContentH = 0; From ad84456490378a083cf20fa39006c30f7429f4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Jan 2020 14:02:24 +0100 Subject: [PATCH 057/479] use favorite pass without overriding global, make saving more configurable --- src/engine/client/client.cpp | 40 +++++++++++++++++++++++++--- src/engine/client/client.h | 2 ++ src/engine/shared/config_variables.h | 2 +- src/game/client/components/menus.cpp | 27 ++++--------------- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index a7728d06..1ae200f6 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -299,6 +299,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_State = IClient::STATE_OFFLINE; m_aServerAddressStr[0] = 0; + m_aServerPassword[0] = 0; mem_zero(m_aSnapshots, sizeof(m_aSnapshots)); m_SnapshotStorage.Init(); @@ -338,9 +339,15 @@ int CClient::SendMsg(CMsgPacker *pMsg, int Flags) void CClient::SendInfo() { + // restore password of favorite if possible + const char *pPassword = m_ServerBrowser.GetFavoritePassword(m_aServerAddressStr); + if(!pPassword) + pPassword = g_Config.m_Password; + str_copy(m_aServerPassword, pPassword, sizeof(m_aServerPassword)); + CMsgPacker Msg(NETMSG_INFO, true); Msg.AddString(GameClient()->NetVersion(), 128); - Msg.AddString(g_Config.m_Password, 128); + Msg.AddString(m_aServerPassword, 128); Msg.AddInt(GameClient()->ClientVersion()); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); } @@ -454,7 +461,11 @@ void CClient::SetState(int s) } m_State = s; if(Old != s) + { GameClient()->OnStateChange(m_State, Old); + if(s == IClient::STATE_ONLINE) + OnClientOnline(); + } } // called when the map is loaded and we should init for a new round @@ -490,6 +501,20 @@ void CClient::EnterGame() OnEnterGame(); } +void CClient::OnClientOnline() +{ + DemoRecorder_HandleAutoStart(); + + // store password and server as favorite if configured, if the server was password protected + CServerInfo Info = {0}; + GetServerInfo(&Info); + bool ShouldStorePassword = g_Config.m_ClSaveServerPasswords == 2 || (g_Config.m_ClSaveServerPasswords == 1 && Info.m_Favorite); + if(m_aServerPassword[0] && ShouldStorePassword && (Info.m_Flags&IServerBrowser::FLAG_PASSWORD)) + { + m_ServerBrowser.SetFavoritePassword(m_aServerAddressStr, m_aServerPassword); + } +} + void CClient::Connect(const char *pAddress) { char aBuf[512]; @@ -536,6 +561,14 @@ void CClient::DisconnectWithReason(const char *pReason) m_DemoPlayer.Stop(); DemoRecorder_Stop(); + // reset password stored in favorites if it's invalid + if(pReason && str_find_nocase(pReason, "password")) + { + const char *pPassword = m_ServerBrowser.GetFavoritePassword(m_aServerAddressStr); + if(pPassword && str_comp(pPassword, m_aServerPassword) == 0) + m_ServerBrowser.SetFavoritePassword(m_aServerAddressStr, 0); + } + // m_RconAuthed = 0; m_UseTempRconCommands = 0; @@ -558,6 +591,8 @@ void CClient::DisconnectWithReason(const char *pReason) // clear the current server info mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo)); mem_zero(&m_ServerAddress, sizeof(m_ServerAddress)); + m_aServerAddressStr[0] = 0; + m_aServerPassword[0] = 0; // clear snapshots m_aSnapshots[SNAP_CURRENT] = 0; @@ -1474,7 +1509,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst; m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast; SetState(IClient::STATE_ONLINE); - DemoRecorder_HandleAutoStart(); } // adjust game time @@ -1515,7 +1549,7 @@ void CClient::PumpNetwork() if(State() != IClient::STATE_OFFLINE && State() != IClient::STATE_QUITING && m_NetClient.State() == NETSTATE_OFFLINE) { SetState(IClient::STATE_OFFLINE); - Disconnect(); + DisconnectWithReason(m_NetClient.ErrorString()); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "offline error='%s'", m_NetClient.ErrorString()); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index afd3739f..fdad37b0 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -82,6 +82,7 @@ class CClient : public IClient, public CDemoPlayer::IListner class CMapChecker m_MapChecker; char m_aServerAddressStr[256]; + char m_aServerPassword[128]; unsigned m_SnapshotParts; int64 m_LocalStartTime; @@ -234,6 +235,7 @@ class CClient : public IClient, public CDemoPlayer::IListner // called when the map is loaded and we should init for a new round void OnEnterGame(); virtual void EnterGame(); + void OnClientOnline(); virtual void Connect(const char *pAddress); void DisconnectWithReason(const char *pReason); diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 72cffe9d..29996757 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -30,7 +30,7 @@ MACRO_CONFIG_INT(ClAutoScreenshotMax, cl_auto_screenshot_max, 10, 0, 1000, CFGFL MACRO_CONFIG_INT(ClShowServerBroadcast, cl_show_server_broadcast, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show server broadcast") MACRO_CONFIG_INT(ClColoredBroadcast, cl_colored_broadcast, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable colored server broadcasts") -MACRO_CONFIG_INT(ClSaveServerPasswords, cl_save_server_passwords, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Save passwords of servers you successfully connect to as favorites") +MACRO_CONFIG_INT(ClSaveServerPasswords, cl_save_server_passwords, 1, 0, 2, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Save server passwords (0 = never, 1 = only favorites, 2 = all servers)") MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string") diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c3db568a..baf45742 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2101,9 +2101,11 @@ int CMenus::Render() CServerInfo ServerInfo = {0}; str_copy(ServerInfo.m_aHostname, g_Config.m_UiServerAddress, sizeof(ServerInfo.m_aHostname)); ServerBrowser()->UpdateFavoriteState(&ServerInfo); - const char *pSaveText = ServerInfo.m_Favorite ? Localize("Save password") : Localize("Save password and server as favorite"); - if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, pSaveText, g_Config.m_ClSaveServerPasswords, &Save)) - g_Config.m_ClSaveServerPasswords ^= 1; + const bool Favorite = ServerInfo.m_Favorite; + const int OnValue = Favorite ? 1 : 2; + const char *pSaveText = Favorite ? Localize("Save password") : Localize("Save password and server as favorite"); + if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, pSaveText, g_Config.m_ClSaveServerPasswords == OnValue, &Save)) + g_Config.m_ClSaveServerPasswords = g_Config.m_ClSaveServerPasswords == OnValue ? 0 : OnValue; // buttons BottomBar.VSplitMid(&Abort, &TryAgain); @@ -2679,11 +2681,6 @@ void CMenus::OnStateChange(int NewState, int OldState) m_Popup = POPUP_PASSWORD; UI()->SetHotItem(&g_Config.m_Password); UI()->SetActiveItem(&g_Config.m_Password); - - // reset password stored in favorites if it's invalid - const char *pPassword = ServerBrowser()->GetFavoritePassword(g_Config.m_UiServerAddress); - if(pPassword && str_comp(pPassword, g_Config.m_Password) == 0) - ServerBrowser()->SetFavoritePassword(g_Config.m_UiServerAddress, 0); } else m_Popup = POPUP_DISCONNECTED; @@ -2695,25 +2692,11 @@ void CMenus::OnStateChange(int NewState, int OldState) m_DownloadLastCheckTime = time_get(); m_DownloadLastCheckSize = 0; m_DownloadSpeed = 0.0f; - - // restore password from favorites - const char *pPassword = ServerBrowser()->GetFavoritePassword(g_Config.m_UiServerAddress); - if(pPassword) - str_copy(g_Config.m_Password, pPassword, sizeof(g_Config.m_Password)); } else if(NewState == IClient::STATE_CONNECTING) m_Popup = POPUP_CONNECTING; else if (NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK) { - if(NewState == IClient::STATE_ONLINE && g_Config.m_ClSaveServerPasswords && g_Config.m_Password[0]) - { - // store password and server as favorite, but only if the server was actually password protected - CServerInfo ServerInfo = {0}; - Client()->GetServerInfo(&ServerInfo); - if(ServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD) - ServerBrowser()->SetFavoritePassword(g_Config.m_UiServerAddress, g_Config.m_Password); - } - m_Popup = POPUP_NONE; SetActive(false); } From 4af1b7af8a0a97b46ab7b48c397bde7f6c91f733 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sat, 25 Jan 2020 14:24:49 +0100 Subject: [PATCH 058/479] Apply preview mapres fixes from review Thanks to @Robyt3 @axblk and @oy --- src/game/editor/editor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index f0c5df76..a41a0b7f 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3264,13 +3264,14 @@ void CEditor::RenderFileDialog() if (m_FileDialogFileType == CEditor::FILETYPE_IMG && !m_PreviewImageIsLoaded && m_FilesSelectedIndex > -1) { int Length = str_length(m_FileList[m_FilesSelectedIndex].m_aFilename); - if (Length >= 4 && !str_comp(m_FileList[m_FilesSelectedIndex].m_aFilename+Length-4, ".png")) + if (Length >= 4 && str_endswith_nocase(m_FileList[m_FilesSelectedIndex].m_aFilename, ".png")) { char aBuffer[1024]; str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_FileList[m_FilesSelectedIndex].m_aFilename); - if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, IStorage::TYPE_ALL)) + if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, m_FileList[m_FilesSelectedIndex].m_StorageType)) { + Graphics()->UnloadTexture(&m_FilePreviewImage); m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, m_FilePreviewImageInfo.m_Format, IGraphics::TEXLOAD_NORESAMPLE); mem_free(m_FilePreviewImageInfo.m_pData); m_PreviewImageIsLoaded = true; From 455e305f476676296539e259b9d4124004163c1d Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 25 Jan 2020 14:33:56 +0100 Subject: [PATCH 059/479] Race: differentiate between personal and map record --- datasrc/network.py | 4 +++- src/game/client/components/infomessages.cpp | 16 ++++++++++------ src/game/client/components/infomessages.h | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/datasrc/network.py b/datasrc/network.py index 820f09a7..8b77f903 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -5,6 +5,7 @@ Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"]) Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"]) # todo 0.8: add RUN_OP, RUN_KICK, RUN_SPEC; rem UNKNOWN ChatModes = Enum("CHAT", ["NONE", "ALL", "TEAM", "WHISPER"]) +RaceRecordTypes = Enum("RECORDTYPE", ["NONE", "PLAYER", "MAP"]) PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING", "BOT"]) GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL", "RACE"]) @@ -68,6 +69,7 @@ Emoticons, Votes, ChatModes, + RaceRecordTypes, GameMsgIDs, ] @@ -452,7 +454,7 @@ NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'), NetIntRange("m_Time", -1, 'max_int'), NetIntAny("m_Diff"), - NetBool("m_NewRecord"), + NetEnum("m_RecordType", RaceRecordTypes) ]), NetMessage("Sv_Checkpoint", [ diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index 9db0687f..10d1cb82 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -97,9 +97,13 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) str_format(aBuf, sizeof(aBuf), "%2d: %s: finished in %s", pMsg->m_ClientID, m_pClient->m_aClients[pMsg->m_ClientID].m_aName, aTime); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "race", aBuf); - if(pMsg->m_NewRecord) + if(pMsg->m_RecordType != RECORDTYPE_NONE) { - str_format(aBuf, sizeof(aBuf), Localize("'%s' has set a new record: %s"), aLabel, aTime); + if(pMsg->m_RecordType == RECORDTYPE_MAP) + str_format(aBuf, sizeof(aBuf), Localize("'%s' has set a new map record: %s"), aLabel, aTime); + else // RECORDTYPE_PLAYER + str_format(aBuf, sizeof(aBuf), Localize("'%s' has set a new personal record: %s"), aLabel, aTime); + if(pMsg->m_Diff < 0) { char aImprovement[64]; @@ -113,7 +117,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) if(m_pClient->m_Snap.m_pGameDataRace && m_pClient->m_Snap.m_pGameDataRace->m_RaceFlags&RACEFLAG_FINISHMSG_AS_CHAT) { - if(!pMsg->m_NewRecord) // don't print the time twice + if(pMsg->m_RecordType == RECORDTYPE_NONE) // don't print the time twice { str_format(aBuf, sizeof(aBuf), Localize("'%s' finished in: %s"), aLabel, aTime); m_pClient->m_pChat->AddLine(aBuf); @@ -128,7 +132,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Finish.m_Time = pMsg->m_Time; Finish.m_Diff = pMsg->m_Diff; - Finish.m_NewRecord = pMsg->m_NewRecord; + Finish.m_RecordType = pMsg->m_RecordType; AddInfoMsg(INFOMSG_FINISH, Finish); } @@ -285,7 +289,7 @@ void CInfoMessages::RenderFinishMsg(const CInfoMsg *pInfoMsg, float x, float y) float TimeW = TextRender()->TextWidth(0, FontSize, aTime, -1, -1.0f); x -= TimeW; - if(pInfoMsg->m_NewRecord) + if(pInfoMsg->m_RecordType != RECORDTYPE_NONE) TextRender()->TextColor(0.2f, 0.6f, 1.0f, 1.0f); TextRender()->Text(0, x, y, FontSize, aTime, -1); @@ -312,6 +316,6 @@ void CInfoMessages::RenderFinishMsg(const CInfoMsg *pInfoMsg, float x, float y) x -= 28.0f; // render player tee - int Emote = pInfoMsg->m_NewRecord ? EMOTE_HAPPY : EMOTE_NORMAL; + int Emote = pInfoMsg->m_RecordType != RECORDTYPE_NONE ? EMOTE_HAPPY : EMOTE_NORMAL; RenderTools()->RenderTee(CAnimState::GetIdle(), &pInfoMsg->m_Player1RenderInfo, Emote, vec2(-1,0), vec2(x, y+28)); } diff --git a/src/game/client/components/infomessages.h b/src/game/client/components/infomessages.h index 4f4cdf62..69a4dc86 100644 --- a/src/game/client/components/infomessages.h +++ b/src/game/client/components/infomessages.h @@ -30,7 +30,7 @@ class CInfoMessages : public CComponent // finish msg int m_Time; int m_Diff; - bool m_NewRecord; + int m_RecordType; }; enum From 07f0b1c95b5708c2e8d879ccf04dfb2ada03e47d Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 25 Jan 2020 15:28:39 +0100 Subject: [PATCH 060/479] Use different colors for player and map record --- src/game/client/components/infomessages.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index 10d1cb82..cceae606 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -289,8 +289,10 @@ void CInfoMessages::RenderFinishMsg(const CInfoMsg *pInfoMsg, float x, float y) float TimeW = TextRender()->TextWidth(0, FontSize, aTime, -1, -1.0f); x -= TimeW; - if(pInfoMsg->m_RecordType != RECORDTYPE_NONE) + if(pInfoMsg->m_RecordType == RECORDTYPE_PLAYER) TextRender()->TextColor(0.2f, 0.6f, 1.0f, 1.0f); + else if(pInfoMsg->m_RecordType == RECORDTYPE_MAP) + TextRender()->TextColor(1.0f, 0.5f, 0.0f, 1.0f); TextRender()->Text(0, x, y, FontSize, aTime, -1); x -= 52.0f + 10.0f; From d1140b0cae9fb71814b007c3cd568eada7485499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 00:27:39 +0100 Subject: [PATCH 061/479] move listbox, refactor+move scrollregion, sync browser selection with address --- src/game/client/components/menus.cpp | 406 +----------------- src/game/client/components/menus.h | 195 ++++----- src/game/client/components/menus_browser.cpp | 334 ++++++++------ src/game/client/components/menus_ingame.cpp | 18 +- src/game/client/components/menus_listbox.cpp | 217 ++++++++++ .../client/components/menus_scrollregion.cpp | 201 +++++++++ src/game/client/components/menus_settings.cpp | 22 +- 7 files changed, 752 insertions(+), 641 deletions(-) create mode 100644 src/game/client/components/menus_listbox.cpp create mode 100644 src/game/client/components/menus_scrollregion.cpp diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c31db28c..ffbbf3db 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -44,9 +44,14 @@ CMenus::CMenus() m_NextPopup = POPUP_NONE; m_ActivePage = PAGE_INTERNET; m_GamePage = PAGE_GAME; + m_SidebarTab = 0; m_SidebarActive = true; m_ShowServerDetails = true; + m_LastBrowserType = -1; + m_LastServerAddress[0] = '\0'; + for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) + m_aSelectedFilters[Type] = 0; m_NeedRestartGraphics = false; m_NeedRestartSound = false; @@ -84,10 +89,6 @@ CMenus::CMenus() m_aCallvoteReason[0] = 0; m_aFilterString[0] = 0; - m_SelectedFilter = 0; - - m_SelectedServer.m_Filter = -1; - m_SelectedServer.m_Index = -1; m_ActiveListBox = ACTLB_NONE; } @@ -944,213 +945,6 @@ void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, RenderTools()->DrawUIRect(&Slider, SliderColor, CUI::CORNER_ALL, Slider.h/2.0f); } - -CMenus::CListBox::CListBox(CMenus *pMenus) -{ - m_pMenus = pMenus; - m_ScrollOffset = vec2(0,0); - m_ListBoxUpdateScroll = false; - m_aFilterString[0] = '\0'; - m_OffsetFilter = 0.0f; -} - -void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, - float HeaderHeight, float Spacing) -{ - CUIRect Header; - CUIRect View = *pRect; - - // background - const float Height = m_pMenus->GetListHeaderHeight(); - View.HSplitTop(Height+Spacing, &Header, 0); - m_pMenus->RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); - - // draw header - View.HSplitTop(Height, &Header, &View); - Header.y += 2.0f; - m_pMenus->UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - - View.HSplitTop(Spacing, &Header, &View); - - // setup the variables - m_ListBoxView = View; -} - -bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) -{ - CUIRect Filter; - CUIRect View = m_ListBoxView; - - // background - View.HSplitTop(FilterHeight+Spacing, &Filter, 0); - m_pMenus->RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); - - // draw filter - View.HSplitTop(FilterHeight, &Filter, &View); - Filter.Margin(Spacing, &Filter); - - float FontSize = Filter.h*ms_FontmodHeight*0.8f; - - CUIRect Label, EditBox; - Filter.VSplitLeft(Filter.w/5.0f, &Label, &EditBox); - Label.y += Spacing; - m_pMenus->UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); - bool Changed = m_pMenus->DoEditBox(m_aFilterString, &EditBox, m_aFilterString, sizeof(m_aFilterString), FontSize, &m_OffsetFilter); - - View.HSplitTop(Spacing, &Filter, &View); - - m_ListBoxView = View; - - return Changed; -} - -void CMenus::CListBox::DoStart(float RowHeight, - const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, - const CUIRect *pRect, bool Background, bool *pActive) -{ - CUIRect View; - if(pRect) - View = *pRect; - else - View = m_ListBoxView; - CUIRect Footer; - - // background - if(Background) - m_pMenus->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - - // draw footers - if(pBottomText) - { - const float Height = m_pMenus->GetListHeaderHeight(); - View.HSplitBottom(Height, &View, &Footer); - Footer.VSplitLeft(10.0f, 0, &Footer); - Footer.y += 2.0f; - m_pMenus->UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - } - - // setup the variables - m_ListBoxView = View; - m_ListBoxSelectedIndex = SelectedIndex; - m_ListBoxNewSelected = SelectedIndex; - m_ListBoxNewSelOffset = 0; - m_ListBoxItemIndex = 0; - m_ListBoxRowHeight = RowHeight; - m_ListBoxNumItems = NumItems; - m_ListBoxItemsPerRow = ItemsPerRow; - m_ListBoxDoneEvents = 0; - m_ListBoxItemActivated = false; - - // handle input - if(!pActive || *pActive) - { - if(m_pMenus->m_DownArrowPressed) - m_ListBoxNewSelOffset += 1; - if(m_pMenus->m_UpArrowPressed) - m_ListBoxNewSelOffset -= 1; - } - - // setup the scrollbar - m_ScrollOffset = vec2(0, 0); - m_pMenus->BeginScrollRegion(&m_ScrollRegion, &m_ListBoxView, &m_ScrollOffset); - m_ListBoxView.y += m_ScrollOffset.y; -} - -CMenus::CListboxItem CMenus::CListBox::DoNextRow() -{ - static CUIRect s_RowView; - CListboxItem Item = {0}; - - if(m_ListBoxItemIndex%m_ListBoxItemsPerRow == 0) - m_ListBoxView.HSplitTop(m_ListBoxRowHeight /*-2.0f*/, &s_RowView, &m_ListBoxView); - m_pMenus->ScrollRegionAddRect(&m_ScrollRegion, s_RowView); - if(m_ListBoxUpdateScroll && m_ListBoxSelectedIndex == m_ListBoxItemIndex) - { - m_pMenus->ScrollRegionScrollHere(&m_ScrollRegion, CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); - m_ListBoxUpdateScroll = false; - } - - s_RowView.VSplitLeft(s_RowView.w/(m_ListBoxItemsPerRow-m_ListBoxItemIndex%m_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); - - if(m_ListBoxSelectedIndex == m_ListBoxItemIndex) - Item.m_Selected = 1; - - Item.m_Visible = !m_pMenus->ScrollRegionIsRectClipped(&m_ScrollRegion, Item.m_Rect); - - m_ListBoxItemIndex++; - return Item; -} - -CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) -{ - int ThisItemIndex = m_ListBoxItemIndex; - if(Selected) - { - if(m_ListBoxSelectedIndex == m_ListBoxNewSelected) - m_ListBoxNewSelected = ThisItemIndex; - m_ListBoxSelectedIndex = ThisItemIndex; - } - - CListboxItem Item = DoNextRow(); - static bool s_ItemClicked = false; - - if(Item.m_Visible && m_pMenus->UI()->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) - { - s_ItemClicked = true; - m_ListBoxNewSelected = ThisItemIndex; - if(pActive) - *pActive = true; - } - else - s_ItemClicked = false; - - const bool ProcessInput = !pActive || *pActive; - - // process input, regard selected index - if(m_ListBoxSelectedIndex == ThisItemIndex) - { - if(ProcessInput && !m_ListBoxDoneEvents) - { - m_ListBoxDoneEvents = 1; - - if(m_pMenus->m_EnterPressed || (s_ItemClicked && m_pMenus->Input()->MouseDoubleClick())) - { - m_ListBoxItemActivated = true; - m_pMenus->UI()->SetActiveItem(0); - } - } - - CUIRect r = Item.m_Rect; - m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); - } - /*else*/ if(m_pMenus->UI()->HotItem() == pId) - { - CUIRect r = Item.m_Rect; - m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); - } - - return Item; -} - -int CMenus::CListBox::DoEnd(bool *pItemActivated) -{ - m_pMenus->EndScrollRegion(&m_ScrollRegion); - if(m_ListBoxNewSelOffset != 0 && m_ListBoxSelectedIndex != -1 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) - { - m_ListBoxNewSelected = clamp(m_ListBoxNewSelected + m_ListBoxNewSelOffset, 0, m_ListBoxNumItems - 1); - m_ListBoxUpdateScroll = true; - } - if(pItemActivated) - *pItemActivated = m_ListBoxItemActivated; - return m_ListBoxNewSelected; -} - -bool CMenus::CListBox::FilterMatches(const char *pNeedle) -{ - return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); -} - - int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier) { // process @@ -2199,13 +1993,13 @@ int CMenus::Render() else if(m_Popup == POPUP_COUNTRY) { // selected filter - CBrowserFilter *pFilter = &m_lFilters[m_SelectedFilter]; + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); CServerFilterInfo FilterInfo; pFilter->GetFilter(&FilterInfo); - static int ActSelection = -2; - if(ActSelection == -2) - ActSelection = FilterInfo.m_Country; + static int s_ActSelection = -2; + if(s_ActSelection == -2) + s_ActSelection = FilterInfo.m_Country; static CListBox s_ListBox(this); int OldSelected = -1; s_ListBox.DoStart(40.0f, 0, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); @@ -2215,7 +2009,7 @@ int CMenus::Render() const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->GetByIndex(i); if(pEntry->m_Blocked) continue; - if(pEntry->m_CountryCode == ActSelection) + if(pEntry->m_CountryCode == s_ActSelection) OldSelected = i; CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected == i); @@ -2248,21 +2042,21 @@ int CMenus::Render() const int NewSelected = s_ListBox.DoEnd(0); if(OldSelected != NewSelected) - ActSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; + s_ActSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; Part.VMargin(120.0f, &Part); static CButtonContainer s_ButtonCountry; if(DoButton_Menu(&s_ButtonCountry, pButtonText, 0, &BottomBar) || m_EnterPressed) { - FilterInfo.m_Country = ActSelection; + FilterInfo.m_Country = s_ActSelection; pFilter->SetFilter(&FilterInfo); m_Popup = POPUP_NONE; } if(m_EscapePressed) { - ActSelection = FilterInfo.m_Country; + s_ActSelection = FilterInfo.m_Country; m_Popup = POPUP_NONE; } } @@ -2904,177 +2698,3 @@ void CMenus::SetMenuPage(int NewPage) m_pClient->m_pCamera->ChangePosition(CameraPos); } } - - -void CMenus::BeginScrollRegion(CScrollRegion* pSr, CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams) -{ - if(pParams) - pSr->m_Params = *pParams; - - pSr->m_WasClipped = UI()->IsClipped(); - pSr->m_OldClipRect = *UI()->ClipArea(); - - const bool ContentOverflows = pSr->m_ContentH > pClipRect->h; - const bool ForceShowScrollbar = pSr->m_Params.m_Flags&CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; - - CUIRect ScrollBarBg; - CUIRect* pModifyRect = (ContentOverflows || ForceShowScrollbar) ? pClipRect : 0; - pClipRect->VSplitRight(pSr->m_Params.m_ScrollbarWidth, pModifyRect, &ScrollBarBg); - ScrollBarBg.Margin(pSr->m_Params.m_ScrollbarMargin, &pSr->m_RailRect); - - // only show scrollbar if required - if(ContentOverflows || ForceShowScrollbar) - { - if(pSr->m_Params.m_ScrollbarBgColor.a > 0) - RenderTools()->DrawRoundRect(&ScrollBarBg, pSr->m_Params.m_ScrollbarBgColor, 4.0f); - if(pSr->m_Params.m_RailBgColor.a > 0) - RenderTools()->DrawRoundRect(&pSr->m_RailRect, pSr->m_Params.m_RailBgColor, pSr->m_RailRect.w/2.0f); - } - if(!ContentOverflows) - pSr->m_ContentScrollOff.y = 0; - - if(pSr->m_Params.m_ClipBgColor.a > 0) - RenderTools()->DrawRoundRect(pClipRect, pSr->m_Params.m_ClipBgColor, 4.0f); - - CUIRect ClipRect = *pClipRect; - if(pSr->m_WasClipped) - { - CUIRect Intersection; - Intersection.x = max(ClipRect.x, pSr->m_OldClipRect.x); - Intersection.y = max(ClipRect.y, pSr->m_OldClipRect.y); - Intersection.w = min(ClipRect.x+ClipRect.w, pSr->m_OldClipRect.x+pSr->m_OldClipRect.w) - ClipRect.x; - Intersection.h = min(ClipRect.y+ClipRect.h, pSr->m_OldClipRect.y+pSr->m_OldClipRect.h) - ClipRect.y; - ClipRect = Intersection; - } - - UI()->ClipEnable(&ClipRect); - - pSr->m_ClipRect = *pClipRect; - pSr->m_ContentH = 0; - *pOutOffset = pSr->m_ContentScrollOff; -} - -void CMenus::EndScrollRegion(CScrollRegion* pSr) -{ - UI()->ClipDisable(); - if(pSr->m_WasClipped) - UI()->ClipEnable(&pSr->m_OldClipRect); - - // only show scrollbar if content overflows - if(pSr->m_ContentH <= pSr->m_ClipRect.h) - return; - - // scroll wheel - CUIRect RegionRect = pSr->m_ClipRect; - RegionRect.w += pSr->m_Params.m_ScrollbarWidth; - if(UI()->MouseInside(&RegionRect)) - { - if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP)) - pSr->m_ScrollY -= pSr->m_Params.m_ScrollSpeed; - else if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN)) - pSr->m_ScrollY += pSr->m_Params.m_ScrollSpeed; - } - - const float SliderHeight = max(pSr->m_Params.m_SliderMinHeight, - pSr->m_ClipRect.h/pSr->m_ContentH * pSr->m_RailRect.h); - - CUIRect Slider = pSr->m_RailRect; - Slider.h = SliderHeight; - const float MaxScroll = pSr->m_RailRect.h - SliderHeight; - - if(pSr->m_RequestScrollY >= 0) - { - pSr->m_ScrollY = pSr->m_RequestScrollY/(pSr->m_ContentH - pSr->m_ClipRect.h) * MaxScroll; - pSr->m_RequestScrollY = -1; - } - - pSr->m_ScrollY = clamp(pSr->m_ScrollY, 0.0f, MaxScroll); - Slider.y += pSr->m_ScrollY; - - bool Hovered = false; - bool Grabbed = false; - const void* pID = &pSr->m_ScrollY; - int Inside = UI()->MouseInside(&Slider); - - if(Inside) - { - UI()->SetHotItem(pID); - - if(!UI()->CheckActiveItem(pID) && UI()->MouseButtonClicked(0)) - { - UI()->SetActiveItem(pID); - pSr->m_MouseGrabStart.y = UI()->MouseY(); - } - - Hovered = true; - } - - if(UI()->CheckActiveItem(pID) && !UI()->MouseButton(0)) - UI()->SetActiveItem(0); - - // move slider - if(UI()->CheckActiveItem(pID) && UI()->MouseButton(0)) - { - float my = UI()->MouseY(); - pSr->m_ScrollY += my - pSr->m_MouseGrabStart.y; - pSr->m_MouseGrabStart.y = my; - - Grabbed = true; - } - - pSr->m_ScrollY = clamp(pSr->m_ScrollY, 0.0f, MaxScroll); - pSr->m_ContentScrollOff.y = -pSr->m_ScrollY/MaxScroll * (pSr->m_ContentH - pSr->m_ClipRect.h); - - vec4 SliderColor = pSr->m_Params.m_SliderColor; - if(Grabbed) - SliderColor = pSr->m_Params.m_SliderColorGrabbed; - else if(Hovered) - SliderColor = pSr->m_Params.m_SliderColorHover; - - RenderTools()->DrawRoundRect(&Slider, SliderColor, Slider.w/2.0f); -} - -void CMenus::ScrollRegionAddRect(CScrollRegion* pSr, CUIRect Rect) -{ - vec2 ContentPos = vec2(pSr->m_ClipRect.x, pSr->m_ClipRect.y); - ContentPos.x += pSr->m_ContentScrollOff.x; - ContentPos.y += pSr->m_ContentScrollOff.y; - pSr->m_LastAddedRect = Rect; - pSr->m_ContentH = max(Rect.y + Rect.h - ContentPos.y, pSr->m_ContentH); -} - -void CMenus::ScrollRegionScrollHere(CScrollRegion* pSr, int Option) -{ - const float MinHeight = min(pSr->m_ClipRect.h, pSr->m_LastAddedRect.h); - const float TopScroll = pSr->m_LastAddedRect.y - - (pSr->m_ClipRect.y + pSr->m_ContentScrollOff.y); - - switch(Option) - { - case CScrollRegion::SCROLLHERE_TOP: - pSr->m_RequestScrollY = TopScroll; - break; - - case CScrollRegion::SCROLLHERE_BOTTOM: - pSr->m_RequestScrollY = TopScroll - (pSr->m_ClipRect.h - MinHeight); - break; - - case CScrollRegion::SCROLLHERE_KEEP_IN_VIEW: - default: { - const float dy = pSr->m_LastAddedRect.y - pSr->m_ClipRect.y; - - if(dy < 0) - pSr->m_RequestScrollY = TopScroll; - else if(dy > (pSr->m_ClipRect.h-MinHeight)) - pSr->m_RequestScrollY = TopScroll - (pSr->m_ClipRect.h - MinHeight); - } break; - } -} - -bool CMenus::ScrollRegionIsRectClipped(CScrollRegion* pSr, const CUIRect& Rect) -{ - return (pSr->m_ClipRect.x > (Rect.x + Rect.w) - || (pSr->m_ClipRect.x + pSr->m_ClipRect.w) < Rect.x - || pSr->m_ClipRect.y > (Rect.y + Rect.h) - || (pSr->m_ClipRect.y + pSr->m_ClipRect.h) < Rect.y); -} diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 4f986485..daf39c7f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -114,41 +115,26 @@ class CMenus : public CComponent int DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect); - /*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - */ - int DoIcon(int ImageId, int SpriteId, const CUIRect *pRect); void DoIconColor(int ImageId, int SpriteId, const CUIRect *pRect, const vec4& Color); int DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect); - // int DoButton_GridHeaderIcon(CButtonContainer *pBC, int ImageID, int SpriteID, const CUIRect *pRect, int Corners); - - //static void ui_draw_browse_icon(int what, const CUIRect *r); - //static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - /*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra); - static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - */ bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false); void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite=false); float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive); void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue); - //static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false); float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current); float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current); void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active); void DoButton_KeySelect(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect); int DoKeyReader(CButtonContainer *pPC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier); - - //static int ui_do_key_reader(void *id, const CUIRect *rect, int key); void UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing); + + // Scroll region : found in menus_scrollregion.cpp struct CScrollRegionParams { float m_ScrollbarWidth; @@ -183,8 +169,35 @@ class CMenus : public CComponent } }; - struct CScrollRegion + /* + Usage: + -- Initialization -- + static CScrollRegion s_ScrollRegion(this); + vec2 ScrollOffset(0, 0); + s_ScrollRegion.Begin(&ScrollRegionRect, &ScrollOffset); + Content = ScrollRegionRect; + Content.y += ScrollOffset.y; + + -- "Register" your content rects -- + CUIRect Rect; + Content.HSplitTop(SomeValue, &Rect, &Content); + s_ScrollRegion.AddRect(Rect); + + -- [Optionnal] Knowing if a rect is clipped -- + s_ScrollRegion.IsRectClipped(Rect); + + -- [Optionnal] Scroll to a rect (to the last added rect)-- + ... + s_ScrollRegion.AddRect(Rect); + s_ScrollRegion.ScrollHere(Option); + + -- End -- + s_ScrollRegion.End(); + */ + class CScrollRegion { + private: + CMenus *m_pMenus; float m_ScrollY; float m_ContentH; float m_RequestScrollY; // [0, ContentHeight] @@ -197,58 +210,23 @@ class CMenus : public CComponent bool m_WasClipped; CScrollRegionParams m_Params; + public: enum { SCROLLHERE_KEEP_IN_VIEW=0, SCROLLHERE_TOP, SCROLLHERE_BOTTOM, }; - CScrollRegion() - { - m_ScrollY = 0; - m_ContentH = 0; - m_RequestScrollY = -1; - m_ContentScrollOff = vec2(0,0); - m_WasClipped = false; - m_Params = CScrollRegionParams(); - } + CScrollRegion(CMenus *pMenus); + void Begin(CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams = 0); + void End(); + void AddRect(CUIRect Rect); + void ScrollHere(int Option = CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + bool IsRectClipped(const CUIRect& Rect) const; + bool IsScrollbarShown() const; }; - // Scroll region - /* - - Usage: - -- Initialization -- - static CScrollRegion s_ScrollRegion; - vec2 ScrollOffset(0, 0); - BeginScrollRegion(&s_ScrollRegion, &ScrollRegionRect, &ScrollOffset); - Content = ScrollRegionRect; - Content.y += ScrollOffset.y; - - -- "Register" your content rects -- - CUIRect Rect; - Content.HSplitTop(SomeValue, &Rect, &Content); - ScrollRegionAddRect(&s_ScrollRegion, Rect); - - -- [Optionnal] Knowing if a rect is clipped -- - ScrollRegionIsRectClipped(&s_ScrollRegion, Rect); - - -- [Optionnal] Scroll to a rect (to the last added rect)-- - ... - ScrollRegionAddRect(&s_ScrollRegion, Rect); - ScrollRegionScrollHere(&s_ScrollRegion, Option); - - -- End -- - EndScrollRegion(&s_ScrollRegion); - - */ - - void BeginScrollRegion(CScrollRegion* pSr, CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams = 0); - void EndScrollRegion(CScrollRegion* pSr); - void ScrollRegionAddRect(CScrollRegion* pSr, CUIRect Rect); - void ScrollRegionScrollHere(CScrollRegion* pSr, int Option = CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); - bool ScrollRegionIsRectClipped(CScrollRegion* pSr, const CUIRect& Rect); - + // Listbox : found in menus_listbox.cpp struct CListboxItem { int m_Visible; @@ -289,6 +267,7 @@ class CMenus : public CComponent bool FilterMatches(const char *pNeedle); }; + enum { POPUP_NONE=0, @@ -342,9 +321,6 @@ class CMenus : public CComponent int m_MenuPage; int m_MenuPageOld; bool m_MenuActive; - int m_SidebarTab; - bool m_SidebarActive; - bool m_ShowServerDetails; bool m_UseMouseButtons; vec2 m_MousePos; vec2 m_PrevMousePos; @@ -511,10 +487,7 @@ class CMenus : public CComponent if(!m_aName[0] && Other.m_aName[0]) return false; int Result = str_comp_nocase(m_aName, Other.m_aName); - if(Result < 0 || (Result == 0 && str_comp_nocase(m_aClan, Other.m_aClan) < 0)) - return true; - - return false; + return Result < 0 || (Result == 0 && str_comp_nocase(m_aClan, Other.m_aClan) < 0); } }; @@ -530,20 +503,21 @@ class CMenus : public CComponent void FriendlistOnUpdate(); + + // server browser class CBrowserFilter { bool m_Extended; int m_Custom; char m_aName[64]; int m_Filter; - class IServerBrowser *m_pServerBrowser; + IServerBrowser *m_pServerBrowser; - static class CServerFilterInfo ms_FilterStandard; - static class CServerFilterInfo ms_FilterFavorites; - static class CServerFilterInfo ms_FilterAll; + static CServerFilterInfo ms_FilterStandard; + static CServerFilterInfo ms_FilterFavorites; + static CServerFilterInfo ms_FilterAll; public: - enum { FILTER_CUSTOM=0, @@ -551,9 +525,11 @@ class CMenus : public CComponent FILTER_STANDARD, FILTER_FAVORITES, }; + // buttons var int m_SwitchButton; int m_aButtonID[3]; + int m_aSelectedServers[IServerBrowser::NUM_TYPES]; CBrowserFilter() {} CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser); @@ -567,17 +543,17 @@ class CMenus : public CComponent int NumSortedServers() const; int NumPlayers() const; - const CServerInfo *SortedGet(int Index) const; - const void *ID(int Index) const; + const CServerInfo* SortedGet(int Index) const; + const CServerInfo* SortedGetSelected() const; + const void* ID(int Index) const; void Reset(); - void GetFilter(class CServerFilterInfo *pFilterInfo) const; - void SetFilter(const class CServerFilterInfo *pFilterInfo); + void GetFilter(CServerFilterInfo *pFilterInfo) const; + void SetFilter(const CServerFilterInfo *pFilterInfo); }; array m_lFilters; - int m_SelectedFilter; int m_RemoveFilterIndex; void LoadFilters(); @@ -605,20 +581,21 @@ class CMenus : public CComponent CInfoOverlay m_InfoOverlay; bool m_InfoOverlayActive; - class CServerEntry + struct CColumn { - public: - int m_Filter; - int m_Index; + int m_ID; + int m_Sort; + CLocConstString m_Caption; + int m_Direction; + float m_Width; + int m_Flags; + CUIRect m_Rect; + CUIRect m_Spacer; + CUI::EAlignment m_Align; }; - CServerEntry m_SelectedServer; - enum { - FIXED=1, - SPACER=2, - COL_BROWSER_FLAG=0, COL_BROWSER_NAME, COL_BROWSER_GAMETYPE, @@ -628,21 +605,35 @@ class CMenus : public CComponent NUM_BROWSER_COLS, }; - struct CColumn + int m_SidebarTab; + bool m_SidebarActive; + bool m_ShowServerDetails; + int m_LastBrowserType; + int m_aSelectedFilters[IServerBrowser::NUM_TYPES]; + char m_LastServerAddress[sizeof(g_Config.m_UiServerAddress)]; + static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; + + CBrowserFilter* GetSelectedBrowserFilter() { - int m_ID; - int m_Sort; - CLocConstString m_Caption; - int m_Direction; - float m_Width; - int m_Flags; - CUIRect m_Rect; - CUIRect m_Spacer; - CUI::EAlignment m_Align; - }; + const int Tab = ServerBrowser()->GetType(); + if(m_aSelectedFilters[Tab] == -1) + return NULL; + return &m_lFilters[m_aSelectedFilters[Tab]]; + } + + const CServerInfo* GetSelectedServerInfo() + { + CBrowserFilter* pSelectedFilter = GetSelectedBrowserFilter(); + if(pSelectedFilter == NULL) + return NULL; + return pSelectedFilter->SortedGetSelected(); + } + + void UpdateServerBrowserAddress(); + void ServerBrowserFilterOnUpdate(); - static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; + // video settings enum { MAX_RESOLUTIONS=256, @@ -668,8 +659,6 @@ class CMenus : public CComponent // found in menus.cpp int Render(); - //void render_background(); - //void render_loading(float percent); void RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); void RenderBackButton(CUIRect MainView); @@ -695,7 +684,6 @@ class CMenus : public CComponent bool RenderServerControlServer(CUIRect MainView); // found in menus_browser.cpp - // int m_ScrollOffset; void RenderServerbrowserServerList(CUIRect View); void RenderServerbrowserSidebar(CUIRect View); void RenderServerbrowserFriendTab(CUIRect View); @@ -705,7 +693,6 @@ class CMenus : public CComponent void RenderDetailInfo(CUIRect View, const CServerInfo *pInfo); void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor = vec4(1,1,1,1)); void RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pInfo); - //void RenderServerbrowserFriends(CUIRect View); void RenderServerbrowserBottomBox(CUIRect View); void RenderServerbrowserOverlay(); void RenderFilterHeader(CUIRect View, int FilterIndex); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 71af4781..d1e2c1e9 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -43,6 +43,8 @@ CMenus::CBrowserFilter::CBrowserFilter(int Custom, const char* pName, IServerBro { m_Extended = false; m_Custom = Custom; + for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) + m_aSelectedServers[Type] = -1; str_copy(m_aName, pName, sizeof(m_aName)); m_pServerBrowser = pServerBrowser; switch(m_Custom) @@ -66,13 +68,13 @@ void CMenus::CBrowserFilter::Reset() switch(m_Custom) { case CBrowserFilter::FILTER_STANDARD: - m_pServerBrowser->SetFilter(m_Filter, &ms_FilterStandard); + SetFilter(&ms_FilterStandard); break; case CBrowserFilter::FILTER_FAVORITES: - m_pServerBrowser->SetFilter(m_Filter, &ms_FilterFavorites); + SetFilter(&ms_FilterFavorites); break; default: - m_pServerBrowser->SetFilter(m_Filter, &ms_FilterAll); + SetFilter(&ms_FilterAll); } } @@ -116,13 +118,18 @@ int CMenus::CBrowserFilter::NumPlayers() const return m_pServerBrowser->NumSortedPlayers(m_Filter); } -const CServerInfo *CMenus::CBrowserFilter::SortedGet(int Index) const +const CServerInfo* CMenus::CBrowserFilter::SortedGet(int Index) const { if(Index < 0 || Index >= m_pServerBrowser->NumSortedServers(m_Filter)) return 0; return m_pServerBrowser->SortedGet(m_Filter, Index); } +const CServerInfo* CMenus::CBrowserFilter::SortedGetSelected() const +{ + return SortedGet(m_aSelectedServers[m_pServerBrowser->GetType()]); +} + void CMenus::CBrowserFilter::SetFilterNum(int Num) { m_Filter = Num; @@ -665,7 +672,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Button, EditButtons; - if(UI()->DoButtonLogic(&m_lFilters[FilterIndex], "", 0, &View)) + if(UI()->DoButtonLogic(pFilter, "", 0, &View)) { Switch = true; // switch later, to make sure we haven't clicked one of the filter buttons (edit...) } @@ -984,7 +991,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(i+1 < NUM_BROWSER_COLS) { - //Cols[i].flags |= SPACER; Headers.VSplitLeft(2, &ms_aBrowserCols[i].m_Spacer, &Headers); } } @@ -1050,93 +1056,145 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) RenderTools()->DrawUIRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.05f), CUI::CORNER_ALL, 5.0f); } - // display important messages in the middle of the screen so no user misses it - { - CUIRect MsgBox = View; - MsgBox.y += View.h/3; + const int BrowserType = ServerBrowser()->GetType(); + int ToBeSelectedFilter = -1; + int ToBeSelectedServer = -1; + bool AddressChanged = str_comp(m_LastServerAddress, g_Config.m_UiServerAddress) != 0; // only update selection based on address if it changed + bool ClearAddressIfNotFound = false; + bool ScrollToSelection = false; - if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) - UI()->DoLabel(&MsgBox, Localize("Refreshing master servers"), 16.0f, CUI::ALIGN_CENTER); - else if(!ServerBrowser()->NumServers()) - UI()->DoLabel(&MsgBox, Localize("No servers found"), 16.0f, CUI::ALIGN_CENTER); - /*else if(ServerBrowser()->NumServers() && !NumServers) - UI()->DoLabel(&MsgBox, Localize("No servers match your filter criteria"), 16.0f, CUI::ALIGN_CENTER);*/ + if(BrowserType != m_LastBrowserType) + { + // restore selected filter and server when changing browser page + m_LastBrowserType = BrowserType; + ToBeSelectedFilter = m_aSelectedFilters[BrowserType]; + if(ToBeSelectedFilter != -1) + { + ScrollToSelection = true; + ToBeSelectedServer = m_lFilters[ToBeSelectedFilter].m_aSelectedServers[BrowserType]; + if(ToBeSelectedServer == -1) + { + AddressChanged = true; + ClearAddressIfNotFound = true; + } + } } - // count all the servers + // count all the servers and update selected filter based on UI state int NumServers = 0; + int SelectedFilter = -1; for(int i = 0; i < m_lFilters.size(); i++) + { + // restore selected filter from browser page + if(ToBeSelectedFilter != -1 && (ToBeSelectedFilter == i) != m_lFilters[i].Extended()) + { + m_lFilters[i].Switch(); + } + if(m_lFilters[i].Extended()) + { + if(SelectedFilter == -1) + { + SelectedFilter = i; + } NumServers += m_lFilters[i].NumSortedServers(); + } + } - int SelectedIndex = m_SelectedServer.m_Index; - int SelectedFilter; - for(SelectedFilter = 0; SelectedFilter < m_lFilters.size(); SelectedFilter++) - if(m_lFilters[SelectedFilter].Extended()) - break; - if(SelectedFilter == m_lFilters.size()) // no selected filter found - SelectedFilter = -1; + if(SelectedFilter != m_aSelectedFilters[BrowserType]) + { + // update stored state based on updated state of UI + m_aSelectedFilters[BrowserType] = SelectedFilter; + ScrollToSelection = true; + UpdateServerBrowserAddress(); + if(SelectedFilter == -1) + { + AddressChanged = true; + ClearAddressIfNotFound = true; + } + } + + const bool CtrlPressed = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL); // handle arrow hotkeys - bool NewSelection = false; if(SelectedFilter > -1) { - int NewIndex = -1; + int SelectedIndex = m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType]; int NewFilter = SelectedFilter; - bool CtrlPressed = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL); + if(m_DownArrowPressed) { if(!CtrlPressed) { - NewIndex = SelectedIndex + 1; - if(NewIndex >= m_lFilters[SelectedFilter].NumSortedServers()) - NewIndex = m_lFilters[SelectedFilter].NumSortedServers() - 1; + ToBeSelectedServer = SelectedIndex + 1; + if(ToBeSelectedServer >= m_lFilters[SelectedFilter].NumSortedServers()) + ToBeSelectedServer = m_lFilters[SelectedFilter].NumSortedServers() - 1; } else if(SelectedFilter + 1 < m_lFilters.size()) { // move to next filter NewFilter = SelectedFilter + 1; - NewIndex = 0; } } else if(m_UpArrowPressed) { if(!CtrlPressed) { - NewIndex = SelectedIndex - 1; - if(NewIndex < 0) - NewIndex = 0; + ToBeSelectedServer = SelectedIndex - 1; + if(ToBeSelectedServer < 0) + ToBeSelectedServer = 0; } else if(SelectedFilter - 1 >= 0) { // move to previous filter NewFilter = SelectedFilter - 1; - NewIndex = 0; } } + if(NewFilter != SelectedFilter) { m_lFilters[NewFilter].Switch(); m_lFilters[SelectedFilter].Switch(); + // try to restore selected server + ToBeSelectedServer = clamp(m_lFilters[NewFilter].m_aSelectedServers[BrowserType], 0, m_lFilters[NewFilter].NumSortedServers()-1); } - if(NewIndex > -1 && NewIndex < m_lFilters[NewFilter].NumSortedServers()) + if(ToBeSelectedServer > -1 && ToBeSelectedServer < m_lFilters[NewFilter].NumSortedServers()) { - m_SelectedServer.m_Filter = NewFilter; - if(m_SelectedServer.m_Index != NewIndex) + m_aSelectedFilters[BrowserType] = NewFilter; + if(m_lFilters[NewFilter].m_aSelectedServers[BrowserType] != ToBeSelectedServer) { - m_SelectedServer.m_Index = NewIndex; + m_lFilters[NewFilter].m_aSelectedServers[BrowserType] = ToBeSelectedServer; m_ShowServerDetails = true; - NewSelection = true; + ScrollToSelection = true; } - const CServerInfo *pItem = ServerBrowser()->SortedGet(NewFilter, NewIndex); - str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); + UpdateServerBrowserAddress(); + } + } + + // display important messages in the middle of the screen so no user misses it + { + const char *pImportantMessage = NULL; + if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) + pImportantMessage = Localize("Refreshing master servers"); + else if(SelectedFilter == -1) + pImportantMessage = Localize("No filter category is selected"); + else if(!ServerBrowser()->NumServers()) + pImportantMessage = Localize("No servers found"); + else if(ServerBrowser()->NumServers() && !NumServers) + pImportantMessage = Localize("No servers match your filter criteria"); + + if(pImportantMessage) + { + CUIRect MsgBox = View; + MsgBox.y += View.h/3; + UI()->DoLabel(&MsgBox, pImportantMessage, 16.0f, CUI::ALIGN_CENTER); } } // scrollbar - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -1144,50 +1202,56 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) ScrollParams.m_SliderMinHeight = 5; ScrollParams.m_ScrollSpeed = 10; View.w += ScrollParams.m_ScrollbarWidth; - BeginScrollRegion(&s_ScrollRegion, &View, &ScrollOffset, &ScrollParams); + s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; - int NumPlayers = ServerBrowser()->NumClients(); - - for(int s = 0; s < m_lFilters.size(); s++) + for(int FilterIndex = 0; FilterIndex < m_lFilters.size(); FilterIndex++) { - CBrowserFilter *pFilter = &m_lFilters[s]; + CBrowserFilter *pFilter = &m_lFilters[FilterIndex]; // filter header CUIRect Row; View.HSplitTop(20.0f, &Row, &View); - ScrollRegionAddRect(&s_ScrollRegion, Row); + s_ScrollRegion.AddRect(Row); // render header - RenderFilterHeader(Row, s); + RenderFilterHeader(Row, FilterIndex); + bool NoMatchingAddressFound = true; // reset selection if server address change and not found if(pFilter->Extended()) { - for (int i = 0; i < pFilter->NumSortedServers(); i++) + for (int ServerIndex = 0; ServerIndex < pFilter->NumSortedServers(); ServerIndex++) { - const CServerInfo *pItem = pFilter->SortedGet(i); + const CServerInfo *pItem = pFilter->SortedGet(ServerIndex); - // select server - if(!str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) + // select server if address changed and match found + bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && pFilter->m_aSelectedServers[BrowserType] == ServerIndex; + if(AddressChanged && !str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) { - if(m_SelectedServer.m_Index != i) // new server selected + if(!IsSelected) + { m_ShowServerDetails = true; - m_SelectedServer.m_Filter = s; - m_SelectedServer.m_Index = i; + m_aSelectedFilters[BrowserType] = FilterIndex; + pFilter->m_aSelectedServers[BrowserType] = ServerIndex; + IsSelected = true; + ScrollToSelection = true; + } + NoMatchingAddressFound = false; } - bool IsSelected = m_SelectedServer.m_Filter == s && m_SelectedServer.m_Index == i; + float ItemHeight = GetListHeaderHeight(); if(!m_SidebarActive && IsSelected && m_ShowServerDetails) - View.HSplitTop(GetListHeaderHeight()*6, &Row, &View); - else - View.HSplitTop(GetListHeaderHeight(), &Row, &View); + { + ItemHeight *= 6.0f; + } + View.HSplitTop(ItemHeight, &Row, &View); - ScrollRegionAddRect(&s_ScrollRegion, Row); - if(IsSelected && NewSelection) // new selection (hotkeys or address input) - ScrollRegionScrollHere(&s_ScrollRegion, CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + s_ScrollRegion.AddRect(Row); + if(IsSelected && ScrollToSelection) // new selection (hotkeys or address input) + s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); // make sure that only those in view can be selected - if(!ScrollRegionIsRectClipped(&s_ScrollRegion, Row)) + if(!s_ScrollRegion.IsRectClipped(Row)) { if(IsSelected) { @@ -1205,30 +1269,43 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) continue; } - if(int ReturnValue = DoBrowserEntry(pFilter->ID(i), Row, pItem, pFilter, IsSelected)) + if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected)) { - m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || m_SelectedServer.m_Index != i; // click twice on line => fold server details - m_SelectedServer.m_Filter = s; - m_SelectedServer.m_Index = i; + m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || pFilter->m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details + m_aSelectedFilters[BrowserType] = FilterIndex; + pFilter->m_aSelectedServers[BrowserType] = ServerIndex; + NoMatchingAddressFound = false; if(g_Config.m_UiAutoswitchInfotab) m_SidebarTab = 0; - str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); + UpdateServerBrowserAddress(); if(Input()->MouseDoubleClick()) Client()->Connect(g_Config.m_UiServerAddress); } - + } + + if(AddressChanged && NoMatchingAddressFound) + { + pFilter->m_aSelectedServers[BrowserType] = -1; + if(ClearAddressIfNotFound) + { + g_Config.m_UiServerAddress[0] = '\0'; + } } } - if(s < m_lFilters.size()-1) + if(FilterIndex < m_lFilters.size()-1) View.HSplitTop(SpacingH, &Row, &View); + } - EndScrollRegion(&s_ScrollRegion); + str_copy(m_LastServerAddress, g_Config.m_UiServerAddress, sizeof(m_LastServerAddress)); + + s_ScrollRegion.End(); // bottom float SpacingW = 3.0f; float ButtonWidth = (Status.w/6.0f)-(SpacingW*5.0)/6.0f; + float FontSize = ButtonHeight*ms_FontmodHeight*0.8f; // cut view CUIRect Left, Label, EditBox, Button; @@ -1240,10 +1317,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Label.VSplitLeft(2.0f, 0, &Label); Label.VSplitRight(ButtonWidth*2.0f+SpacingH, &Label, &EditBox); Label.y += 2.0f; - UI()->DoLabel(&Label, Localize("Search:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_LEFT); EditBox.VSplitRight(EditBox.h, &EditBox, &Button); static float s_ClearOffset = 0.0f; - if(DoEditBox(&g_Config.m_BrFilterString, &EditBox, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), ButtonHeight*ms_FontmodHeight*0.8f, &s_ClearOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&g_Config.m_BrFilterString, &EditBox, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) Client()->ServerBrowserUpdate(); // clear button @@ -1262,9 +1339,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Label.VSplitLeft(2.0f, 0, &Label); Label.VSplitRight(ButtonWidth*2.0f+SpacingH, &Label, &EditBox); Label.y += 2.0f; - UI()->DoLabel(&Label, Localize("Host address:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + UI()->DoLabel(&Label, Localize("Host address:"), FontSize, CUI::ALIGN_LEFT); static float s_AddressOffset = 0.0f; - DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), ButtonHeight*ms_FontmodHeight*0.8f, &s_AddressOffset, false, CUI::CORNER_ALL); + DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_AddressOffset, false, CUI::CORNER_ALL); // render status if(ServerBrowser()->IsRefreshing() && m_ActivePage != PAGE_LAN) @@ -1293,12 +1370,12 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) OffsetServer += RenderOffset; if(Num < 10) OffsetServer += RenderOffset; - Num = NumPlayers; - if(Num < 1000) + int NumPlayers = ServerBrowser()->NumClients();; + if(NumPlayers < 1000) OffsetPlayer += RenderOffset; - if(Num < 100) + if(NumPlayers < 100) OffsetPlayer += RenderOffset; - if(Num < 10) + if(NumPlayers < 10) OffsetPlayer += RenderOffset; char aBuf[128]; Status.VSplitLeft(20.0f, 0, &Status); @@ -1430,7 +1507,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) } // scrollbar - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -1438,7 +1515,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) ScrollParams.m_ScrollbarWidth = 14; ScrollParams.m_ScrollbarMargin = 5; ScrollParams.m_ScrollSpeed = 15; - BeginScrollRegion(&s_ScrollRegion, &View, &ScrollOffset, &ScrollParams); + s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; // show lists @@ -1459,7 +1536,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) View.HSplitTop(8.0f + GetListHeaderHeight(), &Rect, &View); else View.HSplitTop(20.0f + GetListHeaderHeight(), &Rect, &View); - ScrollRegionAddRect(&s_ScrollRegion, Rect); + s_ScrollRegion.AddRect(Rect); if(i == FRIEND_PLAYER_ON) RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 1.0f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); else if(i == FRIEND_CLAN_ON) @@ -1535,7 +1612,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) s_ListExtended[i] ^= 1; } } - EndScrollRegion(&s_ScrollRegion); + s_ScrollRegion.End(); // add friend BottomArea.HSplitTop(GetListHeaderHeight(), &Button, &BottomArea); @@ -1606,17 +1683,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) s_aFilterName[0] = 0; } - // slected filter - CBrowserFilter *pFilter = 0; - for(int i = 0; i < m_lFilters.size(); ++i) - { - if(m_lFilters[i].Extended()) - { - pFilter = &m_lFilters[i]; - m_SelectedFilter = i; - break; - } - } + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); if(!pFilter) return; @@ -1677,10 +1744,11 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(DoButton_CheckBox(&s_BrFilterPureMap, Localize("Standard map"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE_MAP, &Button)) NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PURE_MAP; + bool UpdateFilter = false; if(FilterInfo.m_SortHash != NewSortHash) { FilterInfo.m_SortHash = NewSortHash; - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); @@ -1724,7 +1792,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) str_copy(FilterInfo.m_aGametype[j], FilterInfo.m_aGametype[j + 1], sizeof(FilterInfo.m_aGametype[j])); FilterInfo.m_aGametype[j][0] = 0; } - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } Button.VSplitLeft(2.0f, 0, &Button); } @@ -1758,7 +1826,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(!FilterInfo.m_aGametype[i][0]) { str_copy(FilterInfo.m_aGametype[i], s_aGametype, sizeof(FilterInfo.m_aGametype[i])); - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; s_aGametype[0] = 0; break; } @@ -1773,7 +1841,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) { FilterInfo.m_aGametype[i][0] = 0; } - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } if(!NeedScrollbar) @@ -1794,7 +1862,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) Value = LogarithmicScrollbarScale.ToAbsolute(DoScrollbarH(&s_BrFilterPing, &Button, LogarithmicScrollbarScale.ToRelative(Value, Min, Max)), Min, Max); if(Value != FilterInfo.m_Ping) { FilterInfo.m_Ping = Value; - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } } @@ -1806,7 +1874,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) static float OffsetAddr = 0.0f; static int s_BrFilterServerAddress = 0; if(DoEditBox(&s_BrFilterServerAddress, &Button, FilterInfo.m_aAddress, sizeof(FilterInfo.m_aAddress), FontSize, &OffsetAddr)) - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; // player country { @@ -1820,7 +1888,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(DoButton_CheckBox(&s_BrFilterCountry, "", FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY, &Button)) { FilterInfo.m_SortHash ^= IServerBrowser::FILTER_COUNTRY; - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } Rect.w = Rect.h * 2; vec4 Color(1.0f, 1.0f, 1.0f, FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY ? 1.0f : 0.5f); @@ -1843,20 +1911,25 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(DoButton_SpriteID(&s_LevelButton1, IMAGE_LEVELICONS, FilterInfo.IsLevelFiltered(CServerInfo::LEVEL_CASUAL) ? SPRITE_LEVEL_A_B : SPRITE_LEVEL_A_ON, false, &Icon, CUI::CORNER_L, 5.0f, true)) { FilterInfo.ToggleLevel(CServerInfo::LEVEL_CASUAL); - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } Button.VSplitLeft(Button.h, &Icon, &Button); static CButtonContainer s_LevelButton2; if(DoButton_SpriteID(&s_LevelButton2, IMAGE_LEVELICONS, FilterInfo.IsLevelFiltered(CServerInfo::LEVEL_NORMAL) ? SPRITE_LEVEL_B_B : SPRITE_LEVEL_B_ON, false, &Icon, 0, 5.0f, true)) { FilterInfo.ToggleLevel(CServerInfo::LEVEL_NORMAL); - pFilter->SetFilter(&FilterInfo); + UpdateFilter = true; } Button.VSplitLeft(Button.h, &Icon, &Button); static CButtonContainer s_LevelButton3; if(DoButton_SpriteID(&s_LevelButton3, IMAGE_LEVELICONS, FilterInfo.IsLevelFiltered(CServerInfo::LEVEL_COMPETITIVE) ? SPRITE_LEVEL_C_B : SPRITE_LEVEL_C_ON, false, &Icon, CUI::CORNER_R, 5.0f, true)) { FilterInfo.ToggleLevel(CServerInfo::LEVEL_COMPETITIVE); + UpdateFilter = true; + } + + if(UpdateFilter) + { pFilter->SetFilter(&FilterInfo); } @@ -1868,15 +1941,21 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(DoButton_Menu(&s_ResetButton, Localize("Reset filter"), 0, &Button)) { pFilter->Reset(); + UpdateFilter = true; + } + + if(UpdateFilter) + { + ServerBrowserFilterOnUpdate(); } } void CMenus::RenderServerbrowserInfoTab(CUIRect View) { - const CServerInfo *pItem = 0; - if(m_SelectedServer.m_Filter >= 0 && m_SelectedServer.m_Filter < m_lFilters.size()) + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); + if(pFilter) { - pItem = m_lFilters[m_SelectedServer.m_Filter].SortedGet(m_SelectedServer.m_Index); + const CServerInfo *pItem = pFilter->SortedGet(pFilter->m_aSelectedServers[ServerBrowser()->GetType()]); RenderServerbrowserServerDetail(View, pItem); } } @@ -1911,7 +1990,6 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) for(unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++) { - LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn); UI()->DoLabel(&Row, s_aLabels[i], FontSize, CUI::ALIGN_LEFT, Row.w, false); } @@ -1953,17 +2031,7 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor) { - // slected filter - CBrowserFilter *pFilter = 0; - for(int i = 0; i < m_lFilters.size(); ++i) - { - if(m_lFilters[i].Extended()) - { - pFilter = &m_lFilters[i]; - m_SelectedFilter = i; - break; - } - } + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); CServerFilterInfo FilterInfo; if(pFilter) pFilter->GetFilter(&FilterInfo); @@ -1986,7 +2054,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); float LineHeight = 20.0f; - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -1994,7 +2062,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int ScrollParams.m_ScrollbarWidth = 5; ScrollParams.m_ScrollbarMargin = 1; ScrollParams.m_ScrollSpeed = 15; - BeginScrollRegion(&s_ScrollRegion, &View, &ScrollOffset, &ScrollParams); + s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; if(RowCount != 0) { @@ -2026,7 +2094,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int } Row.HSplitTop(LineHeight, &Name, &Row); - ScrollRegionAddRect(&s_ScrollRegion, Name); + s_ScrollRegion.AddRect(Name); RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); // friend @@ -2111,7 +2179,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int ++Count; } - EndScrollRegion(&s_ScrollRegion); + s_ScrollRegion.End(); } } @@ -2291,6 +2359,24 @@ void CMenus::RenderServerbrowser(CUIRect MainView) RenderServerbrowserOverlay(); } +void CMenus::UpdateServerBrowserAddress() +{ + const CServerInfo *pItem = GetSelectedServerInfo(); + if(pItem == NULL) + { + g_Config.m_UiServerAddress[0] = '\0'; + } + else + { + str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); + } +} + +void CMenus::ServerBrowserFilterOnUpdate() +{ + m_LastBrowserType = -1; // enforces update on server address +} + void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 29a12dc7..33c90254 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -230,13 +230,13 @@ void CMenus::RenderPlayers(CUIRect MainView) MainView.Margin(5.0f, &MainView); // prepare scroll - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollSpeed = 15; - if(s_ScrollRegion.m_ContentH > s_ScrollRegion.m_ClipRect.h) // scrollbar is shown + if(s_ScrollRegion.IsScrollbarShown()) Row.VSplitRight(ScrollParams.m_ScrollbarWidth, &Row, 0); // headline @@ -264,7 +264,7 @@ void CMenus::RenderPlayers(CUIRect MainView) // scroll, ignore margins MainView.Margin(-5.0f, &MainView); - BeginScrollRegion(&s_ScrollRegion, &MainView, &ScrollOffset, &ScrollParams); + s_ScrollRegion.Begin(&MainView, &ScrollOffset, &ScrollParams); MainView.Margin(5.0f, &MainView); MainView.y += ScrollOffset.y; @@ -279,7 +279,7 @@ void CMenus::RenderPlayers(CUIRect MainView) continue; MainView.HSplitTop(ButtonHeight, &Row, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, Row); + s_ScrollRegion.AddRect(Row); if(Count++ % 2 == 0) RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -340,7 +340,7 @@ void CMenus::RenderPlayers(CUIRect MainView) } } } - EndScrollRegion(&s_ScrollRegion); + s_ScrollRegion.End(); } void CMenus::RenderServerInfo(CUIRect MainView) @@ -483,9 +483,9 @@ void CMenus::RenderServerInfo(CUIRect MainView) RenderTools()->DrawUIRect(&Motd, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f); Motd.Margin(5.0f, &Motd); - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); - BeginScrollRegion(&s_ScrollRegion, &Motd, &ScrollOffset); + s_ScrollRegion.Begin(&Motd, &ScrollOffset); Motd.y += ScrollOffset.y; CTextCursor Cursor; @@ -496,9 +496,9 @@ void CMenus::RenderServerInfo(CUIRect MainView) // define the MOTD text area and make it scrollable CUIRect MotdTextArea; Motd.HSplitTop(Cursor.m_Y-Motd.y+ButtonHeight*ms_FontmodHeight*0.8f+5.0f, &MotdTextArea, &Motd); - ScrollRegionAddRect(&s_ScrollRegion, MotdTextArea); + s_ScrollRegion.AddRect(MotdTextArea); - EndScrollRegion(&s_ScrollRegion); + s_ScrollRegion.End(); } bool CMenus::RenderServerControlServer(CUIRect MainView) diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp new file mode 100644 index 00000000..364c99d1 --- /dev/null +++ b/src/game/client/components/menus_listbox.cpp @@ -0,0 +1,217 @@ +/* (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 "menus.h" + +CMenus::CListBox::CListBox(CMenus *pMenus) : m_ScrollRegion(pMenus) +{ + m_pMenus = pMenus; + m_ScrollOffset = vec2(0,0); + m_ListBoxUpdateScroll = false; + m_aFilterString[0] = '\0'; + m_OffsetFilter = 0.0f; +} + +void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, + float HeaderHeight, float Spacing) +{ + CUIRect Header; + CUIRect View = *pRect; + + // background + const float Height = m_pMenus->GetListHeaderHeight(); + View.HSplitTop(Height+Spacing, &Header, 0); + m_pMenus->RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); + + // draw header + View.HSplitTop(Height, &Header, &View); + Header.y += 2.0f; + m_pMenus->UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + + View.HSplitTop(Spacing, &Header, &View); + + // setup the variables + m_ListBoxView = View; +} + +bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) +{ + CUIRect Filter; + CUIRect View = m_ListBoxView; + + // background + View.HSplitTop(FilterHeight+Spacing, &Filter, 0); + m_pMenus->RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); + + // draw filter + View.HSplitTop(FilterHeight, &Filter, &View); + Filter.Margin(Spacing, &Filter); + + float FontSize = Filter.h*ms_FontmodHeight*0.8f; + + CUIRect Label, EditBox; + Filter.VSplitLeft(Filter.w/5.0f, &Label, &EditBox); + Label.y += Spacing; + m_pMenus->UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); + bool Changed = m_pMenus->DoEditBox(m_aFilterString, &EditBox, m_aFilterString, sizeof(m_aFilterString), FontSize, &m_OffsetFilter); + + View.HSplitTop(Spacing, &Filter, &View); + + m_ListBoxView = View; + + return Changed; +} + +void CMenus::CListBox::DoStart(float RowHeight, + const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, + const CUIRect *pRect, bool Background, bool *pActive) +{ + CUIRect View; + if(pRect) + View = *pRect; + else + View = m_ListBoxView; + CUIRect Footer; + + // background + if(Background) + m_pMenus->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + // draw footers + if(pBottomText) + { + const float Height = m_pMenus->GetListHeaderHeight(); + View.HSplitBottom(Height, &View, &Footer); + Footer.VSplitLeft(10.0f, 0, &Footer); + Footer.y += 2.0f; + m_pMenus->UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + } + + // setup the variables + m_ListBoxView = View; + m_ListBoxSelectedIndex = SelectedIndex; + m_ListBoxNewSelected = SelectedIndex; + m_ListBoxNewSelOffset = 0; + m_ListBoxItemIndex = 0; + m_ListBoxRowHeight = RowHeight; + m_ListBoxNumItems = NumItems; + m_ListBoxItemsPerRow = ItemsPerRow; + m_ListBoxDoneEvents = 0; + m_ListBoxItemActivated = false; + + // handle input + if(!pActive || *pActive) + { + if(m_pMenus->m_DownArrowPressed) + m_ListBoxNewSelOffset += 1; + if(m_pMenus->m_UpArrowPressed) + m_ListBoxNewSelOffset -= 1; + } + + // setup the scrollbar + m_ScrollOffset = vec2(0, 0); + m_ScrollRegion.Begin(&m_ListBoxView, &m_ScrollOffset); + m_ListBoxView.y += m_ScrollOffset.y; +} + +CMenus::CListboxItem CMenus::CListBox::DoNextRow() +{ + static CUIRect s_RowView; + CListboxItem Item = {0}; + + if(m_ListBoxItemIndex%m_ListBoxItemsPerRow == 0) + m_ListBoxView.HSplitTop(m_ListBoxRowHeight /*-2.0f*/, &s_RowView, &m_ListBoxView); + m_ScrollRegion.AddRect(s_RowView); + if(m_ListBoxUpdateScroll && m_ListBoxSelectedIndex == m_ListBoxItemIndex) + { + m_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + m_ListBoxUpdateScroll = false; + } + + s_RowView.VSplitLeft(s_RowView.w/(m_ListBoxItemsPerRow-m_ListBoxItemIndex%m_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); + + if(m_ListBoxSelectedIndex == m_ListBoxItemIndex) + Item.m_Selected = 1; + + Item.m_Visible = !m_ScrollRegion.IsRectClipped(Item.m_Rect); + + m_ListBoxItemIndex++; + return Item; +} + +CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) +{ + int ThisItemIndex = m_ListBoxItemIndex; + if(Selected) + { + if(m_ListBoxSelectedIndex == m_ListBoxNewSelected) + m_ListBoxNewSelected = ThisItemIndex; + m_ListBoxSelectedIndex = ThisItemIndex; + } + + CListboxItem Item = DoNextRow(); + static bool s_ItemClicked = false; + + if(Item.m_Visible && m_pMenus->UI()->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) + { + s_ItemClicked = true; + m_ListBoxNewSelected = ThisItemIndex; + if(pActive) + *pActive = true; + } + else + s_ItemClicked = false; + + const bool ProcessInput = !pActive || *pActive; + + // process input, regard selected index + if(m_ListBoxSelectedIndex == ThisItemIndex) + { + if(ProcessInput && !m_ListBoxDoneEvents) + { + m_ListBoxDoneEvents = 1; + + if(m_pMenus->m_EnterPressed || (s_ItemClicked && m_pMenus->Input()->MouseDoubleClick())) + { + m_ListBoxItemActivated = true; + m_pMenus->UI()->SetActiveItem(0); + } + } + + CUIRect r = Item.m_Rect; + m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); + } + /*else*/ if(m_pMenus->UI()->HotItem() == pId) + { + CUIRect r = Item.m_Rect; + m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); + } + + return Item; +} + +int CMenus::CListBox::DoEnd(bool *pItemActivated) +{ + m_ScrollRegion.End(); + if(m_ListBoxNewSelOffset != 0 && m_ListBoxSelectedIndex != -1 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) + { + m_ListBoxNewSelected = clamp(m_ListBoxNewSelected + m_ListBoxNewSelOffset, 0, m_ListBoxNumItems - 1); + m_ListBoxUpdateScroll = true; + } + if(pItemActivated) + *pItemActivated = m_ListBoxItemActivated; + return m_ListBoxNewSelected; +} + +bool CMenus::CListBox::FilterMatches(const char *pNeedle) +{ + return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); +} diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp new file mode 100644 index 00000000..d2c194af --- /dev/null +++ b/src/game/client/components/menus_scrollregion.cpp @@ -0,0 +1,201 @@ +/* (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 "menus.h" + +CMenus::CScrollRegion::CScrollRegion(CMenus *pMenus) +{ + m_pMenus = pMenus; + m_ScrollY = 0; + m_ContentH = 0; + m_RequestScrollY = -1; + m_ContentScrollOff = vec2(0,0); + m_WasClipped = false; + m_Params = CScrollRegionParams(); +} + +void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams) +{ + if(pParams) + m_Params = *pParams; + + m_WasClipped = m_pMenus->UI()->IsClipped(); + m_OldClipRect = *m_pMenus->UI()->ClipArea(); + + const bool ContentOverflows = m_ContentH > pClipRect->h; + const bool ForceShowScrollbar = m_Params.m_Flags&CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; + + CUIRect ScrollBarBg; + CUIRect* pModifyRect = (ContentOverflows || ForceShowScrollbar) ? pClipRect : 0; + pClipRect->VSplitRight(m_Params.m_ScrollbarWidth, pModifyRect, &ScrollBarBg); + ScrollBarBg.Margin(m_Params.m_ScrollbarMargin, &m_RailRect); + + // only show scrollbar if required + if(ContentOverflows || ForceShowScrollbar) + { + if(m_Params.m_ScrollbarBgColor.a > 0) + m_pMenus->RenderTools()->DrawRoundRect(&ScrollBarBg, m_Params.m_ScrollbarBgColor, 4.0f); + if(m_Params.m_RailBgColor.a > 0) + m_pMenus->RenderTools()->DrawRoundRect(&m_RailRect, m_Params.m_RailBgColor, m_RailRect.w/2.0f); + } + if(!ContentOverflows) + m_ContentScrollOff.y = 0; + + if(m_Params.m_ClipBgColor.a > 0) + m_pMenus->RenderTools()->DrawRoundRect(pClipRect, m_Params.m_ClipBgColor, 4.0f); + + CUIRect ClipRect = *pClipRect; + if(m_WasClipped) + { + CUIRect Intersection; + Intersection.x = max(ClipRect.x, m_OldClipRect.x); + Intersection.y = max(ClipRect.y, m_OldClipRect.y); + Intersection.w = min(ClipRect.x+ClipRect.w, m_OldClipRect.x+m_OldClipRect.w) - ClipRect.x; + Intersection.h = min(ClipRect.y+ClipRect.h, m_OldClipRect.y+m_OldClipRect.h) - ClipRect.y; + ClipRect = Intersection; + } + + m_pMenus->UI()->ClipEnable(&ClipRect); + + m_ClipRect = *pClipRect; + m_ContentH = 0; + *pOutOffset = m_ContentScrollOff; +} + +void CMenus::CScrollRegion::End() +{ + m_pMenus->UI()->ClipDisable(); + if(m_WasClipped) + m_pMenus->UI()->ClipEnable(&m_OldClipRect); + + // only show scrollbar if content overflows + if(m_ContentH <= m_ClipRect.h) + return; + + // scroll wheel + CUIRect RegionRect = m_ClipRect; + RegionRect.w += m_Params.m_ScrollbarWidth; + if(m_pMenus->UI()->MouseInside(&RegionRect)) + { + if(m_pMenus->Input()->KeyPress(KEY_MOUSE_WHEEL_UP)) + m_ScrollY -= m_Params.m_ScrollSpeed; + else if(m_pMenus->Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN)) + m_ScrollY += m_Params.m_ScrollSpeed; + } + + const float SliderHeight = max(m_Params.m_SliderMinHeight, + m_ClipRect.h/m_ContentH * m_RailRect.h); + + CUIRect Slider = m_RailRect; + Slider.h = SliderHeight; + const float MaxScroll = m_RailRect.h - SliderHeight; + + if(m_RequestScrollY >= 0) + { + m_ScrollY = m_RequestScrollY/(m_ContentH - m_ClipRect.h) * MaxScroll; + m_RequestScrollY = -1; + } + + m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); + Slider.y += m_ScrollY; + + bool Hovered = false; + bool Grabbed = false; + const void* pID = &m_ScrollY; + int Inside = m_pMenus->UI()->MouseInside(&Slider); + + if(Inside) + { + m_pMenus->UI()->SetHotItem(pID); + + if(!m_pMenus->UI()->CheckActiveItem(pID) && m_pMenus->UI()->MouseButtonClicked(0)) + { + m_pMenus->UI()->SetActiveItem(pID); + m_MouseGrabStart.y = m_pMenus->UI()->MouseY(); + } + + Hovered = true; + } + + if(m_pMenus->UI()->CheckActiveItem(pID) && !m_pMenus->UI()->MouseButton(0)) + m_pMenus->UI()->SetActiveItem(0); + + // move slider + if(m_pMenus->UI()->CheckActiveItem(pID) && m_pMenus->UI()->MouseButton(0)) + { + float my = m_pMenus->UI()->MouseY(); + m_ScrollY += my - m_MouseGrabStart.y; + m_MouseGrabStart.y = my; + + Grabbed = true; + } + + m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); + m_ContentScrollOff.y = -m_ScrollY/MaxScroll * (m_ContentH - m_ClipRect.h); + + vec4 SliderColor = m_Params.m_SliderColor; + if(Grabbed) + SliderColor = m_Params.m_SliderColorGrabbed; + else if(Hovered) + SliderColor = m_Params.m_SliderColorHover; + + m_pMenus->RenderTools()->DrawRoundRect(&Slider, SliderColor, Slider.w/2.0f); +} + +void CMenus::CScrollRegion::AddRect(CUIRect Rect) +{ + vec2 ContentPos = vec2(m_ClipRect.x, m_ClipRect.y); + ContentPos.x += m_ContentScrollOff.x; + ContentPos.y += m_ContentScrollOff.y; + m_LastAddedRect = Rect; + m_ContentH = max(Rect.y + Rect.h - ContentPos.y, m_ContentH); +} + +void CMenus::CScrollRegion::ScrollHere(int Option) +{ + const float MinHeight = min(m_ClipRect.h, m_LastAddedRect.h); + const float TopScroll = m_LastAddedRect.y - (m_ClipRect.y + m_ContentScrollOff.y); + + switch(Option) + { + case CScrollRegion::SCROLLHERE_TOP: + m_RequestScrollY = TopScroll; + break; + + case CScrollRegion::SCROLLHERE_BOTTOM: + m_RequestScrollY = TopScroll - (m_ClipRect.h - MinHeight); + break; + + case CScrollRegion::SCROLLHERE_KEEP_IN_VIEW: + default: { + const float dy = m_LastAddedRect.y - m_ClipRect.y; + + if(dy < 0) + m_RequestScrollY = TopScroll; + else if(dy > (m_ClipRect.h-MinHeight)) + m_RequestScrollY = TopScroll - (m_ClipRect.h - MinHeight); + } break; + } +} + +bool CMenus::CScrollRegion::IsRectClipped(const CUIRect& Rect) const +{ + return (m_ClipRect.x > (Rect.x + Rect.w) + || (m_ClipRect.x + m_ClipRect.w) < Rect.x + || m_ClipRect.y > (Rect.y + Rect.h) + || (m_ClipRect.y + m_ClipRect.h) < Rect.y); +} + +bool CMenus::CScrollRegion::IsScrollbarShown() const +{ + return m_ContentH > m_ClipRect.h; +} \ No newline at end of file diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 1508a9a4..f7c64788 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1539,11 +1539,11 @@ void CMenus::RenderSettingsControls(CUIRect MainView) const float HeaderHeight = 20.0f; - static CScrollRegion s_ScrollRegion; + static CScrollRegion s_ScrollRegion(this); vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); - BeginScrollRegion(&s_ScrollRegion, &MainView, &ScrollOffset, &ScrollParams); + s_ScrollRegion.Begin(&MainView, &ScrollOffset, &ScrollParams); MainView.y += ScrollOffset.y; CUIRect LastExpandRect; @@ -1552,51 +1552,51 @@ void CMenus::RenderSettingsControls(CUIRect MainView) float Split = DoIndependentDropdownMenu(&s_MouseDropdown, &MainView, Localize("Mouse"), HeaderHeight, RenderSettingsControlsMouse, &s_MouseActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_JoystickDropdown = 0; static bool s_JoystickActive = m_pClient->Input()->NumJoysticks() > 0; // hide by default if no joystick found Split = DoIndependentDropdownMenu(&s_JoystickDropdown, &MainView, Localize("Joystick"), HeaderHeight, RenderSettingsControlsJoystick, &s_JoystickActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_MovementDropdown = 0; static bool s_MovementActive = true; Split = DoIndependentDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, RenderSettingsControlsMovement, &s_MovementActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_WeaponDropdown = 0; static bool s_WeaponActive = true; Split = DoIndependentDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, RenderSettingsControlsWeapon, &s_WeaponActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_VotingDropdown = 0; static bool s_VotingActive = true; Split = DoIndependentDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, RenderSettingsControlsVoting, &s_VotingActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_ChatDropdown = 0; static bool s_ChatActive = true; Split = DoIndependentDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, RenderSettingsControlsChat, &s_ChatActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_ScoreboardDropdown = 0; static bool s_ScoreboardActive = true; Split = DoIndependentDropdownMenu(&s_ScoreboardDropdown, &MainView, Localize("Scoreboard"), HeaderHeight, RenderSettingsControlsScoreboard, &s_ScoreboardActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); static int s_MiscDropdown = 0; static bool s_MiscActive = true; Split = DoIndependentDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, RenderSettingsControlsMisc, &s_MiscActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); - ScrollRegionAddRect(&s_ScrollRegion, LastExpandRect); + s_ScrollRegion.AddRect(LastExpandRect); - EndScrollRegion(&s_ScrollRegion); + s_ScrollRegion.End(); // reset button float Spacing = 3.0f; From 7c2ffbe9cac96ee0d9d24084cc5c898d63755b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 00:40:54 +0100 Subject: [PATCH 062/479] add added file to CMakeList --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34f9c8a3..fc67fadf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1458,7 +1458,9 @@ if(CLIENT) components/menus_callback.cpp components/menus_demo.cpp components/menus_ingame.cpp + components/menus_listbox.cpp components/menus_popups.cpp + components/menus_scrollregion.cpp components/menus_settings.cpp components/menus_start.cpp components/motd.cpp From 43b4d071196fbb0426012ccbc7c1091c8761dda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 00:43:39 +0100 Subject: [PATCH 063/479] replace tabs with spaces --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc67fadf..4482bbf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1458,9 +1458,9 @@ if(CLIENT) components/menus_callback.cpp components/menus_demo.cpp components/menus_ingame.cpp - components/menus_listbox.cpp + components/menus_listbox.cpp components/menus_popups.cpp - components/menus_scrollregion.cpp + components/menus_scrollregion.cpp components/menus_settings.cpp components/menus_start.cpp components/motd.cpp From 96249a848b5c4d32d1c05c70f3be292a0a0f2af3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 13:55:37 +0100 Subject: [PATCH 064/479] replace NULL with 0 --- src/game/client/components/menus.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index daf39c7f..0280d76a 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -617,16 +617,14 @@ class CMenus : public CComponent { const int Tab = ServerBrowser()->GetType(); if(m_aSelectedFilters[Tab] == -1) - return NULL; + return 0; return &m_lFilters[m_aSelectedFilters[Tab]]; } const CServerInfo* GetSelectedServerInfo() { CBrowserFilter* pSelectedFilter = GetSelectedBrowserFilter(); - if(pSelectedFilter == NULL) - return NULL; - return pSelectedFilter->SortedGetSelected(); + return pSelectedFilter ? pSelectedFilter->SortedGetSelected() : 0; } void UpdateServerBrowserAddress(); From ff221fcd620cc7f7567ebdce4a7709c5d11cc393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 14:07:26 +0100 Subject: [PATCH 065/479] fix reset of last selected filter on initial launch --- src/game/client/components/menus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index ffbbf3db..0d1025dc 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -51,7 +51,7 @@ CMenus::CMenus() m_LastBrowserType = -1; m_LastServerAddress[0] = '\0'; for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) - m_aSelectedFilters[Type] = 0; + m_aSelectedFilters[Type] = -1; m_NeedRestartGraphics = false; m_NeedRestartSound = false; From c7fe8407afff155da8dd33b897fab7d127f9e99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 20:43:45 +0100 Subject: [PATCH 066/479] add documentation for static instances, fix typo --- src/game/client/components/menus.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 0280d76a..518de465 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -183,10 +183,10 @@ class CMenus : public CComponent Content.HSplitTop(SomeValue, &Rect, &Content); s_ScrollRegion.AddRect(Rect); - -- [Optionnal] Knowing if a rect is clipped -- + -- [Optional] Knowing if a rect is clipped -- s_ScrollRegion.IsRectClipped(Rect); - -- [Optionnal] Scroll to a rect (to the last added rect)-- + -- [Optional] Scroll to a rect (to the last added rect)-- ... s_ScrollRegion.AddRect(Rect); s_ScrollRegion.ScrollHere(Option); @@ -194,6 +194,7 @@ class CMenus : public CComponent -- End -- s_ScrollRegion.End(); */ + // Instances of CScrollRegion must be static, as member addresses are used as UI item IDs class CScrollRegion { private: @@ -234,6 +235,7 @@ class CMenus : public CComponent CUIRect m_Rect; }; + // Instances of CListBox must be static, as member addresses are used as UI item IDs class CListBox { private: From a203e01d6e13ae50dd0c41f825b82d872d57500c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Jan 2020 22:44:24 +0100 Subject: [PATCH 067/479] fix address being cleared on start, keep address on filter change, other fixes --- src/game/client/components/menus.cpp | 5 +- src/game/client/components/menus.h | 14 +++- src/game/client/components/menus_browser.cpp | 85 ++++++++++++-------- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0d1025dc..00a1fdab 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -49,9 +49,10 @@ CMenus::CMenus() m_SidebarActive = true; m_ShowServerDetails = true; m_LastBrowserType = -1; - m_LastServerAddress[0] = '\0'; + m_aLastServerAddress[0] = '\0'; + m_AddressSelection = 0; for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) - m_aSelectedFilters[Type] = -1; + m_aSelectedFilters[Type] = -2; m_NeedRestartGraphics = false; m_NeedRestartSound = false; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 518de465..6691f550 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -605,14 +605,20 @@ class CMenus : public CComponent COL_BROWSER_PLAYERS, COL_BROWSER_PING, NUM_BROWSER_COLS, - }; + ADDR_SELECTION_CHANGE = 1, + ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND = 2, + ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND = 4, + ADDR_SELECTION_REVEAL = 8, + ADDR_SELECTION_UPDATE_ADDRESS = 16, + }; int m_SidebarTab; bool m_SidebarActive; bool m_ShowServerDetails; - int m_LastBrowserType; - int m_aSelectedFilters[IServerBrowser::NUM_TYPES]; - char m_LastServerAddress[sizeof(g_Config.m_UiServerAddress)]; + int m_LastBrowserType; // -1 if not initialized + int m_aSelectedFilters[IServerBrowser::NUM_TYPES]; // -1 if none selected, -2 if not initialized + char m_aLastServerAddress[sizeof(g_Config.m_UiServerAddress)]; // a[0] == 0 if not initialized + int m_AddressSelection; static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; CBrowserFilter* GetSelectedBrowserFilter() diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index d1e2c1e9..97a25b62 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1057,27 +1057,30 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } const int BrowserType = ServerBrowser()->GetType(); - int ToBeSelectedFilter = -1; + int ToBeSelectedFilter = -2; // -2 to not restore, -1 to restore all filters closed int ToBeSelectedServer = -1; - bool AddressChanged = str_comp(m_LastServerAddress, g_Config.m_UiServerAddress) != 0; // only update selection based on address if it changed - bool ClearAddressIfNotFound = false; - bool ScrollToSelection = false; + // update selection based on address if it changed + if(!(m_AddressSelection&ADDR_SELECTION_CHANGE) && m_aLastServerAddress[0] && str_comp(m_aLastServerAddress, g_Config.m_UiServerAddress) != 0) + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_REVEAL; + else if(ServerBrowser()->IsRefreshing()) + m_AddressSelection |= ADDR_SELECTION_CHANGE; - if(BrowserType != m_LastBrowserType) + if(m_LastBrowserType == -1) + m_LastBrowserType = BrowserType; + else if(BrowserType != m_LastBrowserType) { // restore selected filter and server when changing browser page m_LastBrowserType = BrowserType; ToBeSelectedFilter = m_aSelectedFilters[BrowserType]; if(ToBeSelectedFilter != -1) { - ScrollToSelection = true; ToBeSelectedServer = m_lFilters[ToBeSelectedFilter].m_aSelectedServers[BrowserType]; if(ToBeSelectedServer == -1) { - AddressChanged = true; - ClearAddressIfNotFound = true; + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } } + m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; } // count all the servers and update selected filter based on UI state @@ -1086,7 +1089,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) for(int i = 0; i < m_lFilters.size(); i++) { // restore selected filter from browser page - if(ToBeSelectedFilter != -1 && (ToBeSelectedFilter == i) != m_lFilters[i].Extended()) + if(ToBeSelectedFilter != -2 && (ToBeSelectedFilter == i) != m_lFilters[i].Extended()) { m_lFilters[i].Switch(); } @@ -1101,16 +1104,23 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } } - if(SelectedFilter != m_aSelectedFilters[BrowserType]) + if(m_aSelectedFilters[BrowserType] == -2) + m_aSelectedFilters[BrowserType] = SelectedFilter; + else if(SelectedFilter != m_aSelectedFilters[BrowserType]) { // update stored state based on updated state of UI m_aSelectedFilters[BrowserType] = SelectedFilter; - ScrollToSelection = true; UpdateServerBrowserAddress(); + m_AddressSelection |= ADDR_SELECTION_REVEAL; if(SelectedFilter == -1) { - AddressChanged = true; - ClearAddressIfNotFound = true; + // reset address when all filters are closed + m_AddressSelection |= ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND; + } + else if(m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType] == -1) + { + // restore selection based on address only if no stored selection index for this filter + m_AddressSelection |= ADDR_SELECTION_CHANGE; } } @@ -1166,10 +1176,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { m_lFilters[NewFilter].m_aSelectedServers[BrowserType] = ToBeSelectedServer; m_ShowServerDetails = true; - ScrollToSelection = true; + m_AddressSelection |= ADDR_SELECTION_REVEAL; } - UpdateServerBrowserAddress(); + m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; } } @@ -1180,6 +1190,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) pImportantMessage = Localize("Refreshing master servers"); else if(SelectedFilter == -1) pImportantMessage = Localize("No filter category is selected"); + else if(ServerBrowser()->IsRefreshing() && !NumServers) + pImportantMessage = Localize("Fetching server info"); else if(!ServerBrowser()->NumServers()) pImportantMessage = Localize("No servers found"); else if(ServerBrowser()->NumServers() && !NumServers) @@ -1217,7 +1229,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // render header RenderFilterHeader(Row, FilterIndex); - bool NoMatchingAddressFound = true; // reset selection if server address change and not found if(pFilter->Extended()) { for (int ServerIndex = 0; ServerIndex < pFilter->NumSortedServers(); ServerIndex++) @@ -1226,7 +1237,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && pFilter->m_aSelectedServers[BrowserType] == ServerIndex; - if(AddressChanged && !str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) + if((m_AddressSelection&ADDR_SELECTION_CHANGE) && !str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) { if(!IsSelected) { @@ -1234,9 +1245,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_aSelectedFilters[BrowserType] = FilterIndex; pFilter->m_aSelectedServers[BrowserType] = ServerIndex; IsSelected = true; - ScrollToSelection = true; } - NoMatchingAddressFound = false; + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND|ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND); } float ItemHeight = GetListHeaderHeight(); @@ -1247,8 +1257,11 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) View.HSplitTop(ItemHeight, &Row, &View); s_ScrollRegion.AddRect(Row); - if(IsSelected && ScrollToSelection) // new selection (hotkeys or address input) + if(IsSelected && (m_AddressSelection&ADDR_SELECTION_REVEAL)) // new selection (hotkeys or address input) + { s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + m_AddressSelection &= ~ADDR_SELECTION_REVEAL; + } // make sure that only those in view can be selected if(!s_ScrollRegion.IsRectClipped(Row)) @@ -1274,22 +1287,24 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || pFilter->m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details m_aSelectedFilters[BrowserType] = FilterIndex; pFilter->m_aSelectedServers[BrowserType] = ServerIndex; - NoMatchingAddressFound = false; + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND|ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND); if(g_Config.m_UiAutoswitchInfotab) m_SidebarTab = 0; - UpdateServerBrowserAddress(); + UpdateServerBrowserAddress(); // update now instead of using flag because of connect if(Input()->MouseDoubleClick()) Client()->Connect(g_Config.m_UiServerAddress); } } - if(AddressChanged && NoMatchingAddressFound) + if(m_AddressSelection&ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND) { pFilter->m_aSelectedServers[BrowserType] = -1; - if(ClearAddressIfNotFound) - { - g_Config.m_UiServerAddress[0] = '\0'; - } + m_AddressSelection &= ~ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; + } + if(m_AddressSelection&ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND) + { + g_Config.m_UiServerAddress[0] = '\0'; + m_AddressSelection &= ~ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND; } } @@ -1298,7 +1313,12 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } - str_copy(m_LastServerAddress, g_Config.m_UiServerAddress, sizeof(m_LastServerAddress)); + if(m_AddressSelection&ADDR_SELECTION_UPDATE_ADDRESS) + { + UpdateServerBrowserAddress(); + m_AddressSelection &= ~ADDR_SELECTION_UPDATE_ADDRESS; + } + str_copy(m_aLastServerAddress, g_Config.m_UiServerAddress, sizeof(m_aLastServerAddress)); s_ScrollRegion.End(); @@ -1341,7 +1361,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Label.y += 2.0f; UI()->DoLabel(&Label, Localize("Host address:"), FontSize, CUI::ALIGN_LEFT); static float s_AddressOffset = 0.0f; - DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_AddressOffset, false, CUI::CORNER_ALL); + if(DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_AddressOffset, false, CUI::CORNER_ALL)) + { + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + } // render status if(ServerBrowser()->IsRefreshing() && m_ActivePage != PAGE_LAN) @@ -2374,7 +2397,7 @@ void CMenus::UpdateServerBrowserAddress() void CMenus::ServerBrowserFilterOnUpdate() { - m_LastBrowserType = -1; // enforces update on server address + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; } void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2390,6 +2413,4 @@ void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserDat void CMenus::ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); - /*if(pResult->NumArguments() && ((CMenus *)pUserData)->m_MenuPage == PAGE_FAVORITES && ((CMenus *)pUserData)->Client()->State() == IClient::STATE_OFFLINE) - ((CMenus *)pUserData)->ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);*/ } From 9122a42debdbed46a0037fbccf053a816d5fa9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 19 Jan 2020 19:01:00 +0100 Subject: [PATCH 068/479] fix resetting addr on filter change, clear selection on quick filter change, fix missing conchain register --- src/game/client/components/menus.cpp | 1 + src/game/client/components/menus_browser.cpp | 26 ++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 00a1fdab..56a8c6a5 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1534,6 +1534,7 @@ void CMenus::OnInit() if(g_Config.m_ClSkipStartMenu) SetMenuPage(g_Config.m_UiBrowserPage); + Console()->Chain("br_filter_string", ConchainServerbrowserUpdate, this); Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this); Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this); Console()->Chain("add_friend", ConchainFriendlistUpdate, this); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 97a25b62..245c1812 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1110,17 +1110,18 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { // update stored state based on updated state of UI m_aSelectedFilters[BrowserType] = SelectedFilter; - UpdateServerBrowserAddress(); - m_AddressSelection |= ADDR_SELECTION_REVEAL; - if(SelectedFilter == -1) - { - // reset address when all filters are closed - m_AddressSelection |= ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND; - } - else if(m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType] == -1) + if(SelectedFilter != -1) { - // restore selection based on address only if no stored selection index for this filter - m_AddressSelection |= ADDR_SELECTION_CHANGE; + m_AddressSelection |= ADDR_SELECTION_REVEAL; + if(m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType] == -1) + { + // restore selection based on address only if no stored selection index for this filter + m_AddressSelection |= ADDR_SELECTION_CHANGE; + } + else + { + m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; + } } } @@ -1341,7 +1342,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) EditBox.VSplitRight(EditBox.h, &EditBox, &Button); static float s_ClearOffset = 0.0f; if(DoEditBox(&g_Config.m_BrFilterString, &EditBox, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) + { Client()->ServerBrowserUpdate(); + ServerBrowserFilterOnUpdate(); + } // clear button { @@ -2413,4 +2417,6 @@ void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserDat void CMenus::ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); + CMenus *pMenus = (CMenus*)pUserData; + pMenus->ServerBrowserFilterOnUpdate(); } From afe7422acb4b1d5aa6e230f09d005dac2bc3d183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 19 Jan 2020 19:42:38 +0100 Subject: [PATCH 069/479] fix restoring address after changing sorting --- src/game/client/components/menus.cpp | 2 ++ src/game/client/components/menus.h | 7 +++--- src/game/client/components/menus_browser.cpp | 26 +++++++++++++------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 56a8c6a5..06112bde 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1537,6 +1537,8 @@ void CMenus::OnInit() Console()->Chain("br_filter_string", ConchainServerbrowserUpdate, this); Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this); Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this); + Console()->Chain("br_sort", ConchainServerbrowserSortingUpdate, this); + Console()->Chain("br_sort_order", ConchainServerbrowserSortingUpdate, this); Console()->Chain("add_friend", ConchainFriendlistUpdate, this); Console()->Chain("remove_friend", ConchainFriendlistUpdate, this); Console()->Chain("snd_enable_music", ConchainToggleMusic, this); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 6691f550..828ddc77 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -608,9 +608,8 @@ class CMenus : public CComponent ADDR_SELECTION_CHANGE = 1, ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND = 2, - ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND = 4, - ADDR_SELECTION_REVEAL = 8, - ADDR_SELECTION_UPDATE_ADDRESS = 16, + ADDR_SELECTION_REVEAL = 4, + ADDR_SELECTION_UPDATE_ADDRESS = 8, }; int m_SidebarTab; bool m_SidebarActive; @@ -637,6 +636,7 @@ class CMenus : public CComponent void UpdateServerBrowserAddress(); void ServerBrowserFilterOnUpdate(); + void ServerBrowserSortingOnUpdate(); // video settings @@ -706,6 +706,7 @@ class CMenus : public CComponent 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); + static void ConchainServerbrowserSortingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainToggleMusic(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); void DoFriendListEntry(CUIRect *pView, CFriendItem *pFriend, const void *pID, const CContactInfo *pFriendInfo, const CServerInfo *pServerInfo, bool Checked, bool Clan = false); void SetOverlay(int Type, float x, float y, const void *pData); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 245c1812..47dd456c 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1027,6 +1027,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) g_Config.m_BrSortOrder = 0; g_Config.m_BrSort = ms_aBrowserCols[i].m_Sort; } + ServerBrowserSortingOnUpdate(); } } @@ -1077,7 +1078,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) ToBeSelectedServer = m_lFilters[ToBeSelectedFilter].m_aSelectedServers[BrowserType]; if(ToBeSelectedServer == -1) { - m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_REVEAL; } } m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; @@ -1238,7 +1239,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && pFilter->m_aSelectedServers[BrowserType] == ServerIndex; - if((m_AddressSelection&ADDR_SELECTION_CHANGE) && !str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) + if(!str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) { if(!IsSelected) { @@ -1247,7 +1248,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) pFilter->m_aSelectedServers[BrowserType] = ServerIndex; IsSelected = true; } - m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND|ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND); + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); } float ItemHeight = GetListHeaderHeight(); @@ -1288,7 +1289,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || pFilter->m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details m_aSelectedFilters[BrowserType] = FilterIndex; pFilter->m_aSelectedServers[BrowserType] = ServerIndex; - m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND|ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND); + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); if(g_Config.m_UiAutoswitchInfotab) m_SidebarTab = 0; UpdateServerBrowserAddress(); // update now instead of using flag because of connect @@ -1302,11 +1303,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) pFilter->m_aSelectedServers[BrowserType] = -1; m_AddressSelection &= ~ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; } - if(m_AddressSelection&ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND) - { - g_Config.m_UiServerAddress[0] = '\0'; - m_AddressSelection &= ~ADDR_SELECTION_RESET_ADDRESS_IF_NOT_FOUND; - } } if(FilterIndex < m_lFilters.size()-1) @@ -2404,6 +2400,11 @@ void CMenus::ServerBrowserFilterOnUpdate() m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; } +void CMenus::ServerBrowserSortingOnUpdate() +{ + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; +} + void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); @@ -2420,3 +2421,10 @@ void CMenus::ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUser CMenus *pMenus = (CMenus*)pUserData; pMenus->ServerBrowserFilterOnUpdate(); } + +void CMenus::ConchainServerbrowserSortingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + CMenus *pMenus = (CMenus*)pUserData; + pMenus->ServerBrowserSortingOnUpdate(); +} From 5dc79e89152628d4f99243f6d90e63ec15e6b8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 19 Jan 2020 22:16:37 +0100 Subject: [PATCH 070/479] only keep one selected server between filters, store expanded filter for each page separately --- src/game/client/components/menus.cpp | 3 + src/game/client/components/menus.h | 10 ++- src/game/client/components/menus_browser.cpp | 88 ++++++++++---------- 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 06112bde..74f73cff 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -52,7 +52,10 @@ CMenus::CMenus() m_aLastServerAddress[0] = '\0'; m_AddressSelection = 0; for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) + { m_aSelectedFilters[Type] = -2; + m_aSelectedServers[Type] = -1; + } m_NeedRestartGraphics = false; m_NeedRestartSound = false; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 828ddc77..0b66db8e 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -531,7 +531,6 @@ class CMenus : public CComponent // buttons var int m_SwitchButton; int m_aButtonID[3]; - int m_aSelectedServers[IServerBrowser::NUM_TYPES]; CBrowserFilter() {} CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser); @@ -546,7 +545,6 @@ class CMenus : public CComponent int NumSortedServers() const; int NumPlayers() const; const CServerInfo* SortedGet(int Index) const; - const CServerInfo* SortedGetSelected() const; const void* ID(int Index) const; void Reset(); @@ -616,6 +614,7 @@ class CMenus : public CComponent bool m_ShowServerDetails; int m_LastBrowserType; // -1 if not initialized int m_aSelectedFilters[IServerBrowser::NUM_TYPES]; // -1 if none selected, -2 if not initialized + int m_aSelectedServers[IServerBrowser::NUM_TYPES]; // -1 if none selected char m_aLastServerAddress[sizeof(g_Config.m_UiServerAddress)]; // a[0] == 0 if not initialized int m_AddressSelection; static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; @@ -631,7 +630,12 @@ class CMenus : public CComponent const CServerInfo* GetSelectedServerInfo() { CBrowserFilter* pSelectedFilter = GetSelectedBrowserFilter(); - return pSelectedFilter ? pSelectedFilter->SortedGetSelected() : 0; + if(!pSelectedFilter) + return 0; + const int Tab = ServerBrowser()->GetType(); + if(m_aSelectedServers[Tab] < 0 || m_aSelectedServers[Tab] >= pSelectedFilter->NumSortedServers()) + return 0; + return pSelectedFilter->SortedGet(m_aSelectedServers[Tab]); } void UpdateServerBrowserAddress(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 47dd456c..a361084e 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -43,8 +43,6 @@ CMenus::CBrowserFilter::CBrowserFilter(int Custom, const char* pName, IServerBro { m_Extended = false; m_Custom = Custom; - for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) - m_aSelectedServers[Type] = -1; str_copy(m_aName, pName, sizeof(m_aName)); m_pServerBrowser = pServerBrowser; switch(m_Custom) @@ -125,11 +123,6 @@ const CServerInfo* CMenus::CBrowserFilter::SortedGet(int Index) const return m_pServerBrowser->SortedGet(m_Filter, Index); } -const CServerInfo* CMenus::CBrowserFilter::SortedGetSelected() const -{ - return SortedGet(m_aSelectedServers[m_pServerBrowser->GetType()]); -} - void CMenus::CBrowserFilter::SetFilterNum(int Num) { m_Filter = Num; @@ -176,9 +169,16 @@ void CMenus::LoadFilters() m_SidebarActive = rSettingsEntry["sidebar_active"].u.integer; if(rSettingsEntry["sidebar_tab"].type == json_integer) m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), 0, 2); + if(rSettingsEntry["filters"].type == json_array) + { + for(unsigned i = 0; i < rSettingsEntry["filters"].u.array.length && i < IServerBrowser::NUM_TYPES; ++i) + { + if(rSettingsEntry["filters"][i].type == json_integer) + m_aSelectedFilters[i] = rSettingsEntry["filters"][i].u.integer; + } + } // extract filter data - int Extended = 0; const json_value &rFilterEntry = (*pJsonData)["filter"]; for(unsigned i = 0; i < rFilterEntry.u.array.length; ++i) { @@ -190,8 +190,6 @@ void CMenus::LoadFilters() int Type = 0; if(rStart["type"].type == json_integer) Type = rStart["type"].u.integer; - if(rStart["extended"].type == json_integer && rStart["extended"].u.integer) - Extended = i; // filter setting CServerFilterInfo FilterInfo; @@ -231,7 +229,9 @@ void CMenus::LoadFilters() // clean up json_value_free(pJsonData); - m_lFilters[Extended].Switch(); + CBrowserFilter *pSelectedFilter = GetSelectedBrowserFilter(); + if(pSelectedFilter) + pSelectedFilter->Switch(); } void CMenus::SaveFilters() @@ -250,9 +250,18 @@ void CMenus::SaveFilters() io_write(File, aBuf, str_length(aBuf)); str_format(aBuf, sizeof(aBuf), "\t\"sidebar_tab\": %d,\n", m_SidebarTab); io_write(File, aBuf, str_length(aBuf)); + p = "\t\"filters\": [\n"; + io_write(File, p, str_length(p)); + for(int i = 0; i < IServerBrowser::NUM_TYPES; i++) + { + str_format(aBuf, sizeof(aBuf), "\t\t%d,\n", m_aSelectedFilters[i]); + io_write(File, aBuf, str_length(aBuf)); + } + p = "\t],\n"; + io_write(File, p, str_length(p)); // settings end - p = "\t},\n"; + p = "},\n"; io_write(File, p, str_length(p)); // filter @@ -273,8 +282,6 @@ void CMenus::SaveFilters() str_format(aBuf, sizeof(aBuf), "\t\t\"type\": %d,\n", m_lFilters[i].Custom()); io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\"extended\": %d,\n", m_lFilters[i].Extended()?1:0); - io_write(File, aBuf, str_length(aBuf)); // filter setting CServerFilterInfo FilterInfo; @@ -1059,7 +1066,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) const int BrowserType = ServerBrowser()->GetType(); int ToBeSelectedFilter = -2; // -2 to not restore, -1 to restore all filters closed - int ToBeSelectedServer = -1; // update selection based on address if it changed if(!(m_AddressSelection&ADDR_SELECTION_CHANGE) && m_aLastServerAddress[0] && str_comp(m_aLastServerAddress, g_Config.m_UiServerAddress) != 0) m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_REVEAL; @@ -1075,11 +1081,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) ToBeSelectedFilter = m_aSelectedFilters[BrowserType]; if(ToBeSelectedFilter != -1) { - ToBeSelectedServer = m_lFilters[ToBeSelectedFilter].m_aSelectedServers[BrowserType]; - if(ToBeSelectedServer == -1) - { - m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_REVEAL; - } + if(m_aSelectedServers[BrowserType] == -1) + m_AddressSelection |= ADDR_SELECTION_CHANGE; + else + m_AddressSelection |= ADDR_SELECTION_REVEAL; } m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; } @@ -1111,18 +1116,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { // update stored state based on updated state of UI m_aSelectedFilters[BrowserType] = SelectedFilter; + m_aSelectedServers[BrowserType] = -1; if(SelectedFilter != -1) { - m_AddressSelection |= ADDR_SELECTION_REVEAL; - if(m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType] == -1) - { - // restore selection based on address only if no stored selection index for this filter - m_AddressSelection |= ADDR_SELECTION_CHANGE; - } - else - { - m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; - } + m_AddressSelection |= ADDR_SELECTION_CHANGE; } } @@ -1131,14 +1128,14 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // handle arrow hotkeys if(SelectedFilter > -1) { - int SelectedIndex = m_lFilters[SelectedFilter].m_aSelectedServers[BrowserType]; int NewFilter = SelectedFilter; + int ToBeSelectedServer = -1; if(m_DownArrowPressed) { if(!CtrlPressed) { - ToBeSelectedServer = SelectedIndex + 1; + ToBeSelectedServer = m_aSelectedServers[BrowserType] < 0 ? 0 : (m_aSelectedServers[BrowserType] + 1); if(ToBeSelectedServer >= m_lFilters[SelectedFilter].NumSortedServers()) ToBeSelectedServer = m_lFilters[SelectedFilter].NumSortedServers() - 1; } @@ -1152,7 +1149,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { if(!CtrlPressed) { - ToBeSelectedServer = SelectedIndex - 1; + ToBeSelectedServer = m_aSelectedServers[BrowserType] < 0 ? 0 : (m_aSelectedServers[BrowserType] - 1); if(ToBeSelectedServer < 0) ToBeSelectedServer = 0; } @@ -1167,16 +1164,16 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { m_lFilters[NewFilter].Switch(); m_lFilters[SelectedFilter].Switch(); - // try to restore selected server - ToBeSelectedServer = clamp(m_lFilters[NewFilter].m_aSelectedServers[BrowserType], 0, m_lFilters[NewFilter].NumSortedServers()-1); + m_aSelectedServers[BrowserType] = -1; + m_AddressSelection |= ADDR_SELECTION_CHANGE; } if(ToBeSelectedServer > -1 && ToBeSelectedServer < m_lFilters[NewFilter].NumSortedServers()) { m_aSelectedFilters[BrowserType] = NewFilter; - if(m_lFilters[NewFilter].m_aSelectedServers[BrowserType] != ToBeSelectedServer) + if(m_aSelectedServers[BrowserType] != ToBeSelectedServer) { - m_lFilters[NewFilter].m_aSelectedServers[BrowserType] = ToBeSelectedServer; + m_aSelectedServers[BrowserType] = ToBeSelectedServer; m_ShowServerDetails = true; m_AddressSelection |= ADDR_SELECTION_REVEAL; } @@ -1238,14 +1235,14 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) const CServerInfo *pItem = pFilter->SortedGet(ServerIndex); // select server if address changed and match found - bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && pFilter->m_aSelectedServers[BrowserType] == ServerIndex; + bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && m_aSelectedServers[BrowserType] == ServerIndex; if(!str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) { if(!IsSelected) { m_ShowServerDetails = true; m_aSelectedFilters[BrowserType] = FilterIndex; - pFilter->m_aSelectedServers[BrowserType] = ServerIndex; + m_aSelectedServers[BrowserType] = ServerIndex; IsSelected = true; } m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); @@ -1286,9 +1283,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected)) { - m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || pFilter->m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details + m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details m_aSelectedFilters[BrowserType] = FilterIndex; - pFilter->m_aSelectedServers[BrowserType] = ServerIndex; + m_aSelectedServers[BrowserType] = ServerIndex; m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); if(g_Config.m_UiAutoswitchInfotab) m_SidebarTab = 0; @@ -1300,7 +1297,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(m_AddressSelection&ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND) { - pFilter->m_aSelectedServers[BrowserType] = -1; + m_aSelectedServers[BrowserType] = -1; m_AddressSelection &= ~ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; } } @@ -1975,11 +1972,10 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) void CMenus::RenderServerbrowserInfoTab(CUIRect View) { - CBrowserFilter *pFilter = GetSelectedBrowserFilter(); - if(pFilter) + const CServerInfo *pInfo = GetSelectedServerInfo(); + if(pInfo) { - const CServerInfo *pItem = pFilter->SortedGet(pFilter->m_aSelectedServers[ServerBrowser()->GetType()]); - RenderServerbrowserServerDetail(View, pItem); + RenderServerbrowserServerDetail(View, pInfo); } } From 3d1960922deb754297e043debe2b8f3a93eab417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 23 Jan 2020 23:47:53 +0100 Subject: [PATCH 071/479] fix browser header selection problems (closes #2422), add highlight to button when hovered --- src/game/client/components/menus.cpp | 8 +++++--- src/game/client/components/menus_browser.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 74f73cff..c03036ea 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -276,15 +276,17 @@ void CMenus::DoButton_MenuTabTop_Dummy(const char *pText, int Checked, const CUI } int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect) -//void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) { if(Checked) { - RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(pRect, vec4(0.9f, 0.9f, 0.9f, 0.5f), CUI::CORNER_ALL, 5.0f); TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); } - + else if(UI()->HotItem() == pID) + { + RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f); + } CUIRect Label; pRect->VMargin(2.0f, &Label); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index a361084e..cc21e6be 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -376,7 +376,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { // logic int ReturnValue = 0; - int Inside = UI()->MouseInside(&View); + int Inside = UI()->MouseInside(&View) && UI()->MouseInsideClip(); if(UI()->CheckActiveItem(pID)) { From 00387bfc32047ee7882c87b7b65f6664ed4ceb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Jan 2020 18:24:46 +0100 Subject: [PATCH 072/479] default to opening 'all' filter if ui_settings old format --- src/game/client/components/menus_browser.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index cc21e6be..8e064895 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -171,12 +171,19 @@ void CMenus::LoadFilters() m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), 0, 2); if(rSettingsEntry["filters"].type == json_array) { - for(unsigned i = 0; i < rSettingsEntry["filters"].u.array.length && i < IServerBrowser::NUM_TYPES; ++i) + for(unsigned i = 0; i < IServerBrowser::NUM_TYPES; ++i) { - if(rSettingsEntry["filters"][i].type == json_integer) + if(i < rSettingsEntry["filters"].u.array.length && rSettingsEntry["filters"][i].type == json_integer) m_aSelectedFilters[i] = rSettingsEntry["filters"][i].u.integer; + else + m_aSelectedFilters[i] = 2; // default to "all" if not set for all filters } } + else + { + for(unsigned i = 0; i < IServerBrowser::NUM_TYPES; ++i) + m_aSelectedFilters[i] = 2; // default to "all" if not set + } // extract filter data const json_value &rFilterEntry = (*pJsonData)["filter"]; From a601865314766f7e3baffabf32afc422e21f83f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 00:43:42 +0100 Subject: [PATCH 073/479] separate internet and lan address ui vars --- src/engine/client/client.cpp | 1 - src/game/client/components/menus.cpp | 5 +- src/game/client/components/menus.h | 3 +- src/game/client/components/menus_browser.cpp | 69 +++++++++++++------- src/game/client/components/menus_ingame.cpp | 2 +- src/game/variables.h | 3 +- 6 files changed, 52 insertions(+), 31 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 1ae200f6..ef4ecbc5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2034,7 +2034,6 @@ void CClient::Run() // handle pending connects if(m_aCmdConnect[0]) { - str_copy(g_Config.m_UiServerAddress, m_aCmdConnect, sizeof(g_Config.m_UiServerAddress)); Connect(m_aCmdConnect); m_aCmdConnect[0] = 0; } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c03036ea..17ff9d77 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -49,7 +49,6 @@ CMenus::CMenus() m_SidebarActive = true; m_ShowServerDetails = true; m_LastBrowserType = -1; - m_aLastServerAddress[0] = '\0'; m_AddressSelection = 0; for(int Type = 0; Type < IServerBrowser::NUM_TYPES; Type++) { @@ -1922,7 +1921,7 @@ int CMenus::Render() static CButtonContainer s_ButtonTryAgain; if(DoButton_Menu(&s_ButtonTryAgain, Localize("Try again"), 0, &TryAgain) || m_EnterPressed) { - Client()->Connect(g_Config.m_UiServerAddress); + Client()->Connect(GetServerBrowserAddress()); } } else if(m_Popup == POPUP_CONNECTING) @@ -1988,7 +1987,7 @@ int CMenus::Render() else { Box.HSplitTop(27.0f, 0, &Box); - UI()->DoLabel(&Box, g_Config.m_UiServerAddress, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Box, GetServerBrowserAddress(), ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); } } else if(m_Popup == POPUP_LANGUAGE) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 0b66db8e..16977341 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -615,7 +615,6 @@ class CMenus : public CComponent int m_LastBrowserType; // -1 if not initialized int m_aSelectedFilters[IServerBrowser::NUM_TYPES]; // -1 if none selected, -2 if not initialized int m_aSelectedServers[IServerBrowser::NUM_TYPES]; // -1 if none selected - char m_aLastServerAddress[sizeof(g_Config.m_UiServerAddress)]; // a[0] == 0 if not initialized int m_AddressSelection; static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; @@ -639,6 +638,8 @@ class CMenus : public CComponent } void UpdateServerBrowserAddress(); + const char *GetServerBrowserAddress(); + void SetServerBrowserAddress(const char *pAddress); void ServerBrowserFilterOnUpdate(); void ServerBrowserSortingOnUpdate(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 8e064895..7963c096 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1071,14 +1071,12 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) RenderTools()->DrawUIRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.05f), CUI::CORNER_ALL, 5.0f); } - const int BrowserType = ServerBrowser()->GetType(); - int ToBeSelectedFilter = -2; // -2 to not restore, -1 to restore all filters closed // update selection based on address if it changed - if(!(m_AddressSelection&ADDR_SELECTION_CHANGE) && m_aLastServerAddress[0] && str_comp(m_aLastServerAddress, g_Config.m_UiServerAddress) != 0) - m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_REVEAL; - else if(ServerBrowser()->IsRefreshing()) + if(ServerBrowser()->IsRefreshing()) m_AddressSelection |= ADDR_SELECTION_CHANGE; + const int BrowserType = ServerBrowser()->GetType(); + int ToBeSelectedFilter = -2; // -2 to not restore, -1 to restore all filters closed if(m_LastBrowserType == -1) m_LastBrowserType = BrowserType; else if(BrowserType != m_LastBrowserType) @@ -1091,9 +1089,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(m_aSelectedServers[BrowserType] == -1) m_AddressSelection |= ADDR_SELECTION_CHANGE; else - m_AddressSelection |= ADDR_SELECTION_REVEAL; + m_AddressSelection |= ADDR_SELECTION_REVEAL | ADDR_SELECTION_UPDATE_ADDRESS; } - m_AddressSelection |= ADDR_SELECTION_UPDATE_ADDRESS; } // count all the servers and update selected filter based on UI state @@ -1223,6 +1220,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; + const char *pAddress = GetServerBrowserAddress(); for(int FilterIndex = 0; FilterIndex < m_lFilters.size(); FilterIndex++) { CBrowserFilter *pFilter = &m_lFilters[FilterIndex]; @@ -1243,7 +1241,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && m_aSelectedServers[BrowserType] == ServerIndex; - if(!str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress)) + if(!str_comp(pItem->m_aAddress, pAddress)) { if(!IsSelected) { @@ -1298,7 +1296,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_SidebarTab = 0; UpdateServerBrowserAddress(); // update now instead of using flag because of connect if(Input()->MouseDoubleClick()) - Client()->Connect(g_Config.m_UiServerAddress); + Client()->Connect(GetServerBrowserAddress()); } } @@ -1319,7 +1317,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) UpdateServerBrowserAddress(); m_AddressSelection &= ~ADDR_SELECTION_UPDATE_ADDRESS; } - str_copy(m_aLastServerAddress, g_Config.m_UiServerAddress, sizeof(m_aLastServerAddress)); s_ScrollRegion.End(); @@ -1364,10 +1361,22 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Label.VSplitRight(ButtonWidth*2.0f+SpacingH, &Label, &EditBox); Label.y += 2.0f; UI()->DoLabel(&Label, Localize("Host address:"), FontSize, CUI::ALIGN_LEFT); - static float s_AddressOffset = 0.0f; - if(DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_AddressOffset, false, CUI::CORNER_ALL)) + + if(BrowserType == IServerBrowser::TYPE_INTERNET) { - m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + static float s_InternetAddressOffset = 0.0f; + if(DoEditBox(&g_Config.m_UiInternetServerAddress, &EditBox, g_Config.m_UiInternetServerAddress, sizeof(g_Config.m_UiInternetServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) + { + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + } + } + else if(BrowserType == IServerBrowser::TYPE_LAN) + { + static float s_LanAddressOffset = 0.0f; + if(DoEditBox(&g_Config.m_UiLanServerAddress, &EditBox, g_Config.m_UiLanServerAddress, sizeof(g_Config.m_UiLanServerAddress), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) + { + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + } } // render status @@ -1609,8 +1618,8 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) Button.Margin((Button.h - GetListHeaderHeight() + 2.0f) / 2, &Button); if(DoButton_Menu(&(s_FriendJoinButtons[ButtonId%20]), Localize("Join", "Join a server"), 0, &Button) ) { - str_copy(g_Config.m_UiServerAddress, m_lFriendList[i][f].m_pServerInfo->m_aAddress, sizeof(g_Config.m_UiServerAddress)); - Client()->Connect(g_Config.m_UiServerAddress); + SetServerBrowserAddress(m_lFriendList[i][f].m_pServerInfo->m_aAddress); + Client()->Connect(GetServerBrowserAddress()); } } if(f < m_lFriendList[i].size()-1) @@ -2262,7 +2271,7 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView) static CButtonContainer s_JoinButton; if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &Button) || m_EnterPressed) { - Client()->Connect(g_Config.m_UiServerAddress); + Client()->Connect(GetServerBrowserAddress()); m_EnterPressed = false; } } @@ -2388,14 +2397,26 @@ void CMenus::RenderServerbrowser(CUIRect MainView) void CMenus::UpdateServerBrowserAddress() { const CServerInfo *pItem = GetSelectedServerInfo(); - if(pItem == NULL) - { - g_Config.m_UiServerAddress[0] = '\0'; - } - else - { - str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); - } + SetServerBrowserAddress(pItem ? pItem->m_aAddress : ""); +} + +const char *CMenus::GetServerBrowserAddress() +{ + const int Type = ServerBrowser()->GetType(); + if(Type == IServerBrowser::TYPE_INTERNET) + return g_Config.m_UiInternetServerAddress; + else if(Type == IServerBrowser::TYPE_LAN) + return g_Config.m_UiLanServerAddress; + return 0; +} + +void CMenus::SetServerBrowserAddress(const char *pAddress) +{ + const int Type = ServerBrowser()->GetType(); + if(Type == IServerBrowser::TYPE_INTERNET) + str_copy(g_Config.m_UiInternetServerAddress, pAddress, sizeof(g_Config.m_UiInternetServerAddress)); + else if(Type == IServerBrowser::TYPE_LAN) + str_copy(g_Config.m_UiLanServerAddress, pAddress, sizeof(g_Config.m_UiLanServerAddress)); } void CMenus::ServerBrowserFilterOnUpdate() diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 33c90254..e01119a5 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -380,7 +380,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo); Label.y += 2.0f; - str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Address"), g_Config.m_UiServerAddress); + str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Address"), CurrentServerInfo.m_aHostname); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo); diff --git a/src/game/variables.h b/src/game/variables.h index 26f1f640..9345ba61 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -79,7 +79,8 @@ MACRO_CONFIG_STR(PlayerSkinEyes, player_skin_eyes, 24, "standard", CFGFLAG_CLIEN MACRO_CONFIG_INT(UiBrowserPage, ui_browser_page, 5, 5, 8, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface serverbrowser page") MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 5, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface settings page") -MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") +MACRO_CONFIG_STR(UiInternetServerAddress, ui_internet_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (Internet page)") +MACRO_CONFIG_STR(UiLanServerAddress, ui_lan_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (LAN page)") MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor") MACRO_CONFIG_INT(UiAutoswitchInfotab, ui_autoswitch_infotab, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Switch to the info tab when clicking on a server") MACRO_CONFIG_INT(UiWideview, ui_wideview, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Extended menus GUI") From dd1749e882a734f849ca64beb667ed7c857e7323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 00:52:11 +0100 Subject: [PATCH 074/479] rebase and fix integration with favorites-passwords --- src/game/client/components/menus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 17ff9d77..37a80a86 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1901,7 +1901,7 @@ int CMenus::Render() Box.HSplitTop(2.0f, 0, &Box); Box.HSplitTop(20.0f, &Save, &Box); CServerInfo ServerInfo = {0}; - str_copy(ServerInfo.m_aHostname, g_Config.m_UiServerAddress, sizeof(ServerInfo.m_aHostname)); + str_copy(ServerInfo.m_aHostname, GetServerBrowserAddress(), sizeof(ServerInfo.m_aHostname)); ServerBrowser()->UpdateFavoriteState(&ServerInfo); const bool Favorite = ServerInfo.m_Favorite; const int OnValue = Favorite ? 1 : 2; From e0d4dc81de6f71922326a4d03ae30268dc2b682a Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 12:08:16 +0100 Subject: [PATCH 075/479] make it possible to change the max clients on a server via sv_max_clients without restarting the server. closes #2268 --- src/engine/server.h | 1 - src/engine/server/server.cpp | 19 ++++--- src/engine/server/server.h | 2 +- src/engine/shared/network.h | 5 +- src/engine/shared/network_server.cpp | 72 +++++++++++++++----------- src/game/server/entities/character.cpp | 2 +- src/game/server/gamecontext.cpp | 16 +++--- src/game/server/gamecontroller.cpp | 2 +- 8 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/engine/server.h b/src/engine/server.h index 2e5032d0..de5f5f08 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -25,7 +25,6 @@ class IServer : public IInterface int Tick() const { return m_CurrentGameTick; } int TickSpeed() const { return m_TickSpeed; } - virtual int MaxClients() const = 0; virtual const char *ClientName(int ClientID) const = 0; virtual const char *ClientClan(int ClientID) const = 0; virtual int ClientCountry(int ClientID) const = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index a2e15420..98d0de8d 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -459,11 +459,6 @@ bool CServer::ClientIngame(int ClientID) const return ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME; } -int CServer::MaxClients() const -{ - return m_NetServer.MaxClients(); -} - void CServer::InitRconPasswordIfUnset() { if(m_RconPasswordSet) @@ -775,7 +770,7 @@ void CServer::SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int Cli void CServer::UpdateClientRconCommands() { - for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MaxClients(); ClientID += MAX_RCONCMD_RATIO) + for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MAX_CLIENTS; ClientID += MAX_RCONCMD_RATIO) { if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed) { @@ -806,7 +801,7 @@ void CServer::SendMapListEntryRem(const CMapListEntry *pMapListEntry, int Client void CServer::UpdateClientMapListEntries() { - for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MaxClients(); ClientID += MAX_RCONCMD_RATIO) + for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MAX_CLIENTS; ClientID += MAX_RCONCMD_RATIO) { if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed) { @@ -1145,7 +1140,7 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) pPacker->AddInt(PlayerCount); // num players pPacker->AddInt(g_Config.m_SvPlayerSlots); // max players pPacker->AddInt(ClientCount); // num clients - pPacker->AddInt(m_NetServer.MaxClients()); // max clients + pPacker->AddInt(g_Config.m_SvMaxClients); // max clients if(Token != -1) { @@ -1659,6 +1654,13 @@ void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserD } } +void CServer::ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + if(pResult->NumArguments()) + ((CServer *)pUserData)->m_NetServer.SetMaxClients(pResult->GetInteger(0)); +} + void CServer::ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); @@ -1735,6 +1737,7 @@ void CServer::RegisterCommands() Console()->Chain("sv_name", ConchainSpecialInfoupdate, this); Console()->Chain("password", ConchainSpecialInfoupdate, this); + Console()->Chain("sv_max_clients", ConchainMaxclientsUpdate, this); Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this); Console()->Chain("mod_command", ConchainModCommandUpdate, this); Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index b6fd29ce..31e600e5 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -224,7 +224,6 @@ class CServer : public IServer const char *ClientClan(int ClientID) const; int ClientCountry(int ClientID) const; bool ClientIngame(int ClientID) const; - int MaxClients() const; virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID); @@ -269,6 +268,7 @@ class CServer : public IServer static void ConSaveConfig(IConsole::IResult *pResult, void *pUser); static void ConLogout(IConsole::IResult *pResult, void *pUser); static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + static void ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 5ce01962..5964cec9 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -412,6 +412,7 @@ class CNetServer NETSOCKET m_Socket; class CNetBan *m_pNetBan; CSlot m_aSlots[NET_MAX_CLIENTS]; + int m_NumClients; int m_MaxClients; int m_MaxClientsPerIP; @@ -446,10 +447,10 @@ class CNetServer 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; } // - void SetMaxClientsPerIP(int Max); + void SetMaxClients(int MaxClients); + void SetMaxClientsPerIP(int MaxClientsPerIP); }; class CNetConsole diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 3e8dd1b2..5c56d8e5 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.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 @@ -23,14 +24,9 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma m_pNetBan = pNetBan; - // clamp clients - m_MaxClients = MaxClients; - if(m_MaxClients > NET_MAX_CLIENTS) - m_MaxClients = NET_MAX_CLIENTS; - if(m_MaxClients < 1) - m_MaxClients = 1; - - m_MaxClientsPerIP = MaxClientsPerIP; + m_NumClients = 0; + SetMaxClients(MaxClients); + SetMaxClientsPerIP(MaxClientsPerIP); for(int i = 0; i < NET_MAX_CLIENTS; i++) m_aSlots[i].m_Connection.Init(m_Socket, true); @@ -68,6 +64,7 @@ int CNetServer::Drop(int ClientID, const char *pReason) m_pfnDelClient(ClientID, pReason, m_UserPtr); m_aSlots[ClientID].m_Connection.Disconnect(pReason); + m_NumClients--; return 0; } @@ -75,8 +72,11 @@ int CNetServer::Drop(int ClientID, const char *pReason) int CNetServer::Update() { int64 Now = time_get(); - for(int i = 0; i < MaxClients(); i++) + for(int i = 0; i < NET_MAX_CLIENTS; i++) { + if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) + continue; + m_aSlots[i].m_Connection.Update(); if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR) { @@ -134,8 +134,11 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) bool Found = false; // try to find matching slot - for(int i = 0; i < MaxClients(); i++) + for(int i = 0; i < NET_MAX_CLIENTS; i++) { + if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) + continue; + if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) @@ -172,13 +175,18 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT) { - bool Found = false; + // check if there are free slots + if(m_NumClients >= m_MaxClients) + { + const char FullMsg[] = "This server is full"; + CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); + } // only allow a specific number of players with the same ip NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 1; ThisAddr.port = 0; - for(int i = 0; i < MaxClients(); i++) + for(int i = 0; i < NET_MAX_CLIENTS; i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; @@ -197,24 +205,18 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) } } - for(int i = 0; i < MaxClients(); i++) + for(int i = 0; i < NET_MAX_CLIENTS; i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) { - Found = true; + m_NumClients++; m_aSlots[i].m_Connection.SetToken(m_RecvUnpacker.m_Data.m_Token); m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr); if(m_pfnNewClient) m_pfnNewClient(i, m_UserPtr); break; } - } - - if(!Found) - { - const char FullMsg[] = "This server is full"; - CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); - } + } } else if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_TOKEN) m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, NET_TOKENFLAG_RESPONSEONLY); @@ -246,13 +248,20 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) } if(pChunk->m_ClientID == -1) - for(int i = 0; i < MaxClients(); i++) + { + for(int i = 0; i < NET_MAX_CLIENTS; i++) + { + if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) + continue; + if(net_addr_comp(&pChunk->m_Address, m_aSlots[i].m_Connection.PeerAddress()) == 0) { // upgrade the packet, now that we know its recipent pChunk->m_ClientID = i; break; } + } + } if(Token != NET_TOKEN_NONE) { @@ -267,7 +276,8 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) else { dbg_assert(pChunk->m_ClientID >= 0, "errornous client id"); - dbg_assert(pChunk->m_ClientID < MaxClients(), "errornous client id"); + dbg_assert(pChunk->m_ClientID < NET_MAX_CLIENTS, "errornous client id"); + dbg_assert(m_aSlots[pChunk->m_ClientID].m_Connection.State() != NET_CONNSTATE_OFFLINE, "errornous client id"); m_aSlots[pChunk->m_ClientID].m_Connection.SendPacketConnless((const char *)pChunk->m_pData, pChunk->m_DataSize); } @@ -283,7 +293,8 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) int Flags = 0; dbg_assert(pChunk->m_ClientID >= 0, "errornous client id"); - dbg_assert(pChunk->m_ClientID < MaxClients(), "errornous client id"); + dbg_assert(pChunk->m_ClientID < NET_MAX_CLIENTS, "errornous client id"); + dbg_assert(m_aSlots[pChunk->m_ClientID].m_Connection.State() != NET_CONNSTATE_OFFLINE, "errornous client id"); if(pChunk->m_Flags&NETSENDFLAG_VITAL) Flags = NET_CHUNKFLAG_VITAL; @@ -301,13 +312,12 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) return 0; } -void CNetServer::SetMaxClientsPerIP(int Max) +void CNetServer::SetMaxClients(int MaxClients) { - // clamp - if(Max < 1) - Max = 1; - else if(Max > NET_MAX_CLIENTS) - Max = NET_MAX_CLIENTS; + m_MaxClients = clamp(MaxClients, 1, int(NET_MAX_CLIENTS)); +} - m_MaxClientsPerIP = Max; +void CNetServer::SetMaxClientsPerIP(int MaxClientsPerIP) +{ + m_MaxClientsPerIP = clamp(MaxClientsPerIP, 1, int(NET_MAX_CLIENTS)); } diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 2f21f20b..4aa917a8 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -679,7 +679,7 @@ void CCharacter::Die(int Killer, int Weapon) CNetMsg_Sv_KillMsg Msg; Msg.m_Victim = m_pPlayer->GetCID(); Msg.m_ModeSpecial = ModeSpecial; - for(int i = 0 ; i < Server()->MaxClients(); i++) + for(int i = 0 ; i < MAX_CLIENTS; i++) { if(!Server()->ClientIngame(i)) continue; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index e39c8d4a..732af911 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1458,8 +1458,8 @@ void CGameContext::ConchainSettingUpdate(IConsole::IResult *pResult, void *pUser if(pResult->NumArguments()) { CGameContext *pSelf = (CGameContext *)pUserData; - if(pSelf->Server()->MaxClients() < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = pSelf->Server()->MaxClients(); + if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) + g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; pSelf->SendSettings(-1); } } @@ -1563,17 +1563,17 @@ void CGameContext::OnInit() Console()->Chain("sv_matches_per_map", ConchainGameinfoUpdate, this); // clamp sv_player_slots to 0..MaxClients - if(Server()->MaxClients() < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = Server()->MaxClients(); + if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) + g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; #ifdef CONF_DEBUG - // clamp dbg_dummies to 0..MaxClients-1 - if(Server()->MaxClients() <= g_Config.m_DbgDummies) - g_Config.m_DbgDummies = Server()->MaxClients(); + // clamp dbg_dummies to 0..MAX_CLIENTS-1 + if(MAX_CLIENTS <= g_Config.m_DbgDummies) + g_Config.m_DbgDummies = MAX_CLIENTS; if(g_Config.m_DbgDummies) { for(int i = 0; i < g_Config.m_DbgDummies ; i++) - OnClientConnected(Server()->MaxClients() -i-1, true, false); + OnClientConnected(MAX_CLIENTS -i-1, true, false); } #endif } diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 651d24fa..139b65e3 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -88,7 +88,7 @@ void IGameController::DoActivityCheck() for(int j = 0; j < MAX_CLIENTS; ++j) if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS) ++Spectators; - if(Spectators >= Server()->MaxClients() - g_Config.m_SvPlayerSlots) + if(Spectators >= g_Config.m_SvMaxClients - g_Config.m_SvPlayerSlots) Server()->Kick(i, "Kicked for inactivity"); else DoTeamChange(GameServer()->m_apPlayers[i], TEAM_SPECTATORS); From 24344703236b667b766a64f7f876a3ae4e543564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 12:11:05 +0100 Subject: [PATCH 076/479] calculate header height and factor less often --- src/game/client/components/menus_browser.cpp | 31 +++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 7963c096..83e2f090 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -979,8 +979,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { CUIRect Headers, Status; - float SpacingH = 2.0f; - float ButtonHeight = 20.0f; + const float SpacingH = 2.0f; + const float ButtonHeight = 20.0f; + const float HeaderHeight = GetListHeaderHeight(); + const float HeightFactor = GetListHeaderHeightFactor(); // background RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), (Client()->State() == IClient::STATE_OFFLINE) ? CUI::CORNER_ALL : CUI::CORNER_B|CUI::CORNER_TR, 5.0f); @@ -991,7 +993,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) View.VSplitRight(20.0f, &View, &Scroll); } - View.HSplitTop(GetListHeaderHeight(), &Headers, &View); + View.HSplitTop(HeaderHeight, &Headers, &View); View.HSplitBottom(ButtonHeight*3.0f+SpacingH*2.0f, &View, &Status); Headers.VSplitRight(2.f, &Headers, 0); // some margin on the right @@ -1001,7 +1003,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { if(ms_aBrowserCols[i].m_Direction == -1) { - Headers.VSplitLeft(ms_aBrowserCols[i].m_Width*GetListHeaderHeightFactor(), &ms_aBrowserCols[i].m_Rect, &Headers); + Headers.VSplitLeft(ms_aBrowserCols[i].m_Width*HeightFactor, &ms_aBrowserCols[i].m_Rect, &Headers); if(i+1 < NUM_BROWSER_COLS) { @@ -1014,7 +1016,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { if(ms_aBrowserCols[i].m_Direction == 1) { - Headers.VSplitRight(ms_aBrowserCols[i].m_Width*GetListHeaderHeightFactor(), &Headers, &ms_aBrowserCols[i].m_Rect); + Headers.VSplitRight(ms_aBrowserCols[i].m_Width*HeightFactor, &Headers, &ms_aBrowserCols[i].m_Rect); Headers.VSplitRight(2, &Headers, &ms_aBrowserCols[i].m_Spacer); } } @@ -1253,7 +1255,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); } - float ItemHeight = GetListHeaderHeight(); + float ItemHeight = HeaderHeight; if(!m_SidebarActive && IsSelected && m_ShowServerDetails) { ItemHeight *= 6.0f; @@ -1557,21 +1559,22 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // show lists // only ~10 buttons will be displayed at once, a sliding window of 20 buttons ought to be enough static CButtonContainer s_FriendJoinButtons[20]; + const float HeaderHeight = GetListHeaderHeight(); int ButtonId = 0; for(int i = 0; i < NUM_FRIEND_TYPES; ++i) { CUIRect Header; char aBuf[64] = { 0 }; - View.HSplitTop(GetListHeaderHeight(), &Header, &View); + View.HSplitTop(HeaderHeight, &Header, &View); if(s_ListExtended[i]) { // entries for(int f = 0; f < m_lFriendList[i].size(); ++f, ++ButtonId) { if(i == FRIEND_OFF) - View.HSplitTop(8.0f + GetListHeaderHeight(), &Rect, &View); + View.HSplitTop(8.0f + HeaderHeight, &Rect, &View); else - View.HSplitTop(20.0f + GetListHeaderHeight(), &Rect, &View); + View.HSplitTop(20.0f + HeaderHeight, &Rect, &View); s_ScrollRegion.AddRect(Rect); if(i == FRIEND_PLAYER_ON) RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 1.0f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); @@ -1594,7 +1597,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // info if(m_lFriendList[i][f].m_pServerInfo) { - Rect.HSplitTop(GetListHeaderHeight(), &Button, &Rect); + Rect.HSplitTop(HeaderHeight, &Button, &Rect); Button.VSplitLeft(2.0f, 0, &Button); if(m_lFriendList[i][f].m_IsPlayer) str_format(aBuf, sizeof(aBuf), Localize("Playing '%s' on '%s'", "Playing '(gametype)' on '(map)'"), m_lFriendList[i][f].m_pServerInfo->m_aGameType, m_lFriendList[i][f].m_pServerInfo->m_aMap); @@ -1615,7 +1618,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) Rect.VSplitRight(15.0f, &Button, 0); if(m_lFriendList[i][f].m_pServerInfo) { - Button.Margin((Button.h - GetListHeaderHeight() + 2.0f) / 2, &Button); + Button.Margin((Button.h - HeaderHeight + 2.0f) / 2, &Button); if(DoButton_Menu(&(s_FriendJoinButtons[ButtonId%20]), Localize("Join", "Join a server"), 0, &Button) ) { SetServerBrowserAddress(m_lFriendList[i][f].m_pServerInfo->m_aAddress); @@ -1651,21 +1654,21 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) s_ScrollRegion.End(); // add friend - BottomArea.HSplitTop(GetListHeaderHeight(), &Button, &BottomArea); + BottomArea.HSplitTop(HeaderHeight, &Button, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Name"), FontSize, CUI::ALIGN_LEFT); static char s_aName[MAX_NAME_LENGTH] = { 0 }; static float s_OffsetName = 0.0f; DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), Button.h*ms_FontmodHeight*0.8f, &s_OffsetName); - BottomArea.HSplitTop(GetListHeaderHeight(), &Button, &BottomArea); + BottomArea.HSplitTop(HeaderHeight, &Button, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Clan"), FontSize, CUI::ALIGN_LEFT); static char s_aClan[MAX_CLAN_LENGTH] = { 0 }; static float s_OffsetClan = 0.0f; DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), Button.h*ms_FontmodHeight*0.8f, &s_OffsetClan); - BottomArea.HSplitTop(GetListHeaderHeight(), &Button, &BottomArea); + BottomArea.HSplitTop(HeaderHeight, &Button, &BottomArea); RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); if(s_aName[0] || s_aClan[0]) Button.VSplitLeft(Button.h, &Icon, &Label); From f5a915ee369dbd59fa777e3aaf6c982581b0e65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 12:34:25 +0100 Subject: [PATCH 077/479] separate DoFooter from DoStart and remove direct dependence on GetListHeaderHeight() --- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 9 ++++++-- src/game/client/components/menus_demo.cpp | 4 ++-- src/game/client/components/menus_ingame.cpp | 8 +++---- src/game/client/components/menus_listbox.cpp | 23 +++++++++++-------- src/game/client/components/menus_settings.cpp | 22 +++++++++--------- 6 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 37a80a86..fd6781d0 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2010,7 +2010,7 @@ int CMenus::Render() s_ActSelection = FilterInfo.m_Country; static CListBox s_ListBox(this); int OldSelected = -1; - s_ListBox.DoStart(40.0f, 0, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); + s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 16977341..d410db39 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -251,20 +251,25 @@ class CMenus : public CComponent int m_ListBoxNumItems; int m_ListBoxItemsPerRow; bool m_ListBoxItemActivated; + const char *m_pBottomText; + float m_FooterHeight; CScrollRegion m_ScrollRegion; vec2 m_ScrollOffset; char m_aFilterString[64]; float m_OffsetFilter; + protected: + CListboxItem DoNextRow(); + public: CListBox(CMenus *pMenus); void DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight = 20.0f, float Spacing = 2.0f); bool DoFilter(float FilterHeight = 20.0f, float Spacing = 2.0f); - void DoStart(float RowHeight, const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, + void DoFooter(const char *pBottomText, float FooterHeight = 20.0f); // call before DoStart to create a footer + void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect = 0, bool Background = true, bool *pActive = 0); CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = 0); - CListboxItem DoNextRow(); int DoEnd(bool *pItemActivated); bool FilterMatches(const char *pNeedle); }; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 6a23fddb..328069c4 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -377,8 +377,8 @@ void CMenus::RenderDemoList(CUIRect MainView) MainView.HSplitTop(MainView.h - BackgroundHeight - 2 * HMargin, &ListBox, &MainView); static CListBox s_ListBox(this); - s_ListBox.DoHeader(&ListBox, Localize("Recorded"), 20.0f, 2.0f); - s_ListBox.DoStart(20.0f, 0, m_lDemos.size(), 1, m_DemolistSelectedIndex); + s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); + s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { CListboxItem Item = s_ListBox.DoNextItem((void*)(&r.front())); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index e01119a5..54b393a6 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -505,8 +505,8 @@ bool CMenus::RenderServerControlServer(CUIRect MainView) { static CListBox s_ListBox(this); CUIRect List = MainView; - s_ListBox.DoHeader(&List, Localize("Option")); - s_ListBox.DoStart(20.0f, 0, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); + s_ListBox.DoHeader(&List, Localize("Option"), GetListHeaderHeight()); + s_ListBox.DoStart(20.0f, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { @@ -554,8 +554,8 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) static CListBox s_ListBox(this); CUIRect List = MainView; - s_ListBox.DoHeader(&List, Localize("Player")); - s_ListBox.DoStart(20.0f, 0, NumOptions, 1, Selected, 0, true); + s_ListBox.DoHeader(&List, Localize("Player"), GetListHeaderHeight()); + s_ListBox.DoStart(20.0f, NumOptions, 1, Selected, 0, true); for(int i = 0; i < NumOptions; i++) { diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 364c99d1..1d5efe0d 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -27,12 +27,11 @@ void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, CUIRect View = *pRect; // background - const float Height = m_pMenus->GetListHeaderHeight(); - View.HSplitTop(Height+Spacing, &Header, 0); + View.HSplitTop(HeaderHeight+Spacing, &Header, 0); m_pMenus->RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); // draw header - View.HSplitTop(Height, &Header, &View); + View.HSplitTop(HeaderHeight, &Header, &View); Header.y += 2.0f; m_pMenus->UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); @@ -70,8 +69,13 @@ bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) return Changed; } -void CMenus::CListBox::DoStart(float RowHeight, - const char *pBottomText, int NumItems, int ItemsPerRow, int SelectedIndex, +void CMenus::CListBox::DoFooter(const char *pBottomText, float FooterHeight) +{ + m_pBottomText = pBottomText; + m_FooterHeight = FooterHeight; +} + +void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect, bool Background, bool *pActive) { CUIRect View; @@ -79,20 +83,19 @@ void CMenus::CListBox::DoStart(float RowHeight, View = *pRect; else View = m_ListBoxView; - CUIRect Footer; // background if(Background) m_pMenus->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); // draw footers - if(pBottomText) + if(m_pBottomText) { - const float Height = m_pMenus->GetListHeaderHeight(); - View.HSplitBottom(Height, &View, &Footer); + CUIRect Footer; + View.HSplitBottom(m_FooterHeight, &View, &Footer); Footer.VSplitLeft(10.0f, 0, &Footer); Footer.y += 2.0f; - m_pMenus->UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + m_pMenus->UI()->DoLabel(&Footer, m_pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } // setup the variables diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index f7c64788..7570198f 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -427,9 +427,9 @@ void CMenus::RenderSkinSelection(CUIRect MainView) m_pSelectedSkin = 0; int OldSelected = -1; - s_ListBox.DoHeader(&MainView, Localize("Skins")); + s_ListBox.DoHeader(&MainView, Localize("Skins"), GetListHeaderHeight()); m_RefreshSkinSelector = s_ListBox.DoFilter(); - s_ListBox.DoStart(50.0f, 0, s_paSkinList.size(), 10, OldSelected); + s_ListBox.DoStart(50.0f, s_paSkinList.size(), 10, OldSelected); for(int i = 0; i < s_paSkinList.size(); ++i) { @@ -506,9 +506,9 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } static int OldSelected = -1; - s_ListBox.DoHeader(&MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected])); + s_ListBox.DoHeader(&MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected]), GetListHeaderHeight()); s_InitSkinPartList = s_ListBox.DoFilter(); - s_ListBox.DoStart(50.0f, 0, s_paList[m_TeePartSelected].size(), 5, OldSelected); + s_ListBox.DoStart(50.0f, s_paList[m_TeePartSelected].size(), 5, OldSelected); for(int i = 0; i < s_paList[m_TeePartSelected].size(); ++i) { @@ -784,9 +784,9 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) int OldSelected = s_SelectedLanguage; if(Header) - s_ListBox.DoHeader(&MainView, Localize("Language")); + s_ListBox.DoHeader(&MainView, Localize("Language"), GetListHeaderHeight()); bool IsActive = m_ActiveListBox == ACTLB_LANG; - s_ListBox.DoStart(20.0f, 0, s_Languages.size(), 1, s_SelectedLanguage, Header?0:&MainView, Header, &IsActive); + s_ListBox.DoStart(20.0f, s_Languages.size(), 1, s_SelectedLanguage, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { @@ -849,9 +849,9 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) int OldSelected = s_SelectedTheme; if(Header) - s_ListBox.DoHeader(&MainView, Localize("Theme")); + s_ListBox.DoHeader(&MainView, Localize("Theme"), GetListHeaderHeight()); bool IsActive = m_ActiveListBox == ACTLB_THEME; - s_ListBox.DoStart(20.0f, 0, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header, &IsActive); + s_ListBox.DoStart(20.0f, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = m_lThemes.all(); !r.empty(); r.pop_front()) { @@ -1212,8 +1212,8 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) MainView.HSplitTop(10.0f, 0, &MainView); static CListBox s_ListBox(this); int OldSelected = -1; - s_ListBox.DoHeader(&MainView, Localize("Country")); - s_ListBox.DoStart(40.0f, 0, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); + s_ListBox.DoHeader(&MainView, Localize("Country"), GetListHeaderHeight()); + s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -1671,7 +1671,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, int OldSelected = -1; char aBuf[32]; - pListBox->DoStart(20.0f, 0, lModes.size(), 1, OldSelected, pRect); + pListBox->DoStart(20.0f, lModes.size(), 1, OldSelected, pRect); for(int i = 0; i < lModes.size(); ++i) { From 98a4e304df61c377bc797302b54bb13331a8034c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 12:44:05 +0100 Subject: [PATCH 078/479] remove most references to CMenus from CListBox --- src/game/client/components/menus.h | 6 +++- src/game/client/components/menus_listbox.cpp | 30 +++++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index d410db39..e2e945af 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -239,7 +239,11 @@ class CMenus : public CComponent class CListBox { private: - CMenus *m_pMenus; + CMenus *m_pMenus; // TODO: refactor to remove this + CRenderTools *m_pRenderTools; + CUI *m_pUI; + IInput *m_pInput; + CUIRect m_ListBoxView; float m_ListBoxRowHeight; int m_ListBoxItemIndex; diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 1d5efe0d..ce57c5e6 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -13,7 +13,11 @@ CMenus::CListBox::CListBox(CMenus *pMenus) : m_ScrollRegion(pMenus) { - m_pMenus = pMenus; + m_pMenus = pMenus; // TODO: Refactor in order to remove this reference to menus + m_pRenderTools = pMenus->RenderTools(); + m_pUI = pMenus->UI(); + m_pInput = pMenus->Input(); + m_ScrollOffset = vec2(0,0); m_ListBoxUpdateScroll = false; m_aFilterString[0] = '\0'; @@ -28,12 +32,12 @@ void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, // background View.HSplitTop(HeaderHeight+Spacing, &Header, 0); - m_pMenus->RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); + m_pRenderTools->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); // draw header View.HSplitTop(HeaderHeight, &Header, &View); Header.y += 2.0f; - m_pMenus->UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + m_pUI->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); View.HSplitTop(Spacing, &Header, &View); @@ -48,7 +52,7 @@ bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) // background View.HSplitTop(FilterHeight+Spacing, &Filter, 0); - m_pMenus->RenderTools()->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); + m_pRenderTools->DrawUIRect(&Filter, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 5.0f); // draw filter View.HSplitTop(FilterHeight, &Filter, &View); @@ -59,7 +63,7 @@ bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) CUIRect Label, EditBox; Filter.VSplitLeft(Filter.w/5.0f, &Label, &EditBox); Label.y += Spacing; - m_pMenus->UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); + m_pUI->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_CENTER); bool Changed = m_pMenus->DoEditBox(m_aFilterString, &EditBox, m_aFilterString, sizeof(m_aFilterString), FontSize, &m_OffsetFilter); View.HSplitTop(Spacing, &Filter, &View); @@ -86,7 +90,7 @@ void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, i // background if(Background) - m_pMenus->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + m_pRenderTools->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); // draw footers if(m_pBottomText) @@ -95,7 +99,7 @@ void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, i View.HSplitBottom(m_FooterHeight, &View, &Footer); Footer.VSplitLeft(10.0f, 0, &Footer); Footer.y += 2.0f; - m_pMenus->UI()->DoLabel(&Footer, m_pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + m_pUI->DoLabel(&Footer, m_pBottomText, Footer.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } // setup the variables @@ -163,7 +167,7 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected CListboxItem Item = DoNextRow(); static bool s_ItemClicked = false; - if(Item.m_Visible && m_pMenus->UI()->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) + if(Item.m_Visible && m_pUI->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) { s_ItemClicked = true; m_ListBoxNewSelected = ThisItemIndex; @@ -182,20 +186,20 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected { m_ListBoxDoneEvents = 1; - if(m_pMenus->m_EnterPressed || (s_ItemClicked && m_pMenus->Input()->MouseDoubleClick())) + if(m_pMenus->m_EnterPressed || (s_ItemClicked && m_pInput->MouseDoubleClick())) { m_ListBoxItemActivated = true; - m_pMenus->UI()->SetActiveItem(0); + m_pUI->SetActiveItem(0); } } CUIRect r = Item.m_Rect; - m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); + m_pRenderTools->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); } - /*else*/ if(m_pMenus->UI()->HotItem() == pId) + /*else*/ if(m_pUI->HotItem() == pId) { CUIRect r = Item.m_Rect; - m_pMenus->RenderTools()->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); + m_pRenderTools->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); } return Item; From d6b309f1929c5fb190823140abda0ded6f246f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 12:52:14 +0100 Subject: [PATCH 079/479] remove references of CScrollRegion to CMenus --- src/game/client/components/menus.h | 5 +- .../client/components/menus_scrollregion.cpp | 47 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e2e945af..1e677031 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -198,7 +198,10 @@ class CMenus : public CComponent class CScrollRegion { private: - CMenus *m_pMenus; + CRenderTools *m_pRenderTools; + CUI *m_pUI; + IInput *m_pInput; + float m_ScrollY; float m_ContentH; float m_RequestScrollY; // [0, ContentHeight] diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index d2c194af..288e9a30 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -14,7 +14,10 @@ CMenus::CScrollRegion::CScrollRegion(CMenus *pMenus) { - m_pMenus = pMenus; + m_pRenderTools = pMenus->RenderTools(); + m_pUI = pMenus->UI(); + m_pInput = pMenus->Input(); + m_ScrollY = 0; m_ContentH = 0; m_RequestScrollY = -1; @@ -28,8 +31,8 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS if(pParams) m_Params = *pParams; - m_WasClipped = m_pMenus->UI()->IsClipped(); - m_OldClipRect = *m_pMenus->UI()->ClipArea(); + m_WasClipped = m_pUI->IsClipped(); + m_OldClipRect = *m_pUI->ClipArea(); const bool ContentOverflows = m_ContentH > pClipRect->h; const bool ForceShowScrollbar = m_Params.m_Flags&CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; @@ -43,15 +46,15 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS if(ContentOverflows || ForceShowScrollbar) { if(m_Params.m_ScrollbarBgColor.a > 0) - m_pMenus->RenderTools()->DrawRoundRect(&ScrollBarBg, m_Params.m_ScrollbarBgColor, 4.0f); + m_pRenderTools->DrawRoundRect(&ScrollBarBg, m_Params.m_ScrollbarBgColor, 4.0f); if(m_Params.m_RailBgColor.a > 0) - m_pMenus->RenderTools()->DrawRoundRect(&m_RailRect, m_Params.m_RailBgColor, m_RailRect.w/2.0f); + m_pRenderTools->DrawRoundRect(&m_RailRect, m_Params.m_RailBgColor, m_RailRect.w/2.0f); } if(!ContentOverflows) m_ContentScrollOff.y = 0; if(m_Params.m_ClipBgColor.a > 0) - m_pMenus->RenderTools()->DrawRoundRect(pClipRect, m_Params.m_ClipBgColor, 4.0f); + m_pRenderTools->DrawRoundRect(pClipRect, m_Params.m_ClipBgColor, 4.0f); CUIRect ClipRect = *pClipRect; if(m_WasClipped) @@ -64,7 +67,7 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS ClipRect = Intersection; } - m_pMenus->UI()->ClipEnable(&ClipRect); + m_pUI->ClipEnable(&ClipRect); m_ClipRect = *pClipRect; m_ContentH = 0; @@ -73,9 +76,9 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS void CMenus::CScrollRegion::End() { - m_pMenus->UI()->ClipDisable(); + m_pUI->ClipDisable(); if(m_WasClipped) - m_pMenus->UI()->ClipEnable(&m_OldClipRect); + m_pUI->ClipEnable(&m_OldClipRect); // only show scrollbar if content overflows if(m_ContentH <= m_ClipRect.h) @@ -84,11 +87,11 @@ void CMenus::CScrollRegion::End() // scroll wheel CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; - if(m_pMenus->UI()->MouseInside(&RegionRect)) + if(m_pUI->MouseInside(&RegionRect)) { - if(m_pMenus->Input()->KeyPress(KEY_MOUSE_WHEEL_UP)) + if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_UP)) m_ScrollY -= m_Params.m_ScrollSpeed; - else if(m_pMenus->Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN)) + else if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_DOWN)) m_ScrollY += m_Params.m_ScrollSpeed; } @@ -111,28 +114,28 @@ void CMenus::CScrollRegion::End() bool Hovered = false; bool Grabbed = false; const void* pID = &m_ScrollY; - int Inside = m_pMenus->UI()->MouseInside(&Slider); + int Inside = m_pUI->MouseInside(&Slider); if(Inside) { - m_pMenus->UI()->SetHotItem(pID); + m_pUI->SetHotItem(pID); - if(!m_pMenus->UI()->CheckActiveItem(pID) && m_pMenus->UI()->MouseButtonClicked(0)) + if(!m_pUI->CheckActiveItem(pID) && m_pUI->MouseButtonClicked(0)) { - m_pMenus->UI()->SetActiveItem(pID); - m_MouseGrabStart.y = m_pMenus->UI()->MouseY(); + m_pUI->SetActiveItem(pID); + m_MouseGrabStart.y = m_pUI->MouseY(); } Hovered = true; } - if(m_pMenus->UI()->CheckActiveItem(pID) && !m_pMenus->UI()->MouseButton(0)) - m_pMenus->UI()->SetActiveItem(0); + if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) + m_pUI->SetActiveItem(0); // move slider - if(m_pMenus->UI()->CheckActiveItem(pID) && m_pMenus->UI()->MouseButton(0)) + if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) { - float my = m_pMenus->UI()->MouseY(); + float my = m_pUI->MouseY(); m_ScrollY += my - m_MouseGrabStart.y; m_MouseGrabStart.y = my; @@ -148,7 +151,7 @@ void CMenus::CScrollRegion::End() else if(Hovered) SliderColor = m_Params.m_SliderColorHover; - m_pMenus->RenderTools()->DrawRoundRect(&Slider, SliderColor, Slider.w/2.0f); + m_pRenderTools->DrawRoundRect(&Slider, SliderColor, Slider.w/2.0f); } void CMenus::CScrollRegion::AddRect(CUIRect Rect) From 04555317343822ac63150b53636ffc9f6007b862 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 14:20:39 +0100 Subject: [PATCH 080/479] fixed some issues with the last commit --- src/engine/server/server.cpp | 3 ++- src/engine/shared/network_server.cpp | 1 + src/game/server/gamecontext.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 98d0de8d..e98d944e 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1140,7 +1140,7 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) pPacker->AddInt(PlayerCount); // num players pPacker->AddInt(g_Config.m_SvPlayerSlots); // max players pPacker->AddInt(ClientCount); // num clients - pPacker->AddInt(g_Config.m_SvMaxClients); // max clients + pPacker->AddInt(max(ClientCount, g_Config.m_SvMaxClients)); // max clients if(Token != -1) { @@ -1738,6 +1738,7 @@ void CServer::RegisterCommands() Console()->Chain("password", ConchainSpecialInfoupdate, this); Console()->Chain("sv_max_clients", ConchainMaxclientsUpdate, this); + Console()->Chain("sv_max_clients", ConchainSpecialInfoupdate, this); Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this); Console()->Chain("mod_command", ConchainModCommandUpdate, this); Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this); diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 5c56d8e5..dd8dc648 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -180,6 +180,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { const char FullMsg[] = "This server is full"; CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); + continue; } // only allow a specific number of players with the same ip diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 732af911..70c0841c 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1557,6 +1557,7 @@ void CGameContext::OnInit() Console()->Chain("sv_vote_spectate", ConchainSettingUpdate, this); Console()->Chain("sv_teambalance_time", ConchainSettingUpdate, this); Console()->Chain("sv_player_slots", ConchainSettingUpdate, this); + Console()->Chain("sv_max_clients", ConchainSettingUpdate, this); Console()->Chain("sv_scorelimit", ConchainGameinfoUpdate, this); Console()->Chain("sv_timelimit", ConchainGameinfoUpdate, this); From 50610c92acccf8ec444a2262303bfd2f31240584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 14:52:46 +0100 Subject: [PATCH 081/479] change config vars to ui_server_address and ui_server_address_lan --- src/game/client/components/menus_browser.cpp | 12 ++++++------ src/game/variables.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 83e2f090..18da5c20 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1367,7 +1367,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(BrowserType == IServerBrowser::TYPE_INTERNET) { static float s_InternetAddressOffset = 0.0f; - if(DoEditBox(&g_Config.m_UiInternetServerAddress, &EditBox, g_Config.m_UiInternetServerAddress, sizeof(g_Config.m_UiInternetServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -1375,7 +1375,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) else if(BrowserType == IServerBrowser::TYPE_LAN) { static float s_LanAddressOffset = 0.0f; - if(DoEditBox(&g_Config.m_UiLanServerAddress, &EditBox, g_Config.m_UiLanServerAddress, sizeof(g_Config.m_UiLanServerAddress), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&g_Config.m_UiServerAddressLan, &EditBox, g_Config.m_UiServerAddressLan, sizeof(g_Config.m_UiServerAddressLan), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -2407,9 +2407,9 @@ const char *CMenus::GetServerBrowserAddress() { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - return g_Config.m_UiInternetServerAddress; + return g_Config.m_UiServerAddress; else if(Type == IServerBrowser::TYPE_LAN) - return g_Config.m_UiLanServerAddress; + return g_Config.m_UiServerAddressLan; return 0; } @@ -2417,9 +2417,9 @@ void CMenus::SetServerBrowserAddress(const char *pAddress) { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - str_copy(g_Config.m_UiInternetServerAddress, pAddress, sizeof(g_Config.m_UiInternetServerAddress)); + str_copy(g_Config.m_UiServerAddress, pAddress, sizeof(g_Config.m_UiServerAddress)); else if(Type == IServerBrowser::TYPE_LAN) - str_copy(g_Config.m_UiLanServerAddress, pAddress, sizeof(g_Config.m_UiLanServerAddress)); + str_copy(g_Config.m_UiServerAddressLan, pAddress, sizeof(g_Config.m_UiServerAddressLan)); } void CMenus::ServerBrowserFilterOnUpdate() diff --git a/src/game/variables.h b/src/game/variables.h index 9345ba61..1065f36e 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -79,8 +79,8 @@ MACRO_CONFIG_STR(PlayerSkinEyes, player_skin_eyes, 24, "standard", CFGFLAG_CLIEN MACRO_CONFIG_INT(UiBrowserPage, ui_browser_page, 5, 5, 8, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface serverbrowser page") MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 5, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface settings page") -MACRO_CONFIG_STR(UiInternetServerAddress, ui_internet_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (Internet page)") -MACRO_CONFIG_STR(UiLanServerAddress, ui_lan_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (LAN page)") +MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (Internet page)") +MACRO_CONFIG_STR(UiServerAddressLan, ui_server_address_lan, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (LAN page)") MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor") MACRO_CONFIG_INT(UiAutoswitchInfotab, ui_autoswitch_infotab, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Switch to the info tab when clicking on a server") MACRO_CONFIG_INT(UiWideview, ui_wideview, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Extended menus GUI") From d0d857ba4478a533eb4a9e31f09d34ccca3fd53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 18:02:25 +0100 Subject: [PATCH 082/479] implement clicking on scrollregion scrollbar to scroll (closes #2429) --- src/game/client/components/menus_scrollregion.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 288e9a30..1b0ad8bc 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -114,9 +114,10 @@ void CMenus::CScrollRegion::End() bool Hovered = false; bool Grabbed = false; const void* pID = &m_ScrollY; - int Inside = m_pUI->MouseInside(&Slider); + const bool InsideSlider = m_pUI->MouseInside(&Slider); + const bool InsideRail = m_pUI->MouseInside(&m_RailRect); - if(Inside) + if(InsideSlider) { m_pUI->SetHotItem(pID); @@ -128,6 +129,12 @@ void CMenus::CScrollRegion::End() Hovered = true; } + else if(InsideRail && m_pUI->MouseButton(0)) + { + const float SliderDistance = m_pUI->MouseY() - (Slider.y+Slider.h/2); + m_ScrollY += sign(SliderDistance) * log(abs(SliderDistance)); // slow down to reasonable scroll speed; keep sign with logarithm + Hovered = true; + } if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) m_pUI->SetActiveItem(0); From 3eb03f843fbb44ad98122dab5f2d732f1d27f91a Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 21:04:55 +0100 Subject: [PATCH 083/479] fixed ordering when notifying clients about max clients update --- src/engine/server/server.cpp | 15 +++++++++++++++ src/engine/server/server.h | 1 + src/game/server/gamecontext.cpp | 2 -- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index e98d944e..98a8e29c 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1654,11 +1654,25 @@ void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserD } } +void CServer::ConchainPlayerSlotsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + if(pResult->NumArguments()) + { + if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) + g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; + } +} + void CServer::ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); if(pResult->NumArguments()) + { + if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) + g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; ((CServer *)pUserData)->m_NetServer.SetMaxClients(pResult->GetInteger(0)); + } } void CServer::ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -1737,6 +1751,7 @@ void CServer::RegisterCommands() Console()->Chain("sv_name", ConchainSpecialInfoupdate, this); Console()->Chain("password", ConchainSpecialInfoupdate, this); + Console()->Chain("sv_player_slots", ConchainPlayerSlotsUpdate, this); Console()->Chain("sv_max_clients", ConchainMaxclientsUpdate, this); Console()->Chain("sv_max_clients", ConchainSpecialInfoupdate, this); Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 31e600e5..c3baf7dc 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -268,6 +268,7 @@ class CServer : public IServer static void ConSaveConfig(IConsole::IResult *pResult, void *pUser); static void ConLogout(IConsole::IResult *pResult, void *pUser); static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + static void ConchainPlayerSlotsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 70c0841c..5d43101b 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1458,8 +1458,6 @@ void CGameContext::ConchainSettingUpdate(IConsole::IResult *pResult, void *pUser if(pResult->NumArguments()) { CGameContext *pSelf = (CGameContext *)pUserData; - if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; pSelf->SendSettings(-1); } } From 60fd161f06bcda1f66c2ca1b9f1d6eb91fd9d97b Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 26 Jan 2020 21:35:16 +0100 Subject: [PATCH 084/479] Improve json style in automapper rules --- datasrc/editor/automap/desert_main.json | 141 +++++++++----------- datasrc/editor/automap/jungle_main.json | 167 +++++++++++------------- 2 files changed, 141 insertions(+), 167 deletions(-) diff --git a/datasrc/editor/automap/desert_main.json b/datasrc/editor/automap/desert_main.json index f9519cd9..bccd461c 100644 --- a/datasrc/editor/automap/desert_main.json +++ b/datasrc/editor/automap/desert_main.json @@ -10,7 +10,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, @@ -20,7 +20,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, @@ -30,7 +30,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 450 }, @@ -40,7 +40,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 450 }, @@ -50,7 +50,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 450 }, @@ -60,104 +60,93 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 450 }, { "index": 16, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, - - ], + {"x": 0, "y": -1, "value": "empty"} + ] }, { "index": 17, "condition": [ - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 18, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, - - ], + {"x": 0, "y": 1, "value": "empty"} + ] }, { "index": 19, "condition": [ - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 33, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 32, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 35, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 34, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 51, "condition": [ {"x": -1, "y": 1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 50, "condition": [ {"x": 1, "y": 1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 49, "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - - ], + {"x": 0, "y": -1, "value": "full"} + ] }, { "index": 48, "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - ], + {"x": 0, "y": -1, "value": "full"} + ] }] } }, @@ -172,7 +161,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -182,7 +171,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -192,7 +181,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -202,7 +191,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -212,7 +201,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -222,7 +211,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -232,7 +221,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -242,7 +231,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -252,7 +241,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -262,7 +251,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -272,7 +261,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, @@ -282,93 +271,93 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 500 }, { "index": 96, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, - ], + {"x": 0, "y": -1, "value": "empty"} + ] }, { "index": 97, "condition": [ - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 98, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} ], }, { "index": 99, "condition": [ - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 113, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 112, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 115, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 114, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 131, "condition": [ {"x": -1, "y": 1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 130, "condition": [ {"x": 1, "y": 1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 129, "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - ], + {"x": 0, "y": -1, "value": "full"} + ] }, { "index": 128, "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - ], + {"x": 0, "y": -1, "value": "full"} + ] }] } }] diff --git a/datasrc/editor/automap/jungle_main.json b/datasrc/editor/automap/jungle_main.json index 11fe7276..da4fda85 100644 --- a/datasrc/editor/automap/jungle_main.json +++ b/datasrc/editor/automap/jungle_main.json @@ -10,7 +10,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 200 }, @@ -20,70 +20,67 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 200 }, { "index": 16, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, - - ], + {"x": 0, "y": -1, "value": "empty"} + ] }, { "index": 96, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} ], "random": 15 }, { "index": 97, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} ], "random": 15 }, { "index": 98, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, + {"x": 0, "y": -1, "value": "empty"} ], "random": 15 }, { "index": 21, "condition": [ - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 52, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, - - ], + {"x": 0, "y": 1, "value": "empty"} + ] }, { "index": 99, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} ], "random": 10 }, { "index": 100, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} ], "random": 10 }, { "index": 101, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, + {"x": 0, "y": 1, "value": "empty"} ], "random": 10 }, @@ -91,42 +88,38 @@ "index": 21, "hflip": 1, "condition": [ - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 5, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 5, "hflip": 1, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 37, "hflip": 1, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 39, "hflip": 1, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, + {"x": -1, "y": 0, "value": "empty"} ], "random": 2 }, @@ -134,15 +127,14 @@ "index": 37, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 39, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, + {"x": 1, "y": 0, "value": "empty"} ], "random": 2 }, @@ -151,9 +143,8 @@ "condition": [ {"x": -1, "y": 1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 53, @@ -161,7 +152,7 @@ "condition": [ {"x": -1, "y": 1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, + {"x": 0, "y": 1, "value": "full"} ], "random": 2 }, @@ -171,16 +162,15 @@ "condition": [ {"x": 1, "y": 1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 53, "condition": [ {"x": 1, "y": 1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, + {"x": 0, "y": 1, "value": "full"} ], "random": 2 }, @@ -190,16 +180,15 @@ "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - - ], + {"x": 0, "y": -1, "value": "full"} + ] }, { "index": 49, "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": -1, "value": "full"} ], "random": 3 }, @@ -209,7 +198,7 @@ "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": -1, "value": "full"} ], "random": 3 }, @@ -218,9 +207,8 @@ "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - - ], + {"x": 0, "y": -1, "value": "full"} + ] }, { "index": 49, @@ -228,7 +216,7 @@ "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": -1, "value": "full"} ], "random": 3 }, @@ -238,7 +226,7 @@ "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, + {"x": 0, "y": -1, "value": "full"} ], "random": 3 }, @@ -247,9 +235,8 @@ "condition": [ {"x": -1, "y": 0, "value": "empty"}, {"x": -1, "y": 1, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 22, @@ -257,26 +244,24 @@ "condition": [ {"x": 1, "y": 0, "value": "empty"}, {"x": 1, "y": 1, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 33, "condition": [ {"x": 0, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "empty"}, - {"x": 1, "y": 1, "value": "full"}, - - ], + {"x": 1, "y": 1, "value": "full"} + ] }, { "index": 32, "condition": [ {"x": 0, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "empty"}, - {"x": -1, "y": 1, "value": "full"}, - ], + {"x": -1, "y": 1, "value": "full"} + ] }] } }, @@ -291,7 +276,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, @@ -301,7 +286,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, @@ -311,7 +296,7 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, @@ -321,93 +306,93 @@ {"x": 0, "y": 1, "value": "full"}, {"x": 0, "y": -1, "value": "full"}, {"x": 1, "y": 0, "value": "full"}, - {"x": -1, "y": 0, "value": "full"}, + {"x": -1, "y": 0, "value": "full"} ], "random": 150 }, { "index": 26, "condition": [ - {"x": 0, "y": -1, "value": "empty"}, - ], + {"x": 0, "y": -1, "value": "empty"} + ] }, { "index": 25, "condition": [ - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 10, "condition": [ - {"x": 0, "y": 1, "value": "empty"}, - ], + {"x": 0, "y": 1, "value": "empty"} + ] }, { "index": 24, "condition": [ - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 9, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 8, "condition": [ {"x": 0, "y": -1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 40, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": -1, "y": 0, "value": "empty"}, - ], + {"x": -1, "y": 0, "value": "empty"} + ] }, { "index": 41, "condition": [ {"x": 0, "y": 1, "value": "empty"}, - {"x": 1, "y": 0, "value": "empty"}, - ], + {"x": 1, "y": 0, "value": "empty"} + ] }, { "index": 12, "condition": [ {"x": -1, "y": 1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 11, "condition": [ {"x": 1, "y": 1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": 1, "value": "full"}, - ], + {"x": 0, "y": 1, "value": "full"} + ] }, { "index": 27, "condition": [ {"x": 1, "y": -1, "value": "empty"}, {"x": 1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - ], + {"x": 0, "y": -1, "value": "full"} + ] }, { "index": 28, "condition": [ {"x": -1, "y": -1, "value": "empty"}, {"x": -1, "y": 0, "value": "full"}, - {"x": 0, "y": -1, "value": "full"}, - ], + {"x": 0, "y": -1, "value": "full"} + ] }] } }] From f6abc9433a0f559dec7c5011686ec3afe4ce832b Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 21:54:30 +0100 Subject: [PATCH 085/479] some refactoring and network shutdown fixes --- src/engine/server/server.cpp | 13 +++------- src/engine/shared/econ.cpp | 3 +-- src/engine/shared/network.h | 17 +++++-------- src/engine/shared/network_console.cpp | 22 +++++++---------- src/engine/shared/network_server.cpp | 35 +++++++++------------------ 5 files changed, 31 insertions(+), 59 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 98a8e29c..93f29f96 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1318,14 +1318,12 @@ int CServer::Run() BindAddr.port = g_Config.m_SvPort; } - if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0)) + if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) { dbg_msg("server", "couldn't open socket. port %d might already be in use", g_Config.m_SvPort); return -1; } - m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this); - m_Econ.Init(Console(), &m_ServerBan); char aBuf[256]; @@ -1470,13 +1468,8 @@ int CServer::Run() } } // disconnect all clients on shutdown - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(m_aClients[i].m_State != CClient::STATE_EMPTY) - m_NetServer.Drop(i, "Server shutdown"); - - m_Econ.Shutdown(); - } + m_NetServer.Close(); + m_Econ.Shutdown(); GameServer()->OnShutdown(); m_pMap->Unload(); diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp index 1e3e7936..f568564b 100644 --- a/src/engine/shared/econ.cpp +++ b/src/engine/shared/econ.cpp @@ -87,9 +87,8 @@ void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan) BindAddr.port = g_Config.m_EcPort; } - if(m_NetConsole.Open(BindAddr, pNetBan, 0)) + if(m_NetConsole.Open(BindAddr, pNetBan, NewClientCallback, DelClientCallback, this)) { - m_NetConsole.SetCallbacks(NewClientCallback, DelClientCallback, this); m_Ready = true; char aBuf[128]; str_format(aBuf, sizeof(aBuf), "bound to %s:%d", g_Config.m_EcBindaddr, g_Config.m_EcPort); diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 5964cec9..594582d8 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -425,13 +425,10 @@ class CNetServer CNetTokenManager m_TokenManager; CNetTokenCache m_TokenCache; - int m_Flags; public: - int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); - // - bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags); - int Close(); + bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); + void Close(); // the token parameter is only used for connless packets int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0); @@ -440,7 +437,7 @@ class CNetServer void AddToken(const NETADDR *pAddr, TOKEN Token) { m_TokenCache.AddToken(pAddr, Token, 0); }; // - int Drop(int ClientID, const char *pReason); + void Drop(int ClientID, const char *pReason); // status requests const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } @@ -471,11 +468,9 @@ class CNetConsole CNetRecvUnpacker m_RecvUnpacker; public: - void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); - // - bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int Flags); - int Close(); + bool Open(NETADDR BindAddr, class CNetBan *pNetBan, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); + void Close(); // int Recv(char *pLine, int MaxLength, int *pClientID = 0); @@ -484,7 +479,7 @@ class CNetConsole // int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr); - int Drop(int ClientID, const char *pReason); + void Drop(int ClientID, const char *pReason); // status requests const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } diff --git a/src/engine/shared/network_console.cpp b/src/engine/shared/network_console.cpp index bdd3b096..c30872a0 100644 --- a/src/engine/shared/network_console.cpp +++ b/src/engine/shared/network_console.cpp @@ -8,7 +8,7 @@ #include "network.h" -bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, int Flags) +bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) { // zero out the whole structure mem_zero(this, sizeof(*this)); @@ -28,34 +28,30 @@ bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, int Flags) for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) m_aSlots[i].m_Connection.Reset(); - return true; -} - -void CNetConsole::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) -{ m_pfnNewClient = pfnNewClient; m_pfnDelClient = pfnDelClient; m_UserPtr = pUser; + + return true; } -int CNetConsole::Close() +void CNetConsole::Close() { for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) - m_aSlots[i].m_Connection.Disconnect("closing console"); + Drop(i, "Closing console"); net_tcp_close(m_Socket); - - return 0; } -int CNetConsole::Drop(int ClientID, const char *pReason) +void CNetConsole::Drop(int ClientID, const char *pReason) { + if(ClientID < 0 || ClientID >= NET_MAX_CONSOLE_CLIENTS || m_aSlots[ClientID].m_Connection.State() == NET_CONNSTATE_OFFLINE) + return; + if(m_pfnDelClient) m_pfnDelClient(ClientID, pReason, m_UserPtr); m_aSlots[ClientID].m_Connection.Disconnect(pReason); - - return 0; } int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr) diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index dd8dc648..c0c3544c 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -9,7 +9,7 @@ #include "network.h" -bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags) +bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) { // zero out the whole structure mem_zero(this, sizeof(*this)); @@ -31,42 +31,31 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma for(int i = 0; i < NET_MAX_CLIENTS; i++) m_aSlots[i].m_Connection.Init(m_Socket, true); - m_Flags = Flags; - - return true; -} - -int CNetServer::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) -{ m_pfnNewClient = pfnNewClient; m_pfnDelClient = pfnDelClient; m_UserPtr = pUser; - return 0; + + return true; } -int CNetServer::Close() +void CNetServer::Close() { - // TODO: implement me - return 0; + for(int i = 0; i < NET_MAX_CLIENTS; i++) + Drop(i, "Server shutdown"); + + net_udp_close(m_Socket); } -int CNetServer::Drop(int ClientID, const char *pReason) +void CNetServer::Drop(int ClientID, const char *pReason) { - // TODO: insert lots of checks here - /*NETADDR Addr = ClientAddr(ClientID); - - dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"", - ClientID, - Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], - pReason - );*/ + if(ClientID < 0 || ClientID >= NET_MAX_CLIENTS || m_aSlots[ClientID].m_Connection.State() == NET_CONNSTATE_OFFLINE) + return; + if(m_pfnDelClient) m_pfnDelClient(ClientID, pReason, m_UserPtr); m_aSlots[ClientID].m_Connection.Disconnect(pReason); m_NumClients--; - - return 0; } int CNetServer::Update() From b6adba9a35d23ab2f38d82545d7732db1d8929fd Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 22:09:56 +0100 Subject: [PATCH 086/479] fixed json style when saving filter settings --- src/game/client/components/menus_browser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 18da5c20..ecd3a74a 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -261,10 +261,10 @@ void CMenus::SaveFilters() io_write(File, p, str_length(p)); for(int i = 0; i < IServerBrowser::NUM_TYPES; i++) { - str_format(aBuf, sizeof(aBuf), "\t\t%d,\n", m_aSelectedFilters[i]); + str_format(aBuf, sizeof(aBuf), "\t\t%d%s\n", m_aSelectedFilters[i], i < IServerBrowser::NUM_TYPES-1 ? "," : ""); io_write(File, aBuf, str_length(aBuf)); } - p = "\t],\n"; + p = "\t]\n"; io_write(File, p, str_length(p)); // settings end @@ -313,7 +313,7 @@ void CMenus::SaveFilters() io_write(File, aBuf, str_length(aBuf)); str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_address\": \"%s\",\n", FilterInfo.m_aAddress); io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_country\": %d,\n\t\t\t}", FilterInfo.m_Country); + str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_country\": %d\n\t\t\t}", FilterInfo.m_Country); io_write(File, aBuf, str_length(aBuf)); // part end From bcd3e8dfb41b6c2af9bedc8b0abe17f3f922f548 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 22:14:14 +0100 Subject: [PATCH 087/479] fixed building fake_server --- src/tools/fake_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp index 2dfcc366..2fba98a2 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, 0)) + if(!pNet->Open(BindAddr, 0, 0, 0, 0, 0, 0)) return 0; while(1) From 45368daa9eac0b83d6a9aac37269a991ee80c28b Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 26 Jan 2020 22:34:59 +0100 Subject: [PATCH 088/479] fixed navigating with arrow keys in the server browser --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index ecd3a74a..b8c72391 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1243,7 +1243,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && m_aSelectedServers[BrowserType] == ServerIndex; - if(!str_comp(pItem->m_aAddress, pAddress)) + if(!(m_AddressSelection&ADDR_SELECTION_UPDATE_ADDRESS) && !str_comp(pItem->m_aAddress, pAddress)) { if(!IsSelected) { From 70b89cf15e1be5421c88ce7cd2b57a5f5580620b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 23:08:27 +0100 Subject: [PATCH 089/479] add CJsonWriter --- CMakeLists.txt | 2 + src/engine/shared/jsonwriter.cpp | 162 +++++++++++++++++++++++++++++++ src/engine/shared/jsonwriter.h | 79 +++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 src/engine/shared/jsonwriter.cpp create mode 100644 src/engine/shared/jsonwriter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4482bbf6..168fa7e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1323,6 +1323,8 @@ set_src(ENGINE_SHARED GLOB src/engine/shared filecollection.h huffman.cpp huffman.h + jsonwriter.cpp + jsonwriter.h jobs.cpp jobs.h kernel.cpp diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp new file mode 100644 index 00000000..63664cb1 --- /dev/null +++ b/src/engine/shared/jsonwriter.cpp @@ -0,0 +1,162 @@ +/* (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 "jsonwriter.h" + +CJsonWriter::CJsonWriter(IOHANDLE io) +{ + m_IO = io; + m_pState = 0; // no root created yet + m_Indentation = 0; +} + +CJsonWriter::~CJsonWriter() +{ + io_close(m_IO); + + while(m_pState != 0) + { + CState *pState = m_pState; + m_pState = m_pState->m_pParent; + delete pState; + } +} + +void CJsonWriter::BeginObject() +{ + dbg_assert(CanWriteDatatype(), "Cannot write object at this position"); + WriteIndent(false); + WriteInternal("{"); + PushState(OBJECT); +} + +void CJsonWriter::EndObject() +{ + dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Cannot end object here"); + PopState(); + CompleteDataType(); + WriteIndent(true); + WriteInternal("}"); + +} + +void CJsonWriter::BeginArray() +{ + dbg_assert(CanWriteDatatype(), "Cannot write array at this position"); + WriteIndent(false); + WriteInternal("["); + PushState(ARRAY); +} + +void CJsonWriter::EndArray() +{ + dbg_assert(m_pState != 0 && m_pState->m_State == ARRAY, "Cannot end array here"); + PopState(); + CompleteDataType(); + WriteIndent(true); + WriteInternal("]"); +} + +void CJsonWriter::BeginAttribute(const char *pName) +{ + dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Attribute can only be written inside of objects"); + WriteIndent(false); + WriteInternal("\""); + WriteInternal(pName); + WriteInternal("\""); + WriteInternal(" : "); + PushState(ATTRIBUTE); +} + +void CJsonWriter::WriteStrValue(const char *pValue) +{ + dbg_assert(CanWriteDatatype(), "Cannot write value at this position"); + WriteIndent(false); + WriteInternal("\""); + WriteInternal(pValue); + WriteInternal("\""); + CompleteDataType(); +} + +void CJsonWriter::WriteIntValue(int Value) +{ + dbg_assert(CanWriteDatatype(), "Cannot write value at this position"); + WriteIndent(false); + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%d", Value); + WriteInternal(aBuf); + CompleteDataType(); +} + +void CJsonWriter::WriteBoolValue(bool Value) +{ + dbg_assert(CanWriteDatatype(), "Cannot write value at this position"); + WriteIndent(false); + WriteInternal(Value ? "true" : "false"); + CompleteDataType(); +} + +void CJsonWriter::WriteNullValue() +{ + dbg_assert(CanWriteDatatype(), "Cannot write value at this position"); + WriteIndent(false); + WriteInternal("null"); + CompleteDataType(); +} + +bool CJsonWriter::CanWriteDatatype() +{ + return m_pState == 0 + || m_pState->m_State == ARRAY + || m_pState->m_State == ATTRIBUTE; +} + +inline void CJsonWriter::WriteInternal(const char *pStr) +{ + io_write(m_IO, pStr, str_length(pStr)); +} + +void CJsonWriter::WriteIndent(bool EndElement) +{ + const bool NotRootOrAttribute = m_pState != 0 && m_pState->m_State != ATTRIBUTE; + + if(NotRootOrAttribute && !m_pState->m_Empty && !EndElement) + WriteInternal(","); + + if(NotRootOrAttribute || EndElement) + io_write_newline(m_IO); + + if(NotRootOrAttribute) + for(int i = 0; i < m_Indentation; i++) + WriteInternal("\t"); +} + +void CJsonWriter::PushState(EState NewState) +{ + if(m_pState != 0) + m_pState->m_Empty = false; + m_pState = new CState(NewState, m_pState); + if(NewState != ATTRIBUTE) + m_Indentation++; +} + +CJsonWriter::EState CJsonWriter::PopState() +{ + dbg_assert(m_pState != 0, "Stack is empty"); + EState Result = m_pState->m_State; + CState *pToDelete = m_pState; + m_pState = m_pState->m_pParent; + delete pToDelete; + if(Result != ATTRIBUTE) + m_Indentation--; + return Result; +} + +void CJsonWriter::CompleteDataType() +{ + if(m_pState != 0 && m_pState->m_State == ATTRIBUTE) + PopState(); // automatically complete the attribute + + if(m_pState != 0) + m_pState->m_Empty = false; +} \ No newline at end of file diff --git a/src/engine/shared/jsonwriter.h b/src/engine/shared/jsonwriter.h new file mode 100644 index 00000000..9bac7c2a --- /dev/null +++ b/src/engine/shared/jsonwriter.h @@ -0,0 +1,79 @@ +/* (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_SHARED_JSONWRITER_H +#define ENGINE_SHARED_JSONWRITER_H + +#include + +class CJsonWriter +{ + enum EState + { + OBJECT, + ARRAY, + ATTRIBUTE + }; + + class CState + { + public: + EState m_State; + CState *m_pParent; + bool m_Empty; + + CState(EState State, CState *pParent) + { + m_State = State; + m_pParent = pParent; + m_Empty = true; + }; + }; + + IOHANDLE m_IO; + + CState *m_pState; + int m_Indentation; + + bool CanWriteDatatype(); + inline void WriteInternal(const char *pStr); + void WriteIndent(bool EndElement); + void PushState(EState NewState); + EState PopState(); + void CompleteDataType(); + +public: + // Create a new writer object without writing anything to the file yet. + // The file will automatically be closed by the destructor. + CJsonWriter(IOHANDLE io); + ~CJsonWriter(); + + // The root is created by beginning the first datatype (object, array, value). + // The writer must not be used after ending the root, which must be unique. + + // Begin writing a new object + void BeginObject(); + // End current object + void EndObject(); + + // Begin writing a new array + void BeginArray(); + // End current array + void EndArray(); + + // Begin attribute with the given name inside the current object. + // Names inside one object should be unique, but this is not checked here. + // Must be used to write anything inside objects and only there. + // Is automatically ended when the value is ended. + void BeginAttribute(const char *pName); + + // Methods for writing value literals + // - As array values in arrays + // - As attribute values after beginning an attribute inside an object + // - As root value (only once) + void WriteStrValue(const char *pValue); + void WriteIntValue(int Value); + void WriteBoolValue(bool Value); + void WriteNullValue(); +}; + +#endif From 81e883a9ad6d035860d9913104d51c143e2d0329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 23:08:57 +0100 Subject: [PATCH 090/479] use json writer for serverlist --- src/engine/client/serverbrowser.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 51a3ff9d..52a41885 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -638,22 +639,12 @@ void CServerBrowser::SaveServerlist() if(!File) return; - char aBuf[512]; - - // server list - const char *p = "{\"serverlist\": [\n"; - io_write(File, p, str_length(p)); - + CJsonWriter Writer(File); + Writer.BeginObject(); // root + Writer.BeginAttribute("serverlist"); + Writer.BeginArray(); for(int i = 0; i < m_aServerlist[IServerBrowser::TYPE_INTERNET].m_NumServers; ++i) - { - // entry - str_format(aBuf, sizeof(aBuf), "\t\"%s\",\n", m_aServerlist[IServerBrowser::TYPE_INTERNET].m_ppServerlist[i]->m_Info.m_aAddress); - io_write(File, aBuf, str_length(aBuf)); - } - - // server list end - p = "\t]\n}\n"; - io_write(File, p, str_length(p)); - - io_close(File); + Writer.WriteStrValue(m_aServerlist[IServerBrowser::TYPE_INTERNET].m_ppServerlist[i]->m_Info.m_aAddress); + Writer.EndArray(); + Writer.EndObject(); } From bcb6fd92197feec5ebebc8729d726bef5c9f227b Mon Sep 17 00:00:00 2001 From: Flyingsky Date: Sun, 26 Jan 2020 23:30:21 +0100 Subject: [PATCH 091/479] Dropping glu dependency --- bam.lua | 1 - readme.md | 4 ++-- src/engine/client/backend_sdl.cpp | 8 ++------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/bam.lua b/bam.lua index cf251fb1..6811529c 100644 --- a/bam.lua +++ b/bam.lua @@ -208,7 +208,6 @@ function GenerateLinuxSettings(settings, conf, arch, compiler) -- Client settings.link.libs:Add("X11") settings.link.libs:Add("GL") - settings.link.libs:Add("GLU") BuildClient(settings) -- Content diff --git a/readme.md b/readme.md index fb8b833d..342efe46 100644 --- a/readme.md +++ b/readme.md @@ -34,10 +34,10 @@ Installing dependencies sudo apt install build-essential cmake git libfreetype6-dev libsdl2-dev libpnglite-dev libwavpack-dev python3 # Fedora - sudo dnf install @development-tools cmake gcc-c++ git freetype-devel mesa-libGLU-devel pnglite-devel python3 SDL2-devel wavpack-devel + sudo dnf install @development-tools cmake gcc-c++ git freetype-devel pnglite-devel python3 SDL2-devel wavpack-devel # Arch Linux (doesn't have pnglite in its repositories) - sudo pacman -S --needed base-devel cmake freetype2 git glu python sdl2 wavpack + sudo pacman -S --needed base-devel cmake freetype2 git python sdl2 wavpack # macOS brew install cmake freetype sdl2 diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 5ba66fcd..8dcf16ec 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -1,11 +1,6 @@ #include #include "SDL.h" #include "SDL_opengl.h" -#if defined(CONF_PLATFORM_MACOSX) -#include "OpenGL/glu.h" -#else -#include "GL/glu.h" -#endif #include @@ -375,7 +370,8 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer:: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData); } // calculate memory usage From 7518f685dcef61e8ca3743349658ecc233372649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 23:09:34 +0100 Subject: [PATCH 092/479] use json writer for ui_settings --- src/game/client/components/menus_browser.cpp | 129 +++++++++---------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b8c72391..3669350a 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -247,85 +248,77 @@ void CMenus::SaveFilters() if(!File) return; - char aBuf[512]; + CJsonWriter Writer(File); + + Writer.BeginObject(); // root // settings - const char *p = "{\"settings\": {\n"; - io_write(File, p, str_length(p)); - - str_format(aBuf, sizeof(aBuf), "\t\"sidebar_active\": %d,\n", m_SidebarActive); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\"sidebar_tab\": %d,\n", m_SidebarTab); - io_write(File, aBuf, str_length(aBuf)); - p = "\t\"filters\": [\n"; - io_write(File, p, str_length(p)); - for(int i = 0; i < IServerBrowser::NUM_TYPES; i++) - { - str_format(aBuf, sizeof(aBuf), "\t\t%d%s\n", m_aSelectedFilters[i], i < IServerBrowser::NUM_TYPES-1 ? "," : ""); - io_write(File, aBuf, str_length(aBuf)); - } - p = "\t]\n"; - io_write(File, p, str_length(p)); - - // settings end - p = "},\n"; - io_write(File, p, str_length(p)); - - // filter - p = " \"filter\": ["; - io_write(File, p, str_length(p)); + Writer.BeginAttribute("settings"); + Writer.BeginObject(); + { + Writer.BeginAttribute("sidebar_active"); + Writer.WriteIntValue(m_SidebarActive); + + Writer.BeginAttribute("sidebar_tab"); + Writer.WriteIntValue(m_SidebarTab); + Writer.BeginAttribute("filters"); + Writer.BeginArray(); + for(int i = 0; i < IServerBrowser::NUM_TYPES; i++) + Writer.WriteIntValue(m_aSelectedFilters[i]); + Writer.EndArray(); + } + Writer.EndObject(); + + // filter + Writer.BeginAttribute("filter"); + Writer.BeginArray(); for(int i = 0; i < m_lFilters.size(); i++) { // part start - if(i == 0) - p = "\n"; - else - p = ",\n"; - io_write(File, p, str_length(p)); + Writer.BeginObject(); + Writer.BeginAttribute(m_lFilters[i].Name()); + Writer.BeginObject(); + { + Writer.BeginAttribute("type"); + Writer.WriteIntValue(m_lFilters[i].Custom()); - str_format(aBuf, sizeof(aBuf), "\t{\"%s\": {\n", m_lFilters[i].Name()); - io_write(File, aBuf, str_length(aBuf)); + // filter setting + CServerFilterInfo FilterInfo; + m_lFilters[i].GetFilter(&FilterInfo); - str_format(aBuf, sizeof(aBuf), "\t\t\"type\": %d,\n", m_lFilters[i].Custom()); - io_write(File, aBuf, str_length(aBuf)); + Writer.BeginAttribute("settings"); + Writer.BeginObject(); + { + Writer.BeginAttribute("filter_hash"); + Writer.WriteIntValue(FilterInfo.m_SortHash); - // filter setting - CServerFilterInfo FilterInfo; - m_lFilters[i].GetFilter(&FilterInfo); - - str_format(aBuf, sizeof(aBuf), "\t\t\"settings\": {\n"); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_hash\": %d,\n", FilterInfo.m_SortHash); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_gametype\": ["); - io_write(File, aBuf, str_length(aBuf)); - for(unsigned j = 0; j < CServerFilterInfo::MAX_GAMETYPES && FilterInfo.m_aGametype[j][0]; ++j) - { - str_format(aBuf, sizeof(aBuf), "\n\t\t\t\t\"%s\",", FilterInfo.m_aGametype[j]); - io_write(File, aBuf, str_length(aBuf)); + Writer.BeginAttribute("filter_gametype"); + Writer.BeginArray(); + for(unsigned j = 0; j < CServerFilterInfo::MAX_GAMETYPES && FilterInfo.m_aGametype[j][0]; ++j) + Writer.WriteStrValue(FilterInfo.m_aGametype[j]); + Writer.EndArray(); + + Writer.BeginAttribute("filter_ping"); + Writer.WriteIntValue(FilterInfo.m_Ping); + + Writer.BeginAttribute("filter_serverlevel"); + Writer.WriteIntValue(FilterInfo.m_ServerLevel); + + Writer.BeginAttribute("filter_address"); + Writer.WriteStrValue(FilterInfo.m_aAddress); + + Writer.BeginAttribute("filter_country"); + Writer.WriteIntValue(FilterInfo.m_Country); + } + Writer.EndObject(); } - p = "\n\t\t\t],\n"; - io_write(File, p, str_length(p)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_ping\": %d,\n", FilterInfo.m_Ping); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_serverlevel\": %d,\n", FilterInfo.m_ServerLevel); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_address\": \"%s\",\n", FilterInfo.m_aAddress); - io_write(File, aBuf, str_length(aBuf)); - str_format(aBuf, sizeof(aBuf), "\t\t\t\"filter_country\": %d\n\t\t\t}", FilterInfo.m_Country); - io_write(File, aBuf, str_length(aBuf)); - - // part end - p = "\n\t\t}\n\t}"; - io_write(File, p, str_length(p)); - } - - // filter end - p = "]\n}"; - io_write(File, p, str_length(p)); + Writer.EndObject(); + Writer.EndObject(); + } + Writer.EndArray(); - io_close(File); + Writer.EndObject(); // end root } void CMenus::RemoveFilter(int FilterIndex) From b178a345ed08a350412157279ff7a384255564ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 23:27:57 +0100 Subject: [PATCH 093/479] move SaveSkinfile to CSkins and refactor using json writer --- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 1 - src/game/client/components/menus_settings.cpp | 72 ------------------- src/game/client/components/skins.cpp | 59 ++++++++++++++- src/game/client/components/skins.h | 2 + 5 files changed, 60 insertions(+), 76 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index fd6781d0..ae250177 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2247,7 +2247,7 @@ int CMenus::Render() if(m_aSaveSkinName[0] && m_aSaveSkinName[0] != 'x' && m_aSaveSkinName[1] != '_') { m_Popup = POPUP_NONE; - SaveSkinfile(); + m_pClient->m_pSkins->SaveSkinfile(m_aSaveSkinName); m_aSaveSkinName[0] = 0; m_RefreshSkinSelector = true; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 1e677031..0b39ec5b 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -423,7 +423,6 @@ class CMenus : public CComponent int m_TeePartSelected; char m_aSaveSkinName[24]; - void SaveSkinfile(); bool m_RefreshSkinSelector; const CSkins::CSkin *m_pSelectedSkin; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 7570198f..9285c610 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -80,78 +80,6 @@ int CMenus::DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle return UI()->DoButtonLogic(pBC->GetID(), "", 0, pRect); } -void CMenus::SaveSkinfile() -{ - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "skins/%s.json", m_aSaveSkinName); - IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_SAVE); - if(!File) - return; - - // file start - const char *p = "{\"skin\": {"; - io_write(File, p, str_length(p)); - int Count = 0; - - for(int PartIndex = 0; PartIndex < NUM_SKINPARTS; PartIndex++) - { - if(!CSkins::ms_apSkinVariables[PartIndex][0]) - continue; - - // part start - if(Count == 0) - { - p = "\n"; - io_write(File, p, str_length(p)); - } - else - { - p = ",\n"; - io_write(File, p, str_length(p)); - } - str_format(aBuf, sizeof(aBuf), "\t\"%s\": {\n", CSkins::ms_apSkinPartNames[PartIndex]); - io_write(File, aBuf, str_length(aBuf)); - - // part content - str_format(aBuf, sizeof(aBuf), "\t\t\"filename\": \"%s\",\n", CSkins::ms_apSkinVariables[PartIndex]); - io_write(File, aBuf, str_length(aBuf)); - - str_format(aBuf, sizeof(aBuf), "\t\t\"custom_colors\": \"%s\"", *CSkins::ms_apUCCVariables[PartIndex]?"true":"false"); - io_write(File, aBuf, str_length(aBuf)); - - if(*CSkins::ms_apUCCVariables[PartIndex]) - { - for(int c = 0; c < CSkins::NUM_COLOR_COMPONENTS-1; c++) - { - int Val = (*CSkins::ms_apColorVariables[PartIndex] >> (2-c)*8) & 0xff; - str_format(aBuf, sizeof(aBuf), ",\n\t\t\"%s\": %d", CSkins::ms_apColorComponents[c], Val); - io_write(File, aBuf, str_length(aBuf)); - } - if(PartIndex == SKINPART_MARKING) - { - int Val = (*CSkins::ms_apColorVariables[PartIndex] >> 24) & 0xff; - str_format(aBuf, sizeof(aBuf), ",\n\t\t\"%s\": %d", CSkins::ms_apColorComponents[3], Val); - io_write(File, aBuf, str_length(aBuf)); - } - } - - // part end - p = "\n\t}"; - io_write(File, p, str_length(p)); - - ++Count; - } - - // file end - p = "}\n}\n"; - io_write(File, p, str_length(p)); - - io_close(File); - - // add new skin to the skin list - m_pClient->m_pSkins->AddSkin(m_aSaveSkinName); -} - void CMenus::RenderHSLPicker(CUIRect MainView) { CUIRect Label, Button, Picker; diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 0f359908..c525919d 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "skins.h" @@ -165,9 +166,9 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) bool UseCustomColors = false; const json_value &rColour = rPart["custom_colors"]; if(rColour.type == json_string) - { UseCustomColors = str_comp((const char *)rColour, "true") == 0; - } + else if(rColour.type == json_boolean) + UseCustomColors = rColour.u.boolean; Skin.m_aUseCustomColors[PartIndex] = UseCustomColors; // color components @@ -500,3 +501,57 @@ bool CSkins::ValidateSkinParts(char* aPartNames[NUM_SKINPARTS], int* aUseCustomC return true; } + +void CSkins::SaveSkinfile(const char *pSaveSkinName) +{ + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "skins/%s.json", pSaveSkinName); + IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_SAVE); + if(!File) + return; + + CJsonWriter Writer(File); + + Writer.BeginObject(); + Writer.BeginAttribute("skin"); + Writer.BeginObject(); + for(int PartIndex = 0; PartIndex < NUM_SKINPARTS; PartIndex++) + { + if(!ms_apSkinVariables[PartIndex][0]) + continue; + + // part start + Writer.BeginAttribute(ms_apSkinPartNames[PartIndex]); + Writer.BeginObject(); + { + Writer.BeginAttribute("filename"); + Writer.WriteStrValue(ms_apSkinVariables[PartIndex]); + + const bool CustomColors = *ms_apUCCVariables[PartIndex]; + Writer.BeginAttribute("custom_colors"); + Writer.WriteBoolValue(CustomColors); + + if(CustomColors) + { + for(int c = 0; c < NUM_COLOR_COMPONENTS-1; c++) + { + int Val = (*ms_apColorVariables[PartIndex] >> (2-c)*8) & 0xff; + Writer.BeginAttribute(ms_apColorComponents[c]); + Writer.WriteIntValue(Val); + } + if(PartIndex == SKINPART_MARKING) + { + int Val = (*ms_apColorVariables[PartIndex] >> 24) & 0xff; + Writer.BeginAttribute(ms_apColorComponents[3]); + Writer.WriteIntValue(Val); + } + } + } + Writer.EndObject(); + } + Writer.EndObject(); + Writer.EndObject(); + + // add new skin to the skin list + AddSkin(pSaveSkinName); +} diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index cef50aa0..3b9b9c54 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -75,6 +75,8 @@ class CSkins : public CComponent // returns true if everything was valid and nothing changed bool ValidateSkinParts(char *aPartNames[NUM_SKINPARTS], int *aUseCustomColors, int* aPartColors, int GameFlags) const; + void SaveSkinfile(const char *pSaveSkinName); + private: int m_ScanningPart; sorted_array m_aaSkinParts[NUM_SKINPARTS]; From 5b390835fee2002e4277e4b19940498ead001cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 Jan 2020 23:53:31 +0100 Subject: [PATCH 094/479] fix alphabetical order of files in CMakeList --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 168fa7e2..f2992165 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1323,10 +1323,10 @@ set_src(ENGINE_SHARED GLOB src/engine/shared filecollection.h huffman.cpp huffman.h - jsonwriter.cpp - jsonwriter.h jobs.cpp jobs.h + jsonwriter.cpp + jsonwriter.h kernel.cpp linereader.cpp linereader.h From 04df49e319ff5f3579be7f19ea2045712ee6fd02 Mon Sep 17 00:00:00 2001 From: Flyingsky Date: Sun, 26 Jan 2020 23:58:55 +0100 Subject: [PATCH 095/479] Cleaning up remains of glu --- CMakeLists.txt | 4 ++-- bam.lua | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4482bbf6..262cb50b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,7 +394,7 @@ endif() if(TARGET_OS STREQUAL "windows") set(PLATFORM_CLIENT) - set(PLATFORM_CLIENT_LIBS opengl32 glu32 winmm) + set(PLATFORM_CLIENT_LIBS opengl32 winmm) set(PLATFORM_LIBS ws2_32) # Windows sockets elseif(TARGET_OS STREQUAL "mac") find_library(CARBON Carbon) @@ -410,7 +410,7 @@ else() set(PLATFORM_CLIENT) find_package(OpenGL) find_package(X11) - set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${X11_X11_LIB}) + set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) set(PLATFORM_CLIENT_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH}) if(TARGET_OS STREQUAL "linux") set(PLATFORM_LIBS rt) # clock_gettime for glibc < 2.17 diff --git a/bam.lua b/bam.lua index 6811529c..d879883c 100644 --- a/bam.lua +++ b/bam.lua @@ -271,7 +271,6 @@ function GenerateWindowsSettings(settings, conf, target_arch, compiler) settings.link.extrafiles:Add(icons.client) settings.link.extrafiles:Add(manifests.client) settings.link.libs:Add("opengl32") - settings.link.libs:Add("glu32") settings.link.libs:Add("winmm") BuildClient(settings) From 3892014ef80533f69f66e77f9e139d1035ac80ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 17:16:01 +0100 Subject: [PATCH 096/479] escape special characters in json strings and attributes --- src/engine/shared/jsonwriter.cpp | 37 ++++++++++++++++++++++++++------ src/engine/shared/jsonwriter.h | 1 + 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index 63664cb1..a86550c8 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -61,9 +61,7 @@ void CJsonWriter::BeginAttribute(const char *pName) { dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Attribute can only be written inside of objects"); WriteIndent(false); - WriteInternal("\""); - WriteInternal(pName); - WriteInternal("\""); + WriteInternalEscaped(pName); WriteInternal(" : "); PushState(ATTRIBUTE); } @@ -72,9 +70,7 @@ void CJsonWriter::WriteStrValue(const char *pValue) { dbg_assert(CanWriteDatatype(), "Cannot write value at this position"); WriteIndent(false); - WriteInternal("\""); - WriteInternal(pValue); - WriteInternal("\""); + WriteInternalEscaped(pValue); CompleteDataType(); } @@ -116,6 +112,35 @@ inline void CJsonWriter::WriteInternal(const char *pStr) io_write(m_IO, pStr, str_length(pStr)); } +void CJsonWriter::WriteInternalEscaped(const char *pStr) +{ + WriteInternal("\""); + for(int OldPosition = 0, Position = str_utf8_forward(pStr, OldPosition); + OldPosition != Position; + OldPosition = Position, Position = str_utf8_forward(pStr, OldPosition)) + { + int Diff = Position - OldPosition; + if(Diff == 1) + { + switch(*(pStr+OldPosition)) // only single bytes have values that need to be escaped + { + case '\\': WriteInternal("\\\\"); break; + case '\"': WriteInternal("\\\""); break; + case '\n': WriteInternal("\\n"); break; + case '\r': WriteInternal("\\r"); break; + case '\b': WriteInternal("\\b"); break; + case '\f': WriteInternal("\\f"); break; + default: io_write(m_IO, pStr+OldPosition, 1); break; + } + } + else if(Diff > 1) + { + io_write(m_IO, pStr+OldPosition, Diff); + } + } + WriteInternal("\""); +} + void CJsonWriter::WriteIndent(bool EndElement) { const bool NotRootOrAttribute = m_pState != 0 && m_pState->m_State != ATTRIBUTE; diff --git a/src/engine/shared/jsonwriter.h b/src/engine/shared/jsonwriter.h index 9bac7c2a..1ba36601 100644 --- a/src/engine/shared/jsonwriter.h +++ b/src/engine/shared/jsonwriter.h @@ -36,6 +36,7 @@ class CJsonWriter bool CanWriteDatatype(); inline void WriteInternal(const char *pStr); + void WriteInternalEscaped(const char *pStr); void WriteIndent(bool EndElement); void PushState(EState NewState); EState PopState(); From 86dac37199cf1d858c318a992622f67353c3480a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 17:48:30 +0100 Subject: [PATCH 097/479] fix missing margin when gametype scrollbar is shown in browser filter --- src/game/client/components/menus_browser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b8c72391..fb6f66fc 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1883,8 +1883,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) UpdateFilter = true; } - if(!NeedScrollbar) - ServerFilter.HSplitTop(LineSize - 4.f, &Button, &ServerFilter); + ServerFilter.HSplitTop(LineSize - 4.f, &Button, &ServerFilter); { int Value = FilterInfo.m_Ping, Min = 20, Max = 999; From 36ad03f77879eff9576d5ba567ee3df1f7dc3e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 21:02:14 +0100 Subject: [PATCH 098/479] rename BeginAttribute to WriteAttribute, minor comment changes --- src/engine/client/serverbrowser.cpp | 2 +- src/engine/shared/jsonwriter.cpp | 2 +- src/engine/shared/jsonwriter.h | 8 +++--- src/game/client/components/menus_browser.cpp | 28 ++++++++++---------- src/game/client/components/skins.cpp | 12 ++++----- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 52a41885..e1ed1d50 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -641,7 +641,7 @@ void CServerBrowser::SaveServerlist() CJsonWriter Writer(File); Writer.BeginObject(); // root - Writer.BeginAttribute("serverlist"); + Writer.WriteAttribute("serverlist"); Writer.BeginArray(); for(int i = 0; i < m_aServerlist[IServerBrowser::TYPE_INTERNET].m_NumServers; ++i) Writer.WriteStrValue(m_aServerlist[IServerBrowser::TYPE_INTERNET].m_ppServerlist[i]->m_Info.m_aAddress); diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index a86550c8..505d7d72 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -57,7 +57,7 @@ void CJsonWriter::EndArray() WriteInternal("]"); } -void CJsonWriter::BeginAttribute(const char *pName) +void CJsonWriter::WriteAttribute(const char *pName) { dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Attribute can only be written inside of objects"); WriteIndent(false); diff --git a/src/engine/shared/jsonwriter.h b/src/engine/shared/jsonwriter.h index 1ba36601..5d3509fb 100644 --- a/src/engine/shared/jsonwriter.h +++ b/src/engine/shared/jsonwriter.h @@ -61,11 +61,11 @@ class CJsonWriter // End current array void EndArray(); - // Begin attribute with the given name inside the current object. + // Write attribute with the given name inside the current object. // Names inside one object should be unique, but this is not checked here. - // Must be used to write anything inside objects and only there. - // Is automatically ended when the value is ended. - void BeginAttribute(const char *pName); + // Must be used to begin write anything inside objects and only there. + // Must be followed by a datatype for the attribute value. + void WriteAttribute(const char *pName); // Methods for writing value literals // - As array values in arrays diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 3669350a..8b53ff30 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -253,16 +253,16 @@ void CMenus::SaveFilters() Writer.BeginObject(); // root // settings - Writer.BeginAttribute("settings"); + Writer.WriteAttribute("settings"); Writer.BeginObject(); { - Writer.BeginAttribute("sidebar_active"); + Writer.WriteAttribute("sidebar_active"); Writer.WriteIntValue(m_SidebarActive); - Writer.BeginAttribute("sidebar_tab"); + Writer.WriteAttribute("sidebar_tab"); Writer.WriteIntValue(m_SidebarTab); - Writer.BeginAttribute("filters"); + Writer.WriteAttribute("filters"); Writer.BeginArray(); for(int i = 0; i < IServerBrowser::NUM_TYPES; i++) Writer.WriteIntValue(m_aSelectedFilters[i]); @@ -271,44 +271,44 @@ void CMenus::SaveFilters() Writer.EndObject(); // filter - Writer.BeginAttribute("filter"); + Writer.WriteAttribute("filter"); Writer.BeginArray(); for(int i = 0; i < m_lFilters.size(); i++) { // part start Writer.BeginObject(); - Writer.BeginAttribute(m_lFilters[i].Name()); + Writer.WriteAttribute(m_lFilters[i].Name()); Writer.BeginObject(); { - Writer.BeginAttribute("type"); + Writer.WriteAttribute("type"); Writer.WriteIntValue(m_lFilters[i].Custom()); // filter setting CServerFilterInfo FilterInfo; m_lFilters[i].GetFilter(&FilterInfo); - Writer.BeginAttribute("settings"); + Writer.WriteAttribute("settings"); Writer.BeginObject(); { - Writer.BeginAttribute("filter_hash"); + Writer.WriteAttribute("filter_hash"); Writer.WriteIntValue(FilterInfo.m_SortHash); - Writer.BeginAttribute("filter_gametype"); + Writer.WriteAttribute("filter_gametype"); Writer.BeginArray(); for(unsigned j = 0; j < CServerFilterInfo::MAX_GAMETYPES && FilterInfo.m_aGametype[j][0]; ++j) Writer.WriteStrValue(FilterInfo.m_aGametype[j]); Writer.EndArray(); - Writer.BeginAttribute("filter_ping"); + Writer.WriteAttribute("filter_ping"); Writer.WriteIntValue(FilterInfo.m_Ping); - Writer.BeginAttribute("filter_serverlevel"); + Writer.WriteAttribute("filter_serverlevel"); Writer.WriteIntValue(FilterInfo.m_ServerLevel); - Writer.BeginAttribute("filter_address"); + Writer.WriteAttribute("filter_address"); Writer.WriteStrValue(FilterInfo.m_aAddress); - Writer.BeginAttribute("filter_country"); + Writer.WriteAttribute("filter_country"); Writer.WriteIntValue(FilterInfo.m_Country); } Writer.EndObject(); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index c525919d..7f62be1f 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -513,7 +513,7 @@ void CSkins::SaveSkinfile(const char *pSaveSkinName) CJsonWriter Writer(File); Writer.BeginObject(); - Writer.BeginAttribute("skin"); + Writer.WriteAttribute("skin"); Writer.BeginObject(); for(int PartIndex = 0; PartIndex < NUM_SKINPARTS; PartIndex++) { @@ -521,14 +521,14 @@ void CSkins::SaveSkinfile(const char *pSaveSkinName) continue; // part start - Writer.BeginAttribute(ms_apSkinPartNames[PartIndex]); + Writer.WriteAttribute(ms_apSkinPartNames[PartIndex]); Writer.BeginObject(); { - Writer.BeginAttribute("filename"); + Writer.WriteAttribute("filename"); Writer.WriteStrValue(ms_apSkinVariables[PartIndex]); const bool CustomColors = *ms_apUCCVariables[PartIndex]; - Writer.BeginAttribute("custom_colors"); + Writer.WriteAttribute("custom_colors"); Writer.WriteBoolValue(CustomColors); if(CustomColors) @@ -536,13 +536,13 @@ void CSkins::SaveSkinfile(const char *pSaveSkinName) for(int c = 0; c < NUM_COLOR_COMPONENTS-1; c++) { int Val = (*ms_apColorVariables[PartIndex] >> (2-c)*8) & 0xff; - Writer.BeginAttribute(ms_apColorComponents[c]); + Writer.WriteAttribute(ms_apColorComponents[c]); Writer.WriteIntValue(Val); } if(PartIndex == SKINPART_MARKING) { int Val = (*ms_apColorVariables[PartIndex] >> 24) & 0xff; - Writer.BeginAttribute(ms_apColorComponents[3]); + Writer.WriteAttribute(ms_apColorComponents[3]); Writer.WriteIntValue(Val); } } From 8c3aedbf0953c8c3782f7323330ca3cb2409d434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 21:29:27 +0100 Subject: [PATCH 099/479] increase size of inline scoreboard scrollbar to fix it (finally closes #2429) --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index fb6f66fc..9d407125 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2107,7 +2107,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int static float s_ScrollValue = 0.0f; if(Width > View.w) { - View.HSplitBottom(8.0f, &View, &Scroll); + View.HSplitBottom(14.0f, &View, &Scroll); Scroll.VMargin(5.0f, &Scroll); s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); View.x += (View.w - Width) * s_ScrollValue; From d5857a793b875351778e6833959c785e60154628 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 27 Jan 2020 22:33:22 +0100 Subject: [PATCH 100/479] made base pointers for clistbox, cscrollregion static --- src/game/client/components/menus.cpp | 9 +++++- src/game/client/components/menus.h | 31 ++++++++++--------- src/game/client/components/menus_browser.cpp | 8 ++--- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_ingame.cpp | 8 ++--- src/game/client/components/menus_listbox.cpp | 7 +---- .../client/components/menus_scrollregion.cpp | 6 +--- src/game/client/components/menus_settings.cpp | 16 +++++----- 8 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index ae250177..0dc48847 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -37,6 +37,11 @@ float CMenus::ms_ButtonHeight = 25.0f; float CMenus::ms_ListheaderHeight = 17.0f; float CMenus::ms_FontmodHeight = 0.8f; +CMenus *CMenus::CUIElementBase::m_pMenus = 0; +CRenderTools *CMenus::CUIElementBase::m_pRenderTools = 0; +CUI *CMenus::CUIElementBase::m_pUI = 0; +IInput *CMenus::CUIElementBase::m_pInput = 0; + CMenus::CMenus() { @@ -2008,7 +2013,7 @@ int CMenus::Render() static int s_ActSelection = -2; if(s_ActSelection == -2) s_ActSelection = FilterInfo.m_Country; - static CListBox s_ListBox(this); + static CListBox s_ListBox; int OldSelected = -1; s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); @@ -2458,6 +2463,8 @@ void CMenus::OnConsoleInit() // expand the all filter tab by default if(UseDefaultFilters) m_lFilters[m_lFilters.size()-1].Switch(); + + CUIElementBase::Init(this); } void CMenus::OnShutdown() diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 0b39ec5b..b72deb2f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -134,6 +134,18 @@ class CMenus : public CComponent void UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing); + class CUIElementBase + { + protected: + static CMenus *m_pMenus; // TODO: Refactor in order to remove this reference to menus + static CRenderTools *m_pRenderTools; + static CUI *m_pUI; + static IInput *m_pInput; + + public: + static void Init(CMenus *pMenus) { m_pMenus = pMenus; m_pRenderTools = pMenus->RenderTools(); m_pUI = pMenus->UI(); m_pInput = pMenus->Input(); }; + }; + // Scroll region : found in menus_scrollregion.cpp struct CScrollRegionParams { @@ -172,7 +184,7 @@ class CMenus : public CComponent /* Usage: -- Initialization -- - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); s_ScrollRegion.Begin(&ScrollRegionRect, &ScrollOffset); Content = ScrollRegionRect; @@ -195,13 +207,9 @@ class CMenus : public CComponent s_ScrollRegion.End(); */ // Instances of CScrollRegion must be static, as member addresses are used as UI item IDs - class CScrollRegion + class CScrollRegion : private CUIElementBase { private: - CRenderTools *m_pRenderTools; - CUI *m_pUI; - IInput *m_pInput; - float m_ScrollY; float m_ContentH; float m_RequestScrollY; // [0, ContentHeight] @@ -221,7 +229,7 @@ class CMenus : public CComponent SCROLLHERE_BOTTOM, }; - CScrollRegion(CMenus *pMenus); + CScrollRegion(); void Begin(CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams = 0); void End(); void AddRect(CUIRect Rect); @@ -239,14 +247,9 @@ class CMenus : public CComponent }; // Instances of CListBox must be static, as member addresses are used as UI item IDs - class CListBox + class CListBox : private CUIElementBase { private: - CMenus *m_pMenus; // TODO: refactor to remove this - CRenderTools *m_pRenderTools; - CUI *m_pUI; - IInput *m_pInput; - CUIRect m_ListBoxView; float m_ListBoxRowHeight; int m_ListBoxItemIndex; @@ -269,7 +272,7 @@ class CMenus : public CComponent CListboxItem DoNextRow(); public: - CListBox(CMenus *pMenus); + CListBox(); void DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight = 20.0f, float Spacing = 2.0f); bool DoFilter(float FilterHeight = 20.0f, float Spacing = 2.0f); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 4801dd89..f5c75306 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1204,7 +1204,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } // scrollbar - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -1538,7 +1538,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) } // scrollbar - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -2084,7 +2084,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); float LineHeight = 20.0f; - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -2100,7 +2100,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int static float s_ScrollValue = 0.0f; if(Width > View.w) { - View.HSplitBottom(14.0f, &View, &Scroll); + View.HSplitBottom(8.0f, &View, &Scroll); Scroll.VMargin(5.0f, &Scroll); s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); View.x += (View.w - Width) * s_ScrollValue; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 328069c4..bb9cccc7 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -376,7 +376,7 @@ void CMenus::RenderDemoList(CUIRect MainView) CUIRect ListBox, Button, FileIcon; MainView.HSplitTop(MainView.h - BackgroundHeight - 2 * HMargin, &ListBox, &MainView); - static CListBox s_ListBox(this); + static CListBox s_ListBox; s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 54b393a6..064162ed 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -230,7 +230,7 @@ void CMenus::RenderPlayers(CUIRect MainView) MainView.Margin(5.0f, &MainView); // prepare scroll - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -483,7 +483,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) RenderTools()->DrawUIRect(&Motd, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f); Motd.Margin(5.0f, &Motd); - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); s_ScrollRegion.Begin(&Motd, &ScrollOffset); Motd.y += ScrollOffset.y; @@ -503,7 +503,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) bool CMenus::RenderServerControlServer(CUIRect MainView) { - static CListBox s_ListBox(this); + static CListBox s_ListBox; CUIRect List = MainView; s_ListBox.DoHeader(&List, Localize("Option"), GetListHeaderHeight()); s_ListBox.DoStart(20.0f, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); @@ -552,7 +552,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) const float NameWidth = 250.0f; const float ClanWidth = 250.0f; - static CListBox s_ListBox(this); + static CListBox s_ListBox; CUIRect List = MainView; s_ListBox.DoHeader(&List, Localize("Player"), GetListHeaderHeight()); s_ListBox.DoStart(20.0f, NumOptions, 1, Selected, 0, true); diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index ce57c5e6..8a34ecd3 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -11,13 +11,8 @@ #include "menus.h" -CMenus::CListBox::CListBox(CMenus *pMenus) : m_ScrollRegion(pMenus) +CMenus::CListBox::CListBox() { - m_pMenus = pMenus; // TODO: Refactor in order to remove this reference to menus - m_pRenderTools = pMenus->RenderTools(); - m_pUI = pMenus->UI(); - m_pInput = pMenus->Input(); - m_ScrollOffset = vec2(0,0); m_ListBoxUpdateScroll = false; m_aFilterString[0] = '\0'; diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 1b0ad8bc..06ed36bd 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -12,12 +12,8 @@ #include "menus.h" -CMenus::CScrollRegion::CScrollRegion(CMenus *pMenus) +CMenus::CScrollRegion::CScrollRegion() { - m_pRenderTools = pMenus->RenderTools(); - m_pUI = pMenus->UI(); - m_pInput = pMenus->Input(); - m_ScrollY = 0; m_ContentH = 0; m_RequestScrollY = -1; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 9285c610..5b2517ee 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -337,7 +337,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) void CMenus::RenderSkinSelection(CUIRect MainView) { static sorted_array s_paSkinList; - static CListBox s_ListBox(this); + static CListBox s_ListBox; if(m_RefreshSkinSelector) { s_paSkinList.clear(); @@ -414,7 +414,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { static bool s_InitSkinPartList = true; static sorted_array s_paList[6]; - static CListBox s_ListBox(this); + static CListBox s_ListBox; if(s_InitSkinPartList) { for(int p = 0; p < NUM_SKINPARTS; p++) @@ -693,7 +693,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) { static int s_SelectedLanguage = -1; static sorted_array s_Languages; - static CListBox s_ListBox(this); + static CListBox s_ListBox; if(s_Languages.size() == 0) { @@ -757,7 +757,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) { static int s_SelectedTheme = -1; - static CListBox s_ListBox(this); + static CListBox s_ListBox; if(m_lThemes.size() == 0) // not loaded yet { @@ -1138,7 +1138,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) // country flag selector MainView.HSplitTop(10.0f, 0, &MainView); - static CListBox s_ListBox(this); + static CListBox s_ListBox; int OldSelected = -1; s_ListBox.DoHeader(&MainView, Localize("Country"), GetListHeaderHeight()); s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); @@ -1467,7 +1467,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) const float HeaderHeight = 20.0f; - static CScrollRegion s_ScrollRegion(this); + static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); @@ -1875,8 +1875,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ListRec.VSplitRight(1.5f, &ListRec, 0); ListOth.VSplitLeft(1.5f, 0, &ListOth); - static CListBox s_RecListBox(this); - static CListBox s_OthListBox(this); + static CListBox s_RecListBox; + static CListBox s_OthListBox; CheckSettings |= DoResolutionList(&ListRec, &s_RecListBox, m_lRecommendedVideoModes); CheckSettings |= DoResolutionList(&ListOth, &s_OthListBox, m_lOtherVideoModes); } From 0b0bc2400c447abf4701c2f2ad83068693d1e84c Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 27 Jan 2020 22:51:34 +0100 Subject: [PATCH 101/479] added a lost merge --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index f5c75306..679f076e 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2100,7 +2100,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int static float s_ScrollValue = 0.0f; if(Width > View.w) { - View.HSplitBottom(8.0f, &View, &Scroll); + View.HSplitBottom(14.0f, &View, &Scroll); Scroll.VMargin(5.0f, &Scroll); s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); View.x += (View.w - Width) * s_ScrollValue; From 81376fdeaaffc3f51021b4309998a259525f9f28 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Mon, 27 Jan 2020 22:30:48 +0100 Subject: [PATCH 102/479] Add convenience functions to read complete files --- src/base/system.c | 83 +++++++++++++++++++++++++++++++++ src/base/system.h | 86 +++++++++++++++++++++++++++++++++++ src/engine/shared/storage.cpp | 26 +++++++++++ src/engine/storage.h | 2 + 4 files changed, 197 insertions(+) diff --git a/src/base/system.c b/src/base/system.c index c8d304b8..da552384 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -368,6 +368,49 @@ unsigned io_read(IOHANDLE io, void *buffer, unsigned size) return fread(buffer, 1, size, (FILE*)io); } +void io_read_all(IOHANDLE io, void **result, unsigned *result_len) +{ + unsigned char *buffer = malloc(1024); + unsigned len = 0; + unsigned cap = 1024; + unsigned read; + + *result = 0; + *result_len = 0; + + while((read = io_read(io, buffer + len, cap - len)) != 0) + { + len += read; + if(len == cap) + { + cap *= 2; + buffer = realloc(buffer, cap); + } + } + if(len == cap) + { + buffer = realloc(buffer, cap + 1); + } + // ensure null termination + buffer[len] = 0; + *result = buffer; + *result_len = len; +} + +char *io_read_all_str(IOHANDLE io) +{ + void *buffer; + unsigned len; + + io_read_all(io, &buffer, &len); + if(mem_has_null(buffer, len)) + { + free(buffer); + return 0; + } + return buffer; +} + unsigned io_unread_byte(IOHANDLE io, unsigned char byte) { return ungetc(byte, (FILE*)io) == EOF; @@ -1654,6 +1697,33 @@ int fs_rename(const char *oldname, const char *newname) return 0; } +int fs_read(const char *name, void **result, unsigned *result_len) +{ + IOHANDLE file = io_open(name, IOFLAG_READ); + *result = 0; + *result_len = 0; + if(!file) + { + return 1; + } + io_read_all(file, result, result_len); + io_close(file); + return 0; +} + +char *fs_read_str(const char *name) +{ + IOHANDLE file = io_open(name, IOFLAG_READ); + char *result; + if(!file) + { + return 0; + } + result = io_read_all_str(file); + io_close(file); + return result; +} + void swap_endian(void *data, unsigned elem_size, unsigned num) { char *src = (char*) data; @@ -2226,6 +2296,19 @@ int mem_comp(const void *a, const void *b, int size) return memcmp(a,b,size); } +int mem_has_null(const void *block, unsigned size) +{ + const unsigned char *bytes = block; + for(unsigned i = 0; i < size; i++) + { + if(bytes[i] == 0) + { + return 1; + } + } + return 0; +} + void net_stats(NETSTATS *stats_inout) { *stats_inout = network_stats; diff --git a/src/base/system.h b/src/base/system.h index 2fbc4d35..919b4a14 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -178,6 +178,20 @@ void mem_zero(void *block, unsigned size); */ int mem_comp(const void *a, const void *b, int size); +/* + Function: mem_has_null + Checks whether a block of memory contains null bytes. + + Parameters: + block - Pointer to the block to check for nulls. + size - Size of the block. + + Returns: + 1 - The block has a null byte. + 0 - The block does not have a null byte. +*/ +int mem_has_null(const void *block, unsigned size); + /* Group: File IO */ enum { IOFLAG_READ = 1, @@ -220,6 +234,40 @@ IOHANDLE io_open(const char *filename, int flags); */ unsigned io_read(IOHANDLE io, void *buffer, unsigned size); +/* + Function: io_read_all + Reads the rest of the file into a buffer. + + Parameters: + io - Handle to the file to read data from. + result - Receives the file's remaining contents. + result_len - Receives the file's remaining length. + + Remarks: + - Does NOT guarantee that there are no internal null bytes. + - Guarantees that result will contain zero-termination. + - The result must be freed after it has been used. +*/ +void io_read_all(IOHANDLE io, void **result, unsigned *result_len); + +/* + Function: io_read_all_str + Reads the rest of the file into a zero-terminated buffer with + no internal null bytes. + + Parameters: + io - Handle to the file to read data from. + + Returns: + The file's remaining contents or null on failure. + + Remarks: + - Guarantees that there are no internal null bytes. + - Guarantees that result will contain zero-termination. + - The result must be freed after it has been used. +*/ +char *io_read_all_str(IOHANDLE io); + /* Function: io_unread_byte "Unreads" a single byte, making it available for future read @@ -1338,6 +1386,44 @@ int fs_remove(const char *filename); */ int fs_rename(const char *oldname, const char *newname); +/* + Function: fs_read + Reads a whole file into memory and returns its contents. + + Parameters: + name - The filename to read. + result - Receives the file's contents. + result_len - Receives the file's length. + + Returns: + Returns 0 on success, 1 on failure. + + Remarks: + - Does NOT guarantee that there are no internal null bytes. + - Guarantees that result will contain zero-termination. + - The result must be freed after it has been used. +*/ +int fs_read(const char *name, void **result, unsigned *result_len); + +/* + Function: fs_read + Reads a whole file into memory and returns its contents, + guaranteeing a null-terminated string with no internal null + bytes. + + Parameters: + name - The filename to read. + + Returns: + Returns the file's contents on success, null on failure. + + Remarks: + - Guarantees that there are no internal null bytes. + - Guarantees that result will contain zero-termination. + - The result must be freed after it has been used. +*/ +char *fs_read_str(const char *name); + /* Group: Undocumented */ diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 14a39a7f..4a5fce6e 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -378,6 +378,32 @@ class CStorage : public IStorage return 0; } + bool ReadFile(const char *pFilename, int Type, void **ppResult, unsigned *pResultLen) + { + IOHANDLE File = OpenFile(pFilename, IOFLAG_READ, Type); + *ppResult = 0; + *pResultLen = 0; + if(!File) + { + return true; + } + io_read_all(File, ppResult, pResultLen); + io_close(File); + return false; + } + + char *ReadFileStr(const char *pFilename, int Type) + { + IOHANDLE File = OpenFile(pFilename, IOFLAG_READ, Type); + if(!File) + { + return 0; + } + char *pResult = io_read_all_str(File); + io_close(File); + return pResult; + } + struct CFindCBData { CStorage *m_pStorage; diff --git a/src/engine/storage.h b/src/engine/storage.h index bd19248a..3028616f 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -24,6 +24,8 @@ class IStorage : public IInterface virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0; virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0, FCheckCallback pfnCheckCB = 0, const void *pCheckCBData = 0) = 0; + virtual bool ReadFile(const char *pFilename, int Type, void **ppResult, unsigned *pResultLen) = 0; + virtual char *ReadFileStr(const char *pFilename, int Type) = 0; virtual bool FindFile(const char *pFilename, const char *pPath, int Type, char *pBuffer, int BufferSize) = 0; virtual bool FindFile(const char *pFilename, const char *pPath, int Type, char *pBuffer, int BufferSize, const SHA256_DIGEST *pWantedSha256, unsigned WantedCrc, unsigned WantedSize) = 0; virtual bool RemoveFile(const char *pFilename, int Type) = 0; From 7e829cf9fa63c62babdc0094563ad89ecb50c15d Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Mon, 27 Jan 2020 23:58:15 +0100 Subject: [PATCH 103/479] test: Make it easier to generate multiple temporary filenames --- src/test/test.cpp | 8 +++++++- src/test/test.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 761d661f..c14df1dd 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -7,8 +7,14 @@ CTestInfo::CTestInfo() { const ::testing::TestInfo *pTestInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - str_format(m_aFilename, sizeof(m_aFilename), "%s.%s-%d.tmp", + str_format(m_aFilenamePrefix, sizeof(m_aFilenamePrefix), "%s.%s-%d", pTestInfo->test_case_name(), pTestInfo->name(), pid()); + Filename(m_aFilename, sizeof(m_aFilename), ".tmp"); +} + +void CTestInfo::Filename(char *pBuffer, int BufferLength, const char *pSuffix) +{ + str_format(pBuffer, BufferLength, "%s%s", m_aFilenamePrefix, pSuffix); } int main(int argc, char **argv) diff --git a/src/test/test.h b/src/test/test.h index 71f13c9b..89858515 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -4,6 +4,8 @@ class CTestInfo { public: CTestInfo(); + void Filename(char *pBuffer, int BufferLength, const char *pSuffix); + char m_aFilenamePrefix[64]; char m_aFilename[64]; }; #endif // TEST_TEST_H From a2bd9878918465b3a9039806a3774e25a3783ea8 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 00:09:54 +0100 Subject: [PATCH 104/479] test: Add tests for `CJsonWriter` --- CMakeLists.txt | 1 + src/test/jsonwriter.cpp | 98 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/test/jsonwriter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e552d25e..2d20f90d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1721,6 +1721,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST) fs.cpp git_revision.cpp hash.cpp + jsonwriter.cpp storage.cpp str.cpp test.cpp diff --git a/src/test/jsonwriter.cpp b/src/test/jsonwriter.cpp new file mode 100644 index 00000000..4732aa5e --- /dev/null +++ b/src/test/jsonwriter.cpp @@ -0,0 +1,98 @@ +#include "test.h" +#include + +#include +#include + +class JsonWriter : public ::testing::Test +{ +protected: + CTestInfo m_Info; + CJsonWriter *m_pJson; + char m_aOutputFilename[64]; + + JsonWriter() + : m_pJson(0) + { + m_Info.Filename(m_aOutputFilename, sizeof(m_aOutputFilename), + "-got.json"); + IOHANDLE File = io_open(m_aOutputFilename, IOFLAG_WRITE); + EXPECT_TRUE(File); + m_pJson = new CJsonWriter(File); + } + + void Expect(const char *pExpected) + { + ASSERT_TRUE(m_pJson); + delete m_pJson; + m_pJson = 0; + + char *pOutput = fs_read_str(m_aOutputFilename); + ASSERT_TRUE(pOutput); + EXPECT_STREQ(pOutput, pExpected); + bool Correct = str_comp(pOutput, pExpected) == 0; + mem_free(pOutput); + + if(!Correct) + { + char aFilename[64]; + m_Info.Filename(aFilename, sizeof(aFilename), + "-expected.json"); + IOHANDLE File = io_open(aFilename, IOFLAG_WRITE); + ASSERT_TRUE(File); + io_write(File, pExpected, str_length(pExpected)); + io_close(File); + } + else + { + fs_remove(m_aOutputFilename); + } + } +}; + +TEST_F(JsonWriter, EmptyObject) +{ + m_pJson->BeginObject(); + m_pJson->EndObject(); + Expect("{\n}\n"); +} + +TEST_F(JsonWriter, EmptyArray) +{ + m_pJson->BeginArray(); + m_pJson->EndArray(); + Expect("[\n]\n"); +} + +TEST_F(JsonWriter, SpecialCharacters) +{ + m_pJson->BeginObject(); + m_pJson->WriteAttribute("\x01\"'\r\n\t"); + m_pJson->BeginArray(); + m_pJson->WriteStrValue(" \"'abc\x01\n"); + m_pJson->EndArray(); + m_pJson->EndObject(); + Expect( + "{\n" + "\t\"\\u0001\\\"'\\r\\n\\t\": [\n" + "\t\t\" \\\"'abc\\u0001\\n\"\n" + "\t]\n" + "}\n" + ); +} + +TEST_F(JsonWriter, HelloWorld) +{ + m_pJson->WriteStrValue("hello world"); + Expect("\"hello world\"\n"); +} + +TEST_F(JsonWriter, True) { m_pJson->WriteBoolValue(true); Expect("true\n"); } +TEST_F(JsonWriter, False) { m_pJson->WriteBoolValue(false); Expect("false\n"); } +TEST_F(JsonWriter, Null) { m_pJson->WriteNullValue(); Expect("null\n"); } +TEST_F(JsonWriter, EmptyString) { m_pJson->WriteStrValue(""); Expect("\"\"\n"); } +TEST_F(JsonWriter, Zero) { m_pJson->WriteIntValue(0); Expect("0\n"); } +TEST_F(JsonWriter, One) { m_pJson->WriteIntValue(1); Expect("1\n"); } +TEST_F(JsonWriter, MinusOne) { m_pJson->WriteIntValue(-1); Expect("-1\n"); } +TEST_F(JsonWriter, Large) { m_pJson->WriteIntValue(INT_MAX); Expect("2147483647\n"); } +TEST_F(JsonWriter, Small) { m_pJson->WriteIntValue(INT_MIN); Expect("-2147483648\n"); } From a809e59e6a884a3713e46472d19b189491923875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 22:37:10 +0100 Subject: [PATCH 105/479] Implement global support for nested clipping regions --- src/game/client/components/menus.h | 2 - src/game/client/components/menus_browser.cpp | 8 +-- .../client/components/menus_scrollregion.cpp | 19 +----- src/game/client/ui.cpp | 65 +++++++++++++++---- src/game/client/ui.h | 22 ++++++- 5 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index b72deb2f..481f7a70 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -214,12 +214,10 @@ class CMenus : public CComponent float m_ContentH; float m_RequestScrollY; // [0, ContentHeight] CUIRect m_ClipRect; - CUIRect m_OldClipRect; CUIRect m_RailRect; CUIRect m_LastAddedRect; // saved for ScrollHere() vec2 m_MouseGrabStart; vec2 m_ContentScrollOff; - bool m_WasClipped; CScrollRegionParams m_Params; public: diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 679f076e..f1863a46 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -653,13 +653,9 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn View.VSplitLeft(160.0f, &Info, &View); RenderDetailInfo(Info, pEntry); - CUIRect NewClipArea = *UI()->ClipArea(); - CUIRect OldClipArea = NewClipArea; - NewClipArea.x = View.x; - NewClipArea.w = View.w; - UI()->ClipEnable(&NewClipArea); + UI()->ClipEnable(&View); RenderDetailScoreboard(View, pEntry, 4, vec4(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha)); - UI()->ClipEnable(&OldClipArea); + UI()->ClipDisable(); } TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 06ed36bd..64e768ca 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -18,7 +18,6 @@ CMenus::CScrollRegion::CScrollRegion() m_ContentH = 0; m_RequestScrollY = -1; m_ContentScrollOff = vec2(0,0); - m_WasClipped = false; m_Params = CScrollRegionParams(); } @@ -27,9 +26,6 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS if(pParams) m_Params = *pParams; - m_WasClipped = m_pUI->IsClipped(); - m_OldClipRect = *m_pUI->ClipArea(); - const bool ContentOverflows = m_ContentH > pClipRect->h; const bool ForceShowScrollbar = m_Params.m_Flags&CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; @@ -52,18 +48,7 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS if(m_Params.m_ClipBgColor.a > 0) m_pRenderTools->DrawRoundRect(pClipRect, m_Params.m_ClipBgColor, 4.0f); - CUIRect ClipRect = *pClipRect; - if(m_WasClipped) - { - CUIRect Intersection; - Intersection.x = max(ClipRect.x, m_OldClipRect.x); - Intersection.y = max(ClipRect.y, m_OldClipRect.y); - Intersection.w = min(ClipRect.x+ClipRect.w, m_OldClipRect.x+m_OldClipRect.w) - ClipRect.x; - Intersection.h = min(ClipRect.y+ClipRect.h, m_OldClipRect.y+m_OldClipRect.h) - ClipRect.y; - ClipRect = Intersection; - } - - m_pUI->ClipEnable(&ClipRect); + m_pUI->ClipEnable(pClipRect); m_ClipRect = *pClipRect; m_ContentH = 0; @@ -73,8 +58,6 @@ void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CS void CMenus::CScrollRegion::End() { m_pUI->ClipDisable(); - if(m_WasClipped) - m_pUI->ClipEnable(&m_OldClipRect); // only show scrollbar if content overflows if(m_ContentH <= m_ClipRect.h) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 18de8f4e..5041c6fe 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -17,7 +17,6 @@ CUI::CUI() m_pActiveItem = 0; m_pLastActiveItem = 0; m_pBecommingHotItem = 0; - m_Clipped = false; m_MouseX = 0; m_MouseY = 0; @@ -32,6 +31,16 @@ CUI::CUI() m_Screen.h = 480.0f; } +CUI::~CUI() +{ + while(m_pClip) + { + const CClip *pToDelete = m_pClip; + m_pClip = m_pClip->m_pParent; + delete pToDelete; + } +} + int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) { m_MouseX = Mx; @@ -56,7 +65,7 @@ int CUI::MouseInside(const CUIRect *r) const bool CUI::MouseInsideClip() const { - return !m_Clipped || MouseInside(&m_ClipRect) == 1; + return !IsClipped() || MouseInside(ClipArea()) == 1; } void CUI::ConvertMouseMove(float *x, float *y) const @@ -85,19 +94,51 @@ float CUI::PixelSize() return Screen()->w/Graphics()->ScreenWidth(); } -void CUI::ClipEnable(const CUIRect *r) +void CUI::ClipEnable(const CUIRect *pRect) { - m_ClipRect = *r; - m_Clipped = true; - float XScale = Graphics()->ScreenWidth()/Screen()->w; - float YScale = Graphics()->ScreenHeight()/Screen()->h; - Graphics()->ClipEnable((int)(r->x*XScale), (int)(r->y*YScale), (int)(r->w*XScale), (int)(r->h*YScale)); + if(m_pClip == 0) + m_pClip = new CClip(pRect, 0); + else + { + const CUIRect *pOldRect = &m_pClip->m_Rect; + CUIRect Intersection; + Intersection.x = max(pRect->x, pOldRect->x); + Intersection.y = max(pRect->y, pOldRect->y); + Intersection.w = min(pRect->x+pRect->w, pOldRect->x+pOldRect->w) - pRect->x; + Intersection.h = min(pRect->y+pRect->h, pOldRect->y+pOldRect->h) - pRect->y; + m_pClip = new CClip(&Intersection, m_pClip); + } + UpdateClipping(); } void CUI::ClipDisable() { - Graphics()->ClipDisable(); - m_Clipped = false; + const CClip *pToDelete = m_pClip; + m_pClip = m_pClip->m_pParent; + delete pToDelete; + UpdateClipping(); +} + +const CUIRect *CUI::ClipArea() const +{ + if(m_pClip == 0) + return &m_Screen; // fallback + return &m_pClip->m_Rect; +} + +void CUI::UpdateClipping() +{ + const CUIRect *pRect = ClipArea(); + if(pRect) + { + const float XScale = Graphics()->ScreenWidth()/Screen()->w; + const float YScale = Graphics()->ScreenHeight()/Screen()->h; + Graphics()->ClipEnable((int)(pRect->x*XScale), (int)(pRect->y*YScale), (int)(pRect->w*XScale), (int)(pRect->h*YScale)); + } + else + { + Graphics()->ClipDisable(); + } } void CUIRect::HSplitMid(CUIRect *pTop, CUIRect *pBottom) const @@ -264,8 +305,8 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU // logic int ReturnValue = 0; int Inside = MouseInside(pRect); - if(m_Clipped) - Inside &= MouseInside(&m_ClipRect); + if(IsClipped()) + Inside &= MouseInsideClip(); static int ButtonUsed = 0; if(CheckActiveItem(pID)) diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 6aaeb048..0b900aba 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -35,7 +35,21 @@ class CUI unsigned m_LastMouseButtons; CUIRect m_Screen; - CUIRect m_ClipRect; + + class CClip + { + public: + CUIRect m_Rect; + const CClip *m_pParent; + CClip(const CUIRect *pRect, const CClip *pParent) + { + m_Rect = *pRect; + m_pParent = pParent; + } + }; + const CClip *m_pClip; + void UpdateClipping(); + class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; @@ -46,6 +60,7 @@ class CUI class ITextRender *TextRender() const { return m_pTextRender; } CUI(); + ~CUI(); enum { @@ -106,10 +121,11 @@ class CUI CUIRect *Screen(); float PixelSize(); + void ClipEnable(const CUIRect *pRect); void ClipDisable(); - const CUIRect *ClipArea() const { return &m_ClipRect; }; - inline bool IsClipped() const { return m_Clipped; }; + const CUIRect *ClipArea() const; + inline bool IsClipped() const { return m_pClip != 0; }; int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); From 1ed1a4e77e059e65fc9c0903db80fecef4fefb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 22:53:02 +0100 Subject: [PATCH 106/479] fix usage of bool in binary and warning --- src/game/client/ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 5041c6fe..8240acc4 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -306,7 +306,7 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU int ReturnValue = 0; int Inside = MouseInside(pRect); if(IsClipped()) - Inside &= MouseInsideClip(); + Inside &= (MouseInsideClip() ? 1 : 0); static int ButtonUsed = 0; if(CheckActiveItem(pID)) From ca4fd6aaa5b86f172e080195fd67b15ba0a05195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Jan 2020 22:57:23 +0100 Subject: [PATCH 107/479] remove unused field --- src/game/client/ui.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 0b900aba..15fb0540 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -28,7 +28,6 @@ class CUI const void *m_pLastActiveItem; const void *m_pBecommingHotItem; bool m_ActiveItemValid; - bool m_Clipped; float m_MouseX, m_MouseY; // in gui space float m_MouseWorldX, m_MouseWorldY; // in world space unsigned m_MouseButtons; From e4484230a43b189faf292cfbbf03dba595000eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 16:07:37 +0100 Subject: [PATCH 108/479] use static array for clip region stack --- src/game/client/ui.cpp | 38 ++++++++++++++++---------------------- src/game/client/ui.h | 22 ++++++++-------------- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 8240acc4..a0f39741 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -29,16 +29,8 @@ CUI::CUI() m_Screen.y = 0; m_Screen.w = 848.0f; m_Screen.h = 480.0f; -} -CUI::~CUI() -{ - while(m_pClip) - { - const CClip *pToDelete = m_pClip; - m_pClip = m_pClip->m_pParent; - delete pToDelete; - } + m_NumClips = 0; } int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) @@ -96,41 +88,43 @@ float CUI::PixelSize() void CUI::ClipEnable(const CUIRect *pRect) { - if(m_pClip == 0) - m_pClip = new CClip(pRect, 0); - else + if(IsClipped()) { - const CUIRect *pOldRect = &m_pClip->m_Rect; + dbg_assert(m_NumClips < MAX_CLIP_NESTING_DEPTH, "max clip nesting depth exceeded"); + const CUIRect *pOldRect = ClipArea(); CUIRect Intersection; Intersection.x = max(pRect->x, pOldRect->x); Intersection.y = max(pRect->y, pOldRect->y); Intersection.w = min(pRect->x+pRect->w, pOldRect->x+pOldRect->w) - pRect->x; Intersection.h = min(pRect->y+pRect->h, pOldRect->y+pOldRect->h) - pRect->y; - m_pClip = new CClip(&Intersection, m_pClip); + m_aClips[m_NumClips] = Intersection; } + else + { + m_aClips[m_NumClips] = *pRect; + } + m_NumClips++; UpdateClipping(); } void CUI::ClipDisable() { - const CClip *pToDelete = m_pClip; - m_pClip = m_pClip->m_pParent; - delete pToDelete; + dbg_assert(m_NumClips > 0, "no clip region"); + m_NumClips--; UpdateClipping(); } const CUIRect *CUI::ClipArea() const { - if(m_pClip == 0) - return &m_Screen; // fallback - return &m_pClip->m_Rect; + dbg_assert(m_NumClips > 0, "no clip region"); + return &m_aClips[m_NumClips - 1]; } void CUI::UpdateClipping() { - const CUIRect *pRect = ClipArea(); - if(pRect) + if(IsClipped()) { + const CUIRect *pRect = ClipArea(); const float XScale = Graphics()->ScreenWidth()/Screen()->w; const float YScale = Graphics()->ScreenHeight()/Screen()->h; Graphics()->ClipEnable((int)(pRect->x*XScale), (int)(pRect->y*YScale), (int)(pRect->w*XScale), (int)(pRect->h*YScale)); diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 15fb0540..edc3dfa2 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -23,6 +23,11 @@ class CUIRect class CUI { + enum + { + MAX_CLIP_NESTING_DEPTH = 16 + }; + const void *m_pHotItem; const void *m_pActiveItem; const void *m_pLastActiveItem; @@ -35,18 +40,8 @@ class CUI CUIRect m_Screen; - class CClip - { - public: - CUIRect m_Rect; - const CClip *m_pParent; - CClip(const CUIRect *pRect, const CClip *pParent) - { - m_Rect = *pRect; - m_pParent = pParent; - } - }; - const CClip *m_pClip; + CUIRect m_aClips[MAX_CLIP_NESTING_DEPTH]; + unsigned m_NumClips; void UpdateClipping(); class IGraphics *m_pGraphics; @@ -59,7 +54,6 @@ class CUI class ITextRender *TextRender() const { return m_pTextRender; } CUI(); - ~CUI(); enum { @@ -124,7 +118,7 @@ class CUI void ClipEnable(const CUIRect *pRect); void ClipDisable(); const CUIRect *ClipArea() const; - inline bool IsClipped() const { return m_pClip != 0; }; + inline bool IsClipped() const { return m_NumClips > 0; }; int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); From 75289fb8162727310604a5f17a3b9da9b0fcde1d Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 00:13:38 +0100 Subject: [PATCH 109/479] Change some `CJsonWriter` output formatting - Always include final newline. - Only put a space right of a colon. - Properly escape control characters lower than ASCII 0x20. --- src/engine/shared/jsonwriter.cpp | 66 +++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index 505d7d72..8d9e5ffd 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -3,6 +3,21 @@ #include "jsonwriter.h" +static char EscapeJsonChar(char c) +{ + switch(c) + { + case '\"': return '\"'; + case '\\': return '\\'; + case '\b': return 'b'; + case '\n': return 'n'; + case '\r': return 'r'; + case '\t': return 't'; + // Don't escape '\f', who uses that. :) + default: return 0; + } +} + CJsonWriter::CJsonWriter(IOHANDLE io) { m_IO = io; @@ -12,6 +27,7 @@ CJsonWriter::CJsonWriter(IOHANDLE io) CJsonWriter::~CJsonWriter() { + WriteInternal("\n"); io_close(m_IO); while(m_pState != 0) @@ -62,7 +78,7 @@ void CJsonWriter::WriteAttribute(const char *pName) dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Attribute can only be written inside of objects"); WriteIndent(false); WriteInternalEscaped(pName); - WriteInternal(" : "); + WriteInternal(": "); PushState(ATTRIBUTE); } @@ -115,29 +131,41 @@ inline void CJsonWriter::WriteInternal(const char *pStr) void CJsonWriter::WriteInternalEscaped(const char *pStr) { WriteInternal("\""); - for(int OldPosition = 0, Position = str_utf8_forward(pStr, OldPosition); - OldPosition != Position; - OldPosition = Position, Position = str_utf8_forward(pStr, OldPosition)) + int UnwrittenFrom = 0; + int Length = str_length(pStr); + for(int i = 0; i < Length; i++) { - int Diff = Position - OldPosition; - if(Diff == 1) + char SimpleEscape = EscapeJsonChar(pStr[i]); + // Assuming ASCII/UTF-8, exactly everything below 0x20 is a + // control character. + bool NeedsEscape = SimpleEscape || pStr[i] < 0x20; + if(NeedsEscape) { - switch(*(pStr+OldPosition)) // only single bytes have values that need to be escaped + if(i - UnwrittenFrom > 0) { - case '\\': WriteInternal("\\\\"); break; - case '\"': WriteInternal("\\\""); break; - case '\n': WriteInternal("\\n"); break; - case '\r': WriteInternal("\\r"); break; - case '\b': WriteInternal("\\b"); break; - case '\f': WriteInternal("\\f"); break; - default: io_write(m_IO, pStr+OldPosition, 1); break; + io_write(m_IO, pStr + UnwrittenFrom, i - UnwrittenFrom); } - } - else if(Diff > 1) - { - io_write(m_IO, pStr+OldPosition, Diff); + + if(SimpleEscape) + { + char aStr[2]; + aStr[0] = '\\'; + aStr[1] = SimpleEscape; + io_write(m_IO, aStr, sizeof(aStr)); + } + else + { + char aStr[7]; + str_format(aStr, sizeof(aStr), "\\u%04x", pStr[i]); + WriteInternal(aStr); + } + UnwrittenFrom = i + 1; } } + if(Length - UnwrittenFrom > 0) + { + io_write(m_IO, pStr + UnwrittenFrom, Length - UnwrittenFrom); + } WriteInternal("\""); } @@ -184,4 +212,4 @@ void CJsonWriter::CompleteDataType() if(m_pState != 0) m_pState->m_Empty = false; -} \ No newline at end of file +} From 750a24191192caababbbe5e941fab88789ed242f Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 00:31:20 +0100 Subject: [PATCH 110/479] Add some stylistic changes to `CJsonWriter` - Remove all allocations, replacing it with a maximum depth of 16. - Explicitly prefix enum variants with their type. - Rename `io` to `IO`. --- src/engine/shared/jsonwriter.cpp | 79 +++++++++++++++++--------------- src/engine/shared/jsonwriter.h | 29 ++++++------ 2 files changed, 58 insertions(+), 50 deletions(-) diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index 8d9e5ffd..4d12ee3b 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -18,10 +18,10 @@ static char EscapeJsonChar(char c) } } -CJsonWriter::CJsonWriter(IOHANDLE io) +CJsonWriter::CJsonWriter(IOHANDLE IO) { - m_IO = io; - m_pState = 0; // no root created yet + m_IO = IO; + m_NumStates = 0; // no root created yet m_Indentation = 0; } @@ -29,13 +29,6 @@ CJsonWriter::~CJsonWriter() { WriteInternal("\n"); io_close(m_IO); - - while(m_pState != 0) - { - CState *pState = m_pState; - m_pState = m_pState->m_pParent; - delete pState; - } } void CJsonWriter::BeginObject() @@ -43,12 +36,12 @@ void CJsonWriter::BeginObject() dbg_assert(CanWriteDatatype(), "Cannot write object at this position"); WriteIndent(false); WriteInternal("{"); - PushState(OBJECT); + PushState(STATE_OBJECT); } void CJsonWriter::EndObject() { - dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Cannot end object here"); + dbg_assert(TopState()->m_Kind == STATE_OBJECT, "Cannot end object here"); PopState(); CompleteDataType(); WriteIndent(true); @@ -61,12 +54,12 @@ void CJsonWriter::BeginArray() dbg_assert(CanWriteDatatype(), "Cannot write array at this position"); WriteIndent(false); WriteInternal("["); - PushState(ARRAY); + PushState(STATE_ARRAY); } void CJsonWriter::EndArray() { - dbg_assert(m_pState != 0 && m_pState->m_State == ARRAY, "Cannot end array here"); + dbg_assert(TopState()->m_Kind == STATE_ARRAY, "Cannot end array here"); PopState(); CompleteDataType(); WriteIndent(true); @@ -75,11 +68,11 @@ void CJsonWriter::EndArray() void CJsonWriter::WriteAttribute(const char *pName) { - dbg_assert(m_pState != 0 && m_pState->m_State == OBJECT, "Attribute can only be written inside of objects"); + dbg_assert(TopState()->m_Kind == STATE_OBJECT, "Attribute can only be written inside of objects"); WriteIndent(false); WriteInternalEscaped(pName); WriteInternal(": "); - PushState(ATTRIBUTE); + PushState(STATE_ATTRIBUTE); } void CJsonWriter::WriteStrValue(const char *pValue) @@ -118,9 +111,9 @@ void CJsonWriter::WriteNullValue() bool CJsonWriter::CanWriteDatatype() { - return m_pState == 0 - || m_pState->m_State == ARRAY - || m_pState->m_State == ATTRIBUTE; + return m_NumStates == 0 + || TopState()->m_Kind == STATE_ARRAY + || TopState()->m_Kind == STATE_ATTRIBUTE; } inline void CJsonWriter::WriteInternal(const char *pStr) @@ -171,9 +164,10 @@ void CJsonWriter::WriteInternalEscaped(const char *pStr) void CJsonWriter::WriteIndent(bool EndElement) { - const bool NotRootOrAttribute = m_pState != 0 && m_pState->m_State != ATTRIBUTE; + const bool NotRootOrAttribute = m_NumStates != 0 + && TopState()->m_Kind != STATE_ATTRIBUTE; - if(NotRootOrAttribute && !m_pState->m_Empty && !EndElement) + if(NotRootOrAttribute && !TopState()->m_Empty && !EndElement) WriteInternal(","); if(NotRootOrAttribute || EndElement) @@ -184,32 +178,43 @@ void CJsonWriter::WriteIndent(bool EndElement) WriteInternal("\t"); } -void CJsonWriter::PushState(EState NewState) +void CJsonWriter::PushState(unsigned char NewState) { - if(m_pState != 0) - m_pState->m_Empty = false; - m_pState = new CState(NewState, m_pState); - if(NewState != ATTRIBUTE) + dbg_assert(m_NumStates < MAX_DEPTH, "max json depth exceeded"); + if(m_NumStates != 0) + { + m_aStates[m_NumStates - 1].m_Empty = false; + } + m_aStates[m_NumStates] = CState(NewState); + m_NumStates++; + if(NewState != STATE_ATTRIBUTE) + { m_Indentation++; + } +} + +CJsonWriter::CState *CJsonWriter::TopState() +{ + dbg_assert(m_NumStates != 0, "json stack is empty"); + return &m_aStates[m_NumStates - 1]; } -CJsonWriter::EState CJsonWriter::PopState() +unsigned char CJsonWriter::PopState() { - dbg_assert(m_pState != 0, "Stack is empty"); - EState Result = m_pState->m_State; - CState *pToDelete = m_pState; - m_pState = m_pState->m_pParent; - delete pToDelete; - if(Result != ATTRIBUTE) + dbg_assert(m_NumStates != 0, "json stack is empty"); + m_NumStates--; + if(m_aStates[m_NumStates].m_Kind != STATE_ATTRIBUTE) + { m_Indentation--; - return Result; + } + return m_aStates[m_NumStates].m_Kind; } void CJsonWriter::CompleteDataType() { - if(m_pState != 0 && m_pState->m_State == ATTRIBUTE) + if(m_NumStates != 0 && m_aStates[m_NumStates - 1].m_Kind == STATE_ATTRIBUTE) PopState(); // automatically complete the attribute - if(m_pState != 0) - m_pState->m_Empty = false; + if(m_NumStates != 0) + m_aStates[m_NumStates - 1].m_Empty = false; } diff --git a/src/engine/shared/jsonwriter.h b/src/engine/shared/jsonwriter.h index 5d3509fb..441fd5c2 100644 --- a/src/engine/shared/jsonwriter.h +++ b/src/engine/shared/jsonwriter.h @@ -7,45 +7,48 @@ class CJsonWriter { - enum EState + enum { - OBJECT, - ARRAY, - ATTRIBUTE + STATE_INVALID, + STATE_OBJECT, + STATE_ARRAY, + STATE_ATTRIBUTE, + + MAX_DEPTH=16, }; class CState { public: - EState m_State; - CState *m_pParent; + unsigned char m_Kind; bool m_Empty; - CState(EState State, CState *pParent) + CState(unsigned char Kind = STATE_INVALID) { - m_State = State; - m_pParent = pParent; + m_Kind = Kind; m_Empty = true; }; }; IOHANDLE m_IO; - CState *m_pState; + CState m_aStates[MAX_DEPTH]; + int m_NumStates; int m_Indentation; bool CanWriteDatatype(); inline void WriteInternal(const char *pStr); void WriteInternalEscaped(const char *pStr); void WriteIndent(bool EndElement); - void PushState(EState NewState); - EState PopState(); + void PushState(unsigned char NewState); + CState *TopState(); + unsigned char PopState(); void CompleteDataType(); public: // Create a new writer object without writing anything to the file yet. // The file will automatically be closed by the destructor. - CJsonWriter(IOHANDLE io); + CJsonWriter(IOHANDLE IO); ~CJsonWriter(); // The root is created by beginning the first datatype (object, array, value). From e75432e151c9bcd5dd7d0b967e21930a7812f5de Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 20:47:08 +0100 Subject: [PATCH 111/479] Fix name of `fs_read_str` in the doc --- src/base/system.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.h b/src/base/system.h index 919b4a14..a57b4bc1 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1406,7 +1406,7 @@ int fs_rename(const char *oldname, const char *newname); int fs_read(const char *name, void **result, unsigned *result_len); /* - Function: fs_read + Function: fs_read_str Reads a whole file into memory and returns its contents, guaranteeing a null-terminated string with no internal null bytes. From 352adfa031dcf0e683e79024ee5682c7da756779 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 28 Jan 2020 21:33:54 +0100 Subject: [PATCH 112/479] added another check for invalid server info. closes #2444 --- src/engine/client/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index ef4ecbc5..118075ea 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -931,7 +931,7 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo pInfo->m_NumBotSpectators = 0; // don't add invalid info to the server browser list - if(pInfo->m_NumClients < 0 || pInfo->m_NumClients > pInfo->m_MaxClients || pInfo->m_MaxClients < 0 || pInfo->m_MaxClients > MAX_CLIENTS || + if(pInfo->m_NumClients < 0 || pInfo->m_NumClients > pInfo->m_MaxClients || pInfo->m_MaxClients < 0 || pInfo->m_MaxClients > MAX_CLIENTS || pInfo->m_MaxPlayers < pInfo->m_NumPlayers || pInfo->m_NumPlayers < 0 || pInfo->m_NumPlayers > pInfo->m_NumClients || pInfo->m_MaxPlayers < 0 || pInfo->m_MaxPlayers > pInfo->m_MaxClients) return -1; // drop standard gametype with more than MAX_PLAYERS From 93db90b76fce65e50388445f6e06c257ddfe1a26 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 28 Jan 2020 21:36:47 +0100 Subject: [PATCH 113/479] removed some dead code --- src/engine/client/client.cpp | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 118075ea..302b38d5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1617,37 +1617,6 @@ void CClient::OnDemoPlayerMessage(void *pData, int Size) if(!Sys) GameClient()->OnMessage(Msg, &Unpacker); } -/* -const IDemoPlayer::CInfo *client_demoplayer_getinfo() -{ - static DEMOPLAYBACK_INFO ret; - const DEMOREC_PLAYBACKINFO *info = m_DemoPlayer.Info(); - ret.first_tick = info->first_tick; - ret.last_tick = info->last_tick; - ret.current_tick = info->current_tick; - ret.paused = info->paused; - ret.speed = info->speed; - return &ret; -}*/ - -/* -void DemoPlayer()->SetPos(float percent) -{ - demorec_playback_set(percent); -} - -void DemoPlayer()->SetSpeed(float speed) -{ - demorec_playback_setspeed(speed); -} - -void DemoPlayer()->SetPause(int paused) -{ - if(paused) - demorec_playback_pause(); - else - demorec_playback_unpause(); -}*/ void CClient::Update() { From 9b4c32e38cd166bdef545ee1ac5ce37b654e825c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 22:21:22 +0100 Subject: [PATCH 114/479] replace int with bool --- src/game/client/components/menus.h | 4 ++-- src/game/client/components/menus_listbox.cpp | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 481f7a70..8e5c46b6 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -239,8 +239,8 @@ class CMenus : public CComponent // Listbox : found in menus_listbox.cpp struct CListboxItem { - int m_Visible; - int m_Selected; + bool m_Visible; + bool m_Selected; CUIRect m_Rect; }; diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 8a34ecd3..4ced7492 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -140,9 +140,7 @@ CMenus::CListboxItem CMenus::CListBox::DoNextRow() s_RowView.VSplitLeft(s_RowView.w/(m_ListBoxItemsPerRow-m_ListBoxItemIndex%m_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); - if(m_ListBoxSelectedIndex == m_ListBoxItemIndex) - Item.m_Selected = 1; - + Item.m_Selected = m_ListBoxSelectedIndex == m_ListBoxItemIndex; Item.m_Visible = !m_ScrollRegion.IsRectClipped(Item.m_Rect); m_ListBoxItemIndex++; From 0b285ea9dd397bf5ff19821856707fd114d4c9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 22:32:05 +0100 Subject: [PATCH 115/479] improve tenary format --- src/game/client/components/menus.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 8e5c46b6..8189b6e5 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -461,9 +461,14 @@ class CMenus : public CComponent bool m_Valid; CDemoHeader m_Info; - bool operator<(const CDemoItem &Other) const { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : - m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : - str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; } + bool operator<(const CDemoItem &Other) const + { + return !str_comp(m_aFilename, "..") ? true + : !str_comp(Other.m_aFilename, "..") ? false + : m_IsDir && !Other.m_IsDir ? true + : !m_IsDir && Other.m_IsDir ? false + : str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; + } }; sorted_array m_lDemos; From 4c69ee765afd0ab4f28215724c2f8ab196cd33fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 22:39:07 +0100 Subject: [PATCH 116/479] declare CheckHotKey as const, minor format fix --- src/game/client/components/menus.cpp | 4 ++-- src/game/client/components/menus.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0dc48847..3192f6c9 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2608,10 +2608,10 @@ void CMenus::OnRender() m_DownArrowPressed = false; } -bool CMenus::CheckHotKey(int Key) +bool CMenus::CheckHotKey(int Key) const { return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && - !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier + !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 8189b6e5..59658aee 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -779,7 +779,7 @@ class CMenus : public CComponent void SetMenuPage(int NewPage); - bool CheckHotKey(int Key); + bool CheckHotKey(int Key) const; public: struct CSwitchTeamInfo { From f2b6c514ca6f705bcb8f8b2bbcd4435148fc8819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 22:57:11 +0100 Subject: [PATCH 117/479] use pointer to member function for FDropdownCallback --- src/game/client/components/menus.cpp | 4 +- src/game/client/components/menus.h | 22 ++--- src/game/client/components/menus_callback.cpp | 99 +++++++++---------- src/game/client/components/menus_demo.cpp | 44 ++++----- src/game/client/components/menus_settings.cpp | 26 +++-- 5 files changed, 91 insertions(+), 104 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 3192f6c9..947f90b9 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -730,7 +730,7 @@ float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, // render content of expanded menu if(Active) - return HeaderHeight + pfnCallback(View, this); + return HeaderHeight + (this->*pfnCallback)(View); return HeaderHeight; } @@ -777,7 +777,7 @@ float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const c // render content of expanded menu if(Active) - return HeaderHeight + pfnCallback(View, this); + return HeaderHeight + (this->*pfnCallback)(View); return HeaderHeight; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 59658aee..edb9c882 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -93,7 +93,7 @@ class CMenus : public CComponent }; private: - typedef float (*FDropdownCallback)(CUIRect View, void *pUser); + typedef float (CMenus::*FDropdownCallback)(CUIRect View); float ButtonFade(CButtonContainer *pBC, float Seconds, int Checked=0); @@ -696,7 +696,7 @@ class CMenus : public CComponent // found in menus_demo.cpp void RenderDemoPlayer(CUIRect MainView); void RenderDemoList(CUIRect MainView); - static float RenderDemoDetails(CUIRect View, void *pUser); + float RenderDemoDetails(CUIRect View); // found in menus_start.cpp void RenderStartMenu(CUIRect MainView); @@ -756,15 +756,15 @@ class CMenus : public CComponent const sorted_array& lModes); // found in menu_callback.cpp - static float RenderSettingsControlsMouse(CUIRect View, void *pUser); - static float RenderSettingsControlsJoystick(CUIRect View, void *pUser); - static float RenderSettingsControlsMovement(CUIRect View, void *pUser); - static float RenderSettingsControlsWeapon(CUIRect View, void *pUser); - static float RenderSettingsControlsVoting(CUIRect View, void *pUser); - static float RenderSettingsControlsChat(CUIRect View, void *pUser); - static float RenderSettingsControlsScoreboard(CUIRect View, void *pUser); - static float RenderSettingsControlsStats(CUIRect View, void *pUser); - static float RenderSettingsControlsMisc(CUIRect View, void *pUser); + float RenderSettingsControlsMouse(CUIRect View); + float RenderSettingsControlsJoystick(CUIRect View); + float RenderSettingsControlsMovement(CUIRect View); + float RenderSettingsControlsWeapon(CUIRect View); + float RenderSettingsControlsVoting(CUIRect View); + float RenderSettingsControlsChat(CUIRect View); + float RenderSettingsControlsScoreboard(CUIRect View); + float RenderSettingsControlsStats(CUIRect View); + float RenderSettingsControlsMisc(CUIRect View); void DoJoystickAxisPicker(CUIRect View); diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 715c45cb..5d2c9515 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -123,10 +123,9 @@ static void UpdateBindKeys(CBinds* pBinds) } } -float CMenus::RenderSettingsControlsMouse(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsMouse(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 3; float ButtonHeight = 20.0f; @@ -134,33 +133,32 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); CUIRect Button; View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonInpGrab = 0; - if(pSelf->DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !g_Config.m_InpGrab, &Button)) + if(DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !g_Config.m_InpGrab, &Button)) { g_Config.m_InpGrab ^= 1; } View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); return BackgroundHeight; } -float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsJoystick(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); bool JoystickEnabled = g_Config.m_JoystickEnable; - int NumJoysticks = pSelf->m_pClient->Input()->NumJoysticks(); + int NumJoysticks = m_pClient->Input()->NumJoysticks(); int NumOptions = 2; // expandable header & message if(JoystickEnabled && NumJoysticks > 0) { @@ -169,20 +167,20 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) NumOptions++; // joystick selection } NumOptions += 2; // sensitivity & tolerance - NumOptions += pSelf->m_pClient->Input()->GetJoystickNumAxes(); // axis selection + NumOptions += m_pClient->Input()->GetJoystickNumAxes(); // axis selection } float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing+Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); CUIRect Button; View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonJoystickEnable = 0; - if(pSelf->DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), g_Config.m_JoystickEnable, &Button)) + if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), g_Config.m_JoystickEnable, &Button)) { g_Config.m_JoystickEnable ^= 1; } @@ -197,44 +195,43 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View, void *pUser) View.HSplitTop(ButtonHeight, &Button, &View); static CButtonContainer s_ButtonJoystickId; char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "Joystick %d: %s", pSelf->m_pClient->Input()->GetJoystickIndex(), pSelf->m_pClient->Input()->GetJoystickName()); - if(pSelf->DoButton_Menu(&s_ButtonJoystickId, aBuf, 0, &Button)) + str_format(aBuf, sizeof(aBuf), "Joystick %d: %s", m_pClient->Input()->GetJoystickIndex(), m_pClient->Input()->GetJoystickName()); + if(DoButton_Menu(&s_ButtonJoystickId, aBuf, 0, &Button)) { - pSelf->m_pClient->Input()->SelectNextJoystick(); + m_pClient->Input()->SelectNextJoystick(); } } View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoScrollbarOption(&g_Config.m_JoystickTolerance, &g_Config.m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); + DoScrollbarOption(&g_Config.m_JoystickTolerance, &g_Config.m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); // shrink view and draw background View.HSplitTop(Spacing, 0, &View); View.VSplitLeft(View.w/6, 0, &View); View.VSplitRight(View.w/5, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.125f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.125f), CUI::CORNER_ALL, 5.0f); - pSelf->DoJoystickAxisPicker(View); + DoJoystickAxisPicker(View); } else { View.HSplitTop((View.h-ButtonHeight)/2.0f, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->m_pClient->UI()->DoLabel(&Button, Localize("No joysticks found. Plug in a joystick and restart the game."), 13.0f, CUI::ALIGN_CENTER); + m_pClient->UI()->DoLabel(&Button, Localize("No joysticks found. Plug in a joystick and restart the game."), 13.0f, CUI::ALIGN_CENTER); } } return BackgroundHeight; } -float CMenus::RenderSettingsControlsMovement(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsMovement(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 5; float ButtonHeight = 20.0f; @@ -242,17 +239,16 @@ float CMenus::RenderSettingsControlsMovement(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(0, 5, View, ButtonHeight, Spacing); + UiDoGetButtons(0, 5, View, ButtonHeight, Spacing); return BackgroundHeight; } -float CMenus::RenderSettingsControlsWeapon(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsWeapon(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 7; float ButtonHeight = 20.0f; @@ -260,17 +256,16 @@ float CMenus::RenderSettingsControlsWeapon(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(5, 12, View, ButtonHeight, Spacing); + UiDoGetButtons(5, 12, View, ButtonHeight, Spacing); return BackgroundHeight; } -float CMenus::RenderSettingsControlsVoting(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsVoting(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 2; float ButtonHeight = 20.0f; @@ -278,17 +273,16 @@ float CMenus::RenderSettingsControlsVoting(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(12, 14, View, ButtonHeight, Spacing); + UiDoGetButtons(12, 14, View, ButtonHeight, Spacing); return BackgroundHeight; } -float CMenus::RenderSettingsControlsChat(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsChat(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 4; float ButtonHeight = 20.0f; @@ -296,17 +290,15 @@ float CMenus::RenderSettingsControlsChat(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(14, 18, View, ButtonHeight, Spacing); + UiDoGetButtons(14, 18, View, ButtonHeight, Spacing); return BackgroundHeight; } -float CMenus::RenderSettingsControlsScoreboard(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsScoreboard(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - // this is kinda slow, but whatever for(int i = 0; i < g_KeyCount; i++) { @@ -318,7 +310,7 @@ float CMenus::RenderSettingsControlsScoreboard(CUIRect View, void *pUser) { for(int m = 0; m < CBinds::MODIFIER_COUNT; m++) { - const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId, m); + const char *pBind = m_pClient->m_pBinds->Get(KeyId, m); if(!pBind[0]) continue; @@ -339,24 +331,23 @@ float CMenus::RenderSettingsControlsScoreboard(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); + UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); View.HSplitTop(ButtonHeight*2+Spacing*3, 0, &View); View.VSplitLeft(View.w/3, 0, &View); View.VSplitRight(View.w/2, &View, 0); static int s_StatboardConfigDropdown = 0; static bool s_StatboardConfigActive = false; - float Split = pSelf->DoIndependentDropdownMenu(&s_StatboardConfigDropdown, &View, Localize("Configure statboard"), 20.0f, pSelf->RenderSettingsControlsStats, &s_StatboardConfigActive); + float Split = DoIndependentDropdownMenu(&s_StatboardConfigDropdown, &View, Localize("Configure statboard"), 20.0f, RenderSettingsControlsStats, &s_StatboardConfigActive); return BackgroundHeight+Split; } -float CMenus::RenderSettingsControlsMisc(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsMisc(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - UpdateBindKeys(pSelf->m_pClient->m_pBinds); + UpdateBindKeys(m_pClient->m_pBinds); int NumOptions = 12; int StartOption = 20; @@ -365,9 +356,9 @@ float CMenus::RenderSettingsControlsMisc(CUIRect View, void *pUser) float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing; View.HSplitTop(BackgroundHeight, &View, 0); - pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - pSelf->UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); + UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); return BackgroundHeight; } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index bb9cccc7..6b0c840a 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -523,12 +523,10 @@ void CMenus::RenderDemoList(CUIRect MainView) } } -float CMenus::RenderDemoDetails(CUIRect View, void *pUser) +float CMenus::RenderDemoDetails(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - // render demo info - if(!pSelf->m_DemolistSelectedIsDir && pSelf->m_DemolistSelectedIndex >= 0 && pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Valid) + if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) { CUIRect Button; @@ -537,41 +535,41 @@ float CMenus::RenderDemoDetails(CUIRect View, void *pUser) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoInfoBox(&Button, Localize("Created"), pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aTimestamp); + DoInfoBox(&Button, Localize("Created"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoInfoBox(&Button, Localize("Type"), pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aType); + DoInfoBox(&Button, Localize("Type"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - int Length = ((pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | - ((pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); + int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | + ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); - pSelf->DoInfoBox(&Button, Localize("Length"), aBuf); + DoInfoBox(&Button, Localize("Length"), aBuf); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - str_format(aBuf, sizeof(aBuf), "%d", pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_Version); - pSelf->DoInfoBox(&Button, Localize("Version"), aBuf); + str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version); + DoInfoBox(&Button, Localize("Version"), aBuf); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoInfoBox(&Button, Localize("Netversion"), pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aNetversion); + DoInfoBox(&Button, Localize("Netversion"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - const int MarkerCount = DemoGetMarkerCount(pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info); + const int MarkerCount = DemoGetMarkerCount(m_lDemos[m_DemolistSelectedIndex].m_Info); str_format(aBuf, sizeof(aBuf), "%d", MarkerCount); if(MarkerCount > 0) - pSelf->TextRender()->TextColor(0.5, 1, 0.5, 1); - pSelf->DoInfoBox(&Button, Localize("Markers"), aBuf); - pSelf->TextRender()->TextColor(1, 1, 1, 1); + TextRender()->TextColor(0.5, 1, 0.5, 1); + DoInfoBox(&Button, Localize("Markers"), aBuf); + TextRender()->TextColor(1, 1, 1, 1); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - pSelf->DoInfoBox(&Button, Localize("Map"), pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapName); + DoInfoBox(&Button, Localize("Map"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); @@ -579,15 +577,15 @@ float CMenus::RenderDemoDetails(CUIRect View, void *pUser) CUIRect ButtonRight; Button.VSplitMid(&Button, &ButtonRight); - float Size = float((pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | - (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapSize[3]))/1024.0f; + float Size = float((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]))/1024.0f; str_format(aBuf, sizeof(aBuf), Localize("%.3f KiB"), Size); - pSelf->DoInfoBox(&Button, Localize("Size"), aBuf); + DoInfoBox(&Button, Localize("Size"), aBuf); - unsigned Crc = (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | - (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (pSelf->m_lDemos[pSelf->m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); + unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); str_format(aBuf, sizeof(aBuf), "%08x", Crc); - pSelf->DoInfoBox(&ButtonRight, Localize("Crc"), aBuf); + DoInfoBox(&ButtonRight, Localize("Crc"), aBuf); } //unused diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 5b2517ee..918789f7 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1540,54 +1540,52 @@ void CMenus::RenderSettingsControls(CUIRect MainView) m_pClient->m_pBinds->SetDefaults(); } -float CMenus::RenderSettingsControlsStats(CUIRect View, void *pUser) +float CMenus::RenderSettingsControlsStats(CUIRect View) { - CMenus *pSelf = (CMenus*)pUser; - CUIRect Button; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos, Localize("Frags"), g_Config.m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos, Localize("Frags"), g_Config.m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_FRAGS; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+1, Localize("Deaths"), g_Config.m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+1, Localize("Deaths"), g_Config.m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_DEATHS; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+2, Localize("Suicides"), g_Config.m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+2, Localize("Suicides"), g_Config.m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_SUICIDES; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+3, Localize("Ratio"), g_Config.m_ClStatboardInfos & TC_STATS_RATIO, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+3, Localize("Ratio"), g_Config.m_ClStatboardInfos & TC_STATS_RATIO, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_RATIO; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+4, Localize("Net score"), g_Config.m_ClStatboardInfos & TC_STATS_NET, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+4, Localize("Net score"), g_Config.m_ClStatboardInfos & TC_STATS_NET, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_NET; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+5, Localize("Frags per minute"), g_Config.m_ClStatboardInfos & TC_STATS_FPM, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+5, Localize("Frags per minute"), g_Config.m_ClStatboardInfos & TC_STATS_FPM, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_FPM; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+6, Localize("Current spree"), g_Config.m_ClStatboardInfos & TC_STATS_SPREE, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+6, Localize("Current spree"), g_Config.m_ClStatboardInfos & TC_STATS_SPREE, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_SPREE; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+7, Localize("Best spree"), g_Config.m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+7, Localize("Best spree"), g_Config.m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_BESTSPREE; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+9, Localize("Weapons stats"), g_Config.m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+9, Localize("Weapons stats"), g_Config.m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_WEAPS; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+8, Localize("Flag grabs"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+8, Localize("Flag grabs"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; View.HSplitTop(20.0f, &Button, &View); - if(pSelf->DoButton_CheckBox(&g_Config.m_ClStatboardInfos+10, Localize("Flag captures"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) + if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+10, Localize("Flag captures"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) g_Config.m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; return 11*20.0f; From e4488900cdf3c9301e5d778584921f5fd65324f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 23:37:03 +0100 Subject: [PATCH 118/479] remove unused functions and dead code --- src/game/client/components/menus.cpp | 36 --------------------- src/game/client/components/menus.h | 1 - src/game/client/ui.cpp | 48 ---------------------------- src/game/client/ui.h | 1 - 4 files changed, 86 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 947f90b9..3efdad7b 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -267,18 +267,6 @@ int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Ch return UI()->DoButtonLogic(pBC->GetID(), pText, Checked, pRect); } -void CMenus::DoButton_MenuTabTop_Dummy(const char *pText, int Checked, const CUIRect *pRect, float Alpha) -{ - RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f*Alpha), CUI::CORNER_ALL, 5.0f); - CUIRect Temp; - pRect->HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Temp); - TextRender()->TextColor(0.15f, 0.15f, 0.15f, Alpha); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.25f*Alpha); - UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); -} - int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect) { if(Checked) @@ -306,30 +294,6 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -/* -int CMenus::DoButton_GridHeaderIcon(CButtonContainer *pBC, int ImageID, int SpriteID, const CUIRect *pRect, int Corners) -{ - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds); - - RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.5f+(Fade/Seconds)*0.25f), Corners, 5.0f); - - CUIRect Image; - pRect->HMargin(2.0f, &Image); - pRect->VMargin((Image.w-Image.h)/2.0f, &Image); - - Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f); - RenderTools()->SelectSprite(SpriteID); - IGraphics::CQuadItem QuadItem(Image.x, Image.y, Image.w, Image.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - return UI()->DoButtonLogic(pBC->GetID(), "", false, pRect); -} -*/ - int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked, bool Locked) { RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index edb9c882..d8c705a0 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -106,7 +106,6 @@ class CMenus : public CComponent int DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName=0, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f, vec4 ColorHot=vec4(1.0f, 1.0f, 1.0f, 0.75f), bool TextFade=true); int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); int DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha=1.0f, float FontAlpha=1.0f, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f); - void DoButton_MenuTabTop_Dummy(const char *pText, int Checked, const CUIRect *pRect, float Alpha); int DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle Texture, int SpriteID, const CUIRect *pRect, float ImageRatio); int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked=false, bool Locked=false); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index a0f39741..26cc062a 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -362,54 +362,6 @@ int CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float * return 1; } -int CUI::DoColorSelectionLogic(const CUIRect *pRect, const CUIRect *pButton) // it's counter logic! FIXME -{ - if(MouseButtonClicked(0) && MouseInside(pRect) && !MouseInside(pButton)) - return 1; - else - return 0; -} - -/* -int CUI::DoButton(const void *id, const char *text, int checked, const CUIRect *r, ui_draw_button_func draw_func, const void *extra) -{ - // logic - int ret = 0; - int inside = ui_MouseInside(r); - static int button_used = 0; - - if(ui_ActiveItem() == id) - { - if(!ui_MouseButton(button_used)) - { - if(inside && checked >= 0) - ret = 1+button_used; - ui_SetActiveItem(0); - } - } - else if(ui_HotItem() == id) - { - if(ui_MouseButton(0)) - { - ui_SetActiveItem(id); - button_used = 0; - } - - if(ui_MouseButton(1)) - { - ui_SetActiveItem(id); - button_used = 1; - } - } - - if(inside) - ui_SetHotItem(id); - - if(draw_func) - draw_func(id, text, checked, r, extra); - return ret; -}*/ - void CUI::DoLabel(const CUIRect *r, const char *pText, float Size, EAlignment Align, float LineWidth, bool MultiLine) { // TODO: FIX ME!!!! diff --git a/src/game/client/ui.h b/src/game/client/ui.h index edc3dfa2..79f935f3 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -122,7 +122,6 @@ class CUI int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); - int DoColorSelectionLogic(const CUIRect *pRect, const CUIRect *pButton); // TODO: Refactor: Remove this? void DoLabel(const CUIRect *pRect, const char *pText, float Size, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); From 0028c91bfc200b27318b9580d2927f8e333b21e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 23:40:07 +0100 Subject: [PATCH 119/479] rename parameter, minor style change --- src/game/client/components/menus.cpp | 9 +++------ src/game/client/components/menus.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 3efdad7b..df80dd64 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -319,10 +319,7 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c IGraphics::CQuadItem QuadItem(c.x, c.y, c.w, c.h); Graphics()->QuadsDrawTL(&QuadItem, 1); } - if(Checked) - RenderTools()->SelectSprite(SPRITE_MENU_CHECKBOX_ACTIVE); - else - RenderTools()->SelectSprite(SPRITE_MENU_CHECKBOX_INACTIVE); + RenderTools()->SelectSprite(Checked ? SPRITE_MENU_CHECKBOX_ACTIVE : SPRITE_MENU_CHECKBOX_INACTIVE); IGraphics::CQuadItem QuadItem(c.x, c.y, c.w, c.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); @@ -345,10 +342,10 @@ int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, c return DoButton_CheckBox_Common(pID, pText, "", pRect, Checked, Locked); } -int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int SelectedNumber, const CUIRect *pRect) { char aBuf[16]; - str_format(aBuf, sizeof(aBuf), "%d", Checked); + str_format(aBuf, sizeof(aBuf), "%d", SelectedNumber); return DoButton_CheckBox_Common(pID, pText, aBuf, pRect); } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index d8c705a0..45e8f650 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -110,7 +110,7 @@ class CMenus : public CComponent int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked=false, bool Locked=false); int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect, bool Locked=false); - int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoButton_CheckBox_Number(const void *pID, const char *pText, int SelectedNumber, const CUIRect *pRect); int DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect); From b8814aca9316cd716ef57351f171a58a4bcfc8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 23:46:39 +0100 Subject: [PATCH 120/479] change MouseInside to bool --- src/game/client/components/menus.cpp | 10 ++++----- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/ui.cpp | 23 ++++++++++---------- src/game/client/ui.h | 4 ++-- src/game/editor/editor.cpp | 8 +++---- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index df80dd64..b9f220fd 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -375,7 +375,7 @@ int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, int CMenus::DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect) { - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); Graphics()->QuadsBegin(); @@ -394,7 +394,7 @@ int CMenus::DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect int CMenus::DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, const CUIRect *pRect, bool Blend) { - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); Graphics()->QuadsBegin(); @@ -409,7 +409,7 @@ int CMenus::DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, c int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) { - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); Graphics()->QuadsBegin(); @@ -424,7 +424,7 @@ int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners) { - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); bool Changed = false; bool UpdateOffset = false; static int s_AtIndex = 0; @@ -922,7 +922,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in static const void *pGrabbedID = 0; static bool MouseReleased = true; static int ButtonUsed = 0; - int Inside = UI()->MouseInside(pRect) && UI()->MouseInsideClip(); + bool Inside = UI()->MouseInside(pRect) && UI()->MouseInsideClip(); int NewKey = Key; *NewModifier = Modifier; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index f1863a46..aeac0ceb 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -376,7 +376,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { // logic int ReturnValue = 0; - int Inside = UI()->MouseInside(&View) && UI()->MouseInsideClip(); + bool Inside = UI()->MouseInside(&View) && UI()->MouseInsideClip(); if(UI()->CheckActiveItem(pID)) { diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 6b0c840a..981729bd 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -122,7 +122,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, CUI::ALIGN_CENTER); // do the logic - int Inside = UI()->MouseInside(&SeekBar); + bool Inside = UI()->MouseInside(&SeekBar); if(UI()->CheckActiveItem(id)) { diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 26cc062a..683cc5ec 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -48,16 +48,17 @@ int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) return 0; } -int CUI::MouseInside(const CUIRect *r) const +bool CUI::MouseInside(const CUIRect *r) const { - if(m_MouseX >= r->x && m_MouseX < r->x+r->w && m_MouseY >= r->y && m_MouseY < r->y+r->h) - return 1; - return 0; + return m_MouseX >= r->x + && m_MouseX < r->x+r->w + && m_MouseY >= r->y + && m_MouseY < r->y+r->h; } bool CUI::MouseInsideClip() const { - return !IsClipped() || MouseInside(ClipArea()) == 1; + return !IsClipped() || MouseInside(ClipArea()); } void CUI::ConvertMouseMove(float *x, float *y) const @@ -298,9 +299,7 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU { // logic int ReturnValue = 0; - int Inside = MouseInside(pRect); - if(IsClipped()) - Inside &= (MouseInsideClip() ? 1 : 0); + bool Inside = MouseInside(pRect) && MouseInsideClip(); static int ButtonUsed = 0; if(CheckActiveItem(pID)) @@ -333,9 +332,9 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU return ReturnValue; } -int CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY) +bool CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY) { - int Inside = MouseInside(pRect); + bool Inside = MouseInside(pRect); if(CheckActiveItem(pID)) { @@ -352,14 +351,14 @@ int CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float * SetHotItem(pID); if(!CheckActiveItem(pID)) - return 0; + return false; if(pX) *pX = clamp(m_MouseX - pRect->x, 0.0f, pRect->w); if(pY) *pY = clamp(m_MouseY - pRect->y, 0.0f, pRect->h); - return 1; + return true; } void CUI::DoLabel(const CUIRect *r, const char *pText, float Size, EAlignment Align, float LineWidth, bool MultiLine) diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 79f935f3..a5da7b39 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -108,7 +108,7 @@ class CUI void StartCheck() { m_ActiveItemValid = false; }; void FinishCheck() { if(!m_ActiveItemValid) SetActiveItem(0); }; - int MouseInside(const CUIRect *pRect) const; + bool MouseInside(const CUIRect *pRect) const; bool MouseInsideClip() const; void ConvertMouseMove(float *x, float *y) const; @@ -121,7 +121,7 @@ class CUI inline bool IsClipped() const { return m_NumClips > 0; }; int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); - int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); + bool DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); // TODO: Refactor: Remove this? void DoLabel(const CUIRect *pRect, const char *pText, float Size, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 1e9aaa1d..9a5c630b 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -284,7 +284,7 @@ void CEditor::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pU int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners) { - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); bool ReturnValue = false; bool UpdateOffset = false; static int s_AtIndex = 0; @@ -459,7 +459,7 @@ float CEditor::UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Curre // logic float Ret = Current; - int Inside = UI()->MouseInside(&Handle); + bool Inside = UI()->MouseInside(&Handle); if(UI()->CheckActiveItem(pID)) { @@ -703,7 +703,7 @@ int CEditor::UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, in { // logic static float s_Value; - int Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseInside(pRect); if(UI()->CheckActiveItem(pID)) { @@ -1821,7 +1821,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) } static void *s_pEditorID = (void *)&s_pEditorID; - int Inside = UI()->MouseInside(&View); + bool Inside = UI()->MouseInside(&View); // fetch mouse position float wx = UI()->MouseWorldX(); From f935f736a2b8421a9ea10f3b0417f9c4084f0815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 28 Jan 2020 23:56:52 +0100 Subject: [PATCH 121/479] remove unused parameters from DoButtonLogic (checked also, as it's always >= 0) --- src/game/client/components/menus.cpp | 22 +++++++++---------- src/game/client/components/menus_browser.cpp | 20 ++++++++--------- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_ingame.cpp | 2 +- src/game/client/components/menus_listbox.cpp | 2 +- src/game/client/components/menus_settings.cpp | 4 ++-- src/game/client/ui.cpp | 4 ++-- src/game/client/ui.h | 2 +- src/game/editor/editor.cpp | 2 +- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index b9f220fd..dd1d9347 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -153,7 +153,7 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, } Graphics()->QuadsEnd(); - return Active ? UI()->DoButtonLogic(pID, "", Checked, pRect) : 0; + return Active && UI()->DoButtonLogic(pID, pRect); } int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, bool TextFade) @@ -210,7 +210,7 @@ int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); } - return UI()->DoButtonLogic(pBC->GetID(), pText, Checked, pRect); + return UI()->DoButtonLogic(pBC->GetID(), pRect); } void CMenus::DoButton_KeySelect(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect) @@ -244,7 +244,7 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - return UI()->DoButtonLogic(pID, pText, Checked, pRect); + return UI()->DoButtonLogic(pID, pRect); } int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha, float FontAlpha, int Corners, float r, float FontFactor) @@ -264,7 +264,7 @@ int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Ch UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); - return UI()->DoButtonLogic(pBC->GetID(), pText, Checked, pRect); + return UI()->DoButtonLogic(pBC->GetID(), pRect); } int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect) @@ -291,7 +291,7 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); } - return UI()->DoButtonLogic(pID, pText, Checked, pRect); + return UI()->DoButtonLogic(pID, pRect); } int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked, bool Locked) @@ -327,7 +327,7 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c t.y += 1.0f; // lame fix UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, CUI::ALIGN_CENTER); UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - return UI()->DoButtonLogic(pID, pText, 0, pRect); + return UI()->DoButtonLogic(pID, pRect); } int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect, bool Locked) @@ -370,7 +370,7 @@ int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - return UI()->DoButtonLogic(pBC->GetID(), "", false, pRect); + return UI()->DoButtonLogic(pBC->GetID(), pRect); } int CMenus::DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect) @@ -404,7 +404,7 @@ int CMenus::DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, c Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - return UI()->DoButtonLogic(pID, 0, 0, pRect); + return UI()->DoButtonLogic(pID, pRect); } int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) @@ -681,7 +681,7 @@ float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, Label.y += 2.0f; UI()->DoLabel(&Label, pStr, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - if(UI()->DoButtonLogic(pID, 0, 0, &Header)) + if(UI()->DoButtonLogic(pID, &Header)) { if(Active) m_pActiveDropdown = 0; @@ -733,7 +733,7 @@ float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const c Label.y += 2.0f; UI()->DoLabel(&Label, pStr, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - if(UI()->DoButtonLogic(pID, 0, 0, &Header)) + if(UI()->DoButtonLogic(pID, &Header)) *pActive ^= 1; // render content of expanded menu @@ -1613,7 +1613,7 @@ int CMenus::Render() // XText.HMargin(Button.h>=20.0f?2.0f:1.0f, &XText); UI()->DoLabel(&XText, "\xE2\x9C\x95", XText.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - if(UI()->DoButtonLogic(s_QuitButton.GetID(), "\xE2\x9C\x95", 0, &Button)) + if(UI()->DoButtonLogic(s_QuitButton.GetID(), &Button)) // if(DoButton_SpriteCleanID(&s_QuitButton, IMAGE_FRIENDICONS, SPRITE_FRIEND_X_A, &Button, false)) m_Popup = POPUP_QUIT; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index aeac0ceb..4d2a9454 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -675,7 +675,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Button, EditButtons; - if(UI()->DoButtonLogic(pFilter, "", 0, &View)) + if(UI()->DoButtonLogic(pFilter, &View)) { Switch = true; // switch later, to make sure we haven't clicked one of the filter buttons (edit...) } @@ -716,7 +716,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) if(FilterIndex > 0 && (pFilter->Custom() > CBrowserFilter::FILTER_ALL || m_lFilters[FilterIndex-1].Custom() != CBrowserFilter::FILTER_STANDARD)) { DoIcon(IMAGE_TOOLICONS, SPRITE_TOOL_UP_A, &Button); - if(UI()->DoButtonLogic(&pFilter->m_aButtonID[0], "", 0, &Button)) + if(UI()->DoButtonLogic(&pFilter->m_aButtonID[0], &Button)) { Move(true, FilterIndex); Switch = false; @@ -731,7 +731,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) if(FilterIndex >= 0 && FilterIndex < m_lFilters.size()-1 && (pFilter->Custom() != CBrowserFilter::FILTER_STANDARD || m_lFilters[FilterIndex+1].Custom() > CBrowserFilter::FILTER_ALL)) { DoIcon(IMAGE_TOOLICONS, SPRITE_TOOL_DOWN_A, &Button); - if(UI()->DoButtonLogic(&pFilter->m_aButtonID[1], "", 0, &Button)) + if(UI()->DoButtonLogic(&pFilter->m_aButtonID[1], &Button)) { Move(false, FilterIndex); Switch = false; @@ -850,7 +850,7 @@ void CMenus::RenderServerbrowserOverlay() { CUIRect Name, Clan, Score, Flag; ServerScoreBoard.HSplitTop(ButtonHeight, &Name, &ServerScoreBoard); - if(UI()->DoButtonLogic(&pInfo->m_aClients[i], "", 0, &Name)) + if(UI()->DoButtonLogic(&pInfo->m_aClients[i], &Name)) { if(pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_PLAYER) m_pClient->Friends()->RemoveFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); @@ -1635,7 +1635,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) Label.HMargin(2.0f, &Label); UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); static int s_HeaderButton[NUM_FRIEND_TYPES] = { 0 }; - if(UI()->DoButtonLogic(&s_HeaderButton[i], "", 0, &Header)) + if(UI()->DoButtonLogic(&s_HeaderButton[i], &Header)) { s_ListExtended[i] ^= 1; } @@ -1669,7 +1669,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) if(s_aName[0] || s_aClan[0]) DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button)?SPRITE_FRIEND_PLUS_A:SPRITE_FRIEND_PLUS_B, &Icon); static CButtonContainer s_AddFriend; - if((s_aName[0] || s_aClan[0]) && UI()->DoButtonLogic(&s_AddFriend, "", 0, &Button)) + if((s_aName[0] || s_aClan[0]) && UI()->DoButtonLogic(&s_AddFriend, &Button)) { m_pClient->Friends()->AddFriend(s_aName, s_aClan); FriendlistOnUpdate(); @@ -1705,7 +1705,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) if(s_aFilterName[0]) DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); static CButtonContainer s_AddFilter; - if(s_aFilterName[0] && UI()->DoButtonLogic(&s_AddFilter, "", 0, &Button)) + if(s_aFilterName[0] && UI()->DoButtonLogic(&s_AddFilter, &Button)) { m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_CUSTOM, s_aFilterName, ServerBrowser())); s_aFilterName[0] = 0; @@ -1847,7 +1847,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_R, 5.0f); DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Button); static CButtonContainer s_AddGametype; - if(s_aGametype[0] && UI()->DoButtonLogic(&s_AddGametype, "", 0, &Button)) + if(s_aGametype[0] && UI()->DoButtonLogic(&s_AddGametype, &Button)) { for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) { @@ -1922,7 +1922,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) m_pClient->m_pCountryFlags->Render(FilterInfo.m_Country, &Color, Rect.x, Rect.y, Rect.w, Rect.h); static int s_BrFilterCountryIndex = 0; - if((FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) && UI()->DoButtonLogic(&s_BrFilterCountryIndex, "", 0, &Rect)) + if((FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) && UI()->DoButtonLogic(&s_BrFilterCountryIndex, &Rect)) m_Popup = POPUP_COUNTRY; } @@ -2124,7 +2124,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); // friend - if(UI()->DoButtonLogic(&pInfo->m_aClients[i], "", 0, &Name)) + if(UI()->DoButtonLogic(&pInfo->m_aClients[i], &Name)) { if(pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_PLAYER) m_pClient->Friends()->RemoveFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 981729bd..241239ad 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -27,7 +27,7 @@ int CMenus::DoButton_DemoPlayer(CButtonContainer *pBC, const char *pText, const RenderTools()->DrawUIRect(pRect, vec4(1,1,1, 0.5f+(Fade/Seconds)*0.25f), CUI::CORNER_ALL, 5.0f); UI()->DoLabel(pRect, pText, 14.0f, CUI::ALIGN_CENTER); - return UI()->DoButtonLogic(pBC->GetID(), pText, false, pRect); + return UI()->DoButtonLogic(pBC->GetID(), pRect); } void CMenus::RenderDemoPlayer(CUIRect MainView) diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 064162ed..312c1c5c 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -784,7 +784,7 @@ void CMenus::RenderServerControl(CUIRect MainView) Label = ClearButton; Label.y += 2.0f; UI()->DoLabel(&Label, "x", Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - if(UI()->DoButtonLogic(s_ClearButton.GetID(), "x", 0, &ClearButton)) + if(UI()->DoButtonLogic(s_ClearButton.GetID(), &ClearButton)) m_aCallvoteReason[0] = 0; } } diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 4ced7492..5ce89756 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -160,7 +160,7 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected CListboxItem Item = DoNextRow(); static bool s_ItemClicked = false; - if(Item.m_Visible && m_pUI->DoButtonLogic(pId, "", m_ListBoxSelectedIndex == m_ListBoxItemIndex, &Item.m_Rect)) + if(Item.m_Visible && m_pUI->DoButtonLogic(pId, &Item.m_Rect)) { s_ItemClicked = true; m_ListBoxNewSelected = ThisItemIndex; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 918789f7..7a2dcbdf 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -77,7 +77,7 @@ int CMenus::DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - return UI()->DoButtonLogic(pBC->GetID(), "", 0, pRect); + return UI()->DoButtonLogic(pBC->GetID(), pRect); } void CMenus::RenderHSLPicker(CUIRect MainView) @@ -525,7 +525,7 @@ void CMenus::RenderSkinPartPalette(CUIRect MainView) vec4 PartColor = m_pClient->m_pSkins->GetColorV4(*CSkins::ms_apColorVariables[p], p==SKINPART_MARKING); bool Hovered = UI()->HotItem() == &s_aColorPalettes[p]; - bool Clicked = UI()->DoButtonLogic(&s_aColorPalettes[p], "", 0, &Button); + bool Clicked = UI()->DoButtonLogic(&s_aColorPalettes[p], &Button); bool Selected = m_TeePartSelected == p; if(Selected) { diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 683cc5ec..098da521 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -295,7 +295,7 @@ void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const pOtherRect->h = r.h - 2*Cut; } -int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CUI::DoButtonLogic(const void *pID, const CUIRect *pRect) { // logic int ReturnValue = 0; @@ -306,7 +306,7 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU { if(!MouseButton(ButtonUsed)) { - if(Inside && Checked >= 0) + if(Inside) ReturnValue = 1+ButtonUsed; SetActiveItem(0); } diff --git a/src/game/client/ui.h b/src/game/client/ui.h index a5da7b39..76df69f0 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -120,7 +120,7 @@ class CUI const CUIRect *ClipArea() const; inline bool IsClipped() const { return m_NumClips > 0; }; - int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); + int DoButtonLogic(const void *pID, const CUIRect *pRect); bool DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); // TODO: Refactor: Remove this? diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 9a5c630b..c47f1a23 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -533,7 +533,7 @@ int CEditor::DoButton_Editor_Common(const void *pID, const char *pText, int Chec if(UI()->HotItem() == pID && pToolTip) m_pTooltip = (const char *)pToolTip; - return UI()->DoButtonLogic(pID, pText, Checked, pRect); + return UI()->DoButtonLogic(pID, pRect); // Draw here //return UI()->DoButton(id, text, checked, r, draw_func, 0); From 511abe559d4fe57fc418d2d45228924e2156b32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 29 Jan 2020 00:12:59 +0100 Subject: [PATCH 122/479] change pointer to member function syntax --- src/game/client/components/menus_callback.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_settings.cpp | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 5d2c9515..c33e1b2b 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -340,7 +340,7 @@ float CMenus::RenderSettingsControlsScoreboard(CUIRect View) View.VSplitRight(View.w/2, &View, 0); static int s_StatboardConfigDropdown = 0; static bool s_StatboardConfigActive = false; - float Split = DoIndependentDropdownMenu(&s_StatboardConfigDropdown, &View, Localize("Configure statboard"), 20.0f, RenderSettingsControlsStats, &s_StatboardConfigActive); + float Split = DoIndependentDropdownMenu(&s_StatboardConfigDropdown, &View, Localize("Configure statboard"), 20.0f, &CMenus::RenderSettingsControlsStats, &s_StatboardConfigActive); return BackgroundHeight+Split; } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 241239ad..2ff299a2 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -427,7 +427,7 @@ void CMenus::RenderDemoList(CUIRect MainView) MainView.HSplitTop(HMargin, 0, &MainView); static int s_DemoDetailsDropdown = 0; if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) - DoIndependentDropdownMenu(&s_DemoDetailsDropdown, &MainView, aFooterLabel, ButtonHeight, RenderDemoDetails, &s_DemoDetailsActive); + DoIndependentDropdownMenu(&s_DemoDetailsDropdown, &MainView, aFooterLabel, ButtonHeight, &CMenus::RenderDemoDetails, &s_DemoDetailsActive); else { CUIRect Header; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 7a2dcbdf..5fac1b9b 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1477,49 +1477,49 @@ void CMenus::RenderSettingsControls(CUIRect MainView) CUIRect LastExpandRect; static int s_MouseDropdown = 0; static bool s_MouseActive = true; - float Split = DoIndependentDropdownMenu(&s_MouseDropdown, &MainView, Localize("Mouse"), HeaderHeight, RenderSettingsControlsMouse, &s_MouseActive); + float Split = DoIndependentDropdownMenu(&s_MouseDropdown, &MainView, Localize("Mouse"), HeaderHeight, &CMenus::RenderSettingsControlsMouse, &s_MouseActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_JoystickDropdown = 0; static bool s_JoystickActive = m_pClient->Input()->NumJoysticks() > 0; // hide by default if no joystick found - Split = DoIndependentDropdownMenu(&s_JoystickDropdown, &MainView, Localize("Joystick"), HeaderHeight, RenderSettingsControlsJoystick, &s_JoystickActive); + Split = DoIndependentDropdownMenu(&s_JoystickDropdown, &MainView, Localize("Joystick"), HeaderHeight, &CMenus::RenderSettingsControlsJoystick, &s_JoystickActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_MovementDropdown = 0; static bool s_MovementActive = true; - Split = DoIndependentDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, RenderSettingsControlsMovement, &s_MovementActive); + Split = DoIndependentDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, &CMenus::RenderSettingsControlsMovement, &s_MovementActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_WeaponDropdown = 0; static bool s_WeaponActive = true; - Split = DoIndependentDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, RenderSettingsControlsWeapon, &s_WeaponActive); + Split = DoIndependentDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, &CMenus::RenderSettingsControlsWeapon, &s_WeaponActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_VotingDropdown = 0; static bool s_VotingActive = true; - Split = DoIndependentDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, RenderSettingsControlsVoting, &s_VotingActive); + Split = DoIndependentDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, &CMenus::RenderSettingsControlsVoting, &s_VotingActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_ChatDropdown = 0; static bool s_ChatActive = true; - Split = DoIndependentDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, RenderSettingsControlsChat, &s_ChatActive); + Split = DoIndependentDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, &CMenus::RenderSettingsControlsChat, &s_ChatActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_ScoreboardDropdown = 0; static bool s_ScoreboardActive = true; - Split = DoIndependentDropdownMenu(&s_ScoreboardDropdown, &MainView, Localize("Scoreboard"), HeaderHeight, RenderSettingsControlsScoreboard, &s_ScoreboardActive); + Split = DoIndependentDropdownMenu(&s_ScoreboardDropdown, &MainView, Localize("Scoreboard"), HeaderHeight, &CMenus::RenderSettingsControlsScoreboard, &s_ScoreboardActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); static int s_MiscDropdown = 0; static bool s_MiscActive = true; - Split = DoIndependentDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, RenderSettingsControlsMisc, &s_MiscActive); + Split = DoIndependentDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, &CMenus::RenderSettingsControlsMisc, &s_MiscActive); MainView.HSplitTop(Split+10.0f, &LastExpandRect, &MainView); s_ScrollRegion.AddRect(LastExpandRect); From 62d5841a628435a9ad80151ade4b60d20070509c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 29 Jan 2020 02:03:06 +0100 Subject: [PATCH 123/479] use CListBoxItem.m_Selected instead everywhere --- src/game/client/components/menus_demo.cpp | 10 ++++---- src/game/client/components/menus_settings.cpp | 25 ++++++++----------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 2ff299a2..58beba1e 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -381,7 +381,7 @@ void CMenus::RenderDemoList(CUIRect MainView) s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = s_ListBox.DoNextItem((void*)(&r.front())); + CListboxItem Item = s_ListBox.DoNextItem((void*)(&r.front()), (&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex); // marker count const CDemoItem& DemoItem = r.front(); int DemoMarkerCount = 0; @@ -403,20 +403,20 @@ void CMenus::RenderDemoList(CUIRect MainView) IconColor = DemoMarkerCount > 0 ? vec4(0.5, 1, 0.5, 1) : vec4(1,1,1,1); } - DoIconColor(IMAGE_FILEICONS, r.front().m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); - if((&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex) // selected + DoIconColor(IMAGE_FILEICONS, DemoItem.m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); + if(Item.m_Selected) { TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); } else { Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } } } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 5fac1b9b..a8a7c2c0 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -484,15 +484,12 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } const int NewSelected = s_ListBox.DoEnd(0); - if(NewSelected != -1) + if(NewSelected != -1 && NewSelected != OldSelected) { - if(NewSelected != OldSelected) - { - const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; - mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, 24); - g_Config.m_PlayerSkin[0] = 0; - m_SkinModified = true; - } + const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; + mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, 24); + g_Config.m_PlayerSkin[0] = 0; + m_SkinModified = true; } OldSelected = NewSelected; } @@ -718,7 +715,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = s_ListBox.DoNextItem(&r.front(), false, &IsActive); + CListboxItem Item = s_ListBox.DoNextItem(&r.front(), s_SelectedLanguage != -1 && !str_comp(s_Languages[s_SelectedLanguage].m_Name, r.front().m_Name), &IsActive); if(IsActive) m_ActiveListBox = ACTLB_LANG; @@ -731,7 +728,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) 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, true); Item.m_Rect.y += 2.0f; - if(s_SelectedLanguage != -1 && !str_comp(s_Languages[s_SelectedLanguage].m_Name, r.front().m_Name)) + if(Item.m_Selected) { TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); @@ -783,7 +780,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) for(sorted_array::range r = m_lThemes.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = s_ListBox.DoNextItem(&r.front(), false, &IsActive); + CListboxItem Item = s_ListBox.DoNextItem(&r.front(), s_SelectedTheme != -1 && !str_comp(m_lThemes[s_SelectedTheme].m_Name, r.front().m_Name), &IsActive); if(IsActive) m_ActiveListBox = ACTLB_THEME; @@ -822,7 +819,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) else str_copy(aName, "(none)", sizeof(aName)); - if(s_SelectedTheme != -1 && !str_comp(m_lThemes[s_SelectedTheme].m_Name, r.front().m_Name)) + if(Item.m_Selected) { TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); @@ -1166,7 +1163,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) 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(); - if(i == OldSelected) + if(Item.m_Selected) { TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); @@ -1618,7 +1615,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, lModes[i].m_Width/G, lModes[i].m_Height/G); - if(i == OldSelected) + if(Item.m_Selected) { TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); From 89cb9984a0db84ad1ce6dc9026e39f346e124654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 29 Jan 2020 02:08:39 +0100 Subject: [PATCH 124/479] replace DoEnd output pointer argument with getter method --- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 5 +++-- src/game/client/components/menus_demo.cpp | 5 ++--- src/game/client/components/menus_ingame.cpp | 7 +++---- src/game/client/components/menus_listbox.cpp | 6 ++---- src/game/client/components/menus_settings.cpp | 12 ++++++------ 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index dd1d9347..6d458ecc 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2014,7 +2014,7 @@ int CMenus::Render() } } - const int NewSelected = s_ListBox.DoEnd(0); + const int NewSelected = s_ListBox.DoEnd(); if(OldSelected != NewSelected) s_ActSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 45e8f650..d26cbdcf 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -277,8 +277,9 @@ class CMenus : public CComponent void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect = 0, bool Background = true, bool *pActive = 0); CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = 0); - int DoEnd(bool *pItemActivated); - bool FilterMatches(const char *pNeedle); + int DoEnd(); + bool FilterMatches(const char *pNeedle) const; + bool WasItemActivated() const { return m_ListBoxItemActivated; }; }; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 58beba1e..203ac905 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -420,8 +420,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } } } - bool Activated = false; - m_DemolistSelectedIndex = s_ListBox.DoEnd(&Activated); + m_DemolistSelectedIndex = s_ListBox.DoEnd(); DemolistOnUpdate(false); MainView.HSplitTop(HMargin, 0, &MainView); @@ -488,7 +487,7 @@ void CMenus::RenderDemoList(CUIRect MainView) BottomView.VSplitLeft(Spacing, 0, &BottomView); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static CButtonContainer s_PlayButton; - if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play", "DemoBrowser"), 0, &Button) || Activated) + if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play", "DemoBrowser"), 0, &Button) || s_ListBox.WasItemActivated()) { if(m_DemolistSelectedIndex >= 0) { diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 312c1c5c..8a9eb055 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -523,9 +523,8 @@ bool CMenus::RenderServerControlServer(CUIRect MainView) } } - bool doCallVote = false; - m_CallvoteSelectedOption = s_ListBox.DoEnd(&doCallVote); - return doCallVote; + m_CallvoteSelectedOption = s_ListBox.DoEnd(); + return s_ListBox.WasItemActivated(); } void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) @@ -597,7 +596,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) } } - Selected = s_ListBox.DoEnd(0); + Selected = s_ListBox.DoEnd(); m_CallvoteSelectedPlayer = Selected != -1 ? aPlayerIDs[Selected] : -1; } diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 5ce89756..218c8a69 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -198,7 +198,7 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected return Item; } -int CMenus::CListBox::DoEnd(bool *pItemActivated) +int CMenus::CListBox::DoEnd() { m_ScrollRegion.End(); if(m_ListBoxNewSelOffset != 0 && m_ListBoxSelectedIndex != -1 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) @@ -206,12 +206,10 @@ int CMenus::CListBox::DoEnd(bool *pItemActivated) m_ListBoxNewSelected = clamp(m_ListBoxNewSelected + m_ListBoxNewSelOffset, 0, m_ListBoxNumItems - 1); m_ListBoxUpdateScroll = true; } - if(pItemActivated) - *pItemActivated = m_ListBoxItemActivated; return m_ListBoxNewSelected; } -bool CMenus::CListBox::FilterMatches(const char *pNeedle) +bool CMenus::CListBox::FilterMatches(const char *pNeedle) const { return !m_aFilterString[0] || str_find_nocase(pNeedle, m_aFilterString); } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index a8a7c2c0..17782cb8 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -394,7 +394,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) } } - const int NewSelected = s_ListBox.DoEnd(0); + const int NewSelected = s_ListBox.DoEnd(); if(NewSelected != -1 && NewSelected != OldSelected) { m_pSelectedSkin = s_paSkinList[NewSelected]; @@ -483,7 +483,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } } - const int NewSelected = s_ListBox.DoEnd(0); + const int NewSelected = s_ListBox.DoEnd(); if(NewSelected != -1 && NewSelected != OldSelected) { const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; @@ -741,7 +741,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) } } - s_SelectedLanguage = s_ListBox.DoEnd(0); + s_SelectedLanguage = s_ListBox.DoEnd(); if(OldSelected != s_SelectedLanguage) { @@ -832,7 +832,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) } } - s_SelectedTheme = s_ListBox.DoEnd(0); + s_SelectedTheme = s_ListBox.DoEnd(); if(OldSelected != s_SelectedTheme) { @@ -1176,7 +1176,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) } } - const int NewSelected = s_ListBox.DoEnd(0); + const int NewSelected = s_ListBox.DoEnd(); if(OldSelected != NewSelected) g_Config.m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; @@ -1634,7 +1634,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, } } - const int NewSelected = pListBox->DoEnd(0); + const int NewSelected = pListBox->DoEnd(); if(OldSelected != NewSelected) { g_Config.m_GfxScreenWidth = lModes[NewSelected].m_Width; From feb2e05fce71c325104d7bc2584af8560a22369d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 29 Jan 2020 02:13:25 +0100 Subject: [PATCH 125/479] use entries directly as UI IDs, remove unnecessary cast --- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_settings.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 6d458ecc..598625b7 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1986,7 +1986,7 @@ int CMenus::Render() if(pEntry->m_CountryCode == s_ActSelection) OldSelected = i; - CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); if(Item.m_Visible) { CUIRect Label; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 203ac905..802d3c49 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -381,7 +381,7 @@ void CMenus::RenderDemoList(CUIRect MainView) s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = s_ListBox.DoNextItem((void*)(&r.front()), (&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex); + CListboxItem Item = s_ListBox.DoNextItem(&r.front(), (&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex); // marker count const CDemoItem& DemoItem = r.front(); int DemoMarkerCount = 0; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 17782cb8..3c1aba61 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1148,7 +1148,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) if(pEntry->m_CountryCode == g_Config.m_PlayerCountry) OldSelected = i; - CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected == i); + CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); if(Item.m_Visible) { CUIRect Label; From 56b06f0179fccdab2deea0e0def6708ea7e5c594 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 29 Jan 2020 16:49:13 +0100 Subject: [PATCH 126/479] small cleanup --- src/engine/shared/memheap.cpp | 22 +++++++--------------- src/engine/shared/memheap.h | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/engine/shared/memheap.cpp b/src/engine/shared/memheap.cpp index 011a868f..36a8ac70 100644 --- a/src/engine/shared/memheap.cpp +++ b/src/engine/shared/memheap.cpp @@ -7,17 +7,14 @@ // allocates a new chunk to be used void CHeap::NewChunk() { - CChunk *pChunk; - char *pMem; - // allocate memory - pMem = (char*)mem_alloc(sizeof(CChunk)+CHUNK_SIZE, 1); + char *pMem = (char*)mem_alloc(sizeof(CChunk)+CHUNK_SIZE, 1); if(!pMem) return; // the chunk structure is located in the begining of the chunk // init it and return the chunk - pChunk = (CChunk*)pMem; + CChunk *pChunk = (CChunk*)pMem; pChunk->m_pMemory = (char*)(pChunk+1); pChunk->m_pCurrent = pChunk->m_pMemory; pChunk->m_pEnd = pChunk->m_pMemory + CHUNK_SIZE; @@ -29,14 +26,12 @@ void CHeap::NewChunk() //**************** void *CHeap::AllocateFromChunk(unsigned int Size) { - char *pMem; - // check if we need can fit the allocation if(m_pCurrent->m_pCurrent + Size > m_pCurrent->m_pEnd) return (void*)0x0; // get memory and move the pointer forward - pMem = m_pCurrent->m_pCurrent; + char *pMem = m_pCurrent->m_pCurrent; m_pCurrent->m_pCurrent += Size; return pMem; } @@ -45,7 +40,7 @@ void *CHeap::AllocateFromChunk(unsigned int Size) CHeap::CHeap() { m_pCurrent = 0x0; - Reset(); + NewChunk(); } CHeap::~CHeap() @@ -63,11 +58,10 @@ void CHeap::Reset() void CHeap::Clear() { CChunk *pChunk = m_pCurrent; - CChunk *pNext; while(pChunk) { - pNext = pChunk->m_pNext; + CChunk *pNext = pChunk->m_pNext; mem_free(pChunk); pChunk = pNext; } @@ -76,12 +70,10 @@ void CHeap::Clear() } // -void *CHeap::Allocate(unsigned Size) +void *CHeap::Allocate(unsigned int Size) { - char *pMem; - // try to allocate from current chunk - pMem = (char *)AllocateFromChunk(Size); + char *pMem = (char *)AllocateFromChunk(Size); if(!pMem) { // allocate new chunk and add it to the heap diff --git a/src/engine/shared/memheap.h b/src/engine/shared/memheap.h index 41a142ec..7b7e4410 100644 --- a/src/engine/shared/memheap.h +++ b/src/engine/shared/memheap.h @@ -29,6 +29,6 @@ class CHeap CHeap(); ~CHeap(); void Reset(); - void *Allocate(unsigned Size); + void *Allocate(unsigned int Size); }; #endif From 3e0e17c6e14ee55b5a340d46a4a009ea939f6386 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 29 Jan 2020 17:01:02 +0100 Subject: [PATCH 127/479] added a missing delete --- src/engine/server/server.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 93f29f96..f1b45078 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -283,6 +283,7 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_NumMapEntries = 0; m_pFirstMapEntry = 0; m_pLastMapEntry = 0; + m_pMapListHeap = 0; m_MapReload = 0; @@ -1475,7 +1476,15 @@ int CServer::Run() m_pMap->Unload(); if(m_pCurrentMapData) + { mem_free(m_pCurrentMapData); + m_pCurrentMapData = 0; + } + if(m_pMapListHeap) + { + delete m_pMapListHeap; + m_pMapListHeap = 0; + } return 0; } From 9142d556747ca1105f70a0a77861fd732b7b12d1 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 29 Jan 2020 17:12:50 +0100 Subject: [PATCH 128/479] removed unused variable --- src/engine/shared/console.cpp | 6 ------ src/engine/shared/console.h | 1 - 2 files changed, 7 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 78e70c56..593d9b5b 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -670,7 +670,6 @@ CConsole::CConsole(int FlagMask) m_paStrokeStr[0] = "0"; m_paStrokeStr[1] = "1"; m_pTempMapListHeap = 0; - m_NumMapListEntries = 0; m_pFirstMapEntry = 0; m_pLastMapEntry = 0; m_ExecutionQueue.Reset(); @@ -897,7 +896,6 @@ void CConsole::RegisterTempMap(const char *pName) if(!m_pFirstMapEntry) m_pFirstMapEntry = pEntry; str_copy(pEntry->m_aName, pName, TEMPMAP_NAME_LENGTH); - m_NumMapListEntries++; } void CConsole::DeregisterTempMap(const char *pName) @@ -911,11 +909,9 @@ void CConsole::DeregisterTempMap(const char *pName) pEntry = pEntry->m_pNext; } - m_NumMapListEntries--; CHeap *pNewTempMapListHeap = new CHeap(); CMapListEntryTemp *pNewFirstEntry = 0; CMapListEntryTemp *pNewLastEntry = 0; - int NewMapEntryNum = m_NumMapListEntries; for(CMapListEntryTemp *pSrc = m_pFirstMapEntry; pSrc; pSrc = pSrc->m_pNext) { @@ -938,7 +934,6 @@ void CConsole::DeregisterTempMap(const char *pName) m_pTempMapListHeap = pNewTempMapListHeap; m_pFirstMapEntry = pNewFirstEntry; m_pLastMapEntry = pNewLastEntry; - m_NumMapListEntries = NewMapEntryNum; } void CConsole::DeregisterTempMapAll() @@ -947,7 +942,6 @@ void CConsole::DeregisterTempMapAll() m_pTempMapListHeap->Reset(); m_pFirstMapEntry = 0; m_pLastMapEntry = 0; - m_NumMapListEntries = 0; } void CConsole::Con_Chain(IResult *pResult, void *pUserData) diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index bd54b56c..e88d5535 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -163,7 +163,6 @@ class CConsole : public IConsole }; CHeap *m_pTempMapListHeap; - int m_NumMapListEntries; CMapListEntryTemp *m_pFirstMapEntry; CMapListEntryTemp *m_pLastMapEntry; From b731259ceb84b6b27f9d8818c793584ca0b4ae90 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 29 Jan 2020 17:23:02 +0100 Subject: [PATCH 129/479] some cleanup and added a missing delete --- src/engine/shared/console.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 593d9b5b..eef4cae8 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -722,6 +722,11 @@ CConsole::~CConsole() pCommand = pNext; } + if(m_pTempMapListHeap) + { + delete m_pTempMapListHeap; + m_pTempMapListHeap = 0; + } } void CConsole::ParseArguments(int NumArgs, const char **ppArguments) @@ -900,14 +905,8 @@ void CConsole::RegisterTempMap(const char *pName) void CConsole::DeregisterTempMap(const char *pName) { - CMapListEntryTemp *pEntry = m_pFirstMapEntry; - - while(pEntry) - { - if(str_comp_nocase(pName, pEntry->m_aName) == 0) - break; - pEntry = pEntry->m_pNext; - } + if(!m_pFirstMapEntry) + return; CHeap *pNewTempMapListHeap = new CHeap(); CMapListEntryTemp *pNewFirstEntry = 0; @@ -915,7 +914,7 @@ void CConsole::DeregisterTempMap(const char *pName) for(CMapListEntryTemp *pSrc = m_pFirstMapEntry; pSrc; pSrc = pSrc->m_pNext) { - if(pSrc == pEntry) + if(str_comp_nocase(pName, pSrc->m_aName) == 0) continue; CMapListEntryTemp *pDst = (CMapListEntryTemp *)pNewTempMapListHeap->Allocate(sizeof(CMapListEntryTemp)); From 7a8f5390647c420aa8f2a3ab3e142dbe1bf6f0e4 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 29 Jan 2020 19:34:09 +0100 Subject: [PATCH 130/479] Fix `CJsonWriter` UTF-8 output Add a test for it. --- src/engine/shared/jsonwriter.cpp | 2 +- src/test/jsonwriter.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index 4d12ee3b..0af0a140 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -131,7 +131,7 @@ void CJsonWriter::WriteInternalEscaped(const char *pStr) char SimpleEscape = EscapeJsonChar(pStr[i]); // Assuming ASCII/UTF-8, exactly everything below 0x20 is a // control character. - bool NeedsEscape = SimpleEscape || pStr[i] < 0x20; + bool NeedsEscape = SimpleEscape || (unsigned char)pStr[i] < 0x20; if(NeedsEscape) { if(i - UnwrittenFrom > 0) diff --git a/src/test/jsonwriter.cpp b/src/test/jsonwriter.cpp index 4732aa5e..eae56666 100644 --- a/src/test/jsonwriter.cpp +++ b/src/test/jsonwriter.cpp @@ -87,6 +87,12 @@ TEST_F(JsonWriter, HelloWorld) Expect("\"hello world\"\n"); } +TEST_F(JsonWriter, Unicode) +{ + m_pJson->WriteStrValue("Heizölrückstoßabdämpfung"); + Expect("\"Heizölrückstoßabdämpfung\"\n"); +} + TEST_F(JsonWriter, True) { m_pJson->WriteBoolValue(true); Expect("true\n"); } TEST_F(JsonWriter, False) { m_pJson->WriteBoolValue(false); Expect("false\n"); } TEST_F(JsonWriter, Null) { m_pJson->WriteNullValue(); Expect("null\n"); } From de5859b3717406f9f0e728506ad0ef15d4e87337 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 30 Jan 2020 18:19:47 +0100 Subject: [PATCH 131/479] restructured CConfig --- src/engine/shared/config.cpp | 209 ++++++++++++++++------------------- src/engine/shared/config.h | 35 ++++++ 2 files changed, 128 insertions(+), 116 deletions(-) diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index 408b0c9d..d9279019 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -9,149 +9,126 @@ CConfiguration g_Config; -class CConfig : public IConfig +void EscapeParam(char *pDst, const char *pSrc, int size) { - IStorage *m_pStorage; - IConsole *m_pConsole; - IOHANDLE m_ConfigFile; - int m_FlagMask; - - struct CCallback - { - SAVECALLBACKFUNC m_pfnFunc; - void *m_pUserData; - }; - - enum - { - MAX_CALLBACKS = 16 - }; - - CCallback m_aCallbacks[MAX_CALLBACKS]; - int m_NumCallbacks; - - void EscapeParam(char *pDst, const char *pSrc, int size) - { - for(int i = 0; *pSrc && i < size - 1; ++i) - { - if(*pSrc == '"' || *pSrc == '\\') // escape \ and " - *pDst++ = '\\'; - *pDst++ = *pSrc++; - } - *pDst = 0; - } - - static void Con_SaveConfig(IConsole::IResult *pResult, void *pUserData) + for(int i = 0; *pSrc && i < size - 1; ++i) { - char aFilename[128]; - if(pResult->NumArguments()) - str_format(aFilename, sizeof(aFilename), "configs/%s.cfg", pResult->GetString(0)); - else - { - char aDate[20]; - str_timestamp(aDate, sizeof(aDate)); - str_format(aFilename, sizeof(aFilename), "configs/config_%s.cfg", aDate); - } - ((CConfig*)pUserData)->Save(aFilename); + if(*pSrc == '"' || *pSrc == '\\') // escape \ and " + *pDst++ = '\\'; + *pDst++ = *pSrc++; } + *pDst = 0; +} -public: - - CConfig() +static void Con_SaveConfig(IConsole::IResult *pResult, void *pUserData) +{ + char aFilename[128]; + if(pResult->NumArguments()) + str_format(aFilename, sizeof(aFilename), "configs/%s.cfg", pResult->GetString(0)); + else { - m_pStorage = 0; - m_pConsole = 0; - m_ConfigFile = 0; - m_FlagMask = 0; - m_NumCallbacks = 0; + char aDate[20]; + str_timestamp(aDate, sizeof(aDate)); + str_format(aFilename, sizeof(aFilename), "configs/config_%s.cfg", aDate); } + ((CConfig*)pUserData)->Save(aFilename); +} - virtual void Init(int FlagMask) - { - m_pStorage = Kernel()->RequestInterface(); - m_pConsole = Kernel()->RequestInterface(); - m_FlagMask = FlagMask; - Reset(); +CConfig::CConfig() +{ + m_pStorage = 0; + m_pConsole = 0; + m_ConfigFile = 0; + m_FlagMask = 0; + m_NumCallbacks = 0; +} + +void CConfig::Init(int FlagMask) +{ + m_pStorage = Kernel()->RequestInterface(); + m_pConsole = Kernel()->RequestInterface(); + m_FlagMask = FlagMask; + Reset(); - if(m_pConsole) - m_pConsole->Register("save_config", "?s", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_SaveConfig, this, "Save config to file"); - } + if(m_pConsole) + m_pConsole->Register("save_config", "?s", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_SaveConfig, this, "Save config to file"); +} - virtual void Reset() - { - #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) g_Config.m_##Name = def; - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(g_Config.m_##Name, def, len); +void CConfig::Reset() +{ + #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) g_Config.m_##Name = def; + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(g_Config.m_##Name, def, len); - #include "config_variables.h" + #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR - } + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR +} - virtual void RestoreStrings() - { - #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) // nop - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(!g_Config.m_##Name[0] && def[0]) str_copy(g_Config.m_##Name, def, len); +void CConfig::RestoreStrings() +{ + #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) // nop + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(!g_Config.m_##Name[0] && def[0]) str_copy(g_Config.m_##Name, def, len); - #include "config_variables.h" + #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR - } + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR +} - virtual void Save(const char *pFilename) - { - if(!m_pStorage) - return; +void CConfig::Save(const char *pFilename) +{ + if(!m_pStorage) + return; - if(!pFilename) - pFilename = SETTINGS_FILENAME ".cfg"; - m_ConfigFile = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); + if(!pFilename) + pFilename = SETTINGS_FILENAME ".cfg"; + m_ConfigFile = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); - if(!m_ConfigFile) - return; + if(!m_ConfigFile) + return; - WriteLine("# Teeworlds " GAME_VERSION); + WriteLine("# Teeworlds " GAME_VERSION); - char aLineBuf[1024*2]; - char aEscapeBuf[1024*2]; + char aLineBuf[1024*2]; + char aEscapeBuf[1024*2]; - #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask))&&(g_Config.m_##Name!=int(def))){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); WriteLine(aLineBuf); } - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask)&&(str_comp(g_Config.m_##Name,def)))){ EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); } + #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask))&&(g_Config.m_##Name!=int(def))){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); WriteLine(aLineBuf); } + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask)&&(str_comp(g_Config.m_##Name,def)))){ EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); } - #include "config_variables.h" + #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR - for(int i = 0; i < m_NumCallbacks; i++) - m_aCallbacks[i].m_pfnFunc(this, m_aCallbacks[i].m_pUserData); + for(int i = 0; i < m_NumCallbacks; i++) + m_aCallbacks[i].m_pfnFunc(this, m_aCallbacks[i].m_pUserData); - io_close(m_ConfigFile); + io_close(m_ConfigFile); - if(m_pConsole) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "saved config to '%s'", pFilename); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf); - } - } - - virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) + if(m_pConsole) { - dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks"); - m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc; - m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData; - m_NumCallbacks++; + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "saved config to '%s'", pFilename); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf); } +} - virtual void WriteLine(const char *pLine) - { - if(!m_ConfigFile) - return; - io_write(m_ConfigFile, pLine, str_length(pLine)); - io_write_newline(m_ConfigFile); - } -}; +void CConfig::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) +{ + dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks"); + m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc; + m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData; + m_NumCallbacks++; +} + +void CConfig::WriteLine(const char *pLine) +{ + if(!m_ConfigFile) + return; + + io_write(m_ConfigFile, pLine, str_length(pLine)); + io_write_newline(m_ConfigFile); +} IConfig *CreateConfig() { return new CConfig; } diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 1cecd8dc..6ece5843 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -3,6 +3,8 @@ #ifndef ENGINE_SHARED_CONFIG_H #define ENGINE_SHARED_CONFIG_H +#include + struct CConfiguration { #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name; @@ -25,4 +27,37 @@ enum CFGFLAG_BASICACCESS=64, }; +class CConfig : public IConfig +{ + enum + { + MAX_CALLBACKS = 16 + }; + + struct CCallback + { + SAVECALLBACKFUNC m_pfnFunc; + void *m_pUserData; + }; + + class IStorage *m_pStorage; + class IConsole *m_pConsole; + IOHANDLE m_ConfigFile; + int m_FlagMask; + CCallback m_aCallbacks[MAX_CALLBACKS]; + int m_NumCallbacks; + +public: + CConfig(); + + virtual void Init(int FlagMask); + virtual void Reset(); + virtual void RestoreStrings(); + virtual void Save(const char *pFilename); + + virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData); + + virtual void WriteLine(const char *pLine); +}; + #endif From aa1135720f47e7c63cd2dd48ba3b1c4582930a17 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 31 Jan 2020 18:37:25 +0100 Subject: [PATCH 132/479] Namespace conflicts with SDLApplication Thanks to @markph0204 https://github.com/markph0204/pygame/commit/ab30380546e672f917fe54bf253ed14bbdd547bc --- src/osxlaunch/client.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/osxlaunch/client.m b/src/osxlaunch/client.m index 8bdfb745..e8933c1a 100644 --- a/src/osxlaunch/client.m +++ b/src/osxlaunch/client.m @@ -64,10 +64,10 @@ - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #endif -@interface SDLApplication : NSApplication +@interface TWSDLApplication : NSApplication @end -@implementation SDLApplication +@implementation TWSDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { @@ -193,7 +193,7 @@ static void CustomApplicationMain (int argc, char **argv) SDLMain *sdlMain; /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; + [TWSDLApplication sharedApplication]; #ifdef SDL_USE_CPS { @@ -202,7 +202,7 @@ static void CustomApplicationMain (int argc, char **argv) if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; + [TWSDLApplication sharedApplication]; } #endif /* SDL_USE_CPS */ @@ -362,7 +362,7 @@ int main (int argc, char **argv) } #if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; + [TWSDLApplication poseAsClass:[NSApplication class]]; NSApplicationMain (argc, argv); #else CustomApplicationMain (argc, argv); From c0bf37fb4858643a4c4d632be312d8c6403a4a40 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 31 Jan 2020 22:06:32 +0100 Subject: [PATCH 133/479] removed global config value --- src/engine/client/client.cpp | 129 +++--- src/engine/client/client.h | 2 + src/engine/client/graphics_threaded.cpp | 45 +- src/engine/client/graphics_threaded.h | 1 + src/engine/client/input.cpp | 31 +- src/engine/client/input.h | 1 + src/engine/client/serverbrowser.cpp | 15 +- src/engine/client/serverbrowser.h | 2 + src/engine/client/serverbrowser_fav.cpp | 3 +- src/engine/client/serverbrowser_fav.h | 3 +- src/engine/client/serverbrowser_filter.cpp | 23 +- src/engine/client/serverbrowser_filter.h | 5 +- src/engine/client/sound.cpp | 19 +- src/engine/client/sound.h | 1 + src/engine/config.h | 1 + src/engine/console.h | 1 + src/engine/server/register.cpp | 14 +- src/engine/server/register.h | 3 +- src/engine/server/server.cpp | 113 ++--- src/engine/server/server.h | 6 +- src/engine/shared/config.cpp | 12 +- src/engine/shared/config.h | 4 +- src/engine/shared/console.cpp | 45 +- src/engine/shared/console.h | 2 + src/engine/shared/econ.cpp | 23 +- src/engine/shared/econ.h | 3 +- src/engine/shared/engine.cpp | 13 +- src/engine/shared/network.cpp | 15 +- src/engine/shared/network.h | 4 +- src/engine/shared/network_conn.cpp | 12 +- src/game/client/component.h | 1 + src/game/client/components/broadcast.cpp | 6 +- src/game/client/components/camera.cpp | 16 +- src/game/client/components/chat.cpp | 10 +- src/game/client/components/console.cpp | 4 +- src/game/client/components/controls.cpp | 12 +- src/game/client/components/countryflags.cpp | 4 +- src/game/client/components/debughud.cpp | 4 +- src/game/client/components/hud.cpp | 12 +- src/game/client/components/infomessages.cpp | 8 +- src/game/client/components/maplayers.cpp | 20 +- src/game/client/components/menus.cpp | 100 ++--- src/game/client/components/menus.h | 4 +- src/game/client/components/menus_browser.cpp | 96 ++-- src/game/client/components/menus_callback.cpp | 30 +- src/game/client/components/menus_demo.cpp | 6 +- src/game/client/components/menus_ingame.cpp | 24 +- src/game/client/components/menus_settings.cpp | 422 +++++++++--------- src/game/client/components/menus_start.cpp | 18 +- src/game/client/components/motd.cpp | 4 +- src/game/client/components/nameplates.cpp | 12 +- src/game/client/components/notifications.cpp | 6 +- src/game/client/components/players.cpp | 6 +- src/game/client/components/scoreboard.cpp | 8 +- src/game/client/components/skins.cpp | 32 +- src/game/client/components/skins.h | 6 +- src/game/client/components/sounds.cpp | 10 +- src/game/client/components/spectator.cpp | 2 +- src/game/client/components/stats.cpp | 54 +-- src/game/client/components/voting.cpp | 14 +- src/game/client/gameclient.cpp | 42 +- src/game/client/gameclient.h | 4 +- src/game/client/render.cpp | 13 +- src/game/client/render.h | 6 +- src/game/client/ui.cpp | 2 +- src/game/client/ui.h | 4 +- src/game/editor/editor.cpp | 36 +- src/game/editor/editor.h | 2 + src/game/editor/layer_quads.cpp | 2 +- src/game/editor/layer_tiles.cpp | 2 +- src/game/editor/popups.cpp | 2 +- src/game/server/entities/character.cpp | 4 +- src/game/server/gamecontext.cpp | 70 +-- src/game/server/gamecontext.h | 2 + src/game/server/gamecontroller.cpp | 80 ++-- src/game/server/gamemodes/tdm.cpp | 2 +- src/mastersrv/mastersrv.cpp | 8 +- src/versionsrv/versionsrv.cpp | 25 +- 78 files changed, 959 insertions(+), 849 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 302b38d5..88645160 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -247,6 +247,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_pSound = 0; m_pGameClient = 0; m_pMap = 0; + m_pConfig = 0; m_pConsole = 0; m_RenderFrameTime = 0.0001f; @@ -342,7 +343,7 @@ void CClient::SendInfo() // restore password of favorite if possible const char *pPassword = m_ServerBrowser.GetFavoritePassword(m_aServerAddressStr); if(!pPassword) - pPassword = g_Config.m_Password; + pPassword = Config()->Values()->m_Password; str_copy(m_aServerPassword, pPassword, sizeof(m_aServerPassword)); CMsgPacker Msg(NETMSG_INFO, true); @@ -453,7 +454,7 @@ void CClient::SetState(int s) return; int Old = m_State; - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "state change. last=%d current=%d", m_State, s); @@ -508,7 +509,7 @@ void CClient::OnClientOnline() // store password and server as favorite if configured, if the server was password protected CServerInfo Info = {0}; GetServerInfo(&Info); - bool ShouldStorePassword = g_Config.m_ClSaveServerPasswords == 2 || (g_Config.m_ClSaveServerPasswords == 1 && Info.m_Favorite); + bool ShouldStorePassword = Config()->Values()->m_ClSaveServerPasswords == 2 || (Config()->Values()->m_ClSaveServerPasswords == 1 && Info.m_Favorite); if(m_aServerPassword[0] && ShouldStorePassword && (Info.m_Flags&IServerBrowser::FLAG_PASSWORD)) { m_ServerBrowser.SetFavoritePassword(m_aServerAddressStr, m_aServerPassword); @@ -687,7 +688,7 @@ void CClient::DebugRender() int64 Now = time_get(); char aBuffer[512]; - if(!g_Config.m_Debug) + if(!Config()->Values()->m_Debug) return; //m_pGraphics->BlendNormal(); @@ -754,7 +755,7 @@ void CClient::DebugRender() Graphics()->QuadsEnd(); // render graphs - if(g_Config.m_DbgGraphs) + if(Config()->Values()->m_DbgGraphs) { //Graphics()->MapScreen(0,0,400.0f,300.0f); float w = Graphics()->ScreenWidth()/4.0f; @@ -786,7 +787,7 @@ const char *CClient::ErrorString() const void CClient::Render() { - if(g_Config.m_GfxClear) + if(Config()->Values()->m_GfxClear) Graphics()->Clear(1,1,0); GameClient()->OnRender(); @@ -1194,7 +1195,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested first chunk package"); } } @@ -1240,7 +1241,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested next chunk package"); } } @@ -1408,7 +1409,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) { // couldn't find the delta snapshots that the server used // to compress this snapshot. force the server to resync - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot"); @@ -1447,7 +1448,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d", @@ -1715,7 +1716,7 @@ void CClient::Update() } // STRESS TEST: join the server again - if(g_Config.m_DbgStress) + if(Config()->Values()->m_DbgStress) { static int64 ActionTaken = 0; int64 Now = time_get(); @@ -1724,13 +1725,13 @@ void CClient::Update() if(Now > ActionTaken+time_freq()*2) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "stress", "reconnecting!"); - Connect(g_Config.m_DbgStressServer); + Connect(Config()->Values()->m_DbgStressServer); ActionTaken = Now; } } else { - if(Now > ActionTaken+time_freq()*(10+g_Config.m_DbgStress)) + if(Now > ActionTaken+time_freq()*(10+Config()->Values()->m_DbgStress)) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "stress", "disconnecting!"); Disconnect(); @@ -1758,7 +1759,7 @@ void CClient::VersionUpdate() { if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT) { - Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_ContactClient.NetType()); + Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, Config()->Values()->m_ClVersionServer, m_ContactClient.NetType()); m_VersionInfo.m_State = CVersionInfo::STATE_START; } else if(m_VersionInfo.m_State == CVersionInfo::STATE_START) @@ -1808,6 +1809,7 @@ void CClient::InitInterfaces() m_pInput = Kernel()->RequestInterface(); m_pMap = Kernel()->RequestInterface(); m_pMasterServer = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); // @@ -1818,7 +1820,7 @@ void CClient::InitInterfaces() bool CClient::LimitFps() { - if(g_Config.m_GfxVsync || !g_Config.m_GfxLimitFps) return false; + if(Config()->Values()->m_GfxVsync || !Config()->Values()->m_GfxLimitFps) return false; /** If desired frame time is not reached: @@ -1844,7 +1846,7 @@ bool CClient::LimitFps() bool SkipFrame = true; double RenderDeltaTime = (Now - m_LastRenderTime) / (double)time_freq(); - const double DesiredTime = 1.0/g_Config.m_GfxMaxFps; + const double DesiredTime = 1.0/Config()->Values()->m_GfxMaxFps; // we can't skip another frame, so wait instead if(SkipFrame && RenderDeltaTime < DesiredTime && @@ -1878,8 +1880,8 @@ bool CClient::LimitFps() DbgFramesSkippedCount += SkipFrame? 1:0; Now = time_get(); - if(g_Config.m_GfxLimitFps && - g_Config.m_Debug && + if(Config()->Values()->m_GfxLimitFps && + Config()->Values()->m_Debug && (Now - DbgLastSkippedDbgMsg) / (double)time_freq() > 5.0) { char aBuf[128]; @@ -1936,7 +1938,7 @@ void CClient::Run() // open socket { NETADDR BindAddr; - if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(Config()->Values()->m_Bindaddr[0] && net_host_lookup(Config()->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; @@ -1990,7 +1992,7 @@ void CClient::Run() m_FpsGraph.Init(0.0f, 120.0f); // never start with the editor - g_Config.m_ClEditor = 0; + Config()->Values()->m_ClEditor = 0; // process pending commands m_pConsole->StoreCommands(false); @@ -2021,7 +2023,7 @@ void CClient::Run() Input()->MouseModeAbsolute(); m_WindowMustRefocus = 1; } - else if (g_Config.m_DbgFocus && Input()->KeyPress(KEY_ESCAPE, true)) + else if (Config()->Values()->m_DbgFocus && Input()->KeyPress(KEY_ESCAPE, true)) { Input()->MouseModeAbsolute(); m_WindowMustRefocus = 1; @@ -2043,8 +2045,8 @@ void CClient::Run() // update screen in case it got moved int ActScreen = Graphics()->GetWindowScreen(); - if(ActScreen >= 0 && ActScreen != g_Config.m_GfxScreen) - g_Config.m_GfxScreen = ActScreen; + if(ActScreen >= 0 && ActScreen != Config()->Values()->m_GfxScreen) + Config()->Values()->m_GfxScreen = ActScreen; } } @@ -2058,20 +2060,20 @@ void CClient::Run() } if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_D, true)) - g_Config.m_Debug ^= 1; + Config()->Values()->m_Debug ^= 1; if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_G, true)) - g_Config.m_DbgGraphs ^= 1; + Config()->Values()->m_DbgGraphs ^= 1; if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_E, true)) { - g_Config.m_ClEditor = g_Config.m_ClEditor^1; + Config()->Values()->m_ClEditor = Config()->Values()->m_ClEditor^1; Input()->MouseModeRelative(); } // render { - if(g_Config.m_ClEditor) + if(Config()->Values()->m_ClEditor) { if(!m_EditorActive) { @@ -2087,7 +2089,7 @@ void CClient::Run() const bool SkipFrame = LimitFps(); - if(!SkipFrame && (!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle())) + if(!SkipFrame && (!Config()->Values()->m_GfxAsyncRender || m_pGraphics->IsIdle())) { m_RenderFrames++; @@ -2104,7 +2106,7 @@ void CClient::Run() m_LastRenderTime = Now; // when we are stress testing only render every 10th frame - if(!g_Config.m_DbgStress || (m_RenderFrames%10) == 0 ) + if(!Config()->Values()->m_DbgStress || (m_RenderFrames%10) == 0 ) { if(!m_EditorActive) Render(); @@ -2133,21 +2135,21 @@ void CClient::Run() } // beNice - if(g_Config.m_ClCpuThrottle) - thread_sleep(g_Config.m_ClCpuThrottle); - else if(g_Config.m_DbgStress || !m_pGraphics->WindowActive()) + if(Config()->Values()->m_ClCpuThrottle) + thread_sleep(Config()->Values()->m_ClCpuThrottle); + else if(Config()->Values()->m_DbgStress || !m_pGraphics->WindowActive()) thread_sleep(5); - if(g_Config.m_DbgHitch) + if(Config()->Values()->m_DbgHitch) { - thread_sleep(g_Config.m_DbgHitch); - g_Config.m_DbgHitch = 0; + thread_sleep(Config()->Values()->m_DbgHitch); + Config()->Values()->m_DbgHitch = 0; } /* if(ReportTime < time_get()) { - if(0 && g_Config.m_Debug) + if(0 && Config()->Values()->m_Debug) { dbg_msg("client/report", "fps=%.02f (%.02f %.02f) netstate=%d", m_Frames/(float)(ReportInterval/time_freq()), @@ -2219,7 +2221,7 @@ void CClient::Con_Ping(IConsole::IResult *pResult, void *pUserData) void CClient::AutoScreenshot_Start() { - if(g_Config.m_ClAutoScreenshot) + if(Config()->Values()->m_ClAutoScreenshot) { Graphics()->TakeScreenshot("auto/autoscreen"); m_AutoScreenshotRecycle = true; @@ -2228,7 +2230,7 @@ void CClient::AutoScreenshot_Start() void CClient::AutoStatScreenshot_Start() { - if(g_Config.m_ClAutoStatScreenshot) + if(Config()->Values()->m_ClAutoStatScreenshot) { Graphics()->TakeScreenshot("auto/stat"); m_AutoStatScreenshotRecycle = true; @@ -2239,21 +2241,21 @@ void CClient::AutoScreenshot_Cleanup() { if(m_AutoScreenshotRecycle) { - if(g_Config.m_ClAutoScreenshotMax) + if(Config()->Values()->m_ClAutoScreenshotMax) { // clean up auto taken screens CFileCollection AutoScreens; - AutoScreens.Init(Storage(), "screenshots/auto", "autoscreen", ".png", g_Config.m_ClAutoScreenshotMax); + AutoScreens.Init(Storage(), "screenshots/auto", "autoscreen", ".png", Config()->Values()->m_ClAutoScreenshotMax); } m_AutoScreenshotRecycle = false; } if(m_AutoStatScreenshotRecycle) { - if(g_Config.m_ClAutoScreenshotMax) + if(Config()->Values()->m_ClAutoScreenshotMax) { // clean up auto taken stat screens CFileCollection AutoScreens; - AutoScreens.Init(Storage(), "screenshots/auto", "stat", ".png", g_Config.m_ClAutoScreenshotMax); + AutoScreens.Init(Storage(), "screenshots/auto", "stat", ".png", Config()->Values()->m_ClAutoScreenshotMax); } m_AutoStatScreenshotRecycle = false; } @@ -2357,15 +2359,15 @@ void CClient::DemoRecorder_Start(const char *pFilename, bool WithTimestamp) void CClient::DemoRecorder_HandleAutoStart() { - if(g_Config.m_ClAutoDemoRecord) + if(Config()->Values()->m_ClAutoDemoRecord) { DemoRecorder_Stop(); DemoRecorder_Start("auto/autorecord", true); - if(g_Config.m_ClAutoDemoMax) + if(Config()->Values()->m_ClAutoDemoMax) { // clean up auto recorded demos CFileCollection AutoDemos; - AutoDemos.Init(Storage(), "demos/auto", "autorecord", ".demo", g_Config.m_ClAutoDemoMax); + AutoDemos.Init(Storage(), "demos/auto", "autorecord", ".demo", Config()->Values()->m_ClAutoDemoMax); } } } @@ -2416,17 +2418,17 @@ void CClient::ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUse void CClient::SwitchWindowScreen(int Index) { // Todo SDL: remove this when fixed (changing screen when in fullscreen is bugged) - if(g_Config.m_GfxFullscreen) + if(Config()->Values()->m_GfxFullscreen) { ToggleFullscreen(); if(Graphics()->SetWindowScreen(Index)) - g_Config.m_GfxScreen = Index; + Config()->Values()->m_GfxScreen = Index; ToggleFullscreen(); } else { if(Graphics()->SetWindowScreen(Index)) - g_Config.m_GfxScreen = Index; + Config()->Values()->m_GfxScreen = Index; } } @@ -2435,7 +2437,7 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(g_Config.m_GfxScreen != pResult->GetInteger(0)) + if(pSelf->Config()->Values()->m_GfxScreen != pResult->GetInteger(0)) pSelf->SwitchWindowScreen(pResult->GetInteger(0)); } else @@ -2444,8 +2446,8 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, void CClient::ToggleFullscreen() { - if(Graphics()->Fullscreen(g_Config.m_GfxFullscreen^1)) - g_Config.m_GfxFullscreen ^= 1; + if(Graphics()->Fullscreen(Config()->Values()->m_GfxFullscreen^1)) + Config()->Values()->m_GfxFullscreen ^= 1; } void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2453,7 +2455,7 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(g_Config.m_GfxFullscreen != pResult->GetInteger(0)) + if(pSelf->Config()->Values()->m_GfxFullscreen != pResult->GetInteger(0)) pSelf->ToggleFullscreen(); } else @@ -2462,8 +2464,8 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC void CClient::ToggleWindowBordered() { - g_Config.m_GfxBorderless ^= 1; - Graphics()->SetWindowBordered(!g_Config.m_GfxBorderless); + Config()->Values()->m_GfxBorderless ^= 1; + Graphics()->SetWindowBordered(!Config()->Values()->m_GfxBorderless); } void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2471,7 +2473,7 @@ void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(!g_Config.m_GfxFullscreen && (g_Config.m_GfxBorderless != pResult->GetInteger(0))) + if(!pSelf->Config()->Values()->m_GfxFullscreen && (pSelf->Config()->Values()->m_GfxBorderless != pResult->GetInteger(0))) pSelf->ToggleWindowBordered(); } else @@ -2480,8 +2482,8 @@ void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData void CClient::ToggleWindowVSync() { - if(Graphics()->SetVSync(g_Config.m_GfxVsync^1)) - g_Config.m_GfxVsync ^= 1; + if(Graphics()->SetVSync(Config()->Values()->m_GfxVsync^1)) + Config()->Values()->m_GfxVsync ^= 1; } void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2489,7 +2491,7 @@ void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, I CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(g_Config.m_GfxVsync != pResult->GetInteger(0)) + if(pSelf->Config()->Values()->m_GfxVsync != pResult->GetInteger(0)) pSelf->ToggleWindowVSync(); } else @@ -2537,9 +2539,9 @@ void CClient::ConnectOnStart(const char *pAddress) void CClient::DoVersionSpecificActions() { - if(g_Config.m_ClLastVersionPlayed <= 0x0703) - str_copy(g_Config.m_ClMenuMap, "winter", sizeof(g_Config.m_ClMenuMap)); - g_Config.m_ClLastVersionPlayed = CLIENT_VERSION; + if(Config()->Values()->m_ClLastVersionPlayed <= 0x0703) + str_copy(Config()->Values()->m_ClMenuMap, "winter", sizeof(Config()->Values()->m_ClMenuMap)); + Config()->Values()->m_ClLastVersionPlayed = CLIENT_VERSION; } /* @@ -2637,6 +2639,7 @@ int main(int argc, const char **argv) // ignore_convention pEngine->Init(); pConfig->Init(FlagMask); + pConsole->Init(); pEngineMasterServer->Init(); pEngineMasterServer->Load(); @@ -2678,9 +2681,9 @@ int main(int argc, const char **argv) // ignore_convention #if defined(CONF_FAMILY_WINDOWS) bool HideConsole = false; #ifdef CONF_RELEASE - if(!(g_Config.m_ShowConsoleWindow&2)) + if(!(pConfig->Values()->m_ShowConsoleWindow&2)) #else - if(!(g_Config.m_ShowConsoleWindow&1)) + if(!(pConfig->Values()->m_ShowConsoleWindow&1)) #endif { HideConsole = true; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index fdad37b0..0725740e 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -62,6 +62,7 @@ class CClient : public IClient, public CDemoPlayer::IListner IEngineSound *m_pSound; IGameClient *m_pGameClient; IEngineMap *m_pMap; + IConfig *m_pConfig; IConsole *m_pConsole; IStorage *m_pStorage; IEngineMasterServer *m_pMasterServer; @@ -199,6 +200,7 @@ class CClient : public IClient, public CDemoPlayer::IListner IEngineSound *Sound() { return m_pSound; } IGameClient *GameClient() { return m_pGameClient; } IEngineMasterServer *MasterServer() { return m_pMasterServer; } + IConfig *Config() { return m_pConfig; } IStorage *Storage() { return m_pStorage; } CClient(); diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 74bbc24c..99807046 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -332,7 +332,7 @@ int CGraphics_Threaded::LoadTextureRawSub(CTextureHandle TextureID, int x, int y IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) { // don't waste memory on texture if we are stress testing - if(g_Config.m_DbgStress) + if(m_pConfig->Values()->m_DbgStress) return m_InvalidTexture; // grab texture @@ -353,9 +353,9 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig Cmd.m_Flags = CCommandBuffer::TEXFLAG_TEXTURE2D; if(Flags&IGraphics::TEXLOAD_NOMIPMAPS) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS; - if(g_Config.m_GfxTextureCompression) + if(m_pConfig->Values()->m_GfxTextureCompression) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_COMPRESSED; - if(g_Config.m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE) + if(m_pConfig->Values()->m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_QUALITY; if(Flags&IGraphics::TEXLOAD_ARRAY_256) { @@ -397,7 +397,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTexture(const char *pFilename, ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags); mem_free(Img.m_pData); - if(ID.Id() != m_InvalidTexture.Id() && g_Config.m_Debug) + if(ID.Id() != m_InvalidTexture.Id() && m_pConfig->Values()->m_Debug) dbg_msg("graphics/texture", "loaded %s", pFilename); return ID; } @@ -742,15 +742,15 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pTe int CGraphics_Threaded::IssueInit() { int Flags = 0; - if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS; - if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN; - if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; - if(g_Config.m_GfxHighdpi) Flags |= IGraphicsBackend::INITFLAG_HIGHDPI; - if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; - if(g_Config.m_GfxUseX11XRandRWM) Flags |= IGraphicsBackend::INITFLAG_X11XRANDR; - - return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, - &g_Config.m_GfxScreenHeight, &m_ScreenWidth, &m_ScreenHeight, g_Config.m_GfxFsaaSamples, + if(m_pConfig->Values()->m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS; + if(m_pConfig->Values()->m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN; + if(m_pConfig->Values()->m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; + if(m_pConfig->Values()->m_GfxHighdpi) Flags |= IGraphicsBackend::INITFLAG_HIGHDPI; + if(m_pConfig->Values()->m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; + if(m_pConfig->Values()->m_GfxUseX11XRandRWM) Flags |= IGraphicsBackend::INITFLAG_X11XRANDR; + + return m_pBackend->Init("Teeworlds", &m_pConfig->Values()->m_GfxScreen, &m_pConfig->Values()->m_GfxScreenWidth, + &m_pConfig->Values()->m_GfxScreenHeight, &m_ScreenWidth, &m_ScreenHeight, m_pConfig->Values()->m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight); } @@ -760,12 +760,12 @@ int CGraphics_Threaded::InitWindow() return 0; // try disabling fsaa - while(g_Config.m_GfxFsaaSamples) + while(m_pConfig->Values()->m_GfxFsaaSamples) { - g_Config.m_GfxFsaaSamples--; + m_pConfig->Values()->m_GfxFsaaSamples--; - if(g_Config.m_GfxFsaaSamples) - dbg_msg("gfx", "lowering FSAA to %d and trying again", g_Config.m_GfxFsaaSamples); + if(m_pConfig->Values()->m_GfxFsaaSamples) + dbg_msg("gfx", "lowering FSAA to %d and trying again", m_pConfig->Values()->m_GfxFsaaSamples); else dbg_msg("gfx", "disabling FSAA and trying again"); @@ -774,11 +774,11 @@ int CGraphics_Threaded::InitWindow() } // try lowering the resolution - if(g_Config.m_GfxScreenWidth != 640 || g_Config.m_GfxScreenHeight != 480) + if(m_pConfig->Values()->m_GfxScreenWidth != 640 || m_pConfig->Values()->m_GfxScreenHeight != 480) { dbg_msg("gfx", "setting resolution to 640x480 and trying again"); - g_Config.m_GfxScreenWidth = 640; - g_Config.m_GfxScreenHeight = 480; + m_pConfig->Values()->m_GfxScreenWidth = 640; + m_pConfig->Values()->m_GfxScreenHeight = 480; if(IssueInit() == 0) return 0; @@ -793,6 +793,7 @@ int CGraphics_Threaded::Init() { // fetch pointers m_pStorage = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); // init textures @@ -959,7 +960,7 @@ void CGraphics_Threaded::Swap() // add swap command CCommandBuffer::SCommand_Swap Cmd; - Cmd.m_Finish = g_Config.m_GfxFinish; + Cmd.m_Finish = m_pConfig->Values()->m_GfxFinish; m_pCommandBuffer->AddCommand(Cmd); // kick the command buffer @@ -1001,7 +1002,7 @@ void CGraphics_Threaded::WaitForIdle() int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) { - if(g_Config.m_GfxDisplayAllModes) + if(m_pConfig->Values()->m_GfxDisplayAllModes) { int Count = sizeof(g_aFakeModes)/sizeof(CVideoMode); mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes)); diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index bb035d05..c3ec70a3 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -360,6 +360,7 @@ class CGraphics_Threaded : public IEngineGraphics // class IStorage *m_pStorage; + class IConfig *m_pConfig; class IConsole *m_pConsole; CCommandBuffer::SVertex m_aVertices[MAX_VERTICES]; diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 680b94b6..ee65249f 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -42,6 +42,10 @@ CInput::CInput() mem_zero(m_aInputCount, sizeof(m_aInputCount)); mem_zero(m_aInputState, sizeof(m_aInputState)); + m_pConfig = 0; + m_pConsole = 0; + m_pGraphics = 0; + m_InputCounter = 1; m_InputGrabbed = 0; m_pClipboardText = 0; @@ -68,6 +72,7 @@ CInput::~CInput() void CInput::Init() { m_pGraphics = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); // FIXME: unicode handling: use SDL_StartTextInput/SDL_StopTextInput on inputs @@ -121,7 +126,7 @@ SDL_Joystick* CInput::GetActiveJoystick() { return NULL; } - if(m_aSelectedJoystickGUID[0] && str_comp(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID) != 0) + if(m_aSelectedJoystickGUID[0] && str_comp(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID) != 0) { // Refresh if cached GUID differs from configured GUID m_SelectedJoystickIndex = -1; @@ -132,10 +137,10 @@ SDL_Joystick* CInput::GetActiveJoystick() { char aGUID[sizeof(m_aSelectedJoystickGUID)]; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[i]), aGUID, sizeof(aGUID)); - if(str_comp(g_Config.m_JoystickGUID, aGUID) == 0) + if(str_comp(m_pConfig->Values()->m_JoystickGUID, aGUID) == 0) { m_SelectedJoystickIndex = i; - str_copy(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + str_copy(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); break; } } @@ -143,8 +148,8 @@ SDL_Joystick* CInput::GetActiveJoystick() if(m_SelectedJoystickIndex == -1) { m_SelectedJoystickIndex = 0; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[0]), g_Config.m_JoystickGUID, sizeof(g_Config.m_JoystickGUID)); - str_copy(m_aSelectedJoystickGUID, g_Config.m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[0]), m_pConfig->Values()->m_JoystickGUID, sizeof(m_pConfig->Values()->m_JoystickGUID)); + str_copy(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); } } return m_apJoysticks[m_SelectedJoystickIndex]; @@ -168,7 +173,7 @@ void CInput::SelectNextJoystick() if(Num > 1) { const int NextIndex = (m_SelectedJoystickIndex + 1) % Num; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[NextIndex]), g_Config.m_JoystickGUID, sizeof(g_Config.m_JoystickGUID)); + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[NextIndex]), m_pConfig->Values()->m_JoystickGUID, sizeof(m_pConfig->Values()->m_JoystickGUID)); } } @@ -199,27 +204,27 @@ void CInput::MouseRelative(float *x, float *y) return; int nx = 0, ny = 0; - float MouseSens = g_Config.m_InpMousesens/100.0f; - float JoystickSens = g_Config.m_JoystickSens/100.0f; + float MouseSens = m_pConfig->Values()->m_InpMousesens/100.0f; + float JoystickSens = m_pConfig->Values()->m_JoystickSens/100.0f; SDL_GetRelativeMouseState(&nx,&ny); vec2 j = vec2(0.0f, 0.0f); - if(g_Config.m_JoystickEnable && GetActiveJoystick()) + if(m_pConfig->Values()->m_JoystickEnable && GetActiveJoystick()) { const float Max = 50.0f; - j = vec2(GetJoystickAxisValue(g_Config.m_JoystickX), GetJoystickAxisValue(g_Config.m_JoystickY)) * Max; + j = vec2(GetJoystickAxisValue(m_pConfig->Values()->m_JoystickX), GetJoystickAxisValue(m_pConfig->Values()->m_JoystickY)) * Max; const float Len = length(j); - if(Len/sqrtf(2.0f) <= g_Config.m_JoystickTolerance) + if(Len/sqrtf(2.0f) <= m_pConfig->Values()->m_JoystickTolerance) { j = vec2(0.0f, 0.0f); } else { const vec2 nj = Len > 0.0f ? j / Len : vec2(0.0f, 0.0f); - j = nj * min(Len, Max) - nj * g_Config.m_JoystickTolerance; + j = nj * min(Len, Max) - nj * m_pConfig->Values()->m_JoystickTolerance; } } @@ -243,7 +248,7 @@ void CInput::MouseModeRelative() { m_InputGrabbed = 1; SDL_ShowCursor(SDL_DISABLE); - if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, g_Config.m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE) + if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, m_pConfig->Values()->m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "input", "unable to switch relative mouse mode"); } diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 4b226b22..9b98436a 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -8,6 +8,7 @@ class CInput : public IEngineInput { IEngineGraphics *m_pGraphics; + IConfig *m_pConfig; IConsole *m_pConsole; sorted_array m_apJoysticks; diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index e1ed1d50..ffc7b504 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -79,13 +79,14 @@ CServerBrowser::CServerBrowser() void CServerBrowser::Init(class CNetClient *pNetClient, const char *pNetVersion) { + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); m_pMasterServer = Kernel()->RequestInterface(); m_pNetClient = pNetClient; - m_ServerBrowserFavorites.Init(pNetClient, m_pConsole, Kernel()->RequestInterface(), Kernel()->RequestInterface()); - m_ServerBrowserFilter.Init(Kernel()->RequestInterface(), pNetVersion); + m_ServerBrowserFavorites.Init(pNetClient, m_pConsole, Kernel()->RequestInterface(), Config()); + m_ServerBrowserFilter.Init(Config(), Kernel()->RequestInterface(), pNetVersion); } void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CServerInfo *pInfo) @@ -187,7 +188,7 @@ void CServerBrowser::Update(bool ForceResort) m_MasterRefreshTime = Now; - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "requesting server list"); } @@ -197,7 +198,7 @@ void CServerBrowser::Update(bool ForceResort) LoadServerlist(); m_MasterRefreshTime = 0; - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "using backup server list"); } @@ -228,7 +229,7 @@ void CServerBrowser::Update(bool ForceResort) break; // no more then 10 concurrent requests - if(Count == g_Config.m_BrMaxRequests) + if(Count == Config()->Values()->m_BrMaxRequests) break; if(pEntry->m_RequestTime == 0) @@ -301,7 +302,7 @@ void CServerBrowser::Refresh(int RefreshFlags) m_pNetClient->Send(&Packet); } - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "broadcasting for servers"); } @@ -534,7 +535,7 @@ void CServerBrowser::CBFTrackPacket(int TrackID, void *pCallbackUser) void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true); diff --git a/src/engine/client/serverbrowser.h b/src/engine/client/serverbrowser.h index 3e893b30..5b595429 100644 --- a/src/engine/client/serverbrowser.h +++ b/src/engine/client/serverbrowser.h @@ -59,6 +59,7 @@ class CServerBrowser : public IServerBrowser private: class CNetClient *m_pNetClient; + class IConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; class IMasterServer *m_pMasterServer; @@ -66,6 +67,7 @@ class CServerBrowser : public IServerBrowser class CServerBrowserFavorites m_ServerBrowserFavorites; class CServerBrowserFilter m_ServerBrowserFilter; + class IConfig *Config() const { return m_pConfig; } class IConsole *Console() const { return m_pConsole; } class IStorage *Storage() const { return m_pStorage; } diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index f66b7c68..9de470f3 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -29,6 +29,7 @@ CServerBrowserFavorites::CServerBrowserFavorites() void CServerBrowserFavorites::Init(CNetClient *pNetClient, IConsole *pConsole, IEngine *pEngine, IConfig *pConfig) { m_pNetClient = pNetClient; + m_pConfig = pConfig; m_pConsole = pConsole; m_pEngine = pEngine; if(pConfig) @@ -91,7 +92,7 @@ bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR ++m_NumFavoriteServers; - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "added fav '%s'", pHostname); diff --git a/src/engine/client/serverbrowser_fav.h b/src/engine/client/serverbrowser_fav.h index 55eabfe4..fdd013a5 100644 --- a/src/engine/client/serverbrowser_fav.h +++ b/src/engine/client/serverbrowser_fav.h @@ -24,7 +24,7 @@ class CServerBrowserFavorites struct CFavoriteServer { char m_aHostname[128]; - char m_aPassword[sizeof(g_Config.m_Password)]; + char m_aPassword[sizeof(CConfiguration::m_Password)]; NETADDR m_Addr; int m_State; } m_aFavoriteServers[MAX_FAVORITES]; @@ -40,6 +40,7 @@ class CServerBrowserFavorites } m_FavLookup; class CNetClient *m_pNetClient; + class IConfig *m_pConfig; class IConsole *m_pConsole; class IEngine *m_pEngine; diff --git a/src/engine/client/serverbrowser_filter.cpp b/src/engine/client/serverbrowser_filter.cpp index 31a49c22..6df6bcce 100644 --- a/src/engine/client/serverbrowser_filter.cpp +++ b/src/engine/client/serverbrowser_filter.cpp @@ -19,7 +19,7 @@ class SortWrap CServerBrowserFilter::CServerFilter *m_pThis; public: SortWrap(CServerBrowserFilter::CServerFilter *t, SortFunc f) : m_pfnSort(f), m_pThis(t) {} - bool operator()(int a, int b) { return (g_Config.m_BrSortOrder ? (m_pThis->*m_pfnSort)(b, a) : (m_pThis->*m_pfnSort)(a, b)); } + bool operator()(int a, int b) { return (m_pThis->Config()->Values()->m_BrSortOrder ? (m_pThis->*m_pfnSort)(b, a) : (m_pThis->*m_pfnSort)(a, b)); } }; // CServerFilter @@ -157,14 +157,14 @@ void CServerBrowserFilter::CServerFilter::Filter() } } - if(!Filtered && g_Config.m_BrFilterString[0] != 0) + if(!Filtered && Config()->Values()->m_BrFilterString[0] != 0) { int MatchFound = 0; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit = 0; // match against server name - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aName, g_Config.m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aName, Config()->Values()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_SERVERNAME; @@ -173,8 +173,8 @@ void CServerBrowserFilter::CServerFilter::Filter() // match against players for(int p = 0; p < m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients; p++) { - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, g_Config.m_BrFilterString) || - str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, g_Config.m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, Config()->Values()->m_BrFilterString) || + str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, Config()->Values()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYER; @@ -183,14 +183,14 @@ void CServerBrowserFilter::CServerFilter::Filter() } // match against map - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aMap, g_Config.m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aMap, Config()->Values()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME; } // match against game type - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, Config()->Values()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_GAMETYPE; @@ -223,8 +223,8 @@ void CServerBrowserFilter::CServerFilter::Filter() int CServerBrowserFilter::CServerFilter::GetSortHash() const { - int i = g_Config.m_BrSort&0x7; - i |= g_Config.m_BrSortOrder<<3; + int i = Config()->Values()->m_BrSort&0x7; + i |= Config()->Values()->m_BrSortOrder<<3; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) i |= 1<<4; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY) i |= 1<<5; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL) i |= 1<<6; @@ -245,7 +245,7 @@ void CServerBrowserFilter::CServerFilter::Sort() Filter(); // sort - switch(g_Config.m_BrSort) + switch(Config()->Values()->m_BrSort) { case IServerBrowser::SORT_NAME: std::stable_sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowserFilter::CServerFilter::SortCompareName)); @@ -336,8 +336,9 @@ bool CServerBrowserFilter::CServerFilter::SortCompareNumRealClients(int Index1, } // CServerBrowserFilter -void CServerBrowserFilter::Init(IFriends *pFriends, const char *pNetVersion) +void CServerBrowserFilter::Init(IConfig *pConfig, IFriends *pFriends, const char *pNetVersion) { + m_pConfig = pConfig; m_pFriends = pFriends; str_copy(m_aNetVersion, pNetVersion, sizeof(m_aNetVersion)); } diff --git a/src/engine/client/serverbrowser_filter.h b/src/engine/client/serverbrowser_filter.h index ebb98eac..db7ebbb0 100644 --- a/src/engine/client/serverbrowser_filter.h +++ b/src/engine/client/serverbrowser_filter.h @@ -18,6 +18,7 @@ class CServerBrowserFilter { public: CServerBrowserFilter *m_pServerBrowserFilter; + IConfig *Config() const { return m_pServerBrowserFilter->m_pConfig; } // filter settings CServerFilterInfo m_FilterInfo; @@ -46,9 +47,10 @@ class CServerBrowserFilter bool SortCompareNumClients(int Index1, int Index2) const; bool SortCompareNumRealClients(int Index1, int Index2) const; }; + IConfig *Config() { return m_pConfig; } // - void Init(class IFriends *pFriends, const char *pNetVersion); + void Init(class IConfig *pConfig, class IFriends *pFriends, const char *pNetVersion); void Clear(); void Sort(class CServerEntry **ppServerlist, int NumServers, int ResortFlags); @@ -65,6 +67,7 @@ class CServerBrowserFilter int GetNumSortedPlayers(int FilterIndex) const { return m_lFilters[FilterIndex].m_NumSortedPlayers; } private: + class IConfig *m_pConfig; class IFriends *m_pFriends; char m_aNetVersion[128]; array m_lFilters; diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 2d733bb6..9cfe1044 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -207,6 +207,7 @@ int CSound::Init() m_aChannels[i].m_Vol = 255; m_SoundEnabled = 0; + m_pConfig = Kernel()->RequestInterface(); m_pGraphics = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); @@ -214,7 +215,7 @@ int CSound::Init() m_SoundLock = lock_create(); - if(!g_Config.m_SndInit) + if(!m_pConfig->Values()->m_SndInit) return 0; if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) @@ -223,13 +224,13 @@ int CSound::Init() return -1; } - m_MixingRate = g_Config.m_SndRate; + m_MixingRate = m_pConfig->Values()->m_SndRate; // Set 16-bit stereo audio at 22Khz - Format.freq = g_Config.m_SndRate; // ignore_convention + Format.freq = m_pConfig->Values()->m_SndRate; // ignore_convention Format.format = AUDIO_S16; // ignore_convention Format.channels = 2; // ignore_convention - Format.samples = g_Config.m_SndBufferSize; // ignore_convention + Format.samples = m_pConfig->Values()->m_SndBufferSize; // ignore_convention Format.callback = SdlCallback; // ignore_convention Format.userdata = NULL; // ignore_convention @@ -242,7 +243,7 @@ int CSound::Init() else dbg_msg("client/sound", "sound init successful"); - m_MaxFrames = g_Config.m_SndBufferSize*2; + m_MaxFrames = m_pConfig->Values()->m_SndBufferSize*2; m_pMixBuffer = (int *)mem_alloc(m_MaxFrames*2*sizeof(int), 1); SDL_PauseAudio(0); @@ -255,9 +256,9 @@ int CSound::Init() int CSound::Update() { // update volume - int WantedVolume = g_Config.m_SndVolume; + int WantedVolume = m_pConfig->Values()->m_SndVolume; - if(!m_pGraphics->WindowActive() && g_Config.m_SndNonactiveMute) + if(!m_pGraphics->WindowActive() && m_pConfig->Values()->m_SndNonactiveMute) WantedVolume = 0; if(WantedVolume != m_SoundVolume) @@ -378,7 +379,7 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename) WavpackContext *pContext; // don't waste memory on sound when we are stress testing - if(g_Config.m_DbgStress) + if(m_pConfig->Values()->m_DbgStress) return CSampleHandle(); // no need to load sound when we are running with no sound @@ -482,7 +483,7 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename) io_close(s_File); s_File = NULL; - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("sound/wv", "loaded %s", pFilename); RateConvert(SampleID); diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index cec2cded..31e5cadf 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -10,6 +10,7 @@ class CSound : public IEngineSound int m_SoundEnabled; public: + IConfig *m_pConfig; IEngineGraphics *m_pGraphics; IStorage *m_pStorage; diff --git a/src/engine/config.h b/src/engine/config.h index f8840b9f..89a5fea2 100644 --- a/src/engine/config.h +++ b/src/engine/config.h @@ -15,6 +15,7 @@ class IConfig : public IInterface virtual void Reset() = 0; virtual void RestoreStrings() = 0; virtual void Save(const char *pFilename=0) = 0; + virtual class CConfiguration *Values() = 0; virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) = 0; diff --git a/src/engine/console.h b/src/engine/console.h index c0809533..f6f0bd04 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -66,6 +66,7 @@ class IConsole : public IInterface typedef void (*FCommandCallback)(IResult *pResult, void *pUserData); typedef void (*FChainCommandCallback)(IResult *pResult, void *pUserData, FCommandCallback pfnCallback, void *pCallbackUserData); + virtual void Init() = 0; virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int Flagmask) const = 0; virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp) = 0; virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser) = 0; diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index db2ff25f..c90bff6b 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -14,6 +14,7 @@ CRegister::CRegister() { m_pNetServer = 0; m_pMasterServer = 0; + m_pConfig = 0; m_pConsole = 0; m_RegisterState = REGISTERSTATE_START; @@ -45,7 +46,7 @@ void CRegister::RegisterSendFwcheckresponse(NETADDR *pAddr, TOKEN Token) void CRegister::RegisterSendHeartbeat(NETADDR Addr) { static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2]; - unsigned short Port = g_Config.m_SvPort; + unsigned short Port = m_pConfig->Values()->m_SvPort; CNetChunk Packet; mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)); @@ -57,8 +58,8 @@ void CRegister::RegisterSendHeartbeat(NETADDR Addr) Packet.m_pData = &aData; // supply the set port that the master can use if it has problems - if(g_Config.m_SvExternalPort) - Port = g_Config.m_SvExternalPort; + if(m_pConfig->Values()->m_SvExternalPort) + Port = m_pConfig->Values()->m_SvExternalPort; aData[sizeof(SERVERBROWSE_HEARTBEAT)] = Port >> 8; aData[sizeof(SERVERBROWSE_HEARTBEAT)+1] = Port&0xff; m_pNetServer->Send(&Packet); @@ -90,10 +91,11 @@ void CRegister::RegisterGotCount(CNetChunk *pChunk) } } -void CRegister::Init(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole) +void CRegister::Init(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole) { m_pNetServer = pNetServer; m_pMasterServer = pMasterServer; + m_pConfig = pConfig; m_pConsole = pConsole; } @@ -102,7 +104,7 @@ void CRegister::RegisterUpdate(int Nettype) int64 Now = time_get(); int64 Freq = time_freq(); - if(!g_Config.m_SvRegister) + if(!m_pConfig->Values()->m_SvRegister) return; m_pMasterServer->Update(); @@ -274,7 +276,7 @@ int CRegister::RegisterProcessPacket(CNetChunk *pPacket, TOKEN Token) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "ERROR: the master server reports that clients can not connect to this server."); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "ERROR: configure your firewall/nat to let through udp on port %d.", g_Config.m_SvPort); + str_format(aBuf, sizeof(aBuf), "ERROR: configure your firewall/nat to let through udp on port %d.", m_pConfig->Values()->m_SvPort); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); RegisterNewState(REGISTERSTATE_ERROR); return 1; diff --git a/src/engine/server/register.h b/src/engine/server/register.h index 8699fab2..719b9ac4 100644 --- a/src/engine/server/register.h +++ b/src/engine/server/register.h @@ -27,6 +27,7 @@ class CRegister class CNetServer *m_pNetServer; class IEngineMasterServer *m_pMasterServer; + class IConfig *m_pConfig; class IConsole *m_pConsole; int m_RegisterState; @@ -45,7 +46,7 @@ class CRegister public: CRegister(); - void Init(class CNetServer *pNetServer, class IEngineMasterServer *pMasterServer, class IConsole *pConsole); + void Init(class CNetServer *pNetServer, class IEngineMasterServer *pMasterServer, class IConfig *pConfig, class IConsole *pConsole); void RegisterUpdate(int Nettype); int RegisterProcessPacket(struct CNetChunk *pPacket, TOKEN Token); }; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index f1b45078..2a0d716f 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -486,7 +486,7 @@ void CServer::InitRconPasswordIfUnset() aRandomPassword[2 * i + 1] = VALUES[RandomNumber % NUM_VALUES]; } - str_copy(g_Config.m_SvRconPassword, aRandomPassword, sizeof(g_Config.m_SvRconPassword)); + str_copy(Config()->Values()->m_SvRconPassword, aRandomPassword, sizeof(Config()->Values()->m_SvRconPassword)); m_GeneratedRconPassword = 1; } @@ -847,7 +847,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC); - if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0) + if(Config()->Values()->m_Password[0] != 0 && str_comp(Config()->Values()->m_Password, pPassword) != 0) { // wrong password m_NetServer.Drop(ClientID, "Wrong password"); @@ -885,7 +885,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID); - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize); @@ -1007,7 +1007,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0) { - if(g_Config.m_SvRconPassword[0] == 0 && g_Config.m_SvRconModPassword[0] == 0) + if(Config()->Values()->m_SvRconPassword[0] == 0 && Config()->Values()->m_SvRconModPassword[0] == 0) { if(!m_aClients[ClientID].m_NoRconNote) { @@ -1015,7 +1015,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) m_aClients[ClientID].m_NoRconNote = true; } } - else if(g_Config.m_SvRconPassword[0] && str_comp(pPw, g_Config.m_SvRconPassword) == 0) + else if(Config()->Values()->m_SvRconPassword[0] && str_comp(pPw, Config()->Values()->m_SvRconPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_ON, true); SendMsg(&Msg, MSGFLAG_VITAL, ClientID); @@ -1029,7 +1029,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } - else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0) + else if(Config()->Values()->m_SvRconModPassword[0] && str_comp(pPw, Config()->Values()->m_SvRconModPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_ON, true); SendMsg(&Msg, MSGFLAG_VITAL, ClientID); @@ -1044,18 +1044,18 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } - else if(g_Config.m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) + else if(Config()->Values()->m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) { m_aClients[ClientID].m_AuthTries++; char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, g_Config.m_SvRconMaxTries); + str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, Config()->Values()->m_SvRconMaxTries); SendRconLine(ClientID, aBuf); - if(m_aClients[ClientID].m_AuthTries >= g_Config.m_SvRconMaxTries) + if(m_aClients[ClientID].m_AuthTries >= Config()->Values()->m_SvRconMaxTries) { - if(!g_Config.m_SvRconBantime) + if(!Config()->Values()->m_SvRconBantime) m_NetServer.Drop(ClientID, "Too many remote console authentication tries"); else - m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), g_Config.m_SvRconBantime*60, "Too many remote console authentication tries"); + m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), Config()->Values()->m_SvRconBantime*60, "Too many remote console authentication tries"); } } else @@ -1071,7 +1071,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aHex[] = "0123456789ABCDEF"; char aBuf[512]; @@ -1122,8 +1122,8 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) } pPacker->AddString(GameServer()->Version(), 32); - pPacker->AddString(g_Config.m_SvName, 64); - pPacker->AddString(g_Config.m_SvHostname, 128); + pPacker->AddString(Config()->Values()->m_SvName, 64); + pPacker->AddString(Config()->Values()->m_SvHostname, 128); pPacker->AddString(GetMapName(), 32); // gametype @@ -1131,17 +1131,17 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) // flags int Flags = 0; - if(g_Config.m_Password[0]) // password set + if(Config()->Values()->m_Password[0]) // password set Flags |= SERVERINFO_FLAG_PASSWORD; if(GameServer()->TimeScore()) Flags |= SERVERINFO_FLAG_TIMESCORE; pPacker->AddInt(Flags); - pPacker->AddInt(g_Config.m_SvSkillLevel); // server skill level + pPacker->AddInt(Config()->Values()->m_SvSkillLevel); // server skill level pPacker->AddInt(PlayerCount); // num players - pPacker->AddInt(g_Config.m_SvPlayerSlots); // max players + pPacker->AddInt(Config()->Values()->m_SvPlayerSlots); // max players pPacker->AddInt(ClientCount); // num clients - pPacker->AddInt(max(ClientCount, g_Config.m_SvMaxClients)); // max clients + pPacker->AddInt(max(ClientCount, Config()->Values()->m_SvMaxClients)); // max clients if(Token != -1) { @@ -1220,14 +1220,14 @@ void CServer::PumpNetwork() m_Econ.Update(); } -const char *CServer::GetMapName() const +const char *CServer::GetMapName() { // get the name of the map without his path - char *pMapShortName = &g_Config.m_SvMap[0]; - for(int i = 0; i < str_length(g_Config.m_SvMap)-1; i++) + char *pMapShortName = &Config()->Values()->m_SvMap[0]; + for(int i = 0; i < str_length(Config()->Values()->m_SvMap)-1; i++) { - if(g_Config.m_SvMap[i] == '/' || g_Config.m_SvMap[i] == '\\') - pMapShortName = &g_Config.m_SvMap[i+1]; + if(Config()->Values()->m_SvMap[i] == '/' || Config()->Values()->m_SvMap[i] == '\\') + pMapShortName = &Config()->Values()->m_SvMap[i+1]; } return pMapShortName; } @@ -1279,15 +1279,15 @@ int CServer::LoadMap(const char *pMapName) return 1; } -void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole) +void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole) { - m_Register.Init(pNetServer, pMasterServer, pConsole); + m_Register.Init(pNetServer, pMasterServer, pConfig, pConsole); } int CServer::Run() { // - m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->Values()->m_ConsoleOutputLevel, SendRconLineAuthed, this); // list maps m_pMapListHeap = new CHeap(); @@ -1297,38 +1297,38 @@ int CServer::Run() m_pStorage->ListDirectory(IStorage::TYPE_ALL, "maps/", MapListEntryCallback, &Userdata); // load map - if(!LoadMap(g_Config.m_SvMap)) + if(!LoadMap(Config()->Values()->m_SvMap)) { - dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap); + dbg_msg("server", "failed to load map. mapname='%s'", Config()->Values()->m_SvMap); return -1; } - m_MapChunksPerRequest = g_Config.m_SvMapDownloadSpeed; + m_MapChunksPerRequest = Config()->Values()->m_SvMapDownloadSpeed; // start server NETADDR BindAddr; - if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(Config()->Values()->m_Bindaddr[0] && net_host_lookup(Config()->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // sweet! BindAddr.type = NETTYPE_ALL; - BindAddr.port = g_Config.m_SvPort; + BindAddr.port = Config()->Values()->m_SvPort; } else { mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; - BindAddr.port = g_Config.m_SvPort; + BindAddr.port = Config()->Values()->m_SvPort; } - if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) + if(!m_NetServer.Open(BindAddr, &m_ServerBan, Config()->Values()->m_SvMaxClients, Config()->Values()->m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) { - dbg_msg("server", "couldn't open socket. port %d might already be in use", g_Config.m_SvPort); + dbg_msg("server", "couldn't open socket. port %d might already be in use", Config()->Values()->m_SvPort); return -1; } - m_Econ.Init(Console(), &m_ServerBan); + m_Econ.Init(Config(), Console(), &m_ServerBan); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName); + str_format(aBuf, sizeof(aBuf), "server name is '%s'", Config()->Values()->m_SvName); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); GameServer()->OnInit(); @@ -1345,7 +1345,7 @@ int CServer::Run() if(m_GeneratedRconPassword) { dbg_msg("server", "+-------------------------+"); - dbg_msg("server", "| rcon password: '%s' |", g_Config.m_SvRconPassword); + dbg_msg("server", "| rcon password: '%s' |", Config()->Values()->m_SvRconPassword); dbg_msg("server", "+-------------------------+"); } @@ -1363,12 +1363,12 @@ int CServer::Run() int NewTicks = 0; // load new map TODO: don't poll this - if(str_comp(g_Config.m_SvMap, m_aCurrentMap) != 0 || m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range + if(str_comp(Config()->Values()->m_SvMap, m_aCurrentMap) != 0 || m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range { m_MapReload = 0; // load map - if(LoadMap(g_Config.m_SvMap)) + if(LoadMap(Config()->Values()->m_SvMap)) { // new map loaded bool aSpecs[MAX_CLIENTS]; @@ -1394,9 +1394,9 @@ int CServer::Run() } else { - str_format(aBuf, sizeof(aBuf), "failed to load map. mapname='%s'", g_Config.m_SvMap); + str_format(aBuf, sizeof(aBuf), "failed to load map. mapname='%s'", Config()->Values()->m_SvMap); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - str_copy(g_Config.m_SvMap, m_aCurrentMap, sizeof(g_Config.m_SvMap)); + str_copy(Config()->Values()->m_SvMap, m_aCurrentMap, sizeof(Config()->Values()->m_SvMap)); } } @@ -1427,7 +1427,7 @@ int CServer::Run() // snap game if(NewTicks) { - if(g_Config.m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) + if(Config()->Values()->m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) DoSnapshot(); UpdateClientRconCommands(); @@ -1441,7 +1441,7 @@ int CServer::Run() if(ReportTime < time_get()) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { /* static NETSTATS prev_stats; @@ -1578,7 +1578,7 @@ void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser) void CServer::DemoRecorder_HandleAutoStart() { - if(g_Config.m_SvAutoDemoRecord) + if(Config()->Values()->m_SvAutoDemoRecord) { m_DemoRecorder.Stop(); char aFilename[128]; @@ -1586,11 +1586,11 @@ void CServer::DemoRecorder_HandleAutoStart() str_timestamp(aDate, sizeof(aDate)); str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", "auto/autorecord", aDate); m_DemoRecorder.Start(Storage(), m_pConsole, aFilename, GameServer()->NetVersion(), m_aCurrentMap, m_CurrentMapSha256, m_CurrentMapCrc, "server"); - if(g_Config.m_SvAutoDemoMax) + if(Config()->Values()->m_SvAutoDemoMax) { // clean up auto recorded demos CFileCollection AutoDemos; - AutoDemos.Init(Storage(), "demos/server", "autorecord", ".demo", g_Config.m_SvAutoDemoMax); + AutoDemos.Init(Storage(), "demos/server", "autorecord", ".demo", Config()->Values()->m_SvAutoDemoMax); } } } @@ -1649,31 +1649,34 @@ void CServer::ConLogout(IConsole::IResult *pResult, void *pUser) void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); + CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - str_clean_whitespaces(g_Config.m_SvName); - ((CServer *)pUserData)->SendServerInfo(-1); + str_clean_whitespaces(pSelf->Config()->Values()->m_SvName); + pSelf->SendServerInfo(-1); } } void CServer::ConchainPlayerSlotsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); + CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; + if(pSelf->Config()->Values()->m_SvMaxClients < pSelf->Config()->Values()->m_SvPlayerSlots) + pSelf->Config()->Values()->m_SvPlayerSlots = pSelf->Config()->Values()->m_SvMaxClients; } } void CServer::ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); + CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; - ((CServer *)pUserData)->m_NetServer.SetMaxClients(pResult->GetInteger(0)); + if(pSelf->Config()->Values()->m_SvMaxClients < pSelf->Config()->Values()->m_SvPlayerSlots) + pSelf->Config()->Values()->m_SvPlayerSlots = pSelf->Config()->Values()->m_SvMaxClients; + pSelf->m_NetServer.SetMaxClients(pResult->GetInteger(0)); } } @@ -1734,6 +1737,7 @@ void CServer::ConchainRconPasswordSet(IConsole::IResult *pResult, void *pUserDat void CServer::RegisterCommands() { + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_pGameServer = Kernel()->RequestInterface(); m_pMap = Kernel()->RequestInterface(); @@ -1834,7 +1838,7 @@ int main(int argc, const char **argv) // ignore_convention IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_SERVER, argc, argv); // ignore_convention IConfig *pConfig = CreateConfig(); - pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConsole); + pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConfig, pConsole); { bool RegisterFail = false; @@ -1856,6 +1860,7 @@ int main(int argc, const char **argv) // ignore_convention pEngine->Init(); pConfig->Init(FlagMask); + pConsole->Init(); pEngineMasterServer->Init(); pEngineMasterServer->Load(); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index c3baf7dc..b8dc7739 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -62,10 +62,12 @@ class CServerBan : public CNetBan class CServer : public IServer { class IGameServer *m_pGameServer; + class IConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; public: class IGameServer *GameServer() { return m_pGameServer; } + class IConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; } class IStorage *Storage() { return m_pStorage; } @@ -251,10 +253,10 @@ class CServer : public IServer void PumpNetwork(); - const char *GetMapName() const; + const char *GetMapName(); int LoadMap(const char *pMapName); - void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole); + void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole); int Run(); static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser); diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index d9279019..7969cc50 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -7,8 +7,6 @@ #include -CConfiguration g_Config; - void EscapeParam(char *pDst, const char *pSrc, int size) { for(int i = 0; *pSrc && i < size - 1; ++i) @@ -56,8 +54,8 @@ void CConfig::Init(int FlagMask) void CConfig::Reset() { - #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) g_Config.m_##Name = def; - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(g_Config.m_##Name, def, len); + #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) m_Values.m_##Name = def; + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(m_Values.m_##Name, def, len); #include "config_variables.h" @@ -68,7 +66,7 @@ void CConfig::Reset() void CConfig::RestoreStrings() { #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) // nop - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(!g_Config.m_##Name[0] && def[0]) str_copy(g_Config.m_##Name, def, len); + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(!m_Values.m_##Name[0] && def[0]) str_copy(m_Values.m_##Name, def, len); #include "config_variables.h" @@ -93,8 +91,8 @@ void CConfig::Save(const char *pFilename) char aLineBuf[1024*2]; char aEscapeBuf[1024*2]; - #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask))&&(g_Config.m_##Name!=int(def))){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); WriteLine(aLineBuf); } - #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask)&&(str_comp(g_Config.m_##Name,def)))){ EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); } + #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask))&&(m_Values.m_##Name!=int(def))){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, m_Values.m_##Name); WriteLine(aLineBuf); } + #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(((flags)&(CFGFLAG_SAVE))&&((flags)&(m_FlagMask)&&(str_comp(m_Values.m_##Name,def)))){ EscapeParam(aEscapeBuf, m_Values.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); } #include "config_variables.h" diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 6ece5843..0160a6ef 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -14,8 +14,6 @@ struct CConfiguration #undef MACRO_CONFIG_STR }; -extern CConfiguration g_Config; - enum { CFGFLAG_SAVE=1, @@ -46,6 +44,7 @@ class CConfig : public IConfig int m_FlagMask; CCallback m_aCallbacks[MAX_CALLBACKS]; int m_NumCallbacks; + CConfiguration m_Values; public: CConfig(); @@ -54,6 +53,7 @@ class CConfig : public IConfig virtual void Reset(); virtual void RestoreStrings(); virtual void Save(const char *pFilename); + virtual CConfiguration *Values() { return &m_Values; } virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData); diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index eef4cae8..c95d180b 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -407,8 +407,6 @@ bool CConsole::ExecuteFile(const char *pFilename) if(str_comp(pFilename, pCur->m_pFilename) == 0) return false; - if(!m_pStorage) - m_pStorage = Kernel()->RequestInterface(); if(!m_pStorage) return false; @@ -678,6 +676,7 @@ CConsole::CConsole(int FlagMask) mem_zero(m_aPrintCB, sizeof(m_aPrintCB)); m_NumPrintCB = 0; + m_pConfig = 0; m_pStorage = 0; // register some basic commands @@ -689,24 +688,6 @@ CConsole::CConsole(int FlagMask) Register("mod_command", "s?i", CFGFLAG_SERVER, ConModCommandAccess, this, "Specify command accessibility for moderators"); Register("mod_status", "", CFGFLAG_SERVER, ConModCommandStatus, this, "List all commands which are accessible for moderators"); - - // TODO: this should disappear - #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ - { \ - static CIntVariableData Data = { this, &g_Config.m_##Name, Min, Max }; \ - Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \ - } - - #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ - { \ - static CStrVariableData Data = { this, g_Config.m_##Name, Len }; \ - Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \ - } - - #include "config_variables.h" - - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR } CConsole::~CConsole() @@ -729,6 +710,30 @@ CConsole::~CConsole() } } +void CConsole::Init() +{ + m_pConfig = Kernel()->RequestInterface(); + m_pStorage = Kernel()->RequestInterface(); + + // TODO: this should disappear + #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ + { \ + static CIntVariableData Data = { this, &m_pConfig->Values()->m_##Name, Min, Max }; \ + Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \ + } + + #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ + { \ + static CStrVariableData Data = { this, m_pConfig->Values()->m_##Name, Len }; \ + Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \ + } + + #include "config_variables.h" + + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR +} + void CConsole::ParseArguments(int NumArgs, const char **ppArguments) { for(int i = 0; i < NumArgs; i++) diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index e88d5535..3252130e 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -47,6 +47,7 @@ class CConsole : public IConsole }; CExecFile *m_pFirstExec; + class IConfig *m_pConfig; class IStorage *m_pStorage; int m_AccessLevel; @@ -170,6 +171,7 @@ class CConsole : public IConsole CConsole(int FlagMask); ~CConsole(); + virtual void Init(); virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int FlagMask) const; virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp); virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser); diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp index f568564b..d14b5ae1 100644 --- a/src/engine/shared/econ.cpp +++ b/src/engine/shared/econ.cpp @@ -60,8 +60,9 @@ void CEcon::ConLogout(IConsole::IResult *pResult, void *pUserData) pThis->m_NetConsole.Drop(pThis->m_UserClientID, "Logout"); } -void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan) +void CEcon::Init(IConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan) { + m_pConfig = pConfig; m_pConsole = pConsole; for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) @@ -70,32 +71,32 @@ void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan) m_Ready = false; m_UserClientID = -1; - if(g_Config.m_EcPort == 0 || g_Config.m_EcPassword[0] == 0) + if(m_pConfig->Values()->m_EcPort == 0 || m_pConfig->Values()->m_EcPassword[0] == 0) return; NETADDR BindAddr; - if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(m_pConfig->Values()->m_EcBindaddr[0] && net_host_lookup(m_pConfig->Values()->m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; - BindAddr.port = g_Config.m_EcPort; + BindAddr.port = m_pConfig->Values()->m_EcPort; } else { mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; - BindAddr.port = g_Config.m_EcPort; + BindAddr.port = m_pConfig->Values()->m_EcPort; } if(m_NetConsole.Open(BindAddr, pNetBan, NewClientCallback, DelClientCallback, this)) { m_Ready = true; char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "bound to %s:%d", g_Config.m_EcBindaddr, g_Config.m_EcPort); + str_format(aBuf, sizeof(aBuf), "bound to %s:%d", m_pConfig->Values()->m_EcBindaddr, m_pConfig->Values()->m_EcPort); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"econ", aBuf); Console()->Chain("ec_output_level", ConchainEconOutputLevelUpdate, this); - m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_EcOutputLevel, SendLineCB, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(m_pConfig->Values()->m_EcOutputLevel, SendLineCB, this); Console()->Register("logout", "", CFGFLAG_ECON, ConLogout, this, "Logout of econ"); } @@ -118,7 +119,7 @@ void CEcon::Update() dbg_assert(m_aClients[ClientID].m_State != CClient::STATE_EMPTY, "got message from empty slot"); if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTED) { - if(str_comp(aBuf, g_Config.m_EcPassword) == 0) + if(str_comp(aBuf, m_pConfig->Values()->m_EcPassword) == 0) { m_aClients[ClientID].m_State = CClient::STATE_AUTHED; m_NetConsole.Send(ClientID, "Authentication successful. External console access granted."); @@ -134,8 +135,8 @@ void CEcon::Update() m_NetConsole.Send(ClientID, aMsg); if(m_aClients[ClientID].m_AuthTries >= MAX_AUTH_TRIES) { - if(g_Config.m_EcBantime) - m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), g_Config.m_EcBantime*60, "Too many authentication tries"); + if(m_pConfig->Values()->m_EcBantime) + m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), m_pConfig->Values()->m_EcBantime*60, "Too many authentication tries"); m_NetConsole.Drop(ClientID, "Too many authentication tries"); } } @@ -154,7 +155,7 @@ void CEcon::Update() for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; ++i) { if(m_aClients[i].m_State == CClient::STATE_CONNECTED && - time_get() > m_aClients[i].m_TimeConnected + g_Config.m_EcAuthTimeout * time_freq()) + time_get() > m_aClients[i].m_TimeConnected + m_pConfig->Values()->m_EcAuthTimeout * time_freq()) m_NetConsole.Drop(i, "authentication timeout"); } } diff --git a/src/engine/shared/econ.h b/src/engine/shared/econ.h index c9f7c40e..68445cea 100644 --- a/src/engine/shared/econ.h +++ b/src/engine/shared/econ.h @@ -27,6 +27,7 @@ class CEcon }; CClient m_aClients[NET_MAX_CONSOLE_CLIENTS]; + IConfig *m_pConfig; IConsole *m_pConsole; CNetConsole m_NetConsole; @@ -44,7 +45,7 @@ class CEcon public: IConsole *Console() { return m_pConsole; } - void Init(IConsole *pConsole, class CNetBan *pNetBan); + void Init(IConfig *pConfig, IConsole *pConsole, class CNetBan *pNetBan); void Update(); void Send(int ClientID, const char *pLine); void Shutdown(); diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index 2b6a8978..f72d5466 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -20,6 +20,7 @@ static int HostLookupThread(void *pUser) class CEngine : public IEngine { public: + IConfig *m_pConfig; IConsole *m_pConsole; IStorage *m_pStorage; bool m_Logging; @@ -64,7 +65,6 @@ class CEngine : public IEngine // init the network net_init(); - CNetBase::Init(); m_JobPool.Init(1); @@ -73,27 +73,30 @@ class CEngine : public IEngine void Init() { + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); if(!m_pConsole || !m_pStorage) return; + CNetBase::Init(m_pConfig); + m_pConsole->Register("dbg_lognetwork", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_DbgLognetwork, this, "Log the network"); } void InitLogfile() { // open logfile if needed - if(g_Config.m_Logfile[0]) + if(m_pConfig->Values()->m_Logfile[0]) { char aBuf[32]; - if(g_Config.m_LogfileTimestamp) + if(m_pConfig->Values()->m_LogfileTimestamp) str_timestamp(aBuf, sizeof(aBuf)); else aBuf[0] = 0; char aLogFilename[128]; - str_format(aLogFilename, sizeof(aLogFilename), "dumps/%s%s.txt", g_Config.m_Logfile, aBuf); + str_format(aLogFilename, sizeof(aLogFilename), "dumps/%s%s.txt", m_pConfig->Values()->m_Logfile, aBuf); IOHANDLE Handle = m_pStorage->OpenFile(aLogFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(Handle) dbg_logger_filehandle(Handle); @@ -111,7 +114,7 @@ class CEngine : public IEngine void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData) { - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("engine", "job added"); m_JobPool.Add(pJob, pfnFunc, pData); } diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index d354f624..3a41a906 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -70,7 +70,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) continue; // out of sequence, request resend - if(g_Config.m_Debug) + if(CNetBase::Config()->Values()->m_Debug) dbg_msg("conn", "asking for resend %d %d", Header.m_Sequence, (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE); m_pConnection->SignalResend(); continue; // take the next chunk in the packet @@ -195,7 +195,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct // check the size if(Size < NET_PACKETHEADERSIZE || Size > NET_MAX_PACKETSIZE) { - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("network", "packet too small, size=%d", Size); return -1; } @@ -208,7 +208,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct { if(Size < NET_PACKETHEADERSIZE_CONNLESS) { - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("net", "connless packet too small, size=%d", Size); return -1; } @@ -233,7 +233,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct { if(Size - NET_PACKETHEADERSIZE > NET_MAX_PAYLOAD) { - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("network", "packet payload too big, size=%d", Size); return -1; } @@ -257,7 +257,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct // check for errors if(pPacket->m_DataSize < 0) { - if(g_Config.m_Debug) + if(m_pConfig->Values()->m_Debug) dbg_msg("network", "error during packet decoding"); return -1; } @@ -369,7 +369,7 @@ int CNetBase::IsSeqInBackroom(int Seq, int Ack) IOHANDLE CNetBase::ms_DataLogSent = 0; IOHANDLE CNetBase::ms_DataLogRecv = 0; CHuffman CNetBase::ms_Huffman; - +IConfig *CNetBase::m_pConfig = 0; // todo: fix me void CNetBase::OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv) { @@ -433,7 +433,8 @@ static const unsigned gs_aFreqTable[256+1] = { 12,18,18,27,20,18,15,19,11,17,33,12,18,15,19,18,16,26,17,18, 9,10,25,22,22,17,20,16,6,16,15,20,14,18,24,335,1517}; -void CNetBase::Init() +void CNetBase::Init(IConfig *pConfig) { + m_pConfig = pConfig; ms_Huffman.Init(gs_aFreqTable); } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 594582d8..e101c9ec 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -531,13 +531,15 @@ class CNetClient // TODO: both, fix these. This feels like a junk class for stuff that doesn't fit anywere class CNetBase { + static class IConfig *m_pConfig; static IOHANDLE ms_DataLogSent; static IOHANDLE ms_DataLogRecv; static CHuffman ms_Huffman; public: + static IConfig *Config() { return m_pConfig; } static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv); static void CloseLog(); - static void Init(); + static void Init(class IConfig *pConfig); static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize); static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize); diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index f1c2020b..2697443f 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -286,7 +286,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SetError(Str); } - if(g_Config.m_Debug) + if(CNetBase::Config()->Values()->m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; @@ -304,7 +304,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SendControlWithToken(NET_CTRLMSG_CONNECT); dbg_msg("connection", "got token, replying, token=%x mytoken=%x", m_PeerToken, m_Token); } - else if(g_Config.m_Debug) + else if(CNetBase::Config()->Values()->m_Debug) dbg_msg("connection", "got token, token=%x", m_PeerToken); } else @@ -325,7 +325,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); - if(g_Config.m_Debug) + if(CNetBase::Config()->Values()->m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } @@ -337,7 +337,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; - if(g_Config.m_Debug) + if(CNetBase::Config()->Values()->m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } @@ -350,7 +350,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; - if(g_Config.m_Debug) + if(CNetBase::Config()->Values()->m_Debug) dbg_msg("connection", "connecting online"); } } @@ -410,7 +410,7 @@ int CNetConnection::Update() if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed { int NumFlushedChunks = Flush(); - if(NumFlushedChunks && g_Config.m_Debug) + if(NumFlushedChunks && CNetBase::Config()->Values()->m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } diff --git a/src/game/client/component.h b/src/game/client/component.h index 85b202c8..cbd0fb6f 100644 --- a/src/game/client/component.h +++ b/src/game/client/component.h @@ -23,6 +23,7 @@ class CComponent class CUI *UI() const { return m_pClient->UI(); } class ISound *Sound() const { return m_pClient->Sound(); } class CRenderTools *RenderTools() const { return m_pClient->RenderTools(); } + class IConfig *Config() const { return m_pClient->Config(); } class IConsole *Console() const { return m_pClient->Console(); } class IDemoPlayer *DemoPlayer() const { return m_pClient->DemoPlayer(); } class IDemoRecorder *DemoRecorder() const { return m_pClient->DemoRecorder(); } diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index afc84b1e..aacf83b3 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -41,10 +41,10 @@ inline bool IsCharWhitespace(char c) void CBroadcast::RenderServerBroadcast() { - if(!g_Config.m_ClShowServerBroadcast || m_pClient->m_MuteServerBroadcast) + if(!Config()->Values()->m_ClShowServerBroadcast || m_pClient->m_MuteServerBroadcast) return; - const bool ColoredBroadcastEnabled = g_Config.m_ClColoredBroadcast; + const bool ColoredBroadcastEnabled = Config()->Values()->m_ClColoredBroadcast; const float Height = 300; const float Width = Height*Graphics()->ScreenAspect(); @@ -259,7 +259,7 @@ void CBroadcast::OnReset() void CBroadcast::OnMessage(int MsgType, void* pRawMsg) { // process server broadcast message - if(MsgType == NETMSGTYPE_SV_BROADCAST && g_Config.m_ClShowServerBroadcast && + if(MsgType == NETMSGTYPE_SV_BROADCAST && Config()->Values()->m_ClShowServerBroadcast && !m_pClient->m_MuteServerBroadcast) { CNetMsg_Sv_Broadcast *pMsg = (CNetMsg_Sv_Broadcast *)pRawMsg; diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp index 3372f103..6ead7e6c 100644 --- a/src/game/client/components/camera.cpp +++ b/src/game/client/components/camera.cpp @@ -63,10 +63,10 @@ void CCamera::OnRender() vec2 CameraOffset(0, 0); float l = length(m_pClient->m_pControls->m_MousePos); - if(g_Config.m_ClDynamicCamera && l > 0.0001f) // make sure that this isn't 0 + if(Config()->Values()->m_ClDynamicCamera && l > 0.0001f) // make sure that this isn't 0 { - float DeadZone = g_Config.m_ClMouseDeadzone; - float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; + float DeadZone = Config()->Values()->m_ClMouseDeadzone; + float FollowFactor = Config()->Values()->m_ClMouseFollowfactor/100.0f; float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor; CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount; @@ -83,22 +83,22 @@ void CCamera::OnRender() m_Zoom = 0.7f; static vec2 Dir = vec2(1.0f, 0.0f); - if(distance(m_Center, m_RotationCenter) <= (float)g_Config.m_ClRotationRadius+0.5f) + if(distance(m_Center, m_RotationCenter) <= (float)Config()->Values()->m_ClRotationRadius+0.5f) { // do little rotation - float RotPerTick = 360.0f/(float)g_Config.m_ClRotationSpeed * Client()->RenderFrameTime(); + float RotPerTick = 360.0f/(float)Config()->Values()->m_ClRotationSpeed * Client()->RenderFrameTime(); Dir = rotate(Dir, RotPerTick); - m_Center = m_RotationCenter+Dir*(float)g_Config.m_ClRotationRadius; + m_Center = m_RotationCenter+Dir*(float)Config()->Values()->m_ClRotationRadius; } else { // positions for the animation Dir = normalize(m_AnimationStartPos - m_RotationCenter); - vec2 TargetPos = m_RotationCenter + Dir * (float)g_Config.m_ClRotationRadius; + vec2 TargetPos = m_RotationCenter + Dir * (float)Config()->Values()->m_ClRotationRadius; float Distance = distance(m_AnimationStartPos, TargetPos); // move time - m_MoveTime += Client()->RenderFrameTime()*g_Config.m_ClCameraSpeed / 10.0f; + m_MoveTime += Client()->RenderFrameTime()*Config()->Values()->m_ClCameraSpeed / 10.0f; float XVal = 1 - m_MoveTime; XVal = pow(XVal, 7.0f); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index ef4b6f4f..91a32cab 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -535,10 +535,10 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) { - if(*pLine == 0 || (ClientID >= 0 && (!g_Config.m_ClShowsocial || !m_pClient->m_aClients[ClientID].m_Active || // unknown client + if(*pLine == 0 || (ClientID >= 0 && (!Config()->Values()->m_ClShowsocial || !m_pClient->m_aClients[ClientID].m_Active || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore || - g_Config.m_ClFilterchat == 2 || - (m_pClient->m_LocalClientID != ClientID && g_Config.m_ClFilterchat == 1 && !m_pClient->m_aClients[ClientID].m_Friend)))) + Config()->Values()->m_ClFilterchat == 2 || + (m_pClient->m_LocalClientID != ClientID && Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[ClientID].m_Friend)))) return; if(Mode == CHAT_WHISPER) @@ -550,8 +550,8 @@ void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) if(ClientID != m_pClient->m_LocalClientID && TargetID != m_pClient->m_LocalClientID) return; // ignore and chat filter - if(m_pClient->m_aClients[TargetID].m_ChatIgnore || g_Config.m_ClFilterchat == 2 || - (m_pClient->m_LocalClientID != TargetID && g_Config.m_ClFilterchat == 1 && !m_pClient->m_aClients[TargetID].m_Friend)) + if(m_pClient->m_aClients[TargetID].m_ChatIgnore || Config()->Values()->m_ClFilterchat == 2 || + (m_pClient->m_LocalClientID != TargetID && Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[TargetID].m_Friend)) return; } diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index c01accfb..91c31259 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -374,7 +374,7 @@ void CGameConsole::OnRender() Progress = 1.0f; } - if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor) + if (m_ConsoleState == CONSOLE_OPEN && Config()->Values()->m_ClEditor) Toggle(CONSOLETYPE_LOCAL); if (m_ConsoleState == CONSOLE_CLOSED) @@ -743,7 +743,7 @@ void CGameConsole::OnConsoleInit() m_pConsole = Kernel()->RequestInterface(); // - m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, ClientConsolePrintCallback, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->Values()->m_ConsoleOutputLevel, ClientConsolePrintCallback, this); Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console"); Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console"); diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 66e604dd..28ab8aeb 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -102,7 +102,7 @@ void CControls::OnMessage(int Msg, void *pRawMsg) if(Msg == NETMSGTYPE_SV_WEAPONPICKUP) { CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; - if(g_Config.m_ClAutoswitchWeapons) + if(Config()->Values()->m_ClAutoswitchWeapons) m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; } } @@ -155,7 +155,7 @@ int CControls::SnapInput(int *pData) m_InputData.m_Direction = 1; // stress testing - if(g_Config.m_DbgStress) + if(Config()->Values()->m_DbgStress) { float t = Client()->LocalTime(); mem_zero(&m_InputData, sizeof(m_InputData)); @@ -228,14 +228,14 @@ void CControls::ClampMousePos() else { float MouseMax; - if(g_Config.m_ClDynamicCamera) + if(Config()->Values()->m_ClDynamicCamera) { float CameraMaxDistance = 200.0f; - float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; - MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistanceDynamic); + float FollowFactor = Config()->Values()->m_ClMouseFollowfactor/100.0f; + MouseMax = min(CameraMaxDistance/FollowFactor + Config()->Values()->m_ClMouseDeadzone, (float)Config()->Values()->m_ClMouseMaxDistanceDynamic); } else - MouseMax = (float)g_Config.m_ClMouseMaxDistanceStatic; + MouseMax = (float)Config()->Values()->m_ClMouseMaxDistanceStatic; if(length(m_MousePos) > MouseMax) m_MousePos = normalize(m_MousePos)*MouseMax; diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index e9fd00d3..0d6b88c9 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -73,7 +73,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() CCountryFlag CountryFlag; CountryFlag.m_CountryCode = CountryCode; str_copy(CountryFlag.m_aCountryCodeString, pCountryName, sizeof(CountryFlag.m_aCountryCodeString)); - if(g_Config.m_ClLoadCountryFlags) + if(Config()->Values()->m_ClLoadCountryFlags) { // load the graphic file CImageInfo Info; @@ -96,7 +96,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() m_aCountryFlags.add_unsorted(CountryFlag); // print message - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", pCountryName); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); diff --git a/src/game/client/components/debughud.cpp b/src/game/client/components/debughud.cpp index 29cd1ecc..b65bfd0e 100644 --- a/src/game/client/components/debughud.cpp +++ b/src/game/client/components/debughud.cpp @@ -19,7 +19,7 @@ void CDebugHud::RenderNetCorrections() { - if(!g_Config.m_Debug || g_Config.m_DbgGraphs || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) + if(!Config()->Values()->m_Debug || Config()->Values()->m_DbgGraphs || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) return; float Width = 300*Graphics()->ScreenAspect(); @@ -76,7 +76,7 @@ void CDebugHud::RenderNetCorrections() void CDebugHud::RenderTuning() { // render tuning debugging - if(!g_Config.m_DbgTuning) + if(!Config()->Values()->m_DbgTuning) return; CTuningParams StandardTuning; diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index d16d7f5b..982a43c5 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -213,7 +213,7 @@ void CHud::RenderScoreHud() // draw name of the flag holder int ID = FlagCarrier[t]%MAX_CLIENTS; char aName[64]; - str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; @@ -312,7 +312,7 @@ void CHud::RenderScoreHud() // draw name int ID = aPlayerInfo[t].m_ClientID; char aName[64]; - str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; @@ -408,7 +408,7 @@ void CHud::RenderWarmupTimer() void CHud::RenderFps() { - if(g_Config.m_ClShowfps) + if(Config()->Values()->m_ClShowfps) { // calculate avg. fps float FPS = 1.0f / Client()->RenderFrameTime(); @@ -432,7 +432,7 @@ void CHud::RenderConnectionWarning() void CHud::RenderTeambalanceWarning() { // render prompt about team-balance - if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS && g_Config.m_ClWarningTeambalance && m_pClient->m_ServerSettings.m_TeamBalance && + if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS && Config()->Values()->m_ClWarningTeambalance && m_pClient->m_ServerSettings.m_TeamBalance && absolute(m_pClient->m_GameInfo.m_aTeamSize[TEAM_RED]-m_pClient->m_GameInfo.m_aTeamSize[TEAM_BLUE]) >= NUM_TEAMS) { bool Flash = time_get()/(time_freq()/2)%2 == 0; @@ -655,7 +655,7 @@ void CHud::RenderSpectatorHud() char aName[64]; const int SpecID = m_pClient->m_Snap.m_SpecInfo.m_SpectatorID; const int SpecMode = m_pClient->m_Snap.m_SpecInfo.m_SpecMode; - str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : ""); char aBuf[128]; CTextCursor Cursor; @@ -809,7 +809,7 @@ void CHud::OnRender() m_Height = 300.0f; Graphics()->MapScreen(0.0f, 0.0f, m_Width, m_Height); - if(g_Config.m_ClShowhud) + if(Config()->Values()->m_ClShowhud) { if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) { diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index cceae606..f5478a43 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -43,13 +43,13 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) // unpack messages CInfoMsg Kill; Kill.m_Player1ID = pMsg->m_Victim; - str_format(Kill.m_aPlayer1Name, sizeof(Kill.m_aPlayer1Name), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player1ID].m_aName : ""); + str_format(Kill.m_aPlayer1Name, sizeof(Kill.m_aPlayer1Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player1ID].m_aName : ""); Kill.m_Player1RenderInfo = m_pClient->m_aClients[Kill.m_Player1ID].m_RenderInfo; Kill.m_Player2ID = pMsg->m_Killer; if (Kill.m_Player2ID >= 0) { - str_format(Kill.m_aPlayer2Name, sizeof(Kill.m_aPlayer2Name), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player2ID].m_aName : ""); + str_format(Kill.m_aPlayer2Name, sizeof(Kill.m_aPlayer2Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player2ID].m_aName : ""); Kill.m_Player2RenderInfo = m_pClient->m_aClients[Kill.m_Player2ID].m_RenderInfo; } else @@ -127,7 +127,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) { CInfoMsg Finish; Finish.m_Player1ID = pMsg->m_ClientID; - str_format(Finish.m_aPlayer1Name, sizeof(Finish.m_aPlayer1Name), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[pMsg->m_ClientID].m_aName : ""); + str_format(Finish.m_aPlayer1Name, sizeof(Finish.m_aPlayer1Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[pMsg->m_ClientID].m_aName : ""); Finish.m_Player1RenderInfo = m_pClient->m_aClients[Finish.m_Player1ID].m_RenderInfo; Finish.m_Time = pMsg->m_Time; @@ -141,7 +141,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) void CInfoMessages::OnRender() { - if(!g_Config.m_ClShowhud) + if(!Config()->Values()->m_ClShowhud) return; float Width = 400*3.0f*Graphics()->ScreenAspect(); diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 00b61ceb..02b5ab7e 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -39,31 +39,31 @@ void CMapLayers::OnStateChange(int NewState, int OldState) void CMapLayers::LoadBackgroundMap() { - if(!g_Config.m_ClShowMenuMap) + if(!Config()->Values()->m_ClShowMenuMap) return; int HourOfTheDay = time_houroftheday(); char aBuf[128]; // check for the appropriate day/night map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", g_Config.m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->Values()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on generic map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", g_Config.m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", Config()->Values()->m_ClMenuMap); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on day/night alternative map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", g_Config.m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->Values()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { - str_format(aBuf, sizeof(aBuf), "map '%s' not found", g_Config.m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "map '%s' not found", Config()->Values()->m_ClMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); return; } } } - str_format(aBuf, sizeof(aBuf), "loaded map '%s'", g_Config.m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "loaded map '%s'", Config()->Values()->m_ClMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); m_pMenuLayers->Init(Kernel(), m_pMenuMap); @@ -373,7 +373,7 @@ void CMapLayers::OnRender() { CMapItemGroup *pGroup = pLayers->GetGroup(g); - if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) + if(!Config()->Values()->m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) { // set clipping float Points[4]; @@ -423,7 +423,7 @@ void CMapLayers::OnRender() continue; // skip rendering if detail layers is not wanted - if(!(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK))) + if(!(pLayer->m_Flags&LAYERFLAG_DETAIL && !Config()->Values()->m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK))) { if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0)) { @@ -495,11 +495,11 @@ void CMapLayers::OnRender() } } } - if(!g_Config.m_GfxNoclip) + if(!Config()->Values()->m_GfxNoclip) Graphics()->ClipDisable(); } - if(!g_Config.m_GfxNoclip) + if(!Config()->Values()->m_GfxNoclip) Graphics()->ClipDisable(); // reset the screen like it was before diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 598625b7..16b24da7 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -255,7 +255,7 @@ int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Ch float Fade = ButtonFade(pBC, Seconds, Checked); float FadeVal = (Fade/Seconds)*FontAlpha; - RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, g_Config.m_ClMenuAlpha/100.0f*Alpha+FadeVal*0.5f), Corners, r); + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, Config()->Values()->m_ClMenuAlpha/100.0f*Alpha+FadeVal*0.5f), Corners, r); CUIRect Temp; pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp); @@ -1020,8 +1020,8 @@ void CMenus::RenderMenubar(CUIRect Rect) CUIRect Left, Right; Box.VSplitLeft(ButtonWidth*4.0f + Spacing*3.0f, &Left, 0); Box.VSplitRight(ButtonWidth*1.5f + Spacing, 0, &Right); - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); - RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Left.HSplitBottom(25.0f, 0, &Left); Right.HSplitBottom(25.0f, 0, &Right); @@ -1074,28 +1074,28 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header background if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Box.HSplitBottom(25.0f, 0, &Box); Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_GeneralButton; - if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_GENERAL, &Button, - g_Config.m_UiSettingsPage == SETTINGS_GENERAL ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_GENERAL, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_GENERAL ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GENERAL); - g_Config.m_UiSettingsPage = SETTINGS_GENERAL; + Config()->Values()->m_UiSettingsPage = SETTINGS_GENERAL; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); { static CButtonContainer s_PlayerButton; - if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage == SETTINGS_PLAYER, &Button, - g_Config.m_UiSettingsPage == SETTINGS_PLAYER ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_PLAYER); - g_Config.m_UiSettingsPage = SETTINGS_PLAYER; + Config()->Values()->m_UiSettingsPage = SETTINGS_PLAYER; } } @@ -1103,11 +1103,11 @@ void CMenus::RenderMenubar(CUIRect Rect) Box.VSplitLeft(ButtonWidth, &Button, &Box); { static CButtonContainer s_TeeButton; - if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage == SETTINGS_TEE, &Button, - g_Config.m_UiSettingsPage == SETTINGS_TEE ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage == SETTINGS_TEE, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_TEE ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TEE); - g_Config.m_UiSettingsPage = SETTINGS_TEE; + Config()->Values()->m_UiSettingsPage = SETTINGS_TEE; } } @@ -1115,31 +1115,31 @@ void CMenus::RenderMenubar(CUIRect Rect) Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_ControlsButton; - if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_CONTROLS, &Button, - g_Config.m_UiSettingsPage == SETTINGS_CONTROLS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_CONTROLS, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_CONTROLS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_CONTROLS); - g_Config.m_UiSettingsPage = SETTINGS_CONTROLS; + Config()->Values()->m_UiSettingsPage = SETTINGS_CONTROLS; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_GraphicsButton; - if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_GRAPHICS, &Button, - g_Config.m_UiSettingsPage == SETTINGS_GRAPHICS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_GRAPHICS, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_GRAPHICS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GRAPHICS); - g_Config.m_UiSettingsPage = SETTINGS_GRAPHICS; + Config()->Values()->m_UiSettingsPage = SETTINGS_GRAPHICS; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_SoundButton; - if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_SOUND, &Button, - g_Config.m_UiSettingsPage == SETTINGS_SOUND ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_SOUND, &Button, + Config()->Values()->m_UiSettingsPage == SETTINGS_SOUND ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_SOUND); - g_Config.m_UiSettingsPage = SETTINGS_SOUND; + Config()->Values()->m_UiSettingsPage = SETTINGS_SOUND; } } else if((Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_INTERNET && m_MenuPage <= PAGE_LAN) || (Client()->State() == IClient::STATE_ONLINE && m_GamePage >= PAGE_INTERNET && m_GamePage <= PAGE_LAN)) @@ -1154,7 +1154,7 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header backgrounds if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Left.HSplitBottom(25.0f, 0, &Left); @@ -1166,7 +1166,7 @@ void CMenus::RenderMenubar(CUIRect Rect) m_pClient->m_pCamera->ChangePosition(CCamera::POS_INTERNET); ServerBrowser()->SetType(IServerBrowser::TYPE_INTERNET); NewPage = PAGE_INTERNET; - g_Config.m_UiBrowserPage = PAGE_INTERNET; + Config()->Values()->m_UiBrowserPage = PAGE_INTERNET; } Left.VSplitLeft(Spacing, 0, &Left); // little space @@ -1178,7 +1178,7 @@ void CMenus::RenderMenubar(CUIRect Rect) m_pClient->m_pCamera->ChangePosition(CCamera::POS_LAN); ServerBrowser()->SetType(IServerBrowser::TYPE_LAN); NewPage = PAGE_LAN; - g_Config.m_UiBrowserPage = PAGE_LAN; + Config()->Values()->m_UiBrowserPage = PAGE_LAN; } if(Client()->State() == IClient::STATE_OFFLINE) @@ -1194,7 +1194,7 @@ void CMenus::RenderMenubar(CUIRect Rect) if(m_MenuPage == PAGE_DEMOS) { // render header background - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Box.HSplitBottom(25.0f, 0, &Box); @@ -1286,7 +1286,7 @@ void CMenus::RenderBackButton(CUIRect MainView) // render background MainView.HSplitBottom(60.0f, 0, &MainView); MainView.VSplitLeft(ButtonWidth, &MainView, 0); - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); // back to main menu CUIRect Button; @@ -1462,14 +1462,14 @@ void CMenus::UpdatedFilteredVideoModes() void CMenus::UpdateVideoModeSettings() { - m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS, g_Config.m_GfxScreen); + m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS, Config()->Values()->m_GfxScreen); UpdateVideoFormats(); bool Found = false; for(int i = 0; i < m_NumVideoFormats; i++) { - int G = gcd(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); - if(m_aVideoFormats[i].m_WidthValue == g_Config.m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == g_Config.m_GfxScreenHeight/G) + int G = gcd(Config()->Values()->m_GfxScreenWidth, Config()->Values()->m_GfxScreenHeight); + if(m_aVideoFormats[i].m_WidthValue == Config()->Values()->m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == Config()->Values()->m_GfxScreenHeight/G) { m_CurrentVideoFormat = i; Found = true; @@ -1498,11 +1498,11 @@ void CMenus::OnInit() // clear filter lists //m_lFilters.clear(); - if(g_Config.m_ClShowWelcome) + if(Config()->Values()->m_ClShowWelcome) m_Popup = POPUP_LANGUAGE; - g_Config.m_ClShowWelcome = 0; - if(g_Config.m_ClSkipStartMenu) - SetMenuPage(g_Config.m_UiBrowserPage); + Config()->Values()->m_ClShowWelcome = 0; + if(Config()->Values()->m_ClSkipStartMenu) + SetMenuPage(Config()->Values()->m_UiBrowserPage); Console()->Chain("br_filter_string", ConchainServerbrowserUpdate, this); Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this); @@ -1518,7 +1518,7 @@ void CMenus::OnInit() // setup load amount m_LoadCurrent = 0; m_LoadTotal = g_pData->m_NumImages; - if(!g_Config.m_SndAsyncLoading) + if(!Config()->Values()->m_SndAsyncLoading) m_LoadTotal += g_pData->m_NumSounds; } @@ -1546,7 +1546,7 @@ int CMenus::Render() // refresh server browser before we are in browser menu to save time m_pClient->m_pCamera->ChangePosition(CCamera::POS_START); ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); - ServerBrowser()->SetType(g_Config.m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); + ServerBrowser()->SetType(Config()->Values()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); s_First = false; @@ -1582,7 +1582,7 @@ int CMenus::Render() else if(Client()->State() == IClient::STATE_ONLINE && m_GamePage >= PAGE_INTERNET && m_GamePage <= PAGE_LAN) BarHeight += 3.0f + 25.0f; float VMargin = Screen.w/2-365.0f; - if(g_Config.m_UiWideview) + if(Config()->Values()->m_UiWideview) VMargin = min(VMargin, 60.0f); Screen.VMargin(VMargin, &MainView); @@ -1632,8 +1632,8 @@ int CMenus::Render() Row.VSplitRight(5.0f, &Row, 0); Row.VSplitRight(TopOffset, &Row, &Button); static CButtonContainer s_WideButton; - if((m_MenuPage == PAGE_INTERNET || m_MenuPage == PAGE_LAN || m_MenuPage == PAGE_DEMOS) && DoButton_MenuTabTop(&s_WideButton, g_Config.m_UiWideview ? "\xe2\x96\xaa" : "\xe2\x96\xac", false, &Button, 1.0f, 1.0f, CUI::CORNER_B)) - g_Config.m_UiWideview ^= 1; + if((m_MenuPage == PAGE_INTERNET || m_MenuPage == PAGE_LAN || m_MenuPage == PAGE_DEMOS) && DoButton_MenuTabTop(&s_WideButton, Config()->Values()->m_UiWideview ? "\xe2\x96\xaa" : "\xe2\x96\xac", false, &Button, 1.0f, 1.0f, CUI::CORNER_B)) + Config()->Values()->m_UiWideview ^= 1; } // render current page @@ -1862,7 +1862,7 @@ int CMenus::Render() Box.HSplitTop(20.0f, &EditBox, &Box); static float s_OffsetPassword = 0.0f; - DoEditBoxOption(g_Config.m_Password, g_Config.m_Password, sizeof(g_Config.m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); + DoEditBoxOption(Config()->Values()->m_Password, Config()->Values()->m_Password, sizeof(Config()->Values()->m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); Box.HSplitTop(2.0f, 0, &Box); Box.HSplitTop(20.0f, &Save, &Box); @@ -1872,8 +1872,8 @@ int CMenus::Render() const bool Favorite = ServerInfo.m_Favorite; const int OnValue = Favorite ? 1 : 2; const char *pSaveText = Favorite ? Localize("Save password") : Localize("Save password and server as favorite"); - if(DoButton_CheckBox(&g_Config.m_ClSaveServerPasswords, pSaveText, g_Config.m_ClSaveServerPasswords == OnValue, &Save)) - g_Config.m_ClSaveServerPasswords = g_Config.m_ClSaveServerPasswords == OnValue ? 0 : OnValue; + if(DoButton_CheckBox(&Config()->Values()->m_ClSaveServerPasswords, pSaveText, Config()->Values()->m_ClSaveServerPasswords == OnValue, &Save)) + Config()->Values()->m_ClSaveServerPasswords = Config()->Values()->m_ClSaveServerPasswords == OnValue ? 0 : OnValue; // buttons BottomBar.VSplitMid(&Abort, &TryAgain); @@ -2267,13 +2267,13 @@ int CMenus::Render() Box.HSplitTop(ButtonHeight, &EditBox, &Box); static float s_OffsetName = 0.0f; - DoEditBoxOption(g_Config.m_PlayerName, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), &EditBox, Localize("Nickname"), ButtonWidth, &s_OffsetName); + DoEditBoxOption(Config()->Values()->m_PlayerName, Config()->Values()->m_PlayerName, sizeof(Config()->Values()->m_PlayerName), &EditBox, Localize("Nickname"), ButtonWidth, &s_OffsetName); // button static CButtonContainer s_EnterButton; if(DoButton_Menu(&s_EnterButton, pButtonText, 0, &BottomBar) || m_EnterPressed) { - if(g_Config.m_PlayerName[0]) + if(Config()->Values()->m_PlayerName[0]) m_Popup = POPUP_NONE; else PopupMessage(Localize("Error"), Localize("Nickname is empty."), Localize("Ok"), POPUP_FIRST_LAUNCH); @@ -2449,8 +2449,8 @@ void CMenus::OnStateChange(int NewState, int OldState) if(str_find(Client()->ErrorString(), "password")) { m_Popup = POPUP_PASSWORD; - UI()->SetHotItem(&g_Config.m_Password); - UI()->SetActiveItem(&g_Config.m_Password); + UI()->SetHotItem(&Config()->Values()->m_Password); + UI()->SetActiveItem(&Config()->Values()->m_Password); } else m_Popup = POPUP_DISCONNECTED; @@ -2548,7 +2548,7 @@ void CMenus::OnRender() Graphics()->WrapNormal(); // render debug information - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); @@ -2643,9 +2643,9 @@ void CMenus::ToggleMusic() { if(Client()->State() == IClient::STATE_OFFLINE) { - if(g_Config.m_SndMusic && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + if(Config()->Values()->m_SndMusic && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); - else if(!g_Config.m_SndMusic && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + else if(!Config()->Values()->m_SndMusic && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) m_pClient->m_pSounds->Stop(SOUND_MENU); } } @@ -2665,7 +2665,7 @@ void CMenus::SetMenuPage(int NewPage) { case PAGE_START: CameraPos = CCamera::POS_START; break; case PAGE_DEMOS: CameraPos = CCamera::POS_DEMOS; break; - case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS_GENERAL+g_Config.m_UiSettingsPage; break; + case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS_GENERAL+Config()->Values()->m_UiSettingsPage; break; case PAGE_INTERNET: CameraPos = CCamera::POS_INTERNET; break; case PAGE_LAN: CameraPos = CCamera::POS_LAN; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index d26cbdcf..70ee1b48 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -690,8 +690,8 @@ class CMenus : public CComponent void RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); void RenderBackButton(CUIRect MainView); - inline float GetListHeaderHeight() const { return ms_ListheaderHeight + (g_Config.m_UiWideview ? 3.0f : 0.0f); } - inline float GetListHeaderHeightFactor() const { return 1.0f + (g_Config.m_UiWideview ? (3.0f/ms_ListheaderHeight) : 0.0f); } + inline float GetListHeaderHeight() const { return ms_ListheaderHeight + (Config()->Values()->m_UiWideview ? 3.0f : 0.0f); } + inline float GetListHeaderHeightFactor() const { return 1.0f + (Config()->Values()->m_UiWideview ? (3.0f/ms_ListheaderHeight) : 0.0f); } // found in menus_demo.cpp void RenderDemoPlayer(CUIRect MainView); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 4d2a9454..5ac3e0b2 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -474,17 +474,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) + if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aName, g_Config.m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aName, Config()->Values()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aName, (int)(pStr-pEntry->m_aName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aName, -1); @@ -506,17 +506,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) + if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aMap, g_Config.m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aMap, Config()->Values()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aMap, (int)(pStr-pEntry->m_aMap)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aMap, -1); @@ -557,7 +557,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max); - if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) + if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); Button.y += 2.0f; @@ -621,17 +621,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Cursor.m_LineWidth = Button.w; TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) + if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aGameType, g_Config.m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aGameType, Config()->Values()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aGameType, (int)(pStr-pEntry->m_aGameType)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); @@ -883,17 +883,17 @@ void CMenus::RenderServerbrowserOverlay() TextRender()->SetCursor(&Cursor, Name.x, Name.y+(Name.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Name.w; const char *pName = pInfo->m_aClients[i].m_aName; - if(g_Config.m_BrFilterString[0]) + if(Config()->Values()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pName, g_Config.m_BrFilterString); + const char *s = str_find_nocase(pName, Config()->Values()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s+str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pName, -1); @@ -905,17 +905,17 @@ void CMenus::RenderServerbrowserOverlay() TextRender()->SetCursor(&Cursor, Clan.x, Clan.y+(Clan.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Clan.w; const char *pClan = pInfo->m_aClients[i].m_aClan; - if(g_Config.m_BrFilterString[0]) + if(Config()->Values()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pClan, g_Config.m_BrFilterString); + const char *s = str_find_nocase(pClan, Config()->Values()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s+str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pClan, -1); @@ -974,7 +974,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) const float HeightFactor = GetListHeaderHeightFactor(); // background - RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), (Client()->State() == IClient::STATE_OFFLINE) ? CUI::CORNER_ALL : CUI::CORNER_B|CUI::CORNER_TR, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), (Client()->State() == IClient::STATE_OFFLINE) ? CUI::CORNER_ALL : CUI::CORNER_B|CUI::CORNER_TR, 5.0f); // make room for scrollbar { @@ -1022,15 +1022,15 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(i == COL_BROWSER_FLAG) continue; - if(DoButton_GridHeader(ms_aBrowserCols[i].m_Caption, ms_aBrowserCols[i].m_Caption, g_Config.m_BrSort == ms_aBrowserCols[i].m_Sort, ms_aBrowserCols[i].m_Align, &ms_aBrowserCols[i].m_Rect)) + if(DoButton_GridHeader(ms_aBrowserCols[i].m_Caption, ms_aBrowserCols[i].m_Caption, Config()->Values()->m_BrSort == ms_aBrowserCols[i].m_Sort, ms_aBrowserCols[i].m_Align, &ms_aBrowserCols[i].m_Rect)) { if(ms_aBrowserCols[i].m_Sort != -1) { - if(g_Config.m_BrSort == ms_aBrowserCols[i].m_Sort) - g_Config.m_BrSortOrder ^= 1; + if(Config()->Values()->m_BrSort == ms_aBrowserCols[i].m_Sort) + Config()->Values()->m_BrSortOrder ^= 1; else - g_Config.m_BrSortOrder = 0; - g_Config.m_BrSort = ms_aBrowserCols[i].m_Sort; + Config()->Values()->m_BrSortOrder = 0; + Config()->Values()->m_BrSort = ms_aBrowserCols[i].m_Sort; } ServerBrowserSortingOnUpdate(); } @@ -1040,7 +1040,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); { int Column = COL_BROWSER_PING; - switch(g_Config.m_BrSort) + switch(Config()->Values()->m_BrSort) { case IServerBrowser::SORT_NAME: Column = COL_BROWSER_NAME; @@ -1283,7 +1283,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_aSelectedFilters[BrowserType] = FilterIndex; m_aSelectedServers[BrowserType] = ServerIndex; m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); - if(g_Config.m_UiAutoswitchInfotab) + if(Config()->Values()->m_UiAutoswitchInfotab) m_SidebarTab = 0; UpdateServerBrowserAddress(); // update now instead of using flag because of connect if(Input()->MouseDoubleClick()) @@ -1329,7 +1329,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_LEFT); EditBox.VSplitRight(EditBox.h, &EditBox, &Button); static float s_ClearOffset = 0.0f; - if(DoEditBox(&g_Config.m_BrFilterString, &EditBox, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->Values()->m_BrFilterString, &EditBox, Config()->Values()->m_BrFilterString, sizeof(Config()->Values()->m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) { Client()->ServerBrowserUpdate(); ServerBrowserFilterOnUpdate(); @@ -1340,8 +1340,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) static CButtonContainer s_ClearButton; if(DoButton_SpriteID(&s_ClearButton, IMAGE_TOOLICONS, SPRITE_TOOL_X_A, false, &Button, CUI::CORNER_ALL, 5.0f, true)) { - g_Config.m_BrFilterString[0] = 0; - UI()->SetActiveItem(&g_Config.m_BrFilterString); + Config()->Values()->m_BrFilterString[0] = 0; + UI()->SetActiveItem(&Config()->Values()->m_BrFilterString); Client()->ServerBrowserUpdate(); } } @@ -1356,7 +1356,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(BrowserType == IServerBrowser::TYPE_INTERNET) { static float s_InternetAddressOffset = 0.0f; - if(DoEditBox(&g_Config.m_UiServerAddress, &EditBox, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->Values()->m_UiServerAddress, &EditBox, Config()->Values()->m_UiServerAddress, sizeof(Config()->Values()->m_UiServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -1364,7 +1364,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) else if(BrowserType == IServerBrowser::TYPE_LAN) { static float s_LanAddressOffset = 0.0f; - if(DoEditBox(&g_Config.m_UiServerAddressLan, &EditBox, g_Config.m_UiServerAddressLan, sizeof(g_Config.m_UiServerAddressLan), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->Values()->m_UiServerAddressLan, &EditBox, Config()->Values()->m_UiServerAddressLan, sizeof(Config()->Values()->m_UiServerAddressLan), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -1426,7 +1426,7 @@ void CMenus::RenderServerbrowserSidebar(CUIRect View) CUIRect Header, Button; // background - RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // handle Tab key if(m_TabPressed) @@ -2158,17 +2158,17 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Name.w; const char *pName = pInfo->m_aClients[i].m_aName; - if(g_Config.m_BrFilterString[0]) + if(Config()->Values()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pName, g_Config.m_BrFilterString); + const char *s = str_find_nocase(pName, Config()->Values()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s + str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s + str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pName, -1); @@ -2180,17 +2180,17 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int TextRender()->SetCursor(&Cursor, Clan.x, Clan.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Clan.w; const char *pClan = pInfo->m_aClients[i].m_aClan; - if(g_Config.m_BrFilterString[0]) + if(Config()->Values()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pClan, g_Config.m_BrFilterString); + const char *s = str_find_nocase(pClan, Config()->Values()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s + str_length(g_Config.m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s + str_length(Config()->Values()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pClan, -1); @@ -2242,7 +2242,7 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView) float ButtonWidth = MainView.w/2.0f-Spacing/2.0f; // render background - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); // back to main menu CUIRect Button; @@ -2395,9 +2395,9 @@ const char *CMenus::GetServerBrowserAddress() { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - return g_Config.m_UiServerAddress; + return Config()->Values()->m_UiServerAddress; else if(Type == IServerBrowser::TYPE_LAN) - return g_Config.m_UiServerAddressLan; + return Config()->Values()->m_UiServerAddressLan; return 0; } @@ -2405,9 +2405,9 @@ void CMenus::SetServerBrowserAddress(const char *pAddress) { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - str_copy(g_Config.m_UiServerAddress, pAddress, sizeof(g_Config.m_UiServerAddress)); + str_copy(Config()->Values()->m_UiServerAddress, pAddress, sizeof(Config()->Values()->m_UiServerAddress)); else if(Type == IServerBrowser::TYPE_LAN) - str_copy(g_Config.m_UiServerAddressLan, pAddress, sizeof(g_Config.m_UiServerAddressLan)); + str_copy(Config()->Values()->m_UiServerAddressLan, pAddress, sizeof(Config()->Values()->m_UiServerAddressLan)); } void CMenus::ServerBrowserFilterOnUpdate() diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index c33e1b2b..36897bc5 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -139,16 +139,16 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonInpGrab = 0; - if(DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !g_Config.m_InpGrab, &Button)) + if(DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !Config()->Values()->m_InpGrab, &Button)) { - g_Config.m_InpGrab ^= 1; + Config()->Values()->m_InpGrab ^= 1; } View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->Values()->m_InpMousesens, &Config()->Values()->m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&g_Config.m_UiMousesens, &g_Config.m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->Values()->m_UiMousesens, &Config()->Values()->m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); return BackgroundHeight; } @@ -157,7 +157,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) { UpdateBindKeys(m_pClient->m_pBinds); - bool JoystickEnabled = g_Config.m_JoystickEnable; + bool JoystickEnabled = Config()->Values()->m_JoystickEnable; int NumJoysticks = m_pClient->Input()->NumJoysticks(); int NumOptions = 2; // expandable header & message if(JoystickEnabled && NumJoysticks > 0) @@ -180,9 +180,9 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonJoystickEnable = 0; - if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), g_Config.m_JoystickEnable, &Button)) + if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), Config()->Values()->m_JoystickEnable, &Button)) { - g_Config.m_JoystickEnable ^= 1; + Config()->Values()->m_JoystickEnable ^= 1; } if(JoystickEnabled) { @@ -204,11 +204,11 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&g_Config.m_JoystickSens, &g_Config.m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->Values()->m_JoystickSens, &Config()->Values()->m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&g_Config.m_JoystickTolerance, &g_Config.m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); + DoScrollbarOption(&Config()->Values()->m_JoystickTolerance, &Config()->Values()->m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); // shrink view and draw background View.HSplitTop(Spacing, 0, &View); @@ -387,7 +387,7 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) static int s_aActive[g_MaxJoystickAxes][2]; for(int i = 0; i < min(m_pClient->Input()->GetJoystickNumAxes(), g_MaxJoystickAxes); i++) { - bool Active = g_Config.m_JoystickX == i || g_Config.m_JoystickY == i; + bool Active = Config()->Values()->m_JoystickX == i || Config()->Values()->m_JoystickY == i; View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Row, &View); @@ -407,16 +407,16 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) Row.VSplitLeft(StatusMargin, 0, &Row); Row.VSplitLeft(StatusWidth, &Button, &Row); Button.HMargin((ButtonHeight-14.0f)/2.0f, &Button); - DoJoystickBar(&Button, (m_pClient->Input()->GetJoystickAxisValue(i)+1.0f)/2.0f, g_Config.m_JoystickTolerance/50.0f, Active); + DoJoystickBar(&Button, (m_pClient->Input()->GetJoystickAxisValue(i)+1.0f)/2.0f, Config()->Values()->m_JoystickTolerance/50.0f, Active); // Bind to X,Y Row.VSplitLeft(2*StatusMargin, 0, &Row); Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][0], "X", g_Config.m_JoystickX == i, &Button, g_Config.m_JoystickY == i)) - g_Config.m_JoystickX = i; + if(DoButton_CheckBox(&s_aActive[i][0], "X", Config()->Values()->m_JoystickX == i, &Button, Config()->Values()->m_JoystickY == i)) + Config()->Values()->m_JoystickX = i; Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][1], "Y", g_Config.m_JoystickY == i, &Button, g_Config.m_JoystickX == i)) - g_Config.m_JoystickY = i; + if(DoButton_CheckBox(&s_aActive[i][1], "Y", Config()->Values()->m_JoystickY == i, &Button, Config()->Values()->m_JoystickX == i)) + Config()->Values()->m_JoystickY = i; Row.VSplitLeft(StatusMargin, 0, &Row); } } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 802d3c49..ce727213 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -50,7 +50,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) MainView.VSplitRight(450.0f, &MainView, 0); if (m_SeekBarActive || m_MenuActive) // only draw the background if SeekBar or Menu is active - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_T, 10.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_T, 10.0f); MainView.Margin(5.0f, &MainView); @@ -331,7 +331,7 @@ void CMenus::RenderDemoList(CUIRect MainView) // cut view MainView.HSplitBottom(80.0f, &MainView, &BottomView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); BottomView.HSplitTop(20.f, 0, &BottomView); static int s_Inited = 0; @@ -443,7 +443,7 @@ void CMenus::RenderDemoList(CUIRect MainView) float BackgroundWidth = ButtonWidth*(float)NumButtons+(float)(NumButtons-1)*Spacing; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 8a9eb055..99dd070a 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -64,7 +64,7 @@ void CMenus::RenderGame(CUIRect MainView) MainView.HSplitTop(20.0f, 0, &MainView); float NoteHeight = !Info.m_aNotification[0] ? 0.0f : 45.0f; MainView.HSplitTop(20.0f+20.0f+2*Spacing+ NoteHeight, &MainView, 0); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // game options MainView.HSplitTop(20.0f, &Label, &MainView); @@ -214,7 +214,7 @@ void CMenus::RenderPlayers(CUIRect MainView) CUIRect Label, Row; MainView.HSplitBottom(80.0f, &MainView, 0); MainView.HSplitTop(20.0f, 0, &MainView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // player options MainView.HSplitTop(ButtonHeight, &Label, &MainView); @@ -294,7 +294,7 @@ void CMenus::RenderPlayers(CUIRect MainView) Row.VSplitLeft(2*Spacing, 0, &Row); Row.VSplitLeft(NameWidth, &Label, &Row); Label.y += 2.0f; - if(g_Config.m_ClShowUserId) + if(Config()->Values()->m_ClShowUserId) { CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Label.x, Label.y, ButtonHeight*ms_FontmodHeight*0.8f, TEXTFLAG_RENDER); @@ -302,18 +302,18 @@ void CMenus::RenderPlayers(CUIRect MainView) Label.VSplitLeft(ButtonHeight, 0, &Label); } char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Row.VSplitLeft(Spacing, 0, &Row); Row.VSplitLeft(ClanWidth, &Label, &Row); Label.y += 2.0f; - str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aClan : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aClan : ""); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); // ignore button Row.VSplitRight(ButtonHeight/2, &Row, 0); Row.VSplitRight(ButtonHeight, &Row, &Label); - if(g_Config.m_ClFilterchat == 2 || (g_Config.m_ClFilterchat == 1 && !m_pClient->m_aClients[i].m_Friend)) + if(Config()->Values()->m_ClFilterchat == 2 || (Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[i].m_Friend)) DoButton_Toggle(&s_aPlayerIDs[i][0], 1, &Label, false); else if(DoButton_Toggle(&s_aPlayerIDs[i][0], m_pClient->m_aClients[i].m_ChatIgnore, &Label, true)) @@ -355,7 +355,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) // render background MainView.HSplitBottom(80.0f, &MainView, 0); MainView.HSplitTop(20.0f, 0, &MainView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); CUIRect ServerInfo, GameInfo, Motd, Label; @@ -573,7 +573,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Label.x + Label.h / 2, Label.y + Label.h / 2)); Row.VSplitLeft(2*Spacing, 0, &Row); - if(g_Config.m_ClShowUserId) + if(Config()->Values()->m_ClShowUserId) { Row.VSplitLeft(Row.h, &Label, &Row); Label.y += 2.0f; @@ -586,12 +586,12 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) Row.VSplitLeft(NameWidth, &Label, &Row); Label.y += 2.0f; char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : ""); UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Row.VSplitLeft(Spacing, 0, &Row); Row.VSplitLeft(ClanWidth, &Label, &Row); Label.y += 2.0f; - str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aClan : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aClan : ""); UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } } @@ -663,7 +663,7 @@ void CMenus::RenderServerControl(CUIRect MainView) // only print notice CUIRect Bar; MainView.HSplitTop(45.0f, &Bar, &MainView); - RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); Bar.HMargin(15.0f, &Bar); UI()->DoLabel(&Bar, pNotification, 14.0f, CUI::ALIGN_CENTER); return; @@ -708,7 +708,7 @@ void CMenus::RenderServerControl(CUIRect MainView) { MainView.HSplitTop(20.0f+45.0f, &MainView, 0); } - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); if(pNotification && !Authed) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 3c1aba61..791c04b5 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -329,7 +329,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) *CSkins::ms_apColorVariables[p] = NewVal; } if(UseAlpha) - g_Config.m_PlayerColorMarking = (Alp << 24) + NewVal; + Config()->Values()->m_PlayerColorMarking = (Alp << 24) + NewVal; m_SkinModified = true; } } @@ -364,7 +364,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) const CSkins::CSkin *s = s_paSkinList[i]; if(s == 0) continue; - if(!str_comp(s->m_aName, g_Config.m_PlayerSkin)) + if(!str_comp(s->m_aName, Config()->Values()->m_PlayerSkin)) { m_pSelectedSkin = s; OldSelected = i; @@ -398,7 +398,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) if(NewSelected != -1 && NewSelected != OldSelected) { m_pSelectedSkin = s_paSkinList[NewSelected]; - mem_copy(g_Config.m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(g_Config.m_PlayerSkin)); + mem_copy(Config()->Values()->m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(Config()->Values()->m_PlayerSkin)); for(int p = 0; p < NUM_SKINPARTS; p++) { mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, 24); @@ -488,7 +488,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, 24); - g_Config.m_PlayerSkin[0] = 0; + Config()->Values()->m_PlayerSkin[0] = 0; m_SkinModified = true; } OldSelected = NewSelected; @@ -698,7 +698,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) LoadLanguageIndexfile(Storage(), Console(), &s_Languages); for(int i = 0; i < s_Languages.size(); i++) { - if(str_comp(s_Languages[i].m_FileName, g_Config.m_ClLanguagefile) == 0) + if(str_comp(s_Languages[i].m_FileName, Config()->Values()->m_ClLanguagefile) == 0) { s_SelectedLanguage = i; break; @@ -746,7 +746,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) if(OldSelected != s_SelectedLanguage) { m_ActiveListBox = ACTLB_LANG; - str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile)); + str_copy(Config()->Values()->m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(Config()->Values()->m_ClLanguagefile)); g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console()); } } @@ -758,13 +758,13 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) if(m_lThemes.size() == 0) // not loaded yet { - if(!g_Config.m_ClShowMenuMap) - str_copy(g_Config.m_ClMenuMap, "", sizeof(g_Config.m_ClMenuMap)); // cl_menu_map otherwise resets to default on loading + if(!Config()->Values()->m_ClShowMenuMap) + str_copy(Config()->Values()->m_ClMenuMap, "", sizeof(Config()->Values()->m_ClMenuMap)); // cl_menu_map otherwise resets to default on loading m_lThemes.add(CTheme("", false, false)); // no theme Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeScan, (CMenus*)this); Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeIconScan, (CMenus*)this); for(int i = 0; i < m_lThemes.size(); i++) - if(str_comp(m_lThemes[i].m_Name, g_Config.m_ClMenuMap) == 0) + if(str_comp(m_lThemes[i].m_Name, Config()->Values()->m_ClMenuMap) == 0) { s_SelectedTheme = i; break; @@ -837,11 +837,11 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) if(OldSelected != s_SelectedTheme) { m_ActiveListBox = ACTLB_THEME; - str_copy(g_Config.m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(g_Config.m_ClMenuMap)); + str_copy(Config()->Values()->m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(Config()->Values()->m_ClMenuMap)); if(m_lThemes[s_SelectedTheme].m_Name[0]) - g_Config.m_ClShowMenuMap = 1; + Config()->Values()->m_ClShowMenuMap = 1; else - g_Config.m_ClShowMenuMap = 0; + Config()->Values()->m_ClShowMenuMap = 0; m_pClient->m_pMapLayersBackGround->BackgroundMapUpdate(); } } @@ -855,7 +855,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) BottomView.HSplitTop(20.f, 0, &BottomView); // render game menu backgrounds - int NumOptions = max(g_Config.m_ClNameplates ? 6 : 3, g_Config.m_ClShowsocial ? 5 : 4); + int NumOptions = max(Config()->Values()->m_ClNameplates ? 6 : 3, Config()->Values()->m_ClShowsocial ? 5 : 4); float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; @@ -864,15 +864,15 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), this->Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), this->Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Game, &MainView); RenderTools()->DrawUIRect(&Game, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // render client menu background NumOptions = 4; - if(g_Config.m_ClAutoDemoRecord) NumOptions += 1; - if(g_Config.m_ClAutoScreenshot) NumOptions += 1; + if(Config()->Values()->m_ClAutoDemoRecord) NumOptions += 1; + if(Config()->Values()->m_ClAutoScreenshot) NumOptions += 1; BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; MainView.HSplitTop(10.0f, 0, &MainView); @@ -893,81 +893,81 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_DynamicCameraButton = 0; - if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClDynamicCamera, &Button)) + if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), Config()->Values()->m_ClDynamicCamera, &Button)) { - if(g_Config.m_ClDynamicCamera) + if(Config()->Values()->m_ClDynamicCamera) { - g_Config.m_ClDynamicCamera = 0; + Config()->Values()->m_ClDynamicCamera = 0; // force to defaults when using the GUI - g_Config.m_ClMouseMaxDistanceStatic = 400; - // g_Config.m_ClMouseFollowfactor = 0; - // g_Config.m_ClMouseDeadzone = 0; + Config()->Values()->m_ClMouseMaxDistanceStatic = 400; + // Config()->Values()->m_ClMouseFollowfactor = 0; + // Config()->Values()->m_ClMouseDeadzone = 0; } else { - g_Config.m_ClDynamicCamera = 1; + Config()->Values()->m_ClDynamicCamera = 1; // force to defaults when using the GUI - g_Config.m_ClMouseMaxDistanceDynamic = 1000; - g_Config.m_ClMouseFollowfactor = 60; - g_Config.m_ClMouseDeadzone = 300; + Config()->Values()->m_ClMouseMaxDistanceDynamic = 1000; + Config()->Values()->m_ClMouseFollowfactor = 60; + Config()->Values()->m_ClMouseDeadzone = 300; } } GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_AutoswitchWeapons = 0; - if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button)) - g_Config.m_ClAutoswitchWeapons ^= 1; + if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), Config()->Values()->m_ClAutoswitchWeapons, &Button)) + Config()->Values()->m_ClAutoswitchWeapons ^= 1; GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_Nameplates = 0; - if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button)) - g_Config.m_ClNameplates ^= 1; + if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), Config()->Values()->m_ClNameplates, &Button)) + Config()->Values()->m_ClNameplates ^= 1; - if(g_Config.m_ClNameplates) + if(Config()->Values()->m_ClNameplates) { GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_NameplatesAlways = 0; - if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button)) - g_Config.m_ClNameplatesAlways ^= 1; + if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), Config()->Values()->m_ClNameplatesAlways, &Button)) + Config()->Values()->m_ClNameplatesAlways ^= 1; GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&g_Config.m_ClNameplatesSize, &g_Config.m_ClNameplatesSize, &Button, Localize("Size"), 0, 100); + DoScrollbarOption(&Config()->Values()->m_ClNameplatesSize, &Config()->Values()->m_ClNameplatesSize, &Button, Localize("Size"), 0, 100); GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_NameplatesTeamcolors = 0; - if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), g_Config.m_ClNameplatesTeamcolors, &Button)) - g_Config.m_ClNameplatesTeamcolors ^= 1; + if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), Config()->Values()->m_ClNameplatesTeamcolors, &Button)) + Config()->Values()->m_ClNameplatesTeamcolors ^= 1; } // right side GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_Showhud = 0; - if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), g_Config.m_ClShowhud, &Button)) - g_Config.m_ClShowhud ^= 1; + if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), Config()->Values()->m_ClShowhud, &Button)) + Config()->Values()->m_ClShowhud ^= 1; GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_ShowUserId = 0; - if(DoButton_CheckBox(&s_ShowUserId, Localize("Show user IDs"), g_Config.m_ClShowUserId, &Button)) - g_Config.m_ClShowUserId ^= 1; + if(DoButton_CheckBox(&s_ShowUserId, Localize("Show user IDs"), Config()->Values()->m_ClShowUserId, &Button)) + Config()->Values()->m_ClShowUserId ^= 1; GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_Showsocial = 0; - if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), g_Config.m_ClShowsocial, &Button)) - g_Config.m_ClShowsocial ^= 1; + if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), Config()->Values()->m_ClShowsocial, &Button)) + Config()->Values()->m_ClShowsocial ^= 1; // show chat messages button - if(g_Config.m_ClShowsocial) + if(Config()->Values()->m_ClShowsocial) { GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); @@ -983,23 +983,23 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(119.0f, &Button, 0); - if(g_Config.m_ClFilterchat == 0) + if(Config()->Values()->m_ClFilterchat == 0) str_format(aBuf, sizeof(aBuf), Localize("everyone", "Show chat messages from:")); - else if(g_Config.m_ClFilterchat == 1) + else if(Config()->Values()->m_ClFilterchat == 1) str_format(aBuf, sizeof(aBuf), Localize("friends only", "Show chat messages from:")); - else if(g_Config.m_ClFilterchat == 2) + else if(Config()->Values()->m_ClFilterchat == 2) str_format(aBuf, sizeof(aBuf), Localize("no one", "Show chat messages from:")); static CButtonContainer s_ButtonFilterchat; if(DoButton_Menu(&s_ButtonFilterchat, aBuf, 0, &Button)) - g_Config.m_ClFilterchat = (g_Config.m_ClFilterchat + 1) % 3; + Config()->Values()->m_ClFilterchat = (Config()->Values()->m_ClFilterchat + 1) % 3; } GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_EnableColoredBroadcasts = 0; if(DoButton_CheckBox(&s_EnableColoredBroadcasts, Localize("Enable colored server broadcasts"), - g_Config.m_ClColoredBroadcast, &Button)) - g_Config.m_ClColoredBroadcast ^= 1; + Config()->Values()->m_ClColoredBroadcast, &Button)) + Config()->Values()->m_ClColoredBroadcast ^= 1; // render client menu Client.HSplitTop(ButtonHeight, &Label, &Client); @@ -1009,39 +1009,39 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_SkipMainMenu = 0; - if(DoButton_CheckBox(&s_SkipMainMenu, Localize("Skip the main menu"), g_Config.m_ClSkipStartMenu, &Button)) - g_Config.m_ClSkipStartMenu ^= 1; + if(DoButton_CheckBox(&s_SkipMainMenu, Localize("Skip the main menu"), Config()->Values()->m_ClSkipStartMenu, &Button)) + Config()->Values()->m_ClSkipStartMenu ^= 1; Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); - DoScrollbarOption(&g_Config.m_ClMenuAlpha, &g_Config.m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); + DoScrollbarOption(&Config()->Values()->m_ClMenuAlpha, &Config()->Values()->m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_AutoDemoRecord = 0; - if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button)) - g_Config.m_ClAutoDemoRecord ^= 1; + if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), Config()->Values()->m_ClAutoDemoRecord, &Button)) + Config()->Values()->m_ClAutoDemoRecord ^= 1; - if(g_Config.m_ClAutoDemoRecord) + if(Config()->Values()->m_ClAutoDemoRecord) { Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&g_Config.m_ClAutoDemoMax, &g_Config.m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); + DoScrollbarOption(&Config()->Values()->m_ClAutoDemoMax, &Config()->Values()->m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_AutoScreenshot = 0; - if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button)) - g_Config.m_ClAutoScreenshot ^= 1; + if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), Config()->Values()->m_ClAutoScreenshot, &Button)) + Config()->Values()->m_ClAutoScreenshot ^= 1; - if(g_Config.m_ClAutoScreenshot) + if(Config()->Values()->m_ClAutoScreenshot) { Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&g_Config.m_ClAutoScreenshotMax, &g_Config.m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); + DoScrollbarOption(&Config()->Values()->m_ClAutoScreenshotMax, &Config()->Values()->m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -1059,41 +1059,41 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - g_Config.m_ClDynamicCamera = 0; - g_Config.m_ClMouseMaxDistanceStatic = 400; - g_Config.m_ClMouseMaxDistanceDynamic = 1000; - g_Config.m_ClMouseFollowfactor = 60; - g_Config.m_ClMouseDeadzone = 300; - g_Config.m_ClAutoswitchWeapons = 1; - g_Config.m_ClShowhud = 1; - g_Config.m_ClFilterchat = 0; - g_Config.m_ClNameplates = 1; - g_Config.m_ClNameplatesAlways = 1; - g_Config.m_ClNameplatesSize = 50; - g_Config.m_ClNameplatesTeamcolors = 1; - g_Config.m_ClAutoDemoRecord = 0; - g_Config.m_ClAutoDemoMax = 10; - g_Config.m_ClAutoScreenshot = 0; - g_Config.m_ClAutoScreenshotMax = 10; + Config()->Values()->m_ClDynamicCamera = 0; + Config()->Values()->m_ClMouseMaxDistanceStatic = 400; + Config()->Values()->m_ClMouseMaxDistanceDynamic = 1000; + Config()->Values()->m_ClMouseFollowfactor = 60; + Config()->Values()->m_ClMouseDeadzone = 300; + Config()->Values()->m_ClAutoswitchWeapons = 1; + Config()->Values()->m_ClShowhud = 1; + Config()->Values()->m_ClFilterchat = 0; + Config()->Values()->m_ClNameplates = 1; + Config()->Values()->m_ClNameplatesAlways = 1; + Config()->Values()->m_ClNameplatesSize = 50; + Config()->Values()->m_ClNameplatesTeamcolors = 1; + Config()->Values()->m_ClAutoDemoRecord = 0; + Config()->Values()->m_ClAutoDemoMax = 10; + Config()->Values()->m_ClAutoScreenshot = 0; + Config()->Values()->m_ClAutoScreenshotMax = 10; } } void CMenus::RenderSettingsPlayer(CUIRect MainView) { - static int s_PlayerCountry = g_Config.m_PlayerCountry; + static int s_PlayerCountry = Config()->Values()->m_PlayerCountry; static char s_aPlayerName[256] = {0}; static char s_aPlayerClan[256] = {0}; if(!s_aPlayerName[0]) - str_copy(s_aPlayerName, g_Config.m_PlayerName, sizeof(s_aPlayerName)); + str_copy(s_aPlayerName, Config()->Values()->m_PlayerName, sizeof(s_aPlayerName)); if(!s_aPlayerClan[0]) - str_copy(s_aPlayerClan, g_Config.m_PlayerClan, sizeof(s_aPlayerClan)); + str_copy(s_aPlayerClan, Config()->Values()->m_PlayerClan, sizeof(s_aPlayerClan)); CUIRect Button, Left, Right, TopView, Label, Background; @@ -1107,7 +1107,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1126,12 +1126,12 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) // left menu Left.HSplitTop(ButtonHeight, &Button, &Left); static float s_OffsetName = 0.0f; - DoEditBoxOption(g_Config.m_PlayerName, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); + DoEditBoxOption(Config()->Values()->m_PlayerName, Config()->Values()->m_PlayerName, sizeof(Config()->Values()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); // right menu Right.HSplitTop(ButtonHeight, &Button, &Right); static float s_OffsetClan = 0.0f; - DoEditBoxOption(g_Config.m_PlayerClan, g_Config.m_PlayerClan, sizeof(g_Config.m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); + DoEditBoxOption(Config()->Values()->m_PlayerClan, Config()->Values()->m_PlayerClan, sizeof(Config()->Values()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); // country flag selector MainView.HSplitTop(10.0f, 0, &MainView); @@ -1145,7 +1145,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->GetByIndex(i); if(pEntry->m_Blocked) continue; - if(pEntry->m_CountryCode == g_Config.m_PlayerCountry) + if(pEntry->m_CountryCode == Config()->Values()->m_PlayerCountry) OldSelected = i; CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); @@ -1178,14 +1178,14 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) const int NewSelected = s_ListBox.DoEnd(); if(OldSelected != NewSelected) - g_Config.m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; + Config()->Values()->m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; // check if the new settings require a server reload m_NeedRestartPlayer = !( - s_PlayerCountry == g_Config.m_PlayerCountry && - !str_comp(s_aPlayerClan, g_Config.m_PlayerClan) && - !str_comp(s_aPlayerName, g_Config.m_PlayerName) + s_PlayerCountry == Config()->Values()->m_PlayerCountry && + !str_comp(s_aPlayerClan, Config()->Values()->m_PlayerClan) && + !str_comp(s_aPlayerName, Config()->Values()->m_PlayerName) ); } @@ -1245,7 +1245,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) static bool s_CustomSkinMenu = false; static char s_aPlayerSkin[256] = {0}; if(!s_aPlayerSkin[0]) - str_copy(s_aPlayerSkin, g_Config.m_PlayerSkin, sizeof(s_aPlayerSkin)); + str_copy(s_aPlayerSkin, Config()->Values()->m_PlayerSkin, sizeof(s_aPlayerSkin)); CUIRect Button, Label, BottomView, Preview, Background; @@ -1266,7 +1266,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Preview, &MainView); RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1401,7 +1401,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); Preview.y += 2.0f; - UI()->DoLabel(&Preview, g_Config.m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Preview, Config()->Values()->m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -1416,7 +1416,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) float BackgroundWidth = s_CustomSkinMenu||(m_pSelectedSkin && (m_pSelectedSkin->m_Flags&CSkins::SKINFLAG_STANDARD) == 0) ? ButtonWidth*2.0f+SpacingW : ButtonWidth; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); if(s_CustomSkinMenu) @@ -1458,7 +1458,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); BottomView.HSplitTop(20.f, 0, &BottomView); @@ -1528,7 +1528,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; @@ -1542,48 +1542,48 @@ float CMenus::RenderSettingsControlsStats(CUIRect View) CUIRect Button; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos, Localize("Frags"), g_Config.m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_FRAGS; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos, Localize("Frags"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FRAGS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+1, Localize("Deaths"), g_Config.m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_DEATHS; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+1, Localize("Deaths"), Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_DEATHS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+2, Localize("Suicides"), g_Config.m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_SUICIDES; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+2, Localize("Suicides"), Config()->Values()->m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_SUICIDES; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+3, Localize("Ratio"), g_Config.m_ClStatboardInfos & TC_STATS_RATIO, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_RATIO; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+3, Localize("Ratio"), Config()->Values()->m_ClStatboardInfos & TC_STATS_RATIO, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_RATIO; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+4, Localize("Net score"), g_Config.m_ClStatboardInfos & TC_STATS_NET, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_NET; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+4, Localize("Net score"), Config()->Values()->m_ClStatboardInfos & TC_STATS_NET, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_NET; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+5, Localize("Frags per minute"), g_Config.m_ClStatboardInfos & TC_STATS_FPM, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_FPM; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+5, Localize("Frags per minute"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FPM, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FPM; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+6, Localize("Current spree"), g_Config.m_ClStatboardInfos & TC_STATS_SPREE, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_SPREE; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+6, Localize("Current spree"), Config()->Values()->m_ClStatboardInfos & TC_STATS_SPREE, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_SPREE; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+7, Localize("Best spree"), g_Config.m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_BESTSPREE; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+7, Localize("Best spree"), Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_BESTSPREE; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+9, Localize("Weapons stats"), g_Config.m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_WEAPS; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+9, Localize("Weapons stats"), Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_WEAPS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+8, Localize("Flag grabs"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+8, Localize("Flag grabs"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&g_Config.m_ClStatboardInfos+10, Localize("Flag captures"), g_Config.m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) - g_Config.m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; + if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+10, Localize("Flag captures"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) + Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; return 11*20.0f; } @@ -1598,8 +1598,8 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, for(int i = 0; i < lModes.size(); ++i) { - if(g_Config.m_GfxScreenWidth == lModes[i].m_Width && - g_Config.m_GfxScreenHeight == lModes[i].m_Height) + if(Config()->Values()->m_GfxScreenWidth == lModes[i].m_Width && + Config()->Values()->m_GfxScreenHeight == lModes[i].m_Height) { OldSelected = i; } @@ -1637,8 +1637,8 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, const int NewSelected = pListBox->DoEnd(); if(OldSelected != NewSelected) { - g_Config.m_GfxScreenWidth = lModes[NewSelected].m_Width; - g_Config.m_GfxScreenHeight = lModes[NewSelected].m_Height; + Config()->Values()->m_GfxScreenWidth = lModes[NewSelected].m_Width; + Config()->Values()->m_GfxScreenHeight = lModes[NewSelected].m_Height; return true; } return false; @@ -1648,11 +1648,11 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) { bool CheckSettings = false; - static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth; - static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight; - static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples; - static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality; - static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression; + static int s_GfxScreenWidth = Config()->Values()->m_GfxScreenWidth; + static int s_GfxScreenHeight = Config()->Values()->m_GfxScreenHeight; + static int s_GfxFsaaSamples = Config()->Values()->m_GfxFsaaSamples; + static int s_GfxTextureQuality = Config()->Values()->m_GfxTextureQuality; + static int s_GfxTextureCompression = Config()->Values()->m_GfxTextureCompression; CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView, Background; @@ -1662,7 +1662,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) // render screen menu background int NumOptions = 3; - if(Graphics()->GetNumScreens() > 1 && !g_Config.m_GfxFullscreen) + if(Graphics()->GetNumScreens() > 1 && !Config()->Values()->m_GfxFullscreen) ++NumOptions; float ButtonHeight = 20.0f; float Spacing = 2.0f; @@ -1672,7 +1672,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &ScreenLeft, &MainView); RenderTools()->DrawUIRect(&ScreenLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1697,16 +1697,16 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft); ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); static int s_ButtonGfxFullscreen = 0; - if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), Config()->Values()->m_GfxFullscreen, &Button)) Client()->ToggleFullscreen(); - if(!g_Config.m_GfxFullscreen) + if(!Config()->Values()->m_GfxFullscreen) { ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft); ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonGfxBorderless = 0; - if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), Config()->Values()->m_GfxBorderless, &Button)) Client()->ToggleWindowBordered(); } @@ -1724,12 +1724,12 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(120.0f, &Button, 0); - str_format(aBuf, sizeof(aBuf), "#%d (%dx%d)", g_Config.m_GfxScreen+1, Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); + str_format(aBuf, sizeof(aBuf), "#%d (%dx%d)", Config()->Values()->m_GfxScreen+1, Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); static CButtonContainer s_ButtonScreenId; if(DoButton_Menu(&s_ButtonScreenId, aBuf, 0, &Button)) { - g_Config.m_GfxScreen = (g_Config.m_GfxScreen + 1) % Graphics()->GetNumScreens(); - Client()->SwitchWindowScreen(g_Config.m_GfxScreen); + Config()->Values()->m_GfxScreen = (Config()->Values()->m_GfxScreen + 1) % Graphics()->GetNumScreens(); + Client()->SwitchWindowScreen(Config()->Values()->m_GfxScreen); } } @@ -1748,16 +1748,16 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(70.0f, &Button, 0); - str_format(aBuf, sizeof(aBuf), "%dx", g_Config.m_GfxFsaaSamples); + str_format(aBuf, sizeof(aBuf), "%dx", Config()->Values()->m_GfxFsaaSamples); static CButtonContainer s_ButtonGfxFsaaSamples; if(DoButton_Menu(&s_ButtonGfxFsaaSamples, aBuf, 0, &Button)) { - if(!g_Config.m_GfxFsaaSamples) - g_Config.m_GfxFsaaSamples = 2; - else if(g_Config.m_GfxFsaaSamples == 16) - g_Config.m_GfxFsaaSamples = 0; + if(!Config()->Values()->m_GfxFsaaSamples) + Config()->Values()->m_GfxFsaaSamples = 2; + else if(Config()->Values()->m_GfxFsaaSamples == 16) + Config()->Values()->m_GfxFsaaSamples = 0; else - g_Config.m_GfxFsaaSamples *= 2; + Config()->Values()->m_GfxFsaaSamples *= 2; CheckSettings = true; } } @@ -1765,26 +1765,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); static int s_ButtonGfxVsync = 0; - if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), Config()->Values()->m_GfxVsync, &Button)) Client()->ToggleWindowVSync(); ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); // TODO: greyed out checkbox (not clickable) - if(!g_Config.m_GfxVsync) + if(!Config()->Values()->m_GfxVsync) { static int s_ButtonGfxCapFps = 0; - if(DoButton_CheckBox(&s_ButtonGfxCapFps, Localize("Limit Fps"), g_Config.m_GfxLimitFps, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxCapFps, Localize("Limit Fps"), Config()->Values()->m_GfxLimitFps, &Button)) { - g_Config.m_GfxLimitFps ^= 1; + Config()->Values()->m_GfxLimitFps ^= 1; } - if(g_Config.m_GfxLimitFps > 0) + if(Config()->Values()->m_GfxLimitFps > 0) { ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); - DoScrollbarOption(&g_Config.m_GfxMaxFps, &g_Config.m_GfxMaxFps, + DoScrollbarOption(&Config()->Values()->m_GfxMaxFps, &Config()->Values()->m_GfxMaxFps, &Button, Localize("Max fps"), 30, 300); } } @@ -1797,26 +1797,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureQuality = 0; - if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), Config()->Values()->m_GfxTextureQuality, &Button)) { - g_Config.m_GfxTextureQuality ^= 1; + Config()->Values()->m_GfxTextureQuality ^= 1; CheckSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureCompression = 0; - if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), g_Config.m_GfxTextureCompression, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), Config()->Values()->m_GfxTextureCompression, &Button)) { - g_Config.m_GfxTextureCompression ^= 1; + Config()->Values()->m_GfxTextureCompression ^= 1; CheckSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxHighDetail = 0; - if(DoButton_CheckBox(&s_ButtonGfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button)) - g_Config.m_GfxHighDetail ^= 1; + if(DoButton_CheckBox(&s_ButtonGfxHighDetail, Localize("High Detail"), Config()->Values()->m_GfxHighDetail, &Button)) + Config()->Values()->m_GfxHighDetail ^= 1; // render screen modes MainView.HSplitTop(10.0f, 0, &MainView); @@ -1881,26 +1881,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - g_Config.m_GfxScreenWidth = Graphics()->DesktopWidth(); - g_Config.m_GfxScreenHeight = Graphics()->DesktopHeight(); - g_Config.m_GfxBorderless = 0; - g_Config.m_GfxFullscreen = 1; - g_Config.m_GfxVsync = 1; - g_Config.m_GfxFsaaSamples = 0; - g_Config.m_GfxTextureQuality = 1; - g_Config.m_GfxTextureCompression = 0; - g_Config.m_GfxHighDetail = 1; - - if(g_Config.m_GfxDisplayAllModes) + Config()->Values()->m_GfxScreenWidth = Graphics()->DesktopWidth(); + Config()->Values()->m_GfxScreenHeight = Graphics()->DesktopHeight(); + Config()->Values()->m_GfxBorderless = 0; + Config()->Values()->m_GfxFullscreen = 1; + Config()->Values()->m_GfxVsync = 1; + Config()->Values()->m_GfxFsaaSamples = 0; + Config()->Values()->m_GfxTextureQuality = 1; + Config()->Values()->m_GfxTextureCompression = 0; + Config()->Values()->m_GfxHighDetail = 1; + + if(Config()->Values()->m_GfxDisplayAllModes) { - g_Config.m_GfxDisplayAllModes = 0; + Config()->Values()->m_GfxDisplayAllModes = 0; UpdateVideoModeSettings(); } @@ -1910,11 +1910,11 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) // check if the new settings require a restart if(CheckSettings) { - if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth && - s_GfxScreenHeight == g_Config.m_GfxScreenHeight && - s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples && - s_GfxTextureQuality == g_Config.m_GfxTextureQuality && - s_GfxTextureCompression == g_Config.m_GfxTextureCompression) + if(s_GfxScreenWidth == Config()->Values()->m_GfxScreenWidth && + s_GfxScreenHeight == Config()->Values()->m_GfxScreenHeight && + s_GfxFsaaSamples == Config()->Values()->m_GfxFsaaSamples && + s_GfxTextureQuality == Config()->Values()->m_GfxTextureQuality && + s_GfxTextureCompression == Config()->Values()->m_GfxTextureCompression) m_NeedRestartGraphics = false; else m_NeedRestartGraphics = true; @@ -1926,12 +1926,12 @@ void CMenus::RenderSettingsSound(CUIRect MainView) CUIRect Label, Button, Sound, Detail, BottomView, Background; // render sound menu background - int NumOptions = g_Config.m_SndEnable ? 3 : 2; + int NumOptions = Config()->Values()->m_SndEnable ? 3 : 2; float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; float TotalHeight = BackgroundHeight; - if(g_Config.m_SndEnable) + if(Config()->Values()->m_SndEnable) TotalHeight += 10.0f+2.0f*ButtonHeight+Spacing; MainView.HSplitBottom(MainView.h-TotalHeight-20.0f, &MainView, &BottomView); @@ -1939,13 +1939,13 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Sound, &MainView); RenderTools()->DrawUIRect(&Sound, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // render detail menu background - if(g_Config.m_SndEnable) + if(Config()->Values()->m_SndEnable) { BackgroundHeight = 2.0f*ButtonHeight+Spacing; @@ -1954,8 +1954,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) RenderTools()->DrawUIRect(&Detail, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); } - static int s_SndInit = g_Config.m_SndInit; - static int s_SndRate = g_Config.m_SndRate; + static int s_SndInit = Config()->Values()->m_SndInit; + static int s_SndRate = Config()->Values()->m_SndRate; // render sound menu Sound.HSplitTop(ButtonHeight, &Label, &Sound); @@ -1966,15 +1966,15 @@ void CMenus::RenderSettingsSound(CUIRect MainView) CUIRect UseSoundButton; Sound.HSplitTop(ButtonHeight, &UseSoundButton, &Sound); - if(g_Config.m_SndEnable) + if(Config()->Values()->m_SndEnable) { Sound.HSplitTop(Spacing, 0, &Sound); Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonSndMusic = 0; - if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button)) + if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), Config()->Values()->m_SndMusic, &Button)) { - g_Config.m_SndMusic ^= 1; + Config()->Values()->m_SndMusic ^= 1; ToggleMusic(); } @@ -1982,8 +1982,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonSndNonactiveMute = 0; - if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button)) - g_Config.m_SndNonactiveMute ^= 1; + if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), Config()->Values()->m_SndNonactiveMute, &Button)) + Config()->Values()->m_SndNonactiveMute ^= 1; // render detail menu Detail.HSplitTop(ButtonHeight, &Label, &Detail); @@ -2014,26 +2014,26 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Unit.y += 2.0f; UI()->DoLabel(&Unit, "kHz", Unit.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - if(g_Config.m_SndRate != 48000 && g_Config.m_SndRate != 44100) - g_Config.m_SndRate = 48000; - if(g_Config.m_SndRate == 48000) + if(Config()->Values()->m_SndRate != 48000 && Config()->Values()->m_SndRate != 44100) + Config()->Values()->m_SndRate = 48000; + if(Config()->Values()->m_SndRate == 48000) str_copy(aBuf, "48.0", sizeof(aBuf)); else str_copy(aBuf, "44.1", sizeof(aBuf)); static CButtonContainer s_SampleRateButton; if(DoButton_Menu(&s_SampleRateButton, aBuf, 0, &Value)) { - if(g_Config.m_SndRate == 48000) - g_Config.m_SndRate = 44100; + if(Config()->Values()->m_SndRate == 48000) + Config()->Values()->m_SndRate = 44100; else - g_Config.m_SndRate = 48000; + Config()->Values()->m_SndRate = 48000; } - m_NeedRestartSound = g_Config.m_SndInit && (!s_SndInit || s_SndRate != g_Config.m_SndRate); + m_NeedRestartSound = Config()->Values()->m_SndInit && (!s_SndInit || s_SndRate != Config()->Values()->m_SndRate); } Right.HSplitTop(ButtonHeight, &Button, &Right); - DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Volume"), 0, 100, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->Values()->m_SndVolume, &Config()->Values()->m_SndVolume, &Button, Localize("Volume"), 0, 100, &LogarithmicScrollbarScale); } else { @@ -2041,21 +2041,21 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonInitSounds = 0; - if(DoButton_CheckBox(&s_ButtonInitSounds, Localize("Load the sound system"), g_Config.m_SndInit, &Button)) + if(DoButton_CheckBox(&s_ButtonInitSounds, Localize("Load the sound system"), Config()->Values()->m_SndInit, &Button)) { - g_Config.m_SndInit ^= 1; - m_NeedRestartSound = g_Config.m_SndInit && (!s_SndInit || s_SndRate != g_Config.m_SndRate); + Config()->Values()->m_SndInit ^= 1; + m_NeedRestartSound = Config()->Values()->m_SndInit && (!s_SndInit || s_SndRate != Config()->Values()->m_SndRate); } } static int s_ButtonSndEnable = 0; - if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &UseSoundButton)) + if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), Config()->Values()->m_SndEnable, &UseSoundButton)) { - g_Config.m_SndEnable ^= 1; - if(g_Config.m_SndEnable) + Config()->Values()->m_SndEnable ^= 1; + if(Config()->Values()->m_SndEnable) { - g_Config.m_SndInit = 1; - if(g_Config.m_SndMusic) + Config()->Values()->m_SndInit = 1; + if(Config()->Values()->m_SndMusic) m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } else @@ -2069,40 +2069,40 @@ void CMenus::RenderSettingsSound(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - g_Config.m_SndEnable = 1; - g_Config.m_SndInit = 1; - if(!g_Config.m_SndMusic) + Config()->Values()->m_SndEnable = 1; + Config()->Values()->m_SndInit = 1; + if(!Config()->Values()->m_SndMusic) { - g_Config.m_SndMusic = 1; + Config()->Values()->m_SndMusic = 1; m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } - g_Config.m_SndNonactiveMute = 0; - g_Config.m_SndRate = 48000; - g_Config.m_SndVolume = 100; + Config()->Values()->m_SndNonactiveMute = 0; + Config()->Values()->m_SndRate = 48000; + Config()->Values()->m_SndVolume = 100; } } void CMenus::RenderSettings(CUIRect MainView) { // handle which page should be rendered - if(g_Config.m_UiSettingsPage == SETTINGS_GENERAL) + if(Config()->Values()->m_UiSettingsPage == SETTINGS_GENERAL) RenderSettingsGeneral(MainView); - else if(g_Config.m_UiSettingsPage == SETTINGS_PLAYER) + else if(Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER) RenderSettingsPlayer(MainView); - else if(g_Config.m_UiSettingsPage == SETTINGS_TEE) + else if(Config()->Values()->m_UiSettingsPage == SETTINGS_TEE) RenderSettingsTee(MainView); - else if(g_Config.m_UiSettingsPage == SETTINGS_CONTROLS) + else if(Config()->Values()->m_UiSettingsPage == SETTINGS_CONTROLS) RenderSettingsControls(MainView); - else if(g_Config.m_UiSettingsPage == SETTINGS_GRAPHICS) + else if(Config()->Values()->m_UiSettingsPage == SETTINGS_GRAPHICS) RenderSettingsGraphics(MainView); - else if(g_Config.m_UiSettingsPage == SETTINGS_SOUND) + else if(Config()->Values()->m_UiSettingsPage == SETTINGS_SOUND) RenderSettingsSound(MainView); MainView.HSplitBottom(32.0f, 0, &MainView); @@ -2120,7 +2120,7 @@ void CMenus::RenderSettings(CUIRect MainView) // background CUIRect RestartWarning; MainView.HSplitTop(25.0f, &RestartWarning, 0); - RestartWarning.VMargin(g_Config.m_UiWideview ? 210.0f : 140.0f, &RestartWarning); + RestartWarning.VMargin(Config()->Values()->m_UiWideview ? 210.0f : 140.0f, &RestartWarning); RenderTools()->DrawUIRect(&RestartWarning, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // text diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index eaaa3738..2dfa2599 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -28,7 +28,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) MainView.VMargin(MainView.w/2-190.0f, &TopMenu); TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); - RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), CUI::CORNER_B, 10.0f); + RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 10.0f); TopMenu.HSplitTop(145.0f, 0, &TopMenu); @@ -37,13 +37,13 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_SettingsButton; - if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_S)) + if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_S)) NewPage = PAGE_SETTINGS; /*TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Bottom); static int s_LocalServerButton = 0; - if(g_Config.m_ClShowStartMenuImages) + if(Config()->Values()->m_ClShowStartMenuImages) { if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", 10.0f, 0.5f)) { @@ -59,7 +59,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_DemoButton; - if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_D)) + if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_D)) { NewPage = PAGE_DEMOS; DemolistPopulate(); @@ -71,9 +71,9 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_MapEditorButton; - if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) + if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) { - g_Config.m_ClEditor = 1; + Config()->Values()->m_ClEditor = 1; Input()->MouseModeRelative(); EditorHotkeyWasPressed = true; } @@ -86,11 +86,11 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_PlayButton; - if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) - NewPage = g_Config.m_UiBrowserPage; + if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) + NewPage = Config()->Values()->m_UiBrowserPage; BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); - RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, g_Config.m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); + RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static CButtonContainer s_QuitButton; diff --git a/src/game/client/components/motd.cpp b/src/game/client/components/motd.cpp index 65c948fa..2c5d19a4 100644 --- a/src/game/client/components/motd.cpp +++ b/src/game/client/components/motd.cpp @@ -83,8 +83,8 @@ void CMotd::OnMessage(int MsgType, void *pRawMsg) } } - if(m_aServerMotd[0] && g_Config.m_ClMotdTime) - m_ServerMotdTime = time_get()+time_freq()*g_Config.m_ClMotdTime; + if(m_aServerMotd[0] && Config()->Values()->m_ClMotdTime) + m_ServerMotdTime = time_get()+time_freq()*Config()->Values()->m_ClMotdTime; else m_ServerMotdTime = 0; } diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 3195bf9d..c6166bd6 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -22,17 +22,17 @@ void CNamePlates::RenderNameplate( vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick); - float FontSize = 18.0f + 20.0f * g_Config.m_ClNameplatesSize / 100.0f; + float FontSize = 18.0f + 20.0f * Config()->Values()->m_ClNameplatesSize / 100.0f; // render name plate if(m_pClient->m_LocalClientID != ClientID) { float a = 1; - if(g_Config.m_ClNameplatesAlways == 0) + if(Config()->Values()->m_ClNameplatesAlways == 0) a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); char aName[64]; - str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: ""); + str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: ""); CTextCursor Cursor; float tw = TextRender()->TextWidth(0, FontSize, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(FontSize); @@ -40,7 +40,7 @@ void CNamePlates::RenderNameplate( TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a); TextRender()->TextColor(1.0f, 1.0f, 1.0f, a); - if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + if(Config()->Values()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) TextRender()->TextColor(1.0f, 0.5f, 0.5f, a); @@ -50,7 +50,7 @@ void CNamePlates::RenderNameplate( const vec4 IdTextColor(0.1f, 0.1f, 0.1f, a); vec4 BgIdColor(1.0f, 1.0f, 1.0f, a * 0.5f); - if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + if(Config()->Values()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) BgIdColor = vec4(1.0f, 0.5f, 0.5f, a * 0.5f); @@ -71,7 +71,7 @@ void CNamePlates::RenderNameplate( void CNamePlates::OnRender() { - if (!g_Config.m_ClNameplates) + if (!Config()->Values()->m_ClNameplates) return; for(int i = 0; i < MAX_CLIENTS; i++) diff --git a/src/game/client/components/notifications.cpp b/src/game/client/components/notifications.cpp index 584c58bb..b93e70e1 100644 --- a/src/game/client/components/notifications.cpp +++ b/src/game/client/components/notifications.cpp @@ -26,7 +26,7 @@ void CNotifications::Con_SndToggle(IConsole::IResult *pResult, void *pUserData) { CNotifications *pSelf = (CNotifications *)pUserData; - g_Config.m_SndEnable ^= 1; + pSelf->Config()->Values()->m_SndEnable ^= 1; pSelf->m_SoundToggleTime = pSelf->Client()->LocalTime(); } @@ -53,14 +53,14 @@ void CNotifications::RenderSoundNotification() const float Fade = min(1.0f, RemainingDisplayTime / FadeTime); // 0.0 ≤ Fade ≤ 1.0 - vec4 Color = (g_Config.m_SndEnable == 0) ? vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.55f) : vec4(1.f/0xff*0x2b, 1.f/0xff*0xf9, 1.f/0xff*0x2b, 0.55f); + vec4 Color = (Config()->Values()->m_SndEnable == 0) ? vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.55f) : vec4(1.f/0xff*0x2b, 1.f/0xff*0xf9, 1.f/0xff*0x2b, 0.55f); Color = mix(vec4(Color.r, Color.g, Color.b, 0.0f), Color, 0.8*Fade); RenderTools()->DrawUIRect(&Area, Color, CUI::CORNER_ALL, 3.0f); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_SOUNDICONS].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f*Fade, 1.0f*Fade, 1.0f*Fade, 1.0f*Fade); - RenderTools()->SelectSprite(g_Config.m_SndEnable ? SPRITE_SOUNDICON_ON : SPRITE_SOUNDICON_MUTE); + RenderTools()->SelectSprite(Config()->Values()->m_SndEnable ? SPRITE_SOUNDICON_ON : SPRITE_SOUNDICON_MUTE); IGraphics::CQuadItem QuadItem(Area.x, Area.y, Area.w, Area.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index fa4b9be0..f19b0fcd 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -59,7 +59,7 @@ void CPlayers::RenderHook( // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -196,7 +196,7 @@ void CPlayers::RenderPlayer( } // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -426,7 +426,7 @@ void CPlayers::RenderPlayer( } // render the "shadow" tee - if(m_pClient->m_LocalClientID == ClientID && g_Config.m_Debug) + if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_Debug) { vec2 GhostPosition = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick()); CTeeRenderInfo Ghost = RenderInfo; diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 8d412a63..063d2d97 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -118,7 +118,7 @@ float CScoreboard::RenderSpectators(float x, float y, float w) if(Multiple) TextRender()->TextEx(&Cursor, ", ", -1); - if(g_Config.m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) + if(Config()->Values()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) { Cursor.m_X += Cursor.m_FontSize; } @@ -156,7 +156,7 @@ float CScoreboard::RenderSpectators(float x, float y, float w) if(Multiple) TextRender()->TextEx(&Cursor, ", ", -1); - if(g_Config.m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) + if(Config()->Values()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) { RenderTools()->DrawClientID(TextRender(), &Cursor, i); } @@ -194,7 +194,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c float Spacing = 2.0f; float PingOffset = x+Spacing, PingLength = 35.0f; float CountryFlagOffset = PingOffset+PingLength, CountryFlagLength = 20.f; - float IdSize = g_Config.m_ClShowUserId ? LineHeight : 0.0f; + float IdSize = Config()->Values()->m_ClShowUserId ? LineHeight : 0.0f; float ReadyLength = ReadyMode ? 10.f : 0.f; float TeeOffset = CountryFlagOffset+CountryFlagLength+4.0f, TeeLength = 25*TeeSizeMod; float NameOffset = CountryFlagOffset+CountryFlagLength+IdSize, NameLength = 128.0f-IdSize/2-ReadyLength; @@ -569,7 +569,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c TextRender()->TextColor(1.0f, 1.0f, 0.0f, ColorAlpha); // id - if(g_Config.m_ClShowUserId) + if(Config()->Values()->m_ClShowUserId) { TextRender()->SetCursor(&Cursor, NameOffset+TeeLength-IdSize+Spacing, y+Spacing, FontSize, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, pInfo->m_ClientID); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 7f62be1f..5e782256 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -18,12 +18,9 @@ const char * const CSkins::ms_apSkinPartNames[NUM_SKINPARTS] = {"body", "marking", "decoration", "hands", "feet", "eyes"}; /* Localize("body","skins");Localize("marking","skins");Localize("decoration","skins");Localize("hands","skins");Localize("feet","skins");Localize("eyes","skins"); */ const char * const CSkins::ms_apColorComponents[NUM_COLOR_COMPONENTS] = {"hue", "sat", "lgt", "alp"}; -char *const CSkins::ms_apSkinVariables[NUM_SKINPARTS] = {g_Config.m_PlayerSkinBody, g_Config.m_PlayerSkinMarking, g_Config.m_PlayerSkinDecoration, - g_Config.m_PlayerSkinHands, g_Config.m_PlayerSkinFeet, g_Config.m_PlayerSkinEyes}; -int *const CSkins::ms_apUCCVariables[NUM_SKINPARTS] = {&g_Config.m_PlayerUseCustomColorBody, &g_Config.m_PlayerUseCustomColorMarking, &g_Config.m_PlayerUseCustomColorDecoration, - &g_Config.m_PlayerUseCustomColorHands, &g_Config.m_PlayerUseCustomColorFeet, &g_Config.m_PlayerUseCustomColorEyes}; -int *const CSkins::ms_apColorVariables[NUM_SKINPARTS] = {&g_Config.m_PlayerColorBody, &g_Config.m_PlayerColorMarking, &g_Config.m_PlayerColorDecoration, - &g_Config.m_PlayerColorHands, &g_Config.m_PlayerColorFeet, &g_Config.m_PlayerColorEyes}; +char *CSkins::ms_apSkinVariables[NUM_SKINPARTS] = {0}; +int *CSkins::ms_apUCCVariables[NUM_SKINPARTS] = {0}; +int *CSkins::ms_apColorVariables[NUM_SKINPARTS] = {0}; const float MIN_EYE_BODY_COLOR_DIST = 80.f; // between body and eyes (LAB color space) @@ -95,7 +92,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) if(DirType != IStorage::TYPE_SAVE) Part.m_Flags |= SKINFLAG_STANDARD; str_truncate(Part.m_aName, sizeof(Part.m_aName), pName, str_length(pName) - 4); - if(g_Config.m_Debug) + if(pSelf->Config()->Values()->m_Debug) { str_format(aBuf, sizeof(aBuf), "load skin part %s", Part.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins", aBuf); @@ -202,7 +199,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) Skin.m_Flags = SpecialSkin ? SKINFLAG_SPECIAL : 0; if(DirType != IStorage::TYPE_SAVE) Skin.m_Flags |= SKINFLAG_STANDARD; - if(g_Config.m_Debug) + if(pSelf->Config()->Values()->m_Debug) { str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins", aBuf); @@ -215,6 +212,25 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) void CSkins::OnInit() { + ms_apSkinVariables[SKINPART_BODY] = Config()->Values()->m_PlayerSkinBody; + ms_apSkinVariables[SKINPART_MARKING] = Config()->Values()->m_PlayerSkinMarking; + ms_apSkinVariables[SKINPART_DECORATION] = Config()->Values()->m_PlayerSkinDecoration; + ms_apSkinVariables[SKINPART_HANDS] = Config()->Values()->m_PlayerSkinHands; + ms_apSkinVariables[SKINPART_FEET] = Config()->Values()->m_PlayerSkinFeet; + ms_apSkinVariables[SKINPART_EYES] = Config()->Values()->m_PlayerSkinEyes; + ms_apUCCVariables[SKINPART_BODY] = &Config()->Values()->m_PlayerUseCustomColorBody; + ms_apUCCVariables[SKINPART_MARKING] = &Config()->Values()->m_PlayerUseCustomColorMarking; + ms_apUCCVariables[SKINPART_DECORATION] = &Config()->Values()->m_PlayerUseCustomColorDecoration; + ms_apUCCVariables[SKINPART_HANDS] = &Config()->Values()->m_PlayerUseCustomColorHands; + ms_apUCCVariables[SKINPART_FEET] = &Config()->Values()->m_PlayerUseCustomColorFeet; + ms_apUCCVariables[SKINPART_EYES] = &Config()->Values()->m_PlayerUseCustomColorEyes; + ms_apColorVariables[SKINPART_BODY] = &Config()->Values()->m_PlayerColorBody; + ms_apColorVariables[SKINPART_MARKING] = &Config()->Values()->m_PlayerColorMarking; + ms_apColorVariables[SKINPART_DECORATION] = &Config()->Values()->m_PlayerColorDecoration; + ms_apColorVariables[SKINPART_HANDS] = &Config()->Values()->m_PlayerColorHands; + ms_apColorVariables[SKINPART_FEET] = &Config()->Values()->m_PlayerColorFeet; + ms_apColorVariables[SKINPART_EYES] = &Config()->Values()->m_PlayerColorEyes; + for(int p = 0; p < NUM_SKINPARTS; p++) { m_aaSkinParts[p].clear(); diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index 3b9b9c54..af703883 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -49,9 +49,9 @@ class CSkins : public CComponent static const char * const ms_apSkinPartNames[NUM_SKINPARTS]; static const char * const ms_apColorComponents[NUM_COLOR_COMPONENTS]; - static char * const ms_apSkinVariables[NUM_SKINPARTS]; - static int * const ms_apUCCVariables[NUM_SKINPARTS]; // use custom color - static int * const ms_apColorVariables[NUM_SKINPARTS]; + static char *ms_apSkinVariables[NUM_SKINPARTS]; + static int *ms_apUCCVariables[NUM_SKINPARTS]; // use custom color + static int *ms_apColorVariables[NUM_SKINPARTS]; IGraphics::CTextureHandle m_XmasHatTexture; IGraphics::CTextureHandle m_BotTexture; diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 2730015a..983537c3 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -37,7 +37,7 @@ static int LoadSoundsThread(void *pUser) ISound::CSampleHandle CSounds::GetSampleId(int SetId) { - if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + if(!Config()->Values()->m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) return ISound::CSampleHandle(); CDataSoundset *pSet = &g_pData->m_aSounds[SetId]; @@ -71,7 +71,7 @@ void CSounds::OnInit() ClearQueue(); // load sounds - if(g_Config.m_SndAsyncLoading) + if(Config()->Values()->m_SndAsyncLoading) { g_UserData.m_pGameClient = m_pClient; g_UserData.m_Render = false; @@ -143,7 +143,7 @@ void CSounds::Enqueue(int Channel, int SetId) // add sound to the queue if(m_QueuePos < QUEUE_SIZE) { - if(Channel == CHN_MUSIC || !g_Config.m_ClEditor) + if(Channel == CHN_MUSIC || !Config()->Values()->m_ClEditor) { m_aQueue[m_QueuePos].m_Channel = Channel; m_aQueue[m_QueuePos++].m_SetId = SetId; @@ -153,7 +153,7 @@ void CSounds::Enqueue(int Channel, int SetId) void CSounds::Play(int Chn, int SetId, float Vol) { - if(Chn == CHN_MUSIC && !g_Config.m_SndMusic) + if(Chn == CHN_MUSIC && !Config()->Values()->m_SndMusic) return; ISound::CSampleHandle SampleId = GetSampleId(SetId); @@ -169,7 +169,7 @@ void CSounds::Play(int Chn, int SetId, float Vol) void CSounds::PlayAt(int Chn, int SetId, float Vol, vec2 Pos) { - if(Chn == CHN_MUSIC && !g_Config.m_SndMusic) + if(Chn == CHN_MUSIC && !Config()->Values()->m_SndMusic) return; ISound::CSampleHandle SampleId = GetSampleId(SetId); diff --git a/src/game/client/components/spectator.cpp b/src/game/client/components/spectator.cpp index 830a42b2..d55d0740 100644 --- a/src/game/client/components/spectator.cpp +++ b/src/game/client/components/spectator.cpp @@ -308,7 +308,7 @@ void CSpectator::OnRender() } TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f); char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Width/2.0f+x+50.0f, Height/2.0f+y+5.0f, FontSize, TEXTFLAG_RENDER); diff --git a/src/game/client/components/stats.cpp b/src/game/client/components/stats.cpp index 0d151607..b8e168cc 100644 --- a/src/game/client/components/stats.cpp +++ b/src/game/client/components/stats.cpp @@ -49,7 +49,7 @@ void CStats::OnReset() bool CStats::IsActive() const { // force statboard after three seconds of game over if autostatscreenshot is on - if(g_Config.m_ClAutoStatScreenshot && m_ScreenshotTime > -1 && m_ScreenshotTime < time_get()) + if(Config()->Values()->m_ClAutoStatScreenshot && m_ScreenshotTime > -1 && m_ScreenshotTime < time_get()) return true; return m_Active; @@ -113,7 +113,7 @@ void CStats::OnMessage(int MsgType, void *pRawMsg) void CStats::OnRender() { // auto stat screenshot stuff - if(g_Config.m_ClAutoStatScreenshot) + if(Config()->Values()->m_ClAutoStatScreenshot) { // on game over, wait three seconds if(m_ScreenshotTime < 0 && m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) @@ -161,16 +161,16 @@ void CStats::OnRender() } for(int i=0; i<9; i++) - if(g_Config.m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & TC_STATS_FRAGS) { w += 60; // some extra for the merge continue; } else if((1<Values()->m_ClStatboardInfos & TC_STATS_SPREE)) w += 140; // Best spree is a long column name, add a bit more else w += 40; // The combined colunms are a bit long, add some extra @@ -181,12 +181,12 @@ void CStats::OnRender() w += 100; } - if((m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS) && (g_Config.m_ClStatboardInfos&TC_STATS_FLAGCAPTURES)) + if((m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS) && (Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES)) w += 100; bool aDisplayWeapon[NUM_WEAPONS] = {false}; bool NoDisplayedWeapon = true; - if(g_Config.m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) { for(i=0; iText(0, x+10, y-5, 20.0f, Localize("Name"), -1.0f); const char *apHeaders[] = { "K", "D", Localize("Suicides"), Localize("Ratio"), Localize("Net", "Net score"), Localize("FPM"), Localize("Spree"), Localize("Best spree"), Localize("Grabs", "Flag grabs") }; for(i=0; i<9; i++) - if(g_Config.m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & TC_STATS_DEATHS) { pText = "K:D"; px += 60.0f; // some extra for the merge } - else if(1<Values()->m_ClStatboardInfos & TC_STATS_FRAGS) continue; // handle spree columns merge if(1<Values()->m_ClStatboardInfos & TC_STATS_SPREE) continue; px += 40.0f; // some extra for the long name } - else if(1<Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) px += 40.0f; // some extra for the merge if(1<m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS)) continue; @@ -249,7 +249,7 @@ void CStats::OnRender() } // sprite headers now - if(g_Config.m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); @@ -270,7 +270,7 @@ void CStats::OnRender() px += 10; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && g_Config.m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) { px -= 40; Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); @@ -334,9 +334,9 @@ void CStats::OnRender() TextRender()->TextEx(&Cursor, m_pClient->m_aClients[apPlayers[j]].m_aName, -1); px = 325; - if(g_Config.m_ClStatboardInfos & TC_STATS_FRAGS) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_FRAGS) { - if(g_Config.m_ClStatboardInfos & TC_STATS_DEATHS) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS) { px += 60; str_format(aBuf, sizeof(aBuf), "%d:%d", pStats->m_Frags, pStats->m_Deaths); @@ -347,21 +347,21 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - else if(g_Config.m_ClStatboardInfos & TC_STATS_DEATHS) + else if(Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_Deaths); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(g_Config.m_ClStatboardInfos & TC_STATS_SUICIDES) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_SUICIDES) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_Suicides); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(g_Config.m_ClStatboardInfos & TC_STATS_RATIO) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_RATIO) { if(pStats->m_Deaths == 0) str_format(aBuf, sizeof(aBuf), "--"); @@ -371,14 +371,14 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(g_Config.m_ClStatboardInfos & TC_STATS_NET) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_NET) { str_format(aBuf, sizeof(aBuf), "%+d", pStats->m_Frags-pStats->m_Deaths); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(g_Config.m_ClStatboardInfos & TC_STATS_FPM) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_FPM) { float Fpm = pStats->m_IngameTicks > 0 ? (float)(pStats->m_Frags * Client()->GameTickSpeed() * 60) / pStats->m_IngameTicks : 0.f; str_format(aBuf, sizeof(aBuf), "%.1f", Fpm); @@ -386,9 +386,9 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(g_Config.m_ClStatboardInfos & TC_STATS_SPREE) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_SPREE) { - if(g_Config.m_ClStatboardInfos & TC_STATS_BESTSPREE) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) { px += 40; // extra space str_format(aBuf, sizeof(aBuf), "%d (%d)", pStats->m_CurrentSpree, pStats->m_BestSpree); @@ -399,7 +399,7 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - else if(g_Config.m_ClStatboardInfos & TC_STATS_BESTSPREE) + else if(Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) { px += 40; str_format(aBuf, sizeof(aBuf), "%d", pStats->m_BestSpree); @@ -407,7 +407,7 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && g_Config.m_ClStatboardInfos&TC_STATS_FLAGGRABS) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGGRABS) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_FlagGrabs); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); @@ -415,7 +415,7 @@ void CStats::OnRender() px += 100; } px -= 40; - if(g_Config.m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) { const float BarHeight = 0.3f*LineHeight; const float Offset = 40.0f; @@ -462,7 +462,7 @@ void CStats::OnRender() px += 10; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && g_Config.m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) { if(pStats->m_FlagCaptures <= 0) { diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index b5a7f280..c4398ca3 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -180,7 +180,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) if(pMsg->m_ClientID != -1) { char aLabel[64]; - CGameClient::GetPlayerLabel(aLabel, sizeof(aLabel), pMsg->m_ClientID, m_pClient->m_aClients[pMsg->m_ClientID].m_aName); + m_pClient->GetPlayerLabel(aLabel, sizeof(aLabel), pMsg->m_ClientID, m_pClient->m_aClients[pMsg->m_ClientID].m_aName); switch(pMsg->m_Type) { case VOTE_START_OP: @@ -191,20 +191,20 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) case VOTE_START_KICK: { char aName[4]; - if(!g_Config.m_ClShowsocial) + if(!Config()->Values()->m_ClShowsocial) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); - str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to kick '%s' (%s)"), aLabel, g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); - str_format(m_aDescription, sizeof(m_aDescription), "Kick '%s'", g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName); + str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to kick '%s' (%s)"), aLabel, Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); + str_format(m_aDescription, sizeof(m_aDescription), "Kick '%s'", Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName); m_pClient->m_pChat->AddLine(aBuf); break; } case VOTE_START_SPEC: { char aName[4]; - if(!g_Config.m_ClShowsocial) + if(!Config()->Values()->m_ClShowsocial) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); - str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to move '%s' to spectators (%s)"), aLabel, g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); - str_format(m_aDescription, sizeof(m_aDescription), "Move '%s' to spectators", g_Config.m_ClShowsocial ? pMsg->m_pDescription : aName); + str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to move '%s' to spectators (%s)"), aLabel, Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); + str_format(m_aDescription, sizeof(m_aDescription), "Move '%s' to spectators", Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName); m_pClient->m_pChat->AddLine(aBuf); } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index e21bb0c1..69c2fae0 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -131,8 +131,8 @@ const char *CGameClient::NetVersionHashUsed() const { return GAME_NETVERSION_HAS const char *CGameClient::NetVersionHashReal() const{ return GAME_NETVERSION_HASH; } int CGameClient::ClientVersion() const { return CLIENT_VERSION; } const char *CGameClient::GetItemName(int Type) const { return m_NetObjHandler.GetObjName(Type); } -bool CGameClient::IsXmas() const { return g_Config.m_ClShowXmasHats == 2 || (g_Config.m_ClShowXmasHats == 1 && m_IsXmasDay); } -bool CGameClient::IsEaster() const { return g_Config.m_ClShowEasterEggs == 2 || (g_Config.m_ClShowEasterEggs == 1 && m_IsEasterDay); } +bool CGameClient::IsXmas() const { return Config()->Values()->m_ClShowXmasHats == 2 || (Config()->Values()->m_ClShowXmasHats == 1 && m_IsXmasDay); } +bool CGameClient::IsEaster() const { return Config()->Values()->m_ClShowEasterEggs == 2 || (Config()->Values()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } enum { @@ -159,9 +159,9 @@ static int GetStrTeam(int Team, bool Teamplay) void CGameClient::GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName) { - if(!g_Config.m_ClShowsocial) + if(!Config()->Values()->m_ClShowsocial) str_format(aBuf, BufferSize, "%2d:", ClientID); - else if(g_Config.m_ClShowUserId) + else if(Config()->Values()->m_ClShowUserId) str_format(aBuf, BufferSize, "%2d: %s", ClientID, ClientName); else str_format(aBuf, BufferSize, "%s", ClientName); @@ -210,6 +210,7 @@ void CGameClient::OnConsoleInit() m_pTextRender = Kernel()->RequestInterface(); m_pSound = Kernel()->RequestInterface(); m_pInput = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); m_pDemoPlayer = Kernel()->RequestInterface(); @@ -338,14 +339,13 @@ void CGameClient::OnInit() m_pGraphics = Kernel()->RequestInterface(); // propagate pointers - m_UI.SetGraphics(Graphics(), TextRender()); - m_RenderTools.m_pGraphics = Graphics(); - m_RenderTools.m_pUI = UI(); + m_UI.Init(Config(), Graphics(), TextRender()); + m_RenderTools.Init(Config(), Graphics(), UI()); int64 Start = time_get(); // set the language - g_Localization.Load(g_Config.m_ClLanguagefile, Storage(), Console()); + g_Localization.Load(Config()->Values()->m_ClLanguagefile, Storage(), Console()); // TODO: this should be different // setup item sizes @@ -357,7 +357,7 @@ void CGameClient::OnInit() // load default font char aFontName[256]; - str_format(aFontName, sizeof(aFontName), "fonts/%s", g_Config.m_ClFontfile); + str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->Values()->m_ClFontfile); char aFilename[512]; IOHANDLE File = Storage()->OpenFile(aFontName, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); if(File) @@ -477,7 +477,7 @@ void CGameClient::OnReset() void CGameClient::UpdatePositions() { // local character position - if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -760,7 +760,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { if(m_LocalClientID != -1) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid local clientinfo"); return; } @@ -771,7 +771,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { if(m_aClients[pMsg->m_ClientID].m_Active) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientinfo"); return; } @@ -832,7 +832,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(m_LocalClientID == pMsg->m_ClientID || !m_aClients[pMsg->m_ClientID].m_Active) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop"); return; } @@ -863,7 +863,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(!m_aClients[pMsg->m_ClientID].m_Active) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid skin info"); return; } @@ -977,7 +977,7 @@ void CGameClient::OnEnterGame() {} void CGameClient::OnGameOver() { - if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClEditor == 0) + if(Client()->State() != IClient::STATE_DEMOPLAYBACK && Config()->Values()->m_ClEditor == 0) Client()->AutoScreenshot_Start(); } @@ -1088,7 +1088,7 @@ void CGameClient::OnNewSnapshot() const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID); @@ -1101,7 +1101,7 @@ void CGameClient::OnNewSnapshot() ProcessEvents(); - if(g_Config.m_DbgStress) + if(Config()->Values()->m_DbgStress) { if((Client()->GameTick()%100) == 0) { @@ -1536,7 +1536,7 @@ void CGameClient::OnPredict() m_PredictedChar = *World.m_apCharacters[m_LocalClientID]; } - if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick()) + if(Config()->Values()->m_Debug && Config()->Values()->m_ClPredict && m_PredictedTick == Client()->PredGameTick()) { CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; BeforeChar.Write(&Before); @@ -1744,9 +1744,9 @@ void CGameClient::SendSwitchTeam(int Team) void CGameClient::SendStartInfo() { CNetMsg_Cl_StartInfo Msg; - Msg.m_pName = g_Config.m_PlayerName; - Msg.m_pClan = g_Config.m_PlayerClan; - Msg.m_Country = g_Config.m_PlayerCountry; + Msg.m_pName = Config()->Values()->m_PlayerName; + Msg.m_pClan = Config()->Values()->m_PlayerClan; + Msg.m_Country = Config()->Values()->m_PlayerCountry; for(int p = 0; p < NUM_SKINPARTS; p++) { Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 4da2e3ad..533608ef 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -37,6 +37,7 @@ class CGameClient : public IGameClient class ITextRender *m_pTextRender; class IClient *m_pClient; class ISound *m_pSound; + class IConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; class IDemoPlayer *m_pDemoPlayer; @@ -80,6 +81,7 @@ class CGameClient : public IGameClient class ISound *Sound() const { return m_pSound; } class IInput *Input() const { return m_pInput; } class IStorage *Storage() const { return m_pStorage; } + class IConfig *Config() const { return m_pConfig; } class IConsole *Console() { return m_pConsole; } class ITextRender *TextRender() const { return m_pTextRender; } class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; } @@ -265,7 +267,7 @@ class CGameClient : public IGameClient virtual const char *NetVersionHashUsed() const; virtual const char *NetVersionHashReal() const; virtual int ClientVersion() const; - static void GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName); + void GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName); bool IsXmas() const; bool IsEaster() const; diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 4ed14aef..c6ae574b 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -16,6 +16,13 @@ static float gs_SpriteWScale; static float gs_SpriteHScale; +void CRenderTools::Init(IConfig *pConfig, IGraphics *pGraphics, CUI *pUI) +{ + m_pConfig = pConfig; + m_pGraphics = pGraphics; + m_pUI = pUI; +} + void CRenderTools::SelectSprite(CDataSprite *pSpr, int Flags, int sx, int sy) { int x = pSpr->m_X+sx; @@ -524,7 +531,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, const CTeeRenderInfo *pInfo, int } else { - bool Indicate = !pInfo->m_GotAirJump && g_Config.m_ClAirjumpindicator; + bool Indicate = !pInfo->m_GotAirJump && m_pConfig->Values()->m_ClAirjumpindicator; float cs = 1.0f; // color scale if(Indicate) cs = 0.5f; @@ -660,7 +667,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) void CRenderTools::DrawClientID(ITextRender* pTextRender, CTextCursor* pCursor, int ID, const vec4& BgColor, const vec4& TextColor) { - if(!g_Config.m_ClShowUserId) return; + if(!m_pConfig->Values()->m_ClShowUserId) return; char aBuff[4]; str_format(aBuff, sizeof(aBuff), "%2d ", ID); @@ -705,6 +712,6 @@ void CRenderTools::DrawClientID(ITextRender* pTextRender, CTextCursor* pCursor, float CRenderTools::GetClientIdRectSize(float FontSize) { - if(!g_Config.m_ClShowUserId) return 0; + if(!m_pConfig->Values()->m_ClShowUserId) return 0; return 1.4f * FontSize + 0.2f * FontSize; } diff --git a/src/game/client/render.h b/src/game/client/render.h index 3dad57c3..55d43646 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -51,13 +51,17 @@ class CRenderTools void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners); void DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners); -public: + + class IConfig *m_pConfig; class IGraphics *m_pGraphics; class CUI *m_pUI; +public: class IGraphics *Graphics() const { return m_pGraphics; } class CUI *UI() const { return m_pUI; } + void Init(class IConfig *pConfig, class IGraphics *pGraphics, class CUI *pUI); + void SelectSprite(struct CDataSprite *pSprite, int Flags=0, int sx=0, int sy=0); void SelectSprite(int id, int Flags=0, int sx=0, int sy=0); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 098da521..eca8d6fe 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -63,7 +63,7 @@ bool CUI::MouseInsideClip() const void CUI::ConvertMouseMove(float *x, float *y) const { - float Fac = (float)(g_Config.m_UiMousesens)/g_Config.m_InpMousesens; + float Fac = (float)(m_pConfig->Values()->m_UiMousesens)/m_pConfig->Values()->m_InpMousesens; *x = *x*Fac; *y = *y*Fac; } diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 76df69f0..655e1b44 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -44,12 +44,14 @@ class CUI unsigned m_NumClips; void UpdateClipping(); + class IConfig *m_pConfig; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; public: // TODO: Refactor: Fill this in - void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pGraphics = pGraphics; m_pTextRender = pTextRender;} + void Init(class IConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } + class IConfig *Config() const { return m_pConfig; } class IGraphics *Graphics() const { return m_pGraphics; } class ITextRender *TextRender() const { return m_pTextRender; } diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index c47f1a23..7dcd64c9 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -253,7 +253,7 @@ void CEditorImage::LoadAutoMapper() // clean up json_value_free(pJsonData); - if(m_pAutoMapper && g_Config.m_Debug) + if(m_pAutoMapper && m_pEditor->Config()->Values()->m_Debug) { str_format(aBuf, sizeof(aBuf),"loaded %s.json (%s)", m_aName, IAutoMapper::GetTypeName(m_pAutoMapper->GetType())); m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "editor", aBuf); @@ -666,18 +666,18 @@ void CEditor::RenderGrid(CLayerGroup *pGroup) for(int i = 0; i < (int)w; i++) { if((i+YGridOffset) % m_GridFactor == 0) - GridColor = HexToRgba(g_Config.m_EdColorGridOuter); + GridColor = HexToRgba(Config()->Values()->m_EdColorGridOuter); else - GridColor = HexToRgba(g_Config.m_EdColorGridInner); + GridColor = HexToRgba(Config()->Values()->m_EdColorGridInner); Graphics()->SetColor(GridColor.r, GridColor.g, GridColor.b, GridColor.a); IGraphics::CLineItem Line = IGraphics::CLineItem(LineDistance*XOffset, LineDistance*i+LineDistance*YOffset, w+aGroupPoints[2], LineDistance*i+LineDistance*YOffset); Graphics()->LinesDraw(&Line, 1); if((i+XGridOffset) % m_GridFactor == 0) - GridColor = HexToRgba(g_Config.m_EdColorGridOuter); + GridColor = HexToRgba(Config()->Values()->m_EdColorGridOuter); else - GridColor = HexToRgba(g_Config.m_EdColorGridInner); + GridColor = HexToRgba(Config()->Values()->m_EdColorGridInner); Graphics()->SetColor(GridColor.r, GridColor.g, GridColor.b, GridColor.a); Line = IGraphics::CLineItem(LineDistance*i+LineDistance*XOffset, LineDistance*YOffset, LineDistance*i+LineDistance*XOffset, h+aGroupPoints[3]); @@ -1301,13 +1301,13 @@ void CEditor::DoQuad(CQuad *q, int Index) } } - PivotColor = HexToRgba(g_Config.m_EdColorQuadPivotActive); + PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivotActive); } else if(UI()->HotItem() == pID) { ms_pUiGotContext = pID; - PivotColor = HexToRgba(g_Config.m_EdColorQuadPivotHover); + PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivotHover); m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. Hold alt to ignore grid."; if(UI()->MouseButton(0)) @@ -1345,7 +1345,7 @@ void CEditor::DoQuad(CQuad *q, int Index) } } else - PivotColor = HexToRgba(g_Config.m_EdColorQuadPivot); + PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivot); Graphics()->SetColor(PivotColor.r, PivotColor.g, PivotColor.b, PivotColor.a); IGraphics::CQuadItem QuadItem(CenterX, CenterY, 5.0f*m_WorldZoom, 5.0f*m_WorldZoom); @@ -1482,13 +1482,13 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) } } - pointColor = HexToRgba(g_Config.m_EdColorQuadPointActive); + pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPointActive); } else if(UI()->HotItem() == pID) { ms_pUiGotContext = pID; - pointColor = HexToRgba(g_Config.m_EdColorQuadPointHover); + pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPointHover); m_pTooltip = "Left mouse button to move. Hold shift to move the texture. Hold alt to ignore grid."; if(UI()->MouseButton(0)) @@ -1530,7 +1530,7 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) } } else - pointColor = HexToRgba(g_Config.m_EdColorQuadPoint); + pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPoint); Graphics()->SetColor(pointColor.r, pointColor.g, pointColor.b, pointColor.a); IGraphics::CQuadItem QuadItem(px, py, 5.0f*m_WorldZoom, 5.0f*m_WorldZoom); @@ -4260,7 +4260,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) pEditor->m_PopupEventActivated = true; } else - g_Config.m_ClEditor = 0; + pEditor->Config()->Values()->m_ClEditor = 0; return 1; } @@ -4294,7 +4294,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar) ExitButton.VSplitRight(13.f, 0, &ExitButton); if(DoButton_Editor(&s_ExitButton, "\xE2\x9C\x95", 1, &ExitButton, 0, "[ctrl+shift+e] Exit")) { - g_Config.m_ClEditor ^= 1; + Config()->Values()->m_ClEditor ^= 1; Input()->MouseModeRelative(); } } @@ -4368,7 +4368,7 @@ void CEditor::Render() { float OldLevel = m_ZoomLevel; m_ZoomLevel = clamp(m_ZoomLevel + Zoom * 20, 50, 2000); - if(g_Config.m_EdZoomTarget) + if(Config()->Values()->m_EdZoomTarget) ZoomMouseTarget((float)m_ZoomLevel / OldLevel); } } @@ -4441,7 +4441,7 @@ void CEditor::Render() RenderStatusbar(StatusBar); // todo: fix this - if(g_Config.m_EdShowkeys) + if(Config()->Values()->m_EdShowkeys) { Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); CTextCursor Cursor; @@ -4663,13 +4663,13 @@ void CEditor::Init() { m_pInput = Kernel()->RequestInterface(); m_pClient = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_pGraphics = Kernel()->RequestInterface(); m_pTextRender = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); - m_RenderTools.m_pGraphics = m_pGraphics; - m_RenderTools.m_pUI = &m_UI; - m_UI.SetGraphics(m_pGraphics, m_pTextRender); + m_RenderTools.Init(m_pConfig, m_pGraphics, &m_UI); + m_UI.Init(m_pConfig, m_pGraphics, m_pTextRender); m_Map.m_pEditor = this; m_CheckerTexture = Graphics()->LoadTexture("editor/checker.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index f7433677..c0e5dc64 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -502,6 +502,7 @@ class CEditor : public IEditor { class IInput *m_pInput; class IClient *m_pClient; + class IConfig *m_pConfig; class IConsole *m_pConsole; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; @@ -511,6 +512,7 @@ class CEditor : public IEditor public: class IInput *Input() { return m_pInput; }; class IClient *Client() { return m_pClient; }; + class IConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; }; class IGraphics *Graphics() { return m_pGraphics; }; class ITextRender *TextRender() { return m_pTextRender; }; diff --git a/src/game/editor/layer_quads.cpp b/src/game/editor/layer_quads.cpp index b2089d65..f60b902e 100644 --- a/src/game/editor/layer_quads.cpp +++ b/src/game/editor/layer_quads.cpp @@ -81,7 +81,7 @@ CQuad *CLayerQuads::NewQuad() void CLayerQuads::BrushSelecting(CUIRect Rect) { // draw selection rectangle - vec4 RectColor = HexToRgba(g_Config.m_EdColorSelectionQuad); + vec4 RectColor = HexToRgba(m_pEditor->Config()->Values()->m_EdColorSelectionQuad); IGraphics::CLineItem Array[4] = { IGraphics::CLineItem(Rect.x, Rect.y, Rect.x+Rect.w, Rect.y), IGraphics::CLineItem(Rect.x+Rect.w, Rect.y, Rect.x+Rect.w, Rect.y+Rect.h), diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 0c74dc51..7f560ae4 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -216,7 +216,7 @@ void CLayerTiles::Clamp(RECTi *pRect) void CLayerTiles::BrushSelecting(CUIRect Rect) { - vec4 FillColor = HexToRgba(g_Config.m_EdColorSelectionTile); + vec4 FillColor = HexToRgba(m_pEditor->Config()->Values()->m_EdColorSelectionTile); Graphics()->TextureClear(); m_pEditor->Graphics()->QuadsBegin(); diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index aebe3cc5..34f73515 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -795,7 +795,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) if(pEditor->DoButton_Editor(&s_OkButton, "Ok", 0, &Label, 0, 0)) { if(pEditor->m_PopupEventType == POPEVENT_EXIT) - g_Config.m_ClEditor = 0; + pEditor->Config()->Values()->m_ClEditor = 0; else if(pEditor->m_PopupEventType == POPEVENT_LOAD) pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", pEditor->CallbackOpenMap, pEditor); else if(pEditor->m_PopupEventType == POPEVENT_LOAD_CURRENT) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 4aa917a8..8da2865d 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -288,7 +288,7 @@ void CCharacter::FireWeapon() vec2 ProjStartPos = m_Pos+Direction*GetProximityRadius()*0.75f; - if(g_Config.m_Debug) + if(GameServer()->Config()->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "shot player='%d:%s' team=%d weapon=%d", m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), m_pPlayer->GetTeam(), m_ActiveWeapon); @@ -845,7 +845,7 @@ void CCharacter::Snap(int SnappingClient) pCharacter->m_Direction = m_Input.m_Direction; if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 || - (!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID())) + (!GameServer()->Config()->Values()->m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID())) { pCharacter->m_Health = m_Health; pCharacter->m_Armor = m_Armor; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 5d43101b..017baff4 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -264,19 +264,19 @@ void CGameContext::SendWeaponPickup(int ClientID, int Weapon) void CGameContext::SendMotd(int ClientID) { CNetMsg_Sv_Motd Msg; - Msg.m_pMessage = g_Config.m_SvMotd; + Msg.m_pMessage = Config()->Values()->m_SvMotd; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } void CGameContext::SendSettings(int ClientID) { CNetMsg_Sv_ServerSettings Msg; - Msg.m_KickVote = g_Config.m_SvVoteKick; - Msg.m_KickMin = g_Config.m_SvVoteKickMin; - Msg.m_SpecVote = g_Config.m_SvVoteSpectate; + Msg.m_KickVote = Config()->Values()->m_SvVoteKick; + Msg.m_KickMin = Config()->Values()->m_SvVoteKickMin; + Msg.m_SpecVote = Config()->Values()->m_SvVoteSpectate; Msg.m_TeamLock = m_LockTeams != 0; - Msg.m_TeamBalance = g_Config.m_SvTeambalanceTime != 0; - Msg.m_PlayerSlots = g_Config.m_SvPlayerSlots; + Msg.m_TeamBalance = Config()->Values()->m_SvTeambalanceTime != 0; + Msg.m_PlayerSlots = Config()->Values()->m_SvPlayerSlots; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } @@ -571,7 +571,7 @@ void CGameContext::OnClientDirectInput(int ClientID, void *pInput) int NumFailures = m_NetObjHandler.NumObjFailures(); if(m_NetObjHandler.ValidateObj(NETOBJTYPE_PLAYERINPUT, pInput, sizeof(CNetObj_PlayerInput)) == -1) { - if(g_Config.m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) + if(Config()->Values()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "NETOBJTYPE_PLAYERINPUT failed on '%s'", m_NetObjHandler.FailedObjOn()); @@ -589,7 +589,7 @@ void CGameContext::OnClientPredictedInput(int ClientID, void *pInput) int NumFailures = m_NetObjHandler.NumObjFailures(); if(m_NetObjHandler.ValidateObj(NETOBJTYPE_PLAYERINPUT, pInput, sizeof(CNetObj_PlayerInput)) == -1) { - if(g_Config.m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) + if(Config()->Values()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "NETOBJTYPE_PLAYERINPUT corrected on '%s'", m_NetObjHandler.FailedObjOn()); @@ -617,7 +617,7 @@ void CGameContext::OnClientEnter(int ClientID) NewClientInfoMsg.m_Country = Server()->ClientCountry(ClientID); NewClientInfoMsg.m_Silent = false; - if(g_Config.m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) + if(Config()->Values()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) NewClientInfoMsg.m_Silent = true; for(int p = 0; p < NUM_SKINPARTS; p++) @@ -727,7 +727,7 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason) Msg.m_ClientID = ClientID; Msg.m_pReason = pReason; Msg.m_Silent = false; - if(g_Config.m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) + if(Config()->Values()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) Msg.m_Silent = true; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, -1); } @@ -753,7 +753,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) if(!pRawMsg) { - if(g_Config.m_Debug) + if(Config()->Values()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgID), MsgID, m_NetObjHandler.FailedMsgOn()); @@ -766,7 +766,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { if(MsgID == NETMSGTYPE_CL_SAY) { - if(g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) + if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) return; CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg; @@ -798,14 +798,14 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) *(const_cast(pEnd)) = 0; // drop empty and autocreated spam messages (more than 20 characters per second) - if(Length == 0 || (g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat + Server()->TickSpeed()*(Length/20) > Server()->Tick())) + if(Length == 0 || (Config()->Values()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat + Server()->TickSpeed()*(Length/20) > Server()->Tick())) return; pPlayer->m_LastChat = Server()->Tick(); // don't allow spectators to disturb players during a running game in tournament mode int Mode = pMsg->m_Mode; - if((g_Config.m_SvTournamentMode == 2) && + if((Config()->Values()->m_SvTournamentMode == 2) && pPlayer->GetTeam() == TEAM_SPECTATORS && m_pController->IsGameRunning() && !Server()->IsAuthed(ClientID)) @@ -831,7 +831,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else { - if((g_Config.m_SvSpamprotection && ((pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry+Server()->TickSpeed()*3 > Now) || + if((Config()->Values()->m_SvSpamprotection && ((pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry+Server()->TickSpeed()*3 > Now) || (pPlayer->m_LastVoteCall && pPlayer->m_LastVoteCall+Server()->TickSpeed()*VOTE_COOLDOWN > Now))) || pPlayer->GetTeam() == TEAM_SPECTATORS || m_VoteCloseTime) return; @@ -880,7 +880,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else if(str_comp_nocase(pMsg->m_Type, "kick") == 0) { - if(!g_Config.m_SvVoteKick || m_pController->GetRealPlayerNum() < g_Config.m_SvVoteKickMin) + if(!Config()->Values()->m_SvVoteKick || m_pController->GetRealPlayerNum() < Config()->Values()->m_SvVoteKickMin) return; int KickID = str_toint(pMsg->m_Value); @@ -888,13 +888,13 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; str_format(aDesc, sizeof(aDesc), "%2d: %s", KickID, Server()->ClientName(KickID)); - if (!g_Config.m_SvVoteKickBantime) + if (!Config()->Values()->m_SvVoteKickBantime) str_format(aCmd, sizeof(aCmd), "kick %d Kicked by vote", KickID); else { char aAddrStr[NETADDR_MAXSTRSIZE] = {0}; Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr)); - str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, g_Config.m_SvVoteKickBantime); + str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, Config()->Values()->m_SvVoteKickBantime); } char aBuf[128]; str_format(aBuf, sizeof(aBuf), @@ -915,7 +915,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0) { - if(!g_Config.m_SvVoteSpectate) + if(!Config()->Values()->m_SvVoteSpectate) return; int SpectateID = str_toint(pMsg->m_Value); @@ -923,7 +923,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; str_format(aDesc, sizeof(aDesc), "%2d: %s", SpectateID, Server()->ClientName(SpectateID)); - str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, g_Config.m_SvVoteSpectateRejoindelay); + str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, Config()->Values()->m_SvVoteSpectateRejoindelay); char aBuf[128]; str_format(aBuf, sizeof(aBuf), "'%d:%s' voted %s '%d:%s' reason='%s' cmd='%s' force=%d", @@ -981,7 +981,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg; if(pPlayer->GetTeam() == pMsg->m_Team || - (g_Config.m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick()) || + (Config()->Values()->m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick()) || (pMsg->m_Team != TEAM_SPECTATORS && m_LockTeams) || pPlayer->m_TeamChangeTick > Server()->Tick()) return; @@ -1000,7 +1000,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg; - if(g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed() > Server()->Tick()) + if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed() > Server()->Tick()) return; pPlayer->m_LastSetSpectatorMode = Server()->Tick(); @@ -1011,7 +1011,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg; - if(g_Config.m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick()) + if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick()) return; pPlayer->m_LastEmote = Server()->Tick(); @@ -1476,6 +1476,7 @@ void CGameContext::ConchainGameinfoUpdate(IConsole::IResult *pResult, void *pUse void CGameContext::OnConsoleInit() { m_pServer = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); @@ -1504,6 +1505,7 @@ void CGameContext::OnInit() { // init everything m_pServer = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); m_World.SetGameServer(this); m_Events.SetGameServer(this); @@ -1518,15 +1520,15 @@ void CGameContext::OnInit() m_Collision.Init(&m_Layers); // select gametype - if(str_comp_nocase(g_Config.m_SvGametype, "mod") == 0) + if(str_comp_nocase(Config()->Values()->m_SvGametype, "mod") == 0) m_pController = new CGameControllerMOD(this); - else if(str_comp_nocase(g_Config.m_SvGametype, "ctf") == 0) + else if(str_comp_nocase(Config()->Values()->m_SvGametype, "ctf") == 0) m_pController = new CGameControllerCTF(this); - else if(str_comp_nocase(g_Config.m_SvGametype, "lms") == 0) + else if(str_comp_nocase(Config()->Values()->m_SvGametype, "lms") == 0) m_pController = new CGameControllerLMS(this); - else if(str_comp_nocase(g_Config.m_SvGametype, "lts") == 0) + else if(str_comp_nocase(Config()->Values()->m_SvGametype, "lts") == 0) m_pController = new CGameControllerLTS(this); - else if(str_comp_nocase(g_Config.m_SvGametype, "tdm") == 0) + else if(str_comp_nocase(Config()->Values()->m_SvGametype, "tdm") == 0) m_pController = new CGameControllerTDM(this); else m_pController = new CGameControllerDM(this); @@ -1562,16 +1564,16 @@ void CGameContext::OnInit() Console()->Chain("sv_matches_per_map", ConchainGameinfoUpdate, this); // clamp sv_player_slots to 0..MaxClients - if(g_Config.m_SvMaxClients < g_Config.m_SvPlayerSlots) - g_Config.m_SvPlayerSlots = g_Config.m_SvMaxClients; + if(Config()->Values()->m_SvMaxClients < Config()->Values()->m_SvPlayerSlots) + Config()->Values()->m_SvPlayerSlots = Config()->Values()->m_SvMaxClients; #ifdef CONF_DEBUG // clamp dbg_dummies to 0..MAX_CLIENTS-1 - if(MAX_CLIENTS <= g_Config.m_DbgDummies) - g_Config.m_DbgDummies = MAX_CLIENTS; - if(g_Config.m_DbgDummies) + if(MAX_CLIENTS <= Config()->Values()->m_DbgDummies) + Config()->Values()->m_DbgDummies = MAX_CLIENTS; + if(Config()->Values()->m_DbgDummies) { - for(int i = 0; i < g_Config.m_DbgDummies ; i++) + for(int i = 0; i < Config()->Values()->m_DbgDummies ; i++) OnClientConnected(MAX_CLIENTS -i-1, true, false); } #endif diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 6b9c7ed3..451c5633 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -36,6 +36,7 @@ class CGameContext : public IGameServer { IServer *m_pServer; + class IConfig *m_pConfig; class IConsole *m_pConsole; CLayers m_Layers; CCollision m_Collision; @@ -70,6 +71,7 @@ class CGameContext : public IGameServer bool m_Resetting; public: IServer *Server() const { return m_pServer; } + class IConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; } CCollision *Collision() { return &m_Collision; } CTuningParams *Tuning() { return &m_Tuning; } diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 139b65e3..aa3a5a71 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -30,8 +30,8 @@ IGameController::IGameController(CGameContext *pGameServer) m_SuddenDeath = 0; m_aTeamscore[TEAM_RED] = 0; m_aTeamscore[TEAM_BLUE] = 0; - if(g_Config.m_SvWarmup) - SetGameState(IGS_WARMUP_USER, g_Config.m_SvWarmup); + if(GameServer()->Config()->Values()->m_SvWarmup) + SetGameState(IGS_WARMUP_USER, GameServer()->Config()->Values()->m_SvWarmup); else SetGameState(IGS_WARMUP_GAME, TIMER_INFINITE); @@ -39,9 +39,9 @@ IGameController::IGameController(CGameContext *pGameServer) m_GameFlags = 0; m_pGameType = "unknown"; m_GameInfo.m_MatchCurrent = m_MatchCount+1; - m_GameInfo.m_MatchNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvMatchesPerMap) ? g_Config.m_SvMatchesPerMap : 0; - m_GameInfo.m_ScoreLimit = g_Config.m_SvScorelimit; - m_GameInfo.m_TimeLimit = g_Config.m_SvTimelimit; + m_GameInfo.m_MatchNum = (str_length(GameServer()->Config()->Values()->m_SvMaprotation) && GameServer()->Config()->Values()->m_SvMatchesPerMap) ? GameServer()->Config()->Values()->m_SvMatchesPerMap : 0; + m_GameInfo.m_ScoreLimit = GameServer()->Config()->Values()->m_SvScorelimit; + m_GameInfo.m_TimeLimit = GameServer()->Config()->Values()->m_SvTimelimit; // map m_aMapWish[0] = 0; @@ -58,22 +58,22 @@ IGameController::IGameController(CGameContext *pGameServer) //activity void IGameController::DoActivityCheck() { - if(g_Config.m_SvInactiveKickTime == 0) + if(GameServer()->Config()->Values()->m_SvInactiveKickTime == 0) return; for(int i = 0; i < MAX_CLIENTS; ++i) { - if(GameServer()->m_apPlayers[i] && !GameServer()->m_apPlayers[i]->IsDummy() && (GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS || g_Config.m_SvInactiveKick > 0) && - !Server()->IsAuthed(i) && (GameServer()->m_apPlayers[i]->m_InactivityTickCounter > g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60)) + if(GameServer()->m_apPlayers[i] && !GameServer()->m_apPlayers[i]->IsDummy() && (GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS || GameServer()->Config()->Values()->m_SvInactiveKick > 0) && + !Server()->IsAuthed(i) && (GameServer()->m_apPlayers[i]->m_InactivityTickCounter > GameServer()->Config()->Values()->m_SvInactiveKickTime*Server()->TickSpeed()*60)) { if(GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS) { - if(g_Config.m_SvInactiveKickSpec) + if(GameServer()->Config()->Values()->m_SvInactiveKickSpec) Server()->Kick(i, "Kicked for inactivity"); } else { - switch(g_Config.m_SvInactiveKick) + switch(GameServer()->Config()->Values()->m_SvInactiveKick) { case 1: { @@ -88,7 +88,7 @@ void IGameController::DoActivityCheck() for(int j = 0; j < MAX_CLIENTS; ++j) if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS) ++Spectators; - if(Spectators >= g_Config.m_SvMaxClients - g_Config.m_SvPlayerSlots) + if(Spectators >= GameServer()->Config()->Values()->m_SvMaxClients - GameServer()->Config()->Values()->m_SvPlayerSlots) Server()->Kick(i, "Kicked for inactivity"); else DoTeamChange(GameServer()->m_apPlayers[i], TEAM_SPECTATORS); @@ -135,7 +135,7 @@ bool IGameController::CanBeMovedOnBalance(int ClientID) const void IGameController::CheckTeamBalance() { - if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) + if(!IsTeamplay() || !GameServer()->Config()->Values()->m_SvTeambalanceTime) { m_UnbalancedTick = TBALANCE_OK; return; @@ -159,7 +159,7 @@ void IGameController::CheckTeamBalance() void IGameController::DoTeamBalance() { - if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS) + if(!IsTeamplay() || !GameServer()->Config()->Values()->m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS) return; GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); @@ -298,7 +298,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos) Type = PICKUP_LASER; break; case ENTITY_POWERUP_NINJA: - if(g_Config.m_SvPowerups) + if(GameServer()->Config()->Values()->m_SvPowerups) Type = PICKUP_NINJA; } @@ -353,7 +353,7 @@ void IGameController::OnPlayerInfoChange(CPlayer *pPlayer) void IGameController::OnPlayerReadyChange(CPlayer *pPlayer) { - if(g_Config.m_SvPlayerReadyMode && pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_DeadSpecMode) + if(GameServer()->Config()->Values()->m_SvPlayerReadyMode && pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_DeadSpecMode) { // change players ready state pPlayer->m_IsReadyToPlay ^= 1; @@ -371,7 +371,7 @@ void IGameController::OnPlayerReadyChange(CPlayer *pPlayer) // to be called when a player changes state, spectates or disconnects void IGameController::CheckReadyStates(int WithoutID) { - if(g_Config.m_SvPlayerReadyMode) + if(GameServer()->Config()->Values()->m_SvPlayerReadyMode) { switch(m_GameState) { @@ -524,7 +524,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) { m_GameState = GameState; m_GameStateTimer = TIMER_INFINITE; - if(g_Config.m_SvPlayerReadyMode) + if(GameServer()->Config()->Values()->m_SvPlayerReadyMode) { // run warmup till all players are ready SetPlayersReadyState(false); @@ -556,17 +556,17 @@ void IGameController::SetGameState(EGameState GameState, int Timer) // only possible when game, pause or start countdown is running if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_START_COUNTDOWN) { - if(g_Config.m_SvCountdown == 0 && m_GameFlags&GAMEFLAG_SURVIVAL) + if(GameServer()->Config()->Values()->m_SvCountdown == 0 && m_GameFlags&GAMEFLAG_SURVIVAL) { m_GameState = GameState; m_GameStateTimer = 3*Server()->TickSpeed(); GameServer()->m_World.m_Paused = true; } - else if(g_Config.m_SvCountdown > 0) + else if(GameServer()->Config()->Values()->m_SvCountdown > 0) { m_GameState = GameState; - m_GameStateTimer = g_Config.m_SvCountdown*Server()->TickSpeed(); + m_GameStateTimer = GameServer()->Config()->Values()->m_SvCountdown*Server()->TickSpeed(); GameServer()->m_World.m_Paused = true; } else @@ -773,7 +773,7 @@ void IGameController::Tick() if(m_MatchCount >= m_GameInfo.m_MatchNum-1) CycleMap(); - if(g_Config.m_SvMatchSwap) + if(GameServer()->Config()->Values()->m_SvMatchSwap) GameServer()->SwapTeams(); m_MatchCount++; StartMatch(); @@ -791,7 +791,7 @@ void IGameController::Tick() { case IGS_WARMUP_USER: // check if player ready mode was disabled and it waits that all players are ready -> end warmup - if(!g_Config.m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE) + if(!GameServer()->Config()->Values()->m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE) SetGameState(IGS_WARMUP_USER, 0); else if(m_GameStateTimer == 3 * Server()->TickSpeed()) StartMatch(); @@ -822,7 +822,7 @@ void IGameController::Tick() case TBALANCE_OK: break; default: - if(Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) + if(Server()->Tick() > m_UnbalancedTick+GameServer()->Config()->Values()->m_SvTeambalanceTime*Server()->TickSpeed()*60) DoTeamBalance(); } } @@ -843,15 +843,15 @@ void IGameController::Tick() // info void IGameController::CheckGameInfo() { - int MatchNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvMatchesPerMap) ? g_Config.m_SvMatchesPerMap : 0; + int MatchNum = (str_length(GameServer()->Config()->Values()->m_SvMaprotation) && GameServer()->Config()->Values()->m_SvMatchesPerMap) ? GameServer()->Config()->Values()->m_SvMatchesPerMap : 0; if(MatchNum == 0) m_MatchCount = 0; bool GameInfoChanged = (m_GameInfo.m_MatchCurrent != m_MatchCount + 1) || (m_GameInfo.m_MatchNum != MatchNum) || - (m_GameInfo.m_ScoreLimit != g_Config.m_SvScorelimit) || (m_GameInfo.m_TimeLimit != g_Config.m_SvTimelimit); + (m_GameInfo.m_ScoreLimit != GameServer()->Config()->Values()->m_SvScorelimit) || (m_GameInfo.m_TimeLimit != GameServer()->Config()->Values()->m_SvTimelimit); m_GameInfo.m_MatchCurrent = m_MatchCount + 1; m_GameInfo.m_MatchNum = MatchNum; - m_GameInfo.m_ScoreLimit = g_Config.m_SvScorelimit; - m_GameInfo.m_TimeLimit = g_Config.m_SvTimelimit; + m_GameInfo.m_ScoreLimit = GameServer()->Config()->Values()->m_SvScorelimit; + m_GameInfo.m_TimeLimit = GameServer()->Config()->Values()->m_SvTimelimit; if(GameInfoChanged) UpdateGameInfo(-1); } @@ -866,7 +866,7 @@ bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) const if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2]) return false; - if(!g_Config.m_SvTeamdamage && GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) + if(!GameServer()->Config()->Values()->m_SvTeamdamage && GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) return true; } @@ -875,12 +875,12 @@ bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) const bool IGameController::IsFriendlyTeamFire(int Team1, int Team2) const { - return IsTeamplay() && !g_Config.m_SvTeamdamage && Team1 == Team2; + return IsTeamplay() && !GameServer()->Config()->Values()->m_SvTeamdamage && Team1 == Team2; } bool IGameController::IsPlayerReadyMode() const { - return g_Config.m_SvPlayerReadyMode != 0 && (m_GameStateTimer == TIMER_INFINITE && (m_GameState == IGS_WARMUP_USER || m_GameState == IGS_GAME_PAUSED)); + return GameServer()->Config()->Values()->m_SvPlayerReadyMode != 0 && (m_GameStateTimer == TIMER_INFINITE && (m_GameState == IGS_WARMUP_USER || m_GameState == IGS_GAME_PAUSED)); } bool IGameController::IsTeamChangeAllowed() const @@ -944,17 +944,17 @@ void IGameController::CycleMap() char aBuf[256]; str_format(aBuf, sizeof(aBuf), "rotating map to %s", m_aMapWish); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap)); + str_copy(GameServer()->Config()->Values()->m_SvMap, m_aMapWish, sizeof(GameServer()->Config()->Values()->m_SvMap)); m_aMapWish[0] = 0; m_MatchCount = 0; return; } - if(!str_length(g_Config.m_SvMaprotation)) + if(!str_length(GameServer()->Config()->Values()->m_SvMaprotation)) return; // handle maprotation - const char *pMapRotation = g_Config.m_SvMaprotation; - const char *pCurrentMap = g_Config.m_SvMap; + const char *pMapRotation = GameServer()->Config()->Values()->m_SvMaprotation; + const char *pCurrentMap = GameServer()->Config()->Values()->m_SvMap; int CurrentMapLen = str_length(pCurrentMap); const char *pNextMap = pMapRotation; @@ -1003,7 +1003,7 @@ void IGameController::CycleMap() char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(g_Config.m_SvMap, &aBuf[i], sizeof(g_Config.m_SvMap)); + str_copy(GameServer()->Config()->Values()->m_SvMap, &aBuf[i], sizeof(GameServer()->Config()->Values()->m_SvMap)); } // spawn @@ -1110,7 +1110,7 @@ bool IGameController::GetStartRespawnState() const // team bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) const { - if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime) + if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !GameServer()->Config()->Values()->m_SvTeambalanceTime) return true; // simulate what would happen if the player changes team @@ -1130,7 +1130,7 @@ bool IGameController::CanJoinTeam(int Team, int NotThisID) const // check if there're enough player slots left int TeamMod = GameServer()->m_apPlayers[NotThisID] && GameServer()->m_apPlayers[NotThisID]->GetTeam() != TEAM_SPECTATORS ? -1 : 0; - return TeamMod+m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < g_Config.m_SvPlayerSlots; + return TeamMod+m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < GameServer()->Config()->Values()->m_SvPlayerSlots; } int IGameController::ClampTeam(int Team) const @@ -1192,19 +1192,19 @@ void IGameController::DoTeamChange(CPlayer *pPlayer, int Team, bool DoChatMsg) int IGameController::GetStartTeam() { - if(g_Config.m_SvTournamentMode) + if(GameServer()->Config()->Values()->m_SvTournamentMode) return TEAM_SPECTATORS; // determine new team int Team = TEAM_RED; if(IsTeamplay()) { - if(!g_Config.m_DbgStress) // this will force the auto balancer to work overtime aswell + if(!GameServer()->Config()->Values()->m_DbgStress) // this will force the auto balancer to work overtime aswell Team = m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED; } // check if there're enough player slots left - if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < g_Config.m_SvPlayerSlots) + if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < GameServer()->Config()->Values()->m_SvPlayerSlots) { ++m_aTeamSize[Team]; m_UnbalancedTick = TBALANCE_CHECK; diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp index 8a3fd3ca..f8cf6482 100644 --- a/src/game/server/gamemodes/tdm.cpp +++ b/src/game/server/gamemodes/tdm.cpp @@ -28,7 +28,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye m_aTeamscore[pKiller->GetTeam()&1]++; // good shit } - pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*g_Config.m_SvRespawnDelayTDM); + pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*GameServer()->Config()->Values()->m_SvRespawnDelayTDM); return 0; } diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 2395d65e..3f3fcae8 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -288,8 +288,7 @@ int main(int argc, const char **argv) // ignore_convention dbg_logger_stdout(); net_init(); - CNetBase::Init(); - + mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); int FlagMask = CFGFLAG_MASTER; @@ -297,6 +296,8 @@ int main(int argc, const char **argv) // ignore_convention IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); IConfig *pConfig = CreateConfig(); m_pConsole = CreateConsole(FlagMask); + + CNetBase::Init(pConfig); bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(m_pConsole); @@ -306,11 +307,12 @@ int main(int argc, const char **argv) // ignore_convention return -1; pConfig->Init(FlagMask); + m_pConsole->Init(); m_NetBan.Init(m_pConsole, pStorage); if(argc > 1) // ignore_convention m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention - if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(pConfig->Values()->m_Bindaddr[0] && net_host_lookup(pConfig->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index be14743f..a7da0bd7 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -2,6 +2,11 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include +#include +#include +#include +#include + #include #include @@ -74,13 +79,29 @@ void SendVer(NETADDR *pAddr, TOKEN ResponseToken) g_NetOp.Send(&p, ResponseToken); } -int main(int argc, char **argv) // ignore_convention +int main(int argc, const char **argv) // ignore_convention { NETADDR BindAddr; dbg_logger_stdout(); net_init(); - CNetBase::Init(); + + int FlagMask = 0; + IKernel *pKernel = IKernel::Create(); + IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); + IConfig *pConfig = CreateConfig(); + IConsole *pConsole = CreateConsole(FlagMask); + + CNetBase::Init(pConfig); + + bool RegisterFail = !pKernel->RegisterInterface(pStorage); + RegisterFail |= !pKernel->RegisterInterface(pConsole); + RegisterFail |= !pKernel->RegisterInterface(pConfig); + + if(RegisterFail) + return -1; + pConfig->Init(FlagMask); + pConsole->Init(); mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; From 6d836ac626245ad3dae1155e362735df0d6838ab Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 31 Jan 2020 22:14:50 +0100 Subject: [PATCH 134/479] fixed a warning --- src/engine/shared/config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 0160a6ef..e4c45a33 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -5,8 +5,9 @@ #include -struct CConfiguration +class CConfiguration { +public: #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name; #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Save,Desc) char m_##Name[Len]; // Flawfinder: ignore #include "config_variables.h" From 49500269a6bb421fc02212d608d0728b2c8e03d0 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 31 Jan 2020 22:34:41 +0100 Subject: [PATCH 135/479] fixed a clang error --- src/engine/client/serverbrowser_fav.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/serverbrowser_fav.h b/src/engine/client/serverbrowser_fav.h index fdd013a5..3b212a97 100644 --- a/src/engine/client/serverbrowser_fav.h +++ b/src/engine/client/serverbrowser_fav.h @@ -24,7 +24,7 @@ class CServerBrowserFavorites struct CFavoriteServer { char m_aHostname[128]; - char m_aPassword[sizeof(CConfiguration::m_Password)]; + char m_aPassword[32]; NETADDR m_Addr; int m_State; } m_aFavoriteServers[MAX_FAVORITES]; From 78076761ebaecb3b60e1ff733d30bed23028d77a Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 1 Feb 2020 19:56:57 +0100 Subject: [PATCH 136/479] Make the path for accessing config variables shorter Rename `CConfiguration` to `CConfig`, `CConfig` to `CConfigManager` and expose the actual config variables to more modules directly. --- src/engine/client/client.cpp | 143 +++--- src/engine/client/client.h | 6 +- src/engine/client/contacts.cpp | 24 +- src/engine/client/contacts.h | 6 +- src/engine/client/graphics_threaded.cpp | 46 +- src/engine/client/graphics_threaded.h | 2 +- src/engine/client/input.cpp | 28 +- src/engine/client/input.h | 2 +- src/engine/client/serverbrowser.cpp | 15 +- src/engine/client/serverbrowser.h | 4 +- src/engine/client/serverbrowser_fav.cpp | 14 +- src/engine/client/serverbrowser_fav.h | 6 +- src/engine/client/serverbrowser_filter.cpp | 24 +- src/engine/client/serverbrowser_filter.h | 8 +- src/engine/client/sound.cpp | 20 +- src/engine/client/sound.h | 2 +- src/engine/config.h | 8 +- src/engine/server/register.cpp | 12 +- src/engine/server/register.h | 4 +- src/engine/server/server.cpp | 110 ++--- src/engine/server/server.h | 6 +- src/engine/shared/config.cpp | 18 +- src/engine/shared/config.h | 10 +- src/engine/shared/console.cpp | 6 +- src/engine/shared/console.h | 2 +- src/engine/shared/econ.cpp | 22 +- src/engine/shared/econ.h | 4 +- src/engine/shared/engine.cpp | 12 +- src/engine/shared/network.cpp | 14 +- src/engine/shared/network.h | 6 +- src/engine/shared/network_conn.cpp | 12 +- src/game/client/component.h | 2 +- src/game/client/components/binds.cpp | 12 +- src/game/client/components/binds.h | 2 +- src/game/client/components/broadcast.cpp | 6 +- src/game/client/components/camera.cpp | 16 +- src/game/client/components/chat.cpp | 10 +- src/game/client/components/console.cpp | 4 +- src/game/client/components/controls.cpp | 12 +- src/game/client/components/countryflags.cpp | 4 +- src/game/client/components/debughud.cpp | 4 +- src/game/client/components/hud.cpp | 12 +- src/game/client/components/infomessages.cpp | 8 +- src/game/client/components/maplayers.cpp | 20 +- src/game/client/components/menus.cpp | 100 ++--- src/game/client/components/menus.h | 4 +- src/game/client/components/menus_browser.cpp | 96 ++-- src/game/client/components/menus_callback.cpp | 30 +- src/game/client/components/menus_demo.cpp | 6 +- src/game/client/components/menus_ingame.cpp | 24 +- src/game/client/components/menus_settings.cpp | 424 +++++++++--------- src/game/client/components/menus_start.cpp | 18 +- src/game/client/components/motd.cpp | 4 +- src/game/client/components/nameplates.cpp | 12 +- src/game/client/components/notifications.cpp | 6 +- src/game/client/components/players.cpp | 6 +- src/game/client/components/scoreboard.cpp | 8 +- src/game/client/components/skins.cpp | 40 +- src/game/client/components/sounds.cpp | 10 +- src/game/client/components/spectator.cpp | 2 +- src/game/client/components/stats.cpp | 54 +-- src/game/client/components/voting.cpp | 12 +- src/game/client/gameclient.cpp | 38 +- src/game/client/gameclient.h | 4 +- src/game/client/render.cpp | 8 +- src/game/client/render.h | 4 +- src/game/client/ui.cpp | 2 +- src/game/client/ui.h | 6 +- src/game/editor/editor.cpp | 32 +- src/game/editor/editor.h | 4 +- src/game/editor/layer_quads.cpp | 2 +- src/game/editor/layer_tiles.cpp | 2 +- src/game/editor/popups.cpp | 2 +- src/game/server/entities/character.cpp | 4 +- src/game/server/entity.h | 1 + src/game/server/gamecontext.cpp | 72 +-- src/game/server/gamecontext.h | 4 +- src/game/server/gamecontroller.cpp | 81 ++-- src/game/server/gamecontroller.h | 2 + src/game/server/gamemodes/tdm.cpp | 2 +- src/game/server/gameworld.cpp | 2 + src/game/server/gameworld.h | 2 + src/mastersrv/mastersrv.cpp | 9 +- src/versionsrv/versionsrv.cpp | 8 +- 84 files changed, 934 insertions(+), 921 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 88645160..277f7881 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -247,6 +247,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_pSound = 0; m_pGameClient = 0; m_pMap = 0; + m_pConfigManager = 0; m_pConfig = 0; m_pConsole = 0; @@ -343,7 +344,7 @@ void CClient::SendInfo() // restore password of favorite if possible const char *pPassword = m_ServerBrowser.GetFavoritePassword(m_aServerAddressStr); if(!pPassword) - pPassword = Config()->Values()->m_Password; + pPassword = Config()->m_Password; str_copy(m_aServerPassword, pPassword, sizeof(m_aServerPassword)); CMsgPacker Msg(NETMSG_INFO, true); @@ -454,7 +455,7 @@ void CClient::SetState(int s) return; int Old = m_State; - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "state change. last=%d current=%d", m_State, s); @@ -509,7 +510,7 @@ void CClient::OnClientOnline() // store password and server as favorite if configured, if the server was password protected CServerInfo Info = {0}; GetServerInfo(&Info); - bool ShouldStorePassword = Config()->Values()->m_ClSaveServerPasswords == 2 || (Config()->Values()->m_ClSaveServerPasswords == 1 && Info.m_Favorite); + bool ShouldStorePassword = Config()->m_ClSaveServerPasswords == 2 || (Config()->m_ClSaveServerPasswords == 1 && Info.m_Favorite); if(m_aServerPassword[0] && ShouldStorePassword && (Info.m_Flags&IServerBrowser::FLAG_PASSWORD)) { m_ServerBrowser.SetFavoritePassword(m_aServerAddressStr, m_aServerPassword); @@ -688,7 +689,7 @@ void CClient::DebugRender() int64 Now = time_get(); char aBuffer[512]; - if(!Config()->Values()->m_Debug) + if(!Config()->m_Debug) return; //m_pGraphics->BlendNormal(); @@ -755,7 +756,7 @@ void CClient::DebugRender() Graphics()->QuadsEnd(); // render graphs - if(Config()->Values()->m_DbgGraphs) + if(Config()->m_DbgGraphs) { //Graphics()->MapScreen(0,0,400.0f,300.0f); float w = Graphics()->ScreenWidth()/4.0f; @@ -787,7 +788,7 @@ const char *CClient::ErrorString() const void CClient::Render() { - if(Config()->Values()->m_GfxClear) + if(Config()->m_GfxClear) Graphics()->Clear(1,1,0); GameClient()->OnRender(); @@ -1195,7 +1196,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested first chunk package"); } } @@ -1241,7 +1242,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested next chunk package"); } } @@ -1409,7 +1410,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) { // couldn't find the delta snapshots that the server used // to compress this snapshot. force the server to resync - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot"); @@ -1448,7 +1449,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d", @@ -1716,7 +1717,7 @@ void CClient::Update() } // STRESS TEST: join the server again - if(Config()->Values()->m_DbgStress) + if(Config()->m_DbgStress) { static int64 ActionTaken = 0; int64 Now = time_get(); @@ -1725,13 +1726,13 @@ void CClient::Update() if(Now > ActionTaken+time_freq()*2) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "stress", "reconnecting!"); - Connect(Config()->Values()->m_DbgStressServer); + Connect(Config()->m_DbgStressServer); ActionTaken = Now; } } else { - if(Now > ActionTaken+time_freq()*(10+Config()->Values()->m_DbgStress)) + if(Now > ActionTaken+time_freq()*(10+Config()->m_DbgStress)) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "stress", "disconnecting!"); Disconnect(); @@ -1759,7 +1760,7 @@ void CClient::VersionUpdate() { if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT) { - Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, Config()->Values()->m_ClVersionServer, m_ContactClient.NetType()); + Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, Config()->m_ClVersionServer, m_ContactClient.NetType()); m_VersionInfo.m_State = CVersionInfo::STATE_START; } else if(m_VersionInfo.m_State == CVersionInfo::STATE_START) @@ -1809,7 +1810,8 @@ void CClient::InitInterfaces() m_pInput = Kernel()->RequestInterface(); m_pMap = Kernel()->RequestInterface(); m_pMasterServer = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfigManager = Kernel()->RequestInterface(); + m_pConfig = m_pConfigManager->Values(); m_pStorage = Kernel()->RequestInterface(); // @@ -1820,7 +1822,7 @@ void CClient::InitInterfaces() bool CClient::LimitFps() { - if(Config()->Values()->m_GfxVsync || !Config()->Values()->m_GfxLimitFps) return false; + if(Config()->m_GfxVsync || !Config()->m_GfxLimitFps) return false; /** If desired frame time is not reached: @@ -1846,7 +1848,7 @@ bool CClient::LimitFps() bool SkipFrame = true; double RenderDeltaTime = (Now - m_LastRenderTime) / (double)time_freq(); - const double DesiredTime = 1.0/Config()->Values()->m_GfxMaxFps; + const double DesiredTime = 1.0/Config()->m_GfxMaxFps; // we can't skip another frame, so wait instead if(SkipFrame && RenderDeltaTime < DesiredTime && @@ -1880,8 +1882,8 @@ bool CClient::LimitFps() DbgFramesSkippedCount += SkipFrame? 1:0; Now = time_get(); - if(Config()->Values()->m_GfxLimitFps && - Config()->Values()->m_Debug && + if(Config()->m_GfxLimitFps && + Config()->m_Debug && (Now - DbgLastSkippedDbgMsg) / (double)time_freq() > 5.0) { char aBuf[128]; @@ -1938,7 +1940,7 @@ void CClient::Run() // open socket { NETADDR BindAddr; - if(Config()->Values()->m_Bindaddr[0] && net_host_lookup(Config()->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(Config()->m_Bindaddr[0] && net_host_lookup(Config()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; @@ -1992,7 +1994,7 @@ void CClient::Run() m_FpsGraph.Init(0.0f, 120.0f); // never start with the editor - Config()->Values()->m_ClEditor = 0; + Config()->m_ClEditor = 0; // process pending commands m_pConsole->StoreCommands(false); @@ -2023,7 +2025,7 @@ void CClient::Run() Input()->MouseModeAbsolute(); m_WindowMustRefocus = 1; } - else if (Config()->Values()->m_DbgFocus && Input()->KeyPress(KEY_ESCAPE, true)) + else if (Config()->m_DbgFocus && Input()->KeyPress(KEY_ESCAPE, true)) { Input()->MouseModeAbsolute(); m_WindowMustRefocus = 1; @@ -2045,8 +2047,8 @@ void CClient::Run() // update screen in case it got moved int ActScreen = Graphics()->GetWindowScreen(); - if(ActScreen >= 0 && ActScreen != Config()->Values()->m_GfxScreen) - Config()->Values()->m_GfxScreen = ActScreen; + if(ActScreen >= 0 && ActScreen != Config()->m_GfxScreen) + Config()->m_GfxScreen = ActScreen; } } @@ -2060,20 +2062,20 @@ void CClient::Run() } if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_D, true)) - Config()->Values()->m_Debug ^= 1; + Config()->m_Debug ^= 1; if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_G, true)) - Config()->Values()->m_DbgGraphs ^= 1; + Config()->m_DbgGraphs ^= 1; if(IsCtrlPressed && IsLShiftPressed && Input()->KeyPress(KEY_E, true)) { - Config()->Values()->m_ClEditor = Config()->Values()->m_ClEditor^1; + Config()->m_ClEditor = Config()->m_ClEditor^1; Input()->MouseModeRelative(); } // render { - if(Config()->Values()->m_ClEditor) + if(Config()->m_ClEditor) { if(!m_EditorActive) { @@ -2089,7 +2091,7 @@ void CClient::Run() const bool SkipFrame = LimitFps(); - if(!SkipFrame && (!Config()->Values()->m_GfxAsyncRender || m_pGraphics->IsIdle())) + if(!SkipFrame && (!Config()->m_GfxAsyncRender || m_pGraphics->IsIdle())) { m_RenderFrames++; @@ -2106,7 +2108,7 @@ void CClient::Run() m_LastRenderTime = Now; // when we are stress testing only render every 10th frame - if(!Config()->Values()->m_DbgStress || (m_RenderFrames%10) == 0 ) + if(!Config()->m_DbgStress || (m_RenderFrames%10) == 0 ) { if(!m_EditorActive) Render(); @@ -2135,21 +2137,21 @@ void CClient::Run() } // beNice - if(Config()->Values()->m_ClCpuThrottle) - thread_sleep(Config()->Values()->m_ClCpuThrottle); - else if(Config()->Values()->m_DbgStress || !m_pGraphics->WindowActive()) + if(Config()->m_ClCpuThrottle) + thread_sleep(Config()->m_ClCpuThrottle); + else if(Config()->m_DbgStress || !m_pGraphics->WindowActive()) thread_sleep(5); - if(Config()->Values()->m_DbgHitch) + if(Config()->m_DbgHitch) { - thread_sleep(Config()->Values()->m_DbgHitch); - Config()->Values()->m_DbgHitch = 0; + thread_sleep(Config()->m_DbgHitch); + Config()->m_DbgHitch = 0; } /* if(ReportTime < time_get()) { - if(0 && Config()->Values()->m_Debug) + if(0 && Config()->m_Debug) { dbg_msg("client/report", "fps=%.02f (%.02f %.02f) netstate=%d", m_Frames/(float)(ReportInterval/time_freq()), @@ -2221,7 +2223,7 @@ void CClient::Con_Ping(IConsole::IResult *pResult, void *pUserData) void CClient::AutoScreenshot_Start() { - if(Config()->Values()->m_ClAutoScreenshot) + if(Config()->m_ClAutoScreenshot) { Graphics()->TakeScreenshot("auto/autoscreen"); m_AutoScreenshotRecycle = true; @@ -2230,7 +2232,7 @@ void CClient::AutoScreenshot_Start() void CClient::AutoStatScreenshot_Start() { - if(Config()->Values()->m_ClAutoStatScreenshot) + if(Config()->m_ClAutoStatScreenshot) { Graphics()->TakeScreenshot("auto/stat"); m_AutoStatScreenshotRecycle = true; @@ -2241,21 +2243,21 @@ void CClient::AutoScreenshot_Cleanup() { if(m_AutoScreenshotRecycle) { - if(Config()->Values()->m_ClAutoScreenshotMax) + if(Config()->m_ClAutoScreenshotMax) { // clean up auto taken screens CFileCollection AutoScreens; - AutoScreens.Init(Storage(), "screenshots/auto", "autoscreen", ".png", Config()->Values()->m_ClAutoScreenshotMax); + AutoScreens.Init(Storage(), "screenshots/auto", "autoscreen", ".png", Config()->m_ClAutoScreenshotMax); } m_AutoScreenshotRecycle = false; } if(m_AutoStatScreenshotRecycle) { - if(Config()->Values()->m_ClAutoScreenshotMax) + if(Config()->m_ClAutoScreenshotMax) { // clean up auto taken stat screens CFileCollection AutoScreens; - AutoScreens.Init(Storage(), "screenshots/auto", "stat", ".png", Config()->Values()->m_ClAutoScreenshotMax); + AutoScreens.Init(Storage(), "screenshots/auto", "stat", ".png", Config()->m_ClAutoScreenshotMax); } m_AutoStatScreenshotRecycle = false; } @@ -2359,15 +2361,15 @@ void CClient::DemoRecorder_Start(const char *pFilename, bool WithTimestamp) void CClient::DemoRecorder_HandleAutoStart() { - if(Config()->Values()->m_ClAutoDemoRecord) + if(Config()->m_ClAutoDemoRecord) { DemoRecorder_Stop(); DemoRecorder_Start("auto/autorecord", true); - if(Config()->Values()->m_ClAutoDemoMax) + if(Config()->m_ClAutoDemoMax) { // clean up auto recorded demos CFileCollection AutoDemos; - AutoDemos.Init(Storage(), "demos/auto", "autorecord", ".demo", Config()->Values()->m_ClAutoDemoMax); + AutoDemos.Init(Storage(), "demos/auto", "autorecord", ".demo", Config()->m_ClAutoDemoMax); } } } @@ -2418,17 +2420,17 @@ void CClient::ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUse void CClient::SwitchWindowScreen(int Index) { // Todo SDL: remove this when fixed (changing screen when in fullscreen is bugged) - if(Config()->Values()->m_GfxFullscreen) + if(Config()->m_GfxFullscreen) { ToggleFullscreen(); if(Graphics()->SetWindowScreen(Index)) - Config()->Values()->m_GfxScreen = Index; + Config()->m_GfxScreen = Index; ToggleFullscreen(); } else { if(Graphics()->SetWindowScreen(Index)) - Config()->Values()->m_GfxScreen = Index; + Config()->m_GfxScreen = Index; } } @@ -2437,7 +2439,7 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(pSelf->Config()->Values()->m_GfxScreen != pResult->GetInteger(0)) + if(pSelf->Config()->m_GfxScreen != pResult->GetInteger(0)) pSelf->SwitchWindowScreen(pResult->GetInteger(0)); } else @@ -2446,8 +2448,8 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, void CClient::ToggleFullscreen() { - if(Graphics()->Fullscreen(Config()->Values()->m_GfxFullscreen^1)) - Config()->Values()->m_GfxFullscreen ^= 1; + if(Graphics()->Fullscreen(Config()->m_GfxFullscreen^1)) + Config()->m_GfxFullscreen ^= 1; } void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2455,7 +2457,7 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(pSelf->Config()->Values()->m_GfxFullscreen != pResult->GetInteger(0)) + if(pSelf->Config()->m_GfxFullscreen != pResult->GetInteger(0)) pSelf->ToggleFullscreen(); } else @@ -2464,8 +2466,8 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC void CClient::ToggleWindowBordered() { - Config()->Values()->m_GfxBorderless ^= 1; - Graphics()->SetWindowBordered(!Config()->Values()->m_GfxBorderless); + Config()->m_GfxBorderless ^= 1; + Graphics()->SetWindowBordered(!Config()->m_GfxBorderless); } void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2473,7 +2475,7 @@ void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(!pSelf->Config()->Values()->m_GfxFullscreen && (pSelf->Config()->Values()->m_GfxBorderless != pResult->GetInteger(0))) + if(!pSelf->Config()->m_GfxFullscreen && (pSelf->Config()->m_GfxBorderless != pResult->GetInteger(0))) pSelf->ToggleWindowBordered(); } else @@ -2482,8 +2484,8 @@ void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData void CClient::ToggleWindowVSync() { - if(Graphics()->SetVSync(Config()->Values()->m_GfxVsync^1)) - Config()->Values()->m_GfxVsync ^= 1; + if(Graphics()->SetVSync(Config()->m_GfxVsync^1)) + Config()->m_GfxVsync ^= 1; } void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) @@ -2491,7 +2493,7 @@ void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, I CClient *pSelf = (CClient *)pUserData; if(pSelf->Graphics() && pResult->NumArguments()) { - if(pSelf->Config()->Values()->m_GfxVsync != pResult->GetInteger(0)) + if(pSelf->Config()->m_GfxVsync != pResult->GetInteger(0)) pSelf->ToggleWindowVSync(); } else @@ -2539,9 +2541,9 @@ void CClient::ConnectOnStart(const char *pAddress) void CClient::DoVersionSpecificActions() { - if(Config()->Values()->m_ClLastVersionPlayed <= 0x0703) - str_copy(Config()->Values()->m_ClMenuMap, "winter", sizeof(Config()->Values()->m_ClMenuMap)); - Config()->Values()->m_ClLastVersionPlayed = CLIENT_VERSION; + if(Config()->m_ClLastVersionPlayed <= 0x0703) + str_copy(Config()->m_ClMenuMap, "winter", sizeof(Config()->m_ClMenuMap)); + Config()->m_ClLastVersionPlayed = CLIENT_VERSION; } /* @@ -2600,7 +2602,7 @@ int main(int argc, const char **argv) // ignore_convention IEngine *pEngine = CreateEngine("Teeworlds"); IConsole *pConsole = CreateConsole(FlagMask); IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_CLIENT, argc, argv); // ignore_convention - IConfig *pConfig = CreateConfig(); + IConfigManager *pConfigManager = CreateConfigManager(); IEngineSound *pEngineSound = CreateEngineSound(); IEngineInput *pEngineInput = CreateEngineInput(); IEngineTextRender *pEngineTextRender = CreateEngineTextRender(); @@ -2612,7 +2614,7 @@ int main(int argc, const char **argv) // ignore_convention RegisterFail = RegisterFail || !pKernel->RegisterInterface(pEngine); RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole); - RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig); + RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfigManager); RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineSound)); // register as both RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineSound)); @@ -2638,7 +2640,7 @@ int main(int argc, const char **argv) // ignore_convention } pEngine->Init(); - pConfig->Init(FlagMask); + pConfigManager->Init(FlagMask); pConsole->Init(); pEngineMasterServer->Init(); pEngineMasterServer->Load(); @@ -2679,11 +2681,12 @@ int main(int argc, const char **argv) // ignore_convention } } #if defined(CONF_FAMILY_WINDOWS) + CConfig *pConfig = pConfigManager->Values(); bool HideConsole = false; #ifdef CONF_RELEASE - if(!(pConfig->Values()->m_ShowConsoleWindow&2)) + if(!(pConfig->m_ShowConsoleWindow&2)) #else - if(!(pConfig->Values()->m_ShowConsoleWindow&1)) + if(!(pConfig->m_ShowConsoleWindow&1)) #endif { HideConsole = true; @@ -2696,7 +2699,7 @@ int main(int argc, const char **argv) // ignore_convention pClient->DoVersionSpecificActions(); // restore empty config strings to their defaults - pConfig->RestoreStrings(); + pConfigManager->RestoreStrings(); pClient->Engine()->InitLogfile(); @@ -2705,7 +2708,7 @@ int main(int argc, const char **argv) // ignore_convention pClient->Run(); // write down the config and quit - pConfig->Save(); + pConfigManager->Save(); #if defined(CONF_FAMILY_WINDOWS) if(!HideConsole && !QuickEditMode) @@ -2717,7 +2720,7 @@ int main(int argc, const char **argv) // ignore_convention delete pEngine; delete pConsole; delete pStorage; - delete pConfig; + delete pConfigManager; delete pEngineSound; delete pEngineInput; delete pEngineTextRender; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 0725740e..ea6002bb 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -62,7 +62,8 @@ class CClient : public IClient, public CDemoPlayer::IListner IEngineSound *m_pSound; IGameClient *m_pGameClient; IEngineMap *m_pMap; - IConfig *m_pConfig; + IConfigManager *m_pConfigManager; + CConfig *m_pConfig; IConsole *m_pConsole; IStorage *m_pStorage; IEngineMasterServer *m_pMasterServer; @@ -200,7 +201,8 @@ class CClient : public IClient, public CDemoPlayer::IListner IEngineSound *Sound() { return m_pSound; } IGameClient *GameClient() { return m_pGameClient; } IEngineMasterServer *MasterServer() { return m_pMasterServer; } - IConfig *Config() { return m_pConfig; } + IConfigManager *ConfigManager() { return m_pConfigManager; } + CConfig *Config() { return m_pConfig; } IStorage *Storage() { return m_pStorage; } CClient(); diff --git a/src/engine/client/contacts.cpp b/src/engine/client/contacts.cpp index 99e37a22..f136402e 100644 --- a/src/engine/client/contacts.cpp +++ b/src/engine/client/contacts.cpp @@ -98,7 +98,7 @@ void IContactList::RemoveContact(int Index) return; } -void IContactList::ConfigSave(IConfig *pConfig, const char* pCmdStr) +void IContactList::ConfigSave(IConfigManager *pConfigManager, const char* pCmdStr) { char aBuf[128]; const char *pEnd = aBuf+sizeof(aBuf)-4; @@ -129,7 +129,7 @@ void IContactList::ConfigSave(IConfig *pConfig, const char* pCmdStr) *pDst++ = '"'; *pDst++ = 0; - pConfig->WriteLine(aBuf); + pConfigManager->WriteLine(aBuf); } } @@ -159,9 +159,9 @@ void CBlacklist::ConRemoveIgnore(IConsole::IResult *pResult, void *pUserData) void CFriends::Init() { - IConfig *pConfig = Kernel()->RequestInterface(); - if(pConfig) - pConfig->RegisterCallback(ConfigSaveCallback, this); + IConfigManager *pConfigManager = Kernel()->RequestInterface(); + if(pConfigManager) + pConfigManager->RegisterCallback(ConfigSaveCallback, this); IConsole *pConsole = Kernel()->RequestInterface(); if(pConsole) @@ -173,9 +173,9 @@ void CFriends::Init() void CBlacklist::Init() { - IConfig *pConfig = Kernel()->RequestInterface(); - if(pConfig) - pConfig->RegisterCallback(ConfigSaveCallback, this); + IConfigManager *pConfigManager = Kernel()->RequestInterface(); + if(pConfigManager) + pConfigManager->RegisterCallback(ConfigSaveCallback, this); IConsole *pConsole = Kernel()->RequestInterface(); if(pConsole) @@ -185,14 +185,14 @@ void CBlacklist::Init() } } -void CFriends::ConfigSaveCallback(IConfig *pConfig, void *pUserData) +void CFriends::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) { CFriends *pSelf = (CFriends *)pUserData; - pSelf->ConfigSave(pConfig, "add_friend "); + pSelf->ConfigSave(pConfigManager, "add_friend "); } -void CBlacklist::ConfigSaveCallback(IConfig *pConfig, void *pUserData) +void CBlacklist::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) { CBlacklist *pSelf = (CBlacklist *)pUserData; - pSelf->ConfigSave(pConfig, "add_ignore "); + pSelf->ConfigSave(pConfigManager, "add_ignore "); } diff --git a/src/engine/client/contacts.h b/src/engine/client/contacts.h index a495949e..d96d113a 100644 --- a/src/engine/client/contacts.h +++ b/src/engine/client/contacts.h @@ -16,7 +16,7 @@ class IContactList public: IContactList(); - void ConfigSave(IConfig *pConfig, const char* pCmdStr); + void ConfigSave(IConfigManager *pConfigManager, const char* pCmdStr); virtual void Init() = 0; @@ -33,7 +33,7 @@ class IContactList class CFriends: public IFriends, public IContactList { public: - static void ConfigSaveCallback(IConfig *pConfig, void *pUserData); + static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData); void Init(); @@ -52,7 +52,7 @@ class CFriends: public IFriends, public IContactList class CBlacklist: public IBlacklist, public IContactList { public: - static void ConfigSaveCallback(IConfig *pConfig, void *pUserData); + static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData); void Init(); diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 99807046..fa4f2b00 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -332,7 +332,7 @@ int CGraphics_Threaded::LoadTextureRawSub(CTextureHandle TextureID, int x, int y IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) { // don't waste memory on texture if we are stress testing - if(m_pConfig->Values()->m_DbgStress) + if(m_pConfig->m_DbgStress) return m_InvalidTexture; // grab texture @@ -353,9 +353,9 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig Cmd.m_Flags = CCommandBuffer::TEXFLAG_TEXTURE2D; if(Flags&IGraphics::TEXLOAD_NOMIPMAPS) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS; - if(m_pConfig->Values()->m_GfxTextureCompression) + if(m_pConfig->m_GfxTextureCompression) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_COMPRESSED; - if(m_pConfig->Values()->m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE) + if(m_pConfig->m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_QUALITY; if(Flags&IGraphics::TEXLOAD_ARRAY_256) { @@ -397,7 +397,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTexture(const char *pFilename, ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags); mem_free(Img.m_pData); - if(ID.Id() != m_InvalidTexture.Id() && m_pConfig->Values()->m_Debug) + if(ID.Id() != m_InvalidTexture.Id() && m_pConfig->m_Debug) dbg_msg("graphics/texture", "loaded %s", pFilename); return ID; } @@ -742,15 +742,15 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pTe int CGraphics_Threaded::IssueInit() { int Flags = 0; - if(m_pConfig->Values()->m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS; - if(m_pConfig->Values()->m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN; - if(m_pConfig->Values()->m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; - if(m_pConfig->Values()->m_GfxHighdpi) Flags |= IGraphicsBackend::INITFLAG_HIGHDPI; - if(m_pConfig->Values()->m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; - if(m_pConfig->Values()->m_GfxUseX11XRandRWM) Flags |= IGraphicsBackend::INITFLAG_X11XRANDR; - - return m_pBackend->Init("Teeworlds", &m_pConfig->Values()->m_GfxScreen, &m_pConfig->Values()->m_GfxScreenWidth, - &m_pConfig->Values()->m_GfxScreenHeight, &m_ScreenWidth, &m_ScreenHeight, m_pConfig->Values()->m_GfxFsaaSamples, + if(m_pConfig->m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS; + if(m_pConfig->m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN; + if(m_pConfig->m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; + if(m_pConfig->m_GfxHighdpi) Flags |= IGraphicsBackend::INITFLAG_HIGHDPI; + if(m_pConfig->m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; + if(m_pConfig->m_GfxUseX11XRandRWM) Flags |= IGraphicsBackend::INITFLAG_X11XRANDR; + + return m_pBackend->Init("Teeworlds", &m_pConfig->m_GfxScreen, &m_pConfig->m_GfxScreenWidth, + &m_pConfig->m_GfxScreenHeight, &m_ScreenWidth, &m_ScreenHeight, m_pConfig->m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight); } @@ -760,12 +760,12 @@ int CGraphics_Threaded::InitWindow() return 0; // try disabling fsaa - while(m_pConfig->Values()->m_GfxFsaaSamples) + while(m_pConfig->m_GfxFsaaSamples) { - m_pConfig->Values()->m_GfxFsaaSamples--; + m_pConfig->m_GfxFsaaSamples--; - if(m_pConfig->Values()->m_GfxFsaaSamples) - dbg_msg("gfx", "lowering FSAA to %d and trying again", m_pConfig->Values()->m_GfxFsaaSamples); + if(m_pConfig->m_GfxFsaaSamples) + dbg_msg("gfx", "lowering FSAA to %d and trying again", m_pConfig->m_GfxFsaaSamples); else dbg_msg("gfx", "disabling FSAA and trying again"); @@ -774,11 +774,11 @@ int CGraphics_Threaded::InitWindow() } // try lowering the resolution - if(m_pConfig->Values()->m_GfxScreenWidth != 640 || m_pConfig->Values()->m_GfxScreenHeight != 480) + if(m_pConfig->m_GfxScreenWidth != 640 || m_pConfig->m_GfxScreenHeight != 480) { dbg_msg("gfx", "setting resolution to 640x480 and trying again"); - m_pConfig->Values()->m_GfxScreenWidth = 640; - m_pConfig->Values()->m_GfxScreenHeight = 480; + m_pConfig->m_GfxScreenWidth = 640; + m_pConfig->m_GfxScreenHeight = 480; if(IssueInit() == 0) return 0; @@ -793,7 +793,7 @@ int CGraphics_Threaded::Init() { // fetch pointers m_pStorage = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); // init textures @@ -960,7 +960,7 @@ void CGraphics_Threaded::Swap() // add swap command CCommandBuffer::SCommand_Swap Cmd; - Cmd.m_Finish = m_pConfig->Values()->m_GfxFinish; + Cmd.m_Finish = m_pConfig->m_GfxFinish; m_pCommandBuffer->AddCommand(Cmd); // kick the command buffer @@ -1002,7 +1002,7 @@ void CGraphics_Threaded::WaitForIdle() int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) { - if(m_pConfig->Values()->m_GfxDisplayAllModes) + if(m_pConfig->m_GfxDisplayAllModes) { int Count = sizeof(g_aFakeModes)/sizeof(CVideoMode); mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes)); diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index c3ec70a3..4c1df7c0 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -360,7 +360,7 @@ class CGraphics_Threaded : public IEngineGraphics // class IStorage *m_pStorage; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; CCommandBuffer::SVertex m_aVertices[MAX_VERTICES]; diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index ee65249f..c75842ed 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -72,7 +72,7 @@ CInput::~CInput() void CInput::Init() { m_pGraphics = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); // FIXME: unicode handling: use SDL_StartTextInput/SDL_StopTextInput on inputs @@ -126,7 +126,7 @@ SDL_Joystick* CInput::GetActiveJoystick() { return NULL; } - if(m_aSelectedJoystickGUID[0] && str_comp(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID) != 0) + if(m_aSelectedJoystickGUID[0] && str_comp(m_aSelectedJoystickGUID, m_pConfig->m_JoystickGUID) != 0) { // Refresh if cached GUID differs from configured GUID m_SelectedJoystickIndex = -1; @@ -137,10 +137,10 @@ SDL_Joystick* CInput::GetActiveJoystick() { char aGUID[sizeof(m_aSelectedJoystickGUID)]; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[i]), aGUID, sizeof(aGUID)); - if(str_comp(m_pConfig->Values()->m_JoystickGUID, aGUID) == 0) + if(str_comp(m_pConfig->m_JoystickGUID, aGUID) == 0) { m_SelectedJoystickIndex = i; - str_copy(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + str_copy(m_aSelectedJoystickGUID, m_pConfig->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); break; } } @@ -148,8 +148,8 @@ SDL_Joystick* CInput::GetActiveJoystick() if(m_SelectedJoystickIndex == -1) { m_SelectedJoystickIndex = 0; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[0]), m_pConfig->Values()->m_JoystickGUID, sizeof(m_pConfig->Values()->m_JoystickGUID)); - str_copy(m_aSelectedJoystickGUID, m_pConfig->Values()->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[0]), m_pConfig->m_JoystickGUID, sizeof(m_pConfig->m_JoystickGUID)); + str_copy(m_aSelectedJoystickGUID, m_pConfig->m_JoystickGUID, sizeof(m_aSelectedJoystickGUID)); } } return m_apJoysticks[m_SelectedJoystickIndex]; @@ -173,7 +173,7 @@ void CInput::SelectNextJoystick() if(Num > 1) { const int NextIndex = (m_SelectedJoystickIndex + 1) % Num; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[NextIndex]), m_pConfig->Values()->m_JoystickGUID, sizeof(m_pConfig->Values()->m_JoystickGUID)); + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(m_apJoysticks[NextIndex]), m_pConfig->m_JoystickGUID, sizeof(m_pConfig->m_JoystickGUID)); } } @@ -204,27 +204,27 @@ void CInput::MouseRelative(float *x, float *y) return; int nx = 0, ny = 0; - float MouseSens = m_pConfig->Values()->m_InpMousesens/100.0f; - float JoystickSens = m_pConfig->Values()->m_JoystickSens/100.0f; + float MouseSens = m_pConfig->m_InpMousesens/100.0f; + float JoystickSens = m_pConfig->m_JoystickSens/100.0f; SDL_GetRelativeMouseState(&nx,&ny); vec2 j = vec2(0.0f, 0.0f); - if(m_pConfig->Values()->m_JoystickEnable && GetActiveJoystick()) + if(m_pConfig->m_JoystickEnable && GetActiveJoystick()) { const float Max = 50.0f; - j = vec2(GetJoystickAxisValue(m_pConfig->Values()->m_JoystickX), GetJoystickAxisValue(m_pConfig->Values()->m_JoystickY)) * Max; + j = vec2(GetJoystickAxisValue(m_pConfig->m_JoystickX), GetJoystickAxisValue(m_pConfig->m_JoystickY)) * Max; const float Len = length(j); - if(Len/sqrtf(2.0f) <= m_pConfig->Values()->m_JoystickTolerance) + if(Len/sqrtf(2.0f) <= m_pConfig->m_JoystickTolerance) { j = vec2(0.0f, 0.0f); } else { const vec2 nj = Len > 0.0f ? j / Len : vec2(0.0f, 0.0f); - j = nj * min(Len, Max) - nj * m_pConfig->Values()->m_JoystickTolerance; + j = nj * min(Len, Max) - nj * m_pConfig->m_JoystickTolerance; } } @@ -248,7 +248,7 @@ void CInput::MouseModeRelative() { m_InputGrabbed = 1; SDL_ShowCursor(SDL_DISABLE); - if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, m_pConfig->Values()->m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE) + if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, m_pConfig->m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "input", "unable to switch relative mouse mode"); } diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 9b98436a..09e19ef0 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -8,7 +8,7 @@ class CInput : public IEngineInput { IEngineGraphics *m_pGraphics; - IConfig *m_pConfig; + CConfig *m_pConfig; IConsole *m_pConsole; sorted_array m_apJoysticks; diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index ffc7b504..767045cd 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -79,13 +79,14 @@ CServerBrowser::CServerBrowser() void CServerBrowser::Init(class CNetClient *pNetClient, const char *pNetVersion) { - m_pConfig = Kernel()->RequestInterface(); + IConfigManager *pConfigManager = Kernel()->RequestInterface(); + m_pConfig = pConfigManager->Values(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); m_pMasterServer = Kernel()->RequestInterface(); m_pNetClient = pNetClient; - m_ServerBrowserFavorites.Init(pNetClient, m_pConsole, Kernel()->RequestInterface(), Config()); + m_ServerBrowserFavorites.Init(pNetClient, m_pConsole, Kernel()->RequestInterface(), pConfigManager); m_ServerBrowserFilter.Init(Config(), Kernel()->RequestInterface(), pNetVersion); } @@ -188,7 +189,7 @@ void CServerBrowser::Update(bool ForceResort) m_MasterRefreshTime = Now; - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "requesting server list"); } @@ -198,7 +199,7 @@ void CServerBrowser::Update(bool ForceResort) LoadServerlist(); m_MasterRefreshTime = 0; - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "using backup server list"); } @@ -229,7 +230,7 @@ void CServerBrowser::Update(bool ForceResort) break; // no more then 10 concurrent requests - if(Count == Config()->Values()->m_BrMaxRequests) + if(Count == Config()->m_BrMaxRequests) break; if(pEntry->m_RequestTime == 0) @@ -302,7 +303,7 @@ void CServerBrowser::Refresh(int RefreshFlags) m_pNetClient->Send(&Packet); } - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "broadcasting for servers"); } @@ -535,7 +536,7 @@ void CServerBrowser::CBFTrackPacket(int TrackID, void *pCallbackUser) void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true); diff --git a/src/engine/client/serverbrowser.h b/src/engine/client/serverbrowser.h index 5b595429..ed9fff44 100644 --- a/src/engine/client/serverbrowser.h +++ b/src/engine/client/serverbrowser.h @@ -59,7 +59,7 @@ class CServerBrowser : public IServerBrowser private: class CNetClient *m_pNetClient; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; class IMasterServer *m_pMasterServer; @@ -67,7 +67,7 @@ class CServerBrowser : public IServerBrowser class CServerBrowserFavorites m_ServerBrowserFavorites; class CServerBrowserFilter m_ServerBrowserFilter; - class IConfig *Config() const { return m_pConfig; } + class CConfig *Config() const { return m_pConfig; } class IConsole *Console() const { return m_pConsole; } class IStorage *Storage() const { return m_pStorage; } diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index 9de470f3..aeddd2a8 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -26,14 +26,14 @@ CServerBrowserFavorites::CServerBrowserFavorites() m_FavLookup.m_Active = false; } -void CServerBrowserFavorites::Init(CNetClient *pNetClient, IConsole *pConsole, IEngine *pEngine, IConfig *pConfig) +void CServerBrowserFavorites::Init(CNetClient *pNetClient, IConsole *pConsole, IEngine *pEngine, IConfigManager *pConfigManager) { m_pNetClient = pNetClient; - m_pConfig = pConfig; + m_pConfig = pConfigManager->Values(); m_pConsole = pConsole; m_pEngine = pEngine; - if(pConfig) - pConfig->RegisterCallback(ConfigSaveCallback, this); + if(pConfigManager) + pConfigManager->RegisterCallback(ConfigSaveCallback, this); m_pConsole->Register("add_favorite", "s?s", CFGFLAG_CLIENT, ConAddFavorite, this, "Add a server (optionally with password) as a favorite. Also updates password of existing favorite."); m_pConsole->Register("remove_favorite", "s", CFGFLAG_CLIENT, ConRemoveFavorite, this, "Remove a server from favorites"); @@ -92,7 +92,7 @@ bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR ++m_NumFavoriteServers; - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "added fav '%s'", pHostname); @@ -255,7 +255,7 @@ void CServerBrowserFavorites::ConRemoveFavorite(IConsole::IResult *pResult, void pSelf->RemoveFavoriteEx(pResult->GetString(0), 0); } -void CServerBrowserFavorites::ConfigSaveCallback(IConfig *pConfig, void *pUserData) +void CServerBrowserFavorites::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) { CServerBrowserFavorites *pSelf = (CServerBrowserFavorites *)pUserData; @@ -266,6 +266,6 @@ void CServerBrowserFavorites::ConfigSaveCallback(IConfig *pConfig, void *pUserDa str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\" \"%s\"", pSelf->m_aFavoriteServers[i].m_aHostname, pSelf->m_aFavoriteServers[i].m_aPassword); else str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\"", pSelf->m_aFavoriteServers[i].m_aHostname); - pConfig->WriteLine(aBuffer); + pConfigManager->WriteLine(aBuffer); } } diff --git a/src/engine/client/serverbrowser_fav.h b/src/engine/client/serverbrowser_fav.h index 3b212a97..a787d05d 100644 --- a/src/engine/client/serverbrowser_fav.h +++ b/src/engine/client/serverbrowser_fav.h @@ -40,12 +40,12 @@ class CServerBrowserFavorites } m_FavLookup; class CNetClient *m_pNetClient; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; class IEngine *m_pEngine; CServerBrowserFavorites(); - void Init(class CNetClient *pNetClient, class IConsole *pConsole, class IEngine *pEngine, class IConfig *pConfig); + void Init(class CNetClient *pNetClient, class IConsole *pConsole, class IEngine *pEngine, class IConfigManager *pConfigManager); bool AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck, const char *pPassword = 0); CFavoriteServer *FindFavoriteByAddr(const NETADDR &Addr, int *Index); @@ -56,7 +56,7 @@ class CServerBrowserFavorites static void ConAddFavorite(IConsole::IResult *pResult, void *pUserData); static void ConRemoveFavorite(IConsole::IResult *pResult, void *pUserData); - static void ConfigSaveCallback(IConfig *pConfig, void *pUserData); + static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData); }; #endif diff --git a/src/engine/client/serverbrowser_filter.cpp b/src/engine/client/serverbrowser_filter.cpp index 6df6bcce..1f1e69d1 100644 --- a/src/engine/client/serverbrowser_filter.cpp +++ b/src/engine/client/serverbrowser_filter.cpp @@ -19,7 +19,7 @@ class SortWrap CServerBrowserFilter::CServerFilter *m_pThis; public: SortWrap(CServerBrowserFilter::CServerFilter *t, SortFunc f) : m_pfnSort(f), m_pThis(t) {} - bool operator()(int a, int b) { return (m_pThis->Config()->Values()->m_BrSortOrder ? (m_pThis->*m_pfnSort)(b, a) : (m_pThis->*m_pfnSort)(a, b)); } + bool operator()(int a, int b) { return (m_pThis->Config()->m_BrSortOrder ? (m_pThis->*m_pfnSort)(b, a) : (m_pThis->*m_pfnSort)(a, b)); } }; // CServerFilter @@ -157,14 +157,14 @@ void CServerBrowserFilter::CServerFilter::Filter() } } - if(!Filtered && Config()->Values()->m_BrFilterString[0] != 0) + if(!Filtered && Config()->m_BrFilterString[0] != 0) { int MatchFound = 0; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit = 0; // match against server name - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aName, Config()->Values()->m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aName, Config()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_SERVERNAME; @@ -173,8 +173,8 @@ void CServerBrowserFilter::CServerFilter::Filter() // match against players for(int p = 0; p < m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients; p++) { - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, Config()->Values()->m_BrFilterString) || - str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, Config()->Values()->m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, Config()->m_BrFilterString) || + str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, Config()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYER; @@ -183,14 +183,14 @@ void CServerBrowserFilter::CServerFilter::Filter() } // match against map - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aMap, Config()->Values()->m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aMap, Config()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME; } // match against game type - if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, Config()->Values()->m_BrFilterString)) + if(str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, Config()->m_BrFilterString)) { MatchFound = 1; m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_GAMETYPE; @@ -223,8 +223,8 @@ void CServerBrowserFilter::CServerFilter::Filter() int CServerBrowserFilter::CServerFilter::GetSortHash() const { - int i = Config()->Values()->m_BrSort&0x7; - i |= Config()->Values()->m_BrSortOrder<<3; + int i = Config()->m_BrSort&0x7; + i |= Config()->m_BrSortOrder<<3; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) i |= 1<<4; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY) i |= 1<<5; if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL) i |= 1<<6; @@ -245,7 +245,7 @@ void CServerBrowserFilter::CServerFilter::Sort() Filter(); // sort - switch(Config()->Values()->m_BrSort) + switch(Config()->m_BrSort) { case IServerBrowser::SORT_NAME: std::stable_sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowserFilter::CServerFilter::SortCompareName)); @@ -336,7 +336,7 @@ bool CServerBrowserFilter::CServerFilter::SortCompareNumRealClients(int Index1, } // CServerBrowserFilter -void CServerBrowserFilter::Init(IConfig *pConfig, IFriends *pFriends, const char *pNetVersion) +void CServerBrowserFilter::Init(CConfig *pConfig, IFriends *pFriends, const char *pNetVersion) { m_pConfig = pConfig; m_pFriends = pFriends; @@ -414,4 +414,4 @@ void CServerBrowserFilter::SetFilter(int Index, const CServerFilterInfo *pFilter void CServerBrowserFilter::RemoveFilter(int Index) { m_lFilters.remove_index(Index); -} \ No newline at end of file +} diff --git a/src/engine/client/serverbrowser_filter.h b/src/engine/client/serverbrowser_filter.h index db7ebbb0..28633bae 100644 --- a/src/engine/client/serverbrowser_filter.h +++ b/src/engine/client/serverbrowser_filter.h @@ -18,7 +18,7 @@ class CServerBrowserFilter { public: CServerBrowserFilter *m_pServerBrowserFilter; - IConfig *Config() const { return m_pServerBrowserFilter->m_pConfig; } + CConfig *Config() const { return m_pServerBrowserFilter->m_pConfig; } // filter settings CServerFilterInfo m_FilterInfo; @@ -47,10 +47,10 @@ class CServerBrowserFilter bool SortCompareNumClients(int Index1, int Index2) const; bool SortCompareNumRealClients(int Index1, int Index2) const; }; - IConfig *Config() { return m_pConfig; } + CConfig *Config() { return m_pConfig; } // - void Init(class IConfig *pConfig, class IFriends *pFriends, const char *pNetVersion); + void Init(class CConfig *pConfig, class IFriends *pFriends, const char *pNetVersion); void Clear(); void Sort(class CServerEntry **ppServerlist, int NumServers, int ResortFlags); @@ -67,7 +67,7 @@ class CServerBrowserFilter int GetNumSortedPlayers(int FilterIndex) const { return m_lFilters[FilterIndex].m_NumSortedPlayers; } private: - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IFriends *m_pFriends; char m_aNetVersion[128]; array m_lFilters; diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 9cfe1044..39b1bb68 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -207,7 +207,7 @@ int CSound::Init() m_aChannels[i].m_Vol = 255; m_SoundEnabled = 0; - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pGraphics = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); @@ -215,7 +215,7 @@ int CSound::Init() m_SoundLock = lock_create(); - if(!m_pConfig->Values()->m_SndInit) + if(!m_pConfig->m_SndInit) return 0; if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) @@ -224,13 +224,13 @@ int CSound::Init() return -1; } - m_MixingRate = m_pConfig->Values()->m_SndRate; + m_MixingRate = m_pConfig->m_SndRate; // Set 16-bit stereo audio at 22Khz - Format.freq = m_pConfig->Values()->m_SndRate; // ignore_convention + Format.freq = m_pConfig->m_SndRate; // ignore_convention Format.format = AUDIO_S16; // ignore_convention Format.channels = 2; // ignore_convention - Format.samples = m_pConfig->Values()->m_SndBufferSize; // ignore_convention + Format.samples = m_pConfig->m_SndBufferSize; // ignore_convention Format.callback = SdlCallback; // ignore_convention Format.userdata = NULL; // ignore_convention @@ -243,7 +243,7 @@ int CSound::Init() else dbg_msg("client/sound", "sound init successful"); - m_MaxFrames = m_pConfig->Values()->m_SndBufferSize*2; + m_MaxFrames = m_pConfig->m_SndBufferSize*2; m_pMixBuffer = (int *)mem_alloc(m_MaxFrames*2*sizeof(int), 1); SDL_PauseAudio(0); @@ -256,9 +256,9 @@ int CSound::Init() int CSound::Update() { // update volume - int WantedVolume = m_pConfig->Values()->m_SndVolume; + int WantedVolume = m_pConfig->m_SndVolume; - if(!m_pGraphics->WindowActive() && m_pConfig->Values()->m_SndNonactiveMute) + if(!m_pGraphics->WindowActive() && m_pConfig->m_SndNonactiveMute) WantedVolume = 0; if(WantedVolume != m_SoundVolume) @@ -379,7 +379,7 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename) WavpackContext *pContext; // don't waste memory on sound when we are stress testing - if(m_pConfig->Values()->m_DbgStress) + if(m_pConfig->m_DbgStress) return CSampleHandle(); // no need to load sound when we are running with no sound @@ -483,7 +483,7 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename) io_close(s_File); s_File = NULL; - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("sound/wv", "loaded %s", pFilename); RateConvert(SampleID); diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index 31e5cadf..3c585c7d 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -10,7 +10,7 @@ class CSound : public IEngineSound int m_SoundEnabled; public: - IConfig *m_pConfig; + CConfig *m_pConfig; IEngineGraphics *m_pGraphics; IStorage *m_pStorage; diff --git a/src/engine/config.h b/src/engine/config.h index 89a5fea2..0e106abb 100644 --- a/src/engine/config.h +++ b/src/engine/config.h @@ -5,23 +5,23 @@ #include "kernel.h" -class IConfig : public IInterface +class IConfigManager : public IInterface { MACRO_INTERFACE("config", 0) public: - typedef void (*SAVECALLBACKFUNC)(IConfig *pConfig, void *pUserData); + typedef void (*SAVECALLBACKFUNC)(IConfigManager *pConfigManager, void *pUserData); virtual void Init(int FlagMask) = 0; virtual void Reset() = 0; virtual void RestoreStrings() = 0; virtual void Save(const char *pFilename=0) = 0; - virtual class CConfiguration *Values() = 0; + virtual class CConfig *Values() = 0; virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) = 0; virtual void WriteLine(const char *pLine) = 0; }; -extern IConfig *CreateConfig(); +extern IConfigManager *CreateConfigManager(); #endif diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index c90bff6b..6b6e9df9 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -46,7 +46,7 @@ void CRegister::RegisterSendFwcheckresponse(NETADDR *pAddr, TOKEN Token) void CRegister::RegisterSendHeartbeat(NETADDR Addr) { static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2]; - unsigned short Port = m_pConfig->Values()->m_SvPort; + unsigned short Port = m_pConfig->m_SvPort; CNetChunk Packet; mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)); @@ -58,8 +58,8 @@ void CRegister::RegisterSendHeartbeat(NETADDR Addr) Packet.m_pData = &aData; // supply the set port that the master can use if it has problems - if(m_pConfig->Values()->m_SvExternalPort) - Port = m_pConfig->Values()->m_SvExternalPort; + if(m_pConfig->m_SvExternalPort) + Port = m_pConfig->m_SvExternalPort; aData[sizeof(SERVERBROWSE_HEARTBEAT)] = Port >> 8; aData[sizeof(SERVERBROWSE_HEARTBEAT)+1] = Port&0xff; m_pNetServer->Send(&Packet); @@ -91,7 +91,7 @@ void CRegister::RegisterGotCount(CNetChunk *pChunk) } } -void CRegister::Init(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole) +void CRegister::Init(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, CConfig *pConfig, IConsole *pConsole) { m_pNetServer = pNetServer; m_pMasterServer = pMasterServer; @@ -104,7 +104,7 @@ void CRegister::RegisterUpdate(int Nettype) int64 Now = time_get(); int64 Freq = time_freq(); - if(!m_pConfig->Values()->m_SvRegister) + if(!m_pConfig->m_SvRegister) return; m_pMasterServer->Update(); @@ -276,7 +276,7 @@ int CRegister::RegisterProcessPacket(CNetChunk *pPacket, TOKEN Token) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "ERROR: the master server reports that clients can not connect to this server."); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "ERROR: configure your firewall/nat to let through udp on port %d.", m_pConfig->Values()->m_SvPort); + str_format(aBuf, sizeof(aBuf), "ERROR: configure your firewall/nat to let through udp on port %d.", m_pConfig->m_SvPort); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); RegisterNewState(REGISTERSTATE_ERROR); return 1; diff --git a/src/engine/server/register.h b/src/engine/server/register.h index 719b9ac4..eedfb18c 100644 --- a/src/engine/server/register.h +++ b/src/engine/server/register.h @@ -27,7 +27,7 @@ class CRegister class CNetServer *m_pNetServer; class IEngineMasterServer *m_pMasterServer; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; int m_RegisterState; @@ -46,7 +46,7 @@ class CRegister public: CRegister(); - void Init(class CNetServer *pNetServer, class IEngineMasterServer *pMasterServer, class IConfig *pConfig, class IConsole *pConsole); + void Init(class CNetServer *pNetServer, class IEngineMasterServer *pMasterServer, class CConfig *pConfig, class IConsole *pConsole); void RegisterUpdate(int Nettype); int RegisterProcessPacket(struct CNetChunk *pPacket, TOKEN Token); }; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 2a0d716f..a015a58d 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -486,7 +486,7 @@ void CServer::InitRconPasswordIfUnset() aRandomPassword[2 * i + 1] = VALUES[RandomNumber % NUM_VALUES]; } - str_copy(Config()->Values()->m_SvRconPassword, aRandomPassword, sizeof(Config()->Values()->m_SvRconPassword)); + str_copy(Config()->m_SvRconPassword, aRandomPassword, sizeof(Config()->m_SvRconPassword)); m_GeneratedRconPassword = 1; } @@ -847,7 +847,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC); - if(Config()->Values()->m_Password[0] != 0 && str_comp(Config()->Values()->m_Password, pPassword) != 0) + if(Config()->m_Password[0] != 0 && str_comp(Config()->m_Password, pPassword) != 0) { // wrong password m_NetServer.Drop(ClientID, "Wrong password"); @@ -885,7 +885,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID); - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize); @@ -1007,7 +1007,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0) { - if(Config()->Values()->m_SvRconPassword[0] == 0 && Config()->Values()->m_SvRconModPassword[0] == 0) + if(Config()->m_SvRconPassword[0] == 0 && Config()->m_SvRconModPassword[0] == 0) { if(!m_aClients[ClientID].m_NoRconNote) { @@ -1015,7 +1015,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) m_aClients[ClientID].m_NoRconNote = true; } } - else if(Config()->Values()->m_SvRconPassword[0] && str_comp(pPw, Config()->Values()->m_SvRconPassword) == 0) + else if(Config()->m_SvRconPassword[0] && str_comp(pPw, Config()->m_SvRconPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_ON, true); SendMsg(&Msg, MSGFLAG_VITAL, ClientID); @@ -1029,7 +1029,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } - else if(Config()->Values()->m_SvRconModPassword[0] && str_comp(pPw, Config()->Values()->m_SvRconModPassword) == 0) + else if(Config()->m_SvRconModPassword[0] && str_comp(pPw, Config()->m_SvRconModPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_ON, true); SendMsg(&Msg, MSGFLAG_VITAL, ClientID); @@ -1044,18 +1044,18 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } - else if(Config()->Values()->m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) + else if(Config()->m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) { m_aClients[ClientID].m_AuthTries++; char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, Config()->Values()->m_SvRconMaxTries); + str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, Config()->m_SvRconMaxTries); SendRconLine(ClientID, aBuf); - if(m_aClients[ClientID].m_AuthTries >= Config()->Values()->m_SvRconMaxTries) + if(m_aClients[ClientID].m_AuthTries >= Config()->m_SvRconMaxTries) { - if(!Config()->Values()->m_SvRconBantime) + if(!Config()->m_SvRconBantime) m_NetServer.Drop(ClientID, "Too many remote console authentication tries"); else - m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), Config()->Values()->m_SvRconBantime*60, "Too many remote console authentication tries"); + m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), Config()->m_SvRconBantime*60, "Too many remote console authentication tries"); } } else @@ -1071,7 +1071,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aHex[] = "0123456789ABCDEF"; char aBuf[512]; @@ -1122,8 +1122,8 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) } pPacker->AddString(GameServer()->Version(), 32); - pPacker->AddString(Config()->Values()->m_SvName, 64); - pPacker->AddString(Config()->Values()->m_SvHostname, 128); + pPacker->AddString(Config()->m_SvName, 64); + pPacker->AddString(Config()->m_SvHostname, 128); pPacker->AddString(GetMapName(), 32); // gametype @@ -1131,17 +1131,17 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) // flags int Flags = 0; - if(Config()->Values()->m_Password[0]) // password set + if(Config()->m_Password[0]) // password set Flags |= SERVERINFO_FLAG_PASSWORD; if(GameServer()->TimeScore()) Flags |= SERVERINFO_FLAG_TIMESCORE; pPacker->AddInt(Flags); - pPacker->AddInt(Config()->Values()->m_SvSkillLevel); // server skill level + pPacker->AddInt(Config()->m_SvSkillLevel); // server skill level pPacker->AddInt(PlayerCount); // num players - pPacker->AddInt(Config()->Values()->m_SvPlayerSlots); // max players + pPacker->AddInt(Config()->m_SvPlayerSlots); // max players pPacker->AddInt(ClientCount); // num clients - pPacker->AddInt(max(ClientCount, Config()->Values()->m_SvMaxClients)); // max clients + pPacker->AddInt(max(ClientCount, Config()->m_SvMaxClients)); // max clients if(Token != -1) { @@ -1223,11 +1223,11 @@ void CServer::PumpNetwork() const char *CServer::GetMapName() { // get the name of the map without his path - char *pMapShortName = &Config()->Values()->m_SvMap[0]; - for(int i = 0; i < str_length(Config()->Values()->m_SvMap)-1; i++) + char *pMapShortName = &Config()->m_SvMap[0]; + for(int i = 0; i < str_length(Config()->m_SvMap)-1; i++) { - if(Config()->Values()->m_SvMap[i] == '/' || Config()->Values()->m_SvMap[i] == '\\') - pMapShortName = &Config()->Values()->m_SvMap[i+1]; + if(Config()->m_SvMap[i] == '/' || Config()->m_SvMap[i] == '\\') + pMapShortName = &Config()->m_SvMap[i+1]; } return pMapShortName; } @@ -1279,7 +1279,7 @@ int CServer::LoadMap(const char *pMapName) return 1; } -void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole) +void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, CConfig *pConfig, IConsole *pConsole) { m_Register.Init(pNetServer, pMasterServer, pConfig, pConsole); } @@ -1287,7 +1287,7 @@ void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterS int CServer::Run() { // - m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->Values()->m_ConsoleOutputLevel, SendRconLineAuthed, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->m_ConsoleOutputLevel, SendRconLineAuthed, this); // list maps m_pMapListHeap = new CHeap(); @@ -1297,38 +1297,38 @@ int CServer::Run() m_pStorage->ListDirectory(IStorage::TYPE_ALL, "maps/", MapListEntryCallback, &Userdata); // load map - if(!LoadMap(Config()->Values()->m_SvMap)) + if(!LoadMap(Config()->m_SvMap)) { - dbg_msg("server", "failed to load map. mapname='%s'", Config()->Values()->m_SvMap); + dbg_msg("server", "failed to load map. mapname='%s'", Config()->m_SvMap); return -1; } - m_MapChunksPerRequest = Config()->Values()->m_SvMapDownloadSpeed; + m_MapChunksPerRequest = Config()->m_SvMapDownloadSpeed; // start server NETADDR BindAddr; - if(Config()->Values()->m_Bindaddr[0] && net_host_lookup(Config()->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(Config()->m_Bindaddr[0] && net_host_lookup(Config()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // sweet! BindAddr.type = NETTYPE_ALL; - BindAddr.port = Config()->Values()->m_SvPort; + BindAddr.port = Config()->m_SvPort; } else { mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; - BindAddr.port = Config()->Values()->m_SvPort; + BindAddr.port = Config()->m_SvPort; } - if(!m_NetServer.Open(BindAddr, &m_ServerBan, Config()->Values()->m_SvMaxClients, Config()->Values()->m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) + if(!m_NetServer.Open(BindAddr, &m_ServerBan, Config()->m_SvMaxClients, Config()->m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) { - dbg_msg("server", "couldn't open socket. port %d might already be in use", Config()->Values()->m_SvPort); + dbg_msg("server", "couldn't open socket. port %d might already be in use", Config()->m_SvPort); return -1; } m_Econ.Init(Config(), Console(), &m_ServerBan); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "server name is '%s'", Config()->Values()->m_SvName); + str_format(aBuf, sizeof(aBuf), "server name is '%s'", Config()->m_SvName); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); GameServer()->OnInit(); @@ -1345,7 +1345,7 @@ int CServer::Run() if(m_GeneratedRconPassword) { dbg_msg("server", "+-------------------------+"); - dbg_msg("server", "| rcon password: '%s' |", Config()->Values()->m_SvRconPassword); + dbg_msg("server", "| rcon password: '%s' |", Config()->m_SvRconPassword); dbg_msg("server", "+-------------------------+"); } @@ -1363,12 +1363,12 @@ int CServer::Run() int NewTicks = 0; // load new map TODO: don't poll this - if(str_comp(Config()->Values()->m_SvMap, m_aCurrentMap) != 0 || m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range + if(str_comp(Config()->m_SvMap, m_aCurrentMap) != 0 || m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range { m_MapReload = 0; // load map - if(LoadMap(Config()->Values()->m_SvMap)) + if(LoadMap(Config()->m_SvMap)) { // new map loaded bool aSpecs[MAX_CLIENTS]; @@ -1394,9 +1394,9 @@ int CServer::Run() } else { - str_format(aBuf, sizeof(aBuf), "failed to load map. mapname='%s'", Config()->Values()->m_SvMap); + str_format(aBuf, sizeof(aBuf), "failed to load map. mapname='%s'", Config()->m_SvMap); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - str_copy(Config()->Values()->m_SvMap, m_aCurrentMap, sizeof(Config()->Values()->m_SvMap)); + str_copy(Config()->m_SvMap, m_aCurrentMap, sizeof(Config()->m_SvMap)); } } @@ -1427,7 +1427,7 @@ int CServer::Run() // snap game if(NewTicks) { - if(Config()->Values()->m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) + if(Config()->m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) DoSnapshot(); UpdateClientRconCommands(); @@ -1441,7 +1441,7 @@ int CServer::Run() if(ReportTime < time_get()) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { /* static NETSTATS prev_stats; @@ -1578,7 +1578,7 @@ void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser) void CServer::DemoRecorder_HandleAutoStart() { - if(Config()->Values()->m_SvAutoDemoRecord) + if(Config()->m_SvAutoDemoRecord) { m_DemoRecorder.Stop(); char aFilename[128]; @@ -1586,11 +1586,11 @@ void CServer::DemoRecorder_HandleAutoStart() str_timestamp(aDate, sizeof(aDate)); str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", "auto/autorecord", aDate); m_DemoRecorder.Start(Storage(), m_pConsole, aFilename, GameServer()->NetVersion(), m_aCurrentMap, m_CurrentMapSha256, m_CurrentMapCrc, "server"); - if(Config()->Values()->m_SvAutoDemoMax) + if(Config()->m_SvAutoDemoMax) { // clean up auto recorded demos CFileCollection AutoDemos; - AutoDemos.Init(Storage(), "demos/server", "autorecord", ".demo", Config()->Values()->m_SvAutoDemoMax); + AutoDemos.Init(Storage(), "demos/server", "autorecord", ".demo", Config()->m_SvAutoDemoMax); } } } @@ -1652,7 +1652,7 @@ void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserD CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - str_clean_whitespaces(pSelf->Config()->Values()->m_SvName); + str_clean_whitespaces(pSelf->Config()->m_SvName); pSelf->SendServerInfo(-1); } } @@ -1663,8 +1663,8 @@ void CServer::ConchainPlayerSlotsUpdate(IConsole::IResult *pResult, void *pUserD CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - if(pSelf->Config()->Values()->m_SvMaxClients < pSelf->Config()->Values()->m_SvPlayerSlots) - pSelf->Config()->Values()->m_SvPlayerSlots = pSelf->Config()->Values()->m_SvMaxClients; + if(pSelf->Config()->m_SvMaxClients < pSelf->Config()->m_SvPlayerSlots) + pSelf->Config()->m_SvPlayerSlots = pSelf->Config()->m_SvMaxClients; } } @@ -1674,8 +1674,8 @@ void CServer::ConchainMaxclientsUpdate(IConsole::IResult *pResult, void *pUserDa CServer *pSelf = (CServer *)pUserData; if(pResult->NumArguments()) { - if(pSelf->Config()->Values()->m_SvMaxClients < pSelf->Config()->Values()->m_SvPlayerSlots) - pSelf->Config()->Values()->m_SvPlayerSlots = pSelf->Config()->Values()->m_SvMaxClients; + if(pSelf->Config()->m_SvMaxClients < pSelf->Config()->m_SvPlayerSlots) + pSelf->Config()->m_SvPlayerSlots = pSelf->Config()->m_SvMaxClients; pSelf->m_NetServer.SetMaxClients(pResult->GetInteger(0)); } } @@ -1737,7 +1737,7 @@ void CServer::ConchainRconPasswordSet(IConsole::IResult *pResult, void *pUserDat void CServer::RegisterCommands() { - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); m_pGameServer = Kernel()->RequestInterface(); m_pMap = Kernel()->RequestInterface(); @@ -1836,9 +1836,9 @@ int main(int argc, const char **argv) // ignore_convention IConsole *pConsole = CreateConsole(CFGFLAG_SERVER|CFGFLAG_ECON); IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer(); IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_SERVER, argc, argv); // ignore_convention - IConfig *pConfig = CreateConfig(); + IConfigManager *pConfigManager = CreateConfigManager(); - pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConfig, pConsole); + pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConfigManager->Values(), pConsole); { bool RegisterFail = false; @@ -1850,7 +1850,7 @@ int main(int argc, const char **argv) // ignore_convention RegisterFail = RegisterFail || !pKernel->RegisterInterface(pGameServer); RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole); RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage); - RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig); + RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfigManager); RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineMasterServer)); // register as both RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineMasterServer)); @@ -1859,7 +1859,7 @@ int main(int argc, const char **argv) // ignore_convention } pEngine->Init(); - pConfig->Init(FlagMask); + pConfigManager->Init(FlagMask); pConsole->Init(); pEngineMasterServer->Init(); pEngineMasterServer->Load(); @@ -1878,7 +1878,7 @@ int main(int argc, const char **argv) // ignore_convention } // restore empty config strings to their defaults - pConfig->RestoreStrings(); + pConfigManager->RestoreStrings(); pEngine->InitLogfile(); @@ -1897,7 +1897,7 @@ int main(int argc, const char **argv) // ignore_convention delete pConsole; delete pEngineMasterServer; delete pStorage; - delete pConfig; + delete pConfigManager; return Ret; } diff --git a/src/engine/server/server.h b/src/engine/server/server.h index b8dc7739..6bdb468d 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -62,12 +62,12 @@ class CServerBan : public CNetBan class CServer : public IServer { class IGameServer *m_pGameServer; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; public: class IGameServer *GameServer() { return m_pGameServer; } - class IConfig *Config() { return m_pConfig; } + class CConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; } class IStorage *Storage() { return m_pStorage; } @@ -256,7 +256,7 @@ class CServer : public IServer const char *GetMapName(); int LoadMap(const char *pMapName); - void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConfig *pConfig, IConsole *pConsole); + void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, CConfig *pConfig, IConsole *pConsole); int Run(); static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser); diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index 7969cc50..aedaa04b 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -29,10 +29,10 @@ static void Con_SaveConfig(IConsole::IResult *pResult, void *pUserData) str_timestamp(aDate, sizeof(aDate)); str_format(aFilename, sizeof(aFilename), "configs/config_%s.cfg", aDate); } - ((CConfig*)pUserData)->Save(aFilename); + ((CConfigManager *)pUserData)->Save(aFilename); } -CConfig::CConfig() +CConfigManager::CConfigManager() { m_pStorage = 0; m_pConsole = 0; @@ -41,7 +41,7 @@ CConfig::CConfig() m_NumCallbacks = 0; } -void CConfig::Init(int FlagMask) +void CConfigManager::Init(int FlagMask) { m_pStorage = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); @@ -52,7 +52,7 @@ void CConfig::Init(int FlagMask) m_pConsole->Register("save_config", "?s", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_SaveConfig, this, "Save config to file"); } -void CConfig::Reset() +void CConfigManager::Reset() { #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) m_Values.m_##Name = def; #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(m_Values.m_##Name, def, len); @@ -63,7 +63,7 @@ void CConfig::Reset() #undef MACRO_CONFIG_STR } -void CConfig::RestoreStrings() +void CConfigManager::RestoreStrings() { #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) // nop #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if(!m_Values.m_##Name[0] && def[0]) str_copy(m_Values.m_##Name, def, len); @@ -74,7 +74,7 @@ void CConfig::RestoreStrings() #undef MACRO_CONFIG_STR } -void CConfig::Save(const char *pFilename) +void CConfigManager::Save(const char *pFilename) { if(!m_pStorage) return; @@ -112,7 +112,7 @@ void CConfig::Save(const char *pFilename) } } -void CConfig::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) +void CConfigManager::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) { dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks"); m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc; @@ -120,7 +120,7 @@ void CConfig::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) m_NumCallbacks++; } -void CConfig::WriteLine(const char *pLine) +void CConfigManager::WriteLine(const char *pLine) { if(!m_ConfigFile) return; @@ -129,4 +129,4 @@ void CConfig::WriteLine(const char *pLine) io_write_newline(m_ConfigFile); } -IConfig *CreateConfig() { return new CConfig; } +IConfigManager *CreateConfigManager() { return new CConfigManager; } diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index e4c45a33..b2b70a84 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -5,7 +5,7 @@ #include -class CConfiguration +class CConfig { public: #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name; @@ -26,7 +26,7 @@ enum CFGFLAG_BASICACCESS=64, }; -class CConfig : public IConfig +class CConfigManager : public IConfigManager { enum { @@ -45,16 +45,16 @@ class CConfig : public IConfig int m_FlagMask; CCallback m_aCallbacks[MAX_CALLBACKS]; int m_NumCallbacks; - CConfiguration m_Values; + CConfig m_Values; public: - CConfig(); + CConfigManager(); virtual void Init(int FlagMask); virtual void Reset(); virtual void RestoreStrings(); virtual void Save(const char *pFilename); - virtual CConfiguration *Values() { return &m_Values; } + virtual CConfig *Values() { return &m_Values; } virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData); diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index c95d180b..f2be4a7f 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -712,19 +712,19 @@ CConsole::~CConsole() void CConsole::Init() { - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pStorage = Kernel()->RequestInterface(); // TODO: this should disappear #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ { \ - static CIntVariableData Data = { this, &m_pConfig->Values()->m_##Name, Min, Max }; \ + static CIntVariableData Data = { this, &m_pConfig->m_##Name, Min, Max }; \ Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \ } #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ { \ - static CStrVariableData Data = { this, m_pConfig->Values()->m_##Name, Len }; \ + static CStrVariableData Data = { this, m_pConfig->m_##Name, Len }; \ Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \ } diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index 3252130e..42c00025 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -47,7 +47,7 @@ class CConsole : public IConsole }; CExecFile *m_pFirstExec; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IStorage *m_pStorage; int m_AccessLevel; diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp index d14b5ae1..0aff8720 100644 --- a/src/engine/shared/econ.cpp +++ b/src/engine/shared/econ.cpp @@ -60,7 +60,7 @@ void CEcon::ConLogout(IConsole::IResult *pResult, void *pUserData) pThis->m_NetConsole.Drop(pThis->m_UserClientID, "Logout"); } -void CEcon::Init(IConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan) +void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan) { m_pConfig = pConfig; m_pConsole = pConsole; @@ -71,32 +71,32 @@ void CEcon::Init(IConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan) m_Ready = false; m_UserClientID = -1; - if(m_pConfig->Values()->m_EcPort == 0 || m_pConfig->Values()->m_EcPassword[0] == 0) + if(m_pConfig->m_EcPort == 0 || m_pConfig->m_EcPassword[0] == 0) return; NETADDR BindAddr; - if(m_pConfig->Values()->m_EcBindaddr[0] && net_host_lookup(m_pConfig->Values()->m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(m_pConfig->m_EcBindaddr[0] && net_host_lookup(m_pConfig->m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; - BindAddr.port = m_pConfig->Values()->m_EcPort; + BindAddr.port = m_pConfig->m_EcPort; } else { mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; - BindAddr.port = m_pConfig->Values()->m_EcPort; + BindAddr.port = m_pConfig->m_EcPort; } if(m_NetConsole.Open(BindAddr, pNetBan, NewClientCallback, DelClientCallback, this)) { m_Ready = true; char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "bound to %s:%d", m_pConfig->Values()->m_EcBindaddr, m_pConfig->Values()->m_EcPort); + str_format(aBuf, sizeof(aBuf), "bound to %s:%d", m_pConfig->m_EcBindaddr, m_pConfig->m_EcPort); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"econ", aBuf); Console()->Chain("ec_output_level", ConchainEconOutputLevelUpdate, this); - m_PrintCBIndex = Console()->RegisterPrintCallback(m_pConfig->Values()->m_EcOutputLevel, SendLineCB, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(m_pConfig->m_EcOutputLevel, SendLineCB, this); Console()->Register("logout", "", CFGFLAG_ECON, ConLogout, this, "Logout of econ"); } @@ -119,7 +119,7 @@ void CEcon::Update() dbg_assert(m_aClients[ClientID].m_State != CClient::STATE_EMPTY, "got message from empty slot"); if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTED) { - if(str_comp(aBuf, m_pConfig->Values()->m_EcPassword) == 0) + if(str_comp(aBuf, m_pConfig->m_EcPassword) == 0) { m_aClients[ClientID].m_State = CClient::STATE_AUTHED; m_NetConsole.Send(ClientID, "Authentication successful. External console access granted."); @@ -135,8 +135,8 @@ void CEcon::Update() m_NetConsole.Send(ClientID, aMsg); if(m_aClients[ClientID].m_AuthTries >= MAX_AUTH_TRIES) { - if(m_pConfig->Values()->m_EcBantime) - m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), m_pConfig->Values()->m_EcBantime*60, "Too many authentication tries"); + if(m_pConfig->m_EcBantime) + m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), m_pConfig->m_EcBantime*60, "Too many authentication tries"); m_NetConsole.Drop(ClientID, "Too many authentication tries"); } } @@ -155,7 +155,7 @@ void CEcon::Update() for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; ++i) { if(m_aClients[i].m_State == CClient::STATE_CONNECTED && - time_get() > m_aClients[i].m_TimeConnected + m_pConfig->Values()->m_EcAuthTimeout * time_freq()) + time_get() > m_aClients[i].m_TimeConnected + m_pConfig->m_EcAuthTimeout * time_freq()) m_NetConsole.Drop(i, "authentication timeout"); } } diff --git a/src/engine/shared/econ.h b/src/engine/shared/econ.h index 68445cea..ba66c2dd 100644 --- a/src/engine/shared/econ.h +++ b/src/engine/shared/econ.h @@ -27,7 +27,7 @@ class CEcon }; CClient m_aClients[NET_MAX_CONSOLE_CLIENTS]; - IConfig *m_pConfig; + CConfig *m_pConfig; IConsole *m_pConsole; CNetConsole m_NetConsole; @@ -45,7 +45,7 @@ class CEcon public: IConsole *Console() { return m_pConsole; } - void Init(IConfig *pConfig, IConsole *pConsole, class CNetBan *pNetBan); + void Init(CConfig *pConfig, IConsole *pConsole, class CNetBan *pNetBan); void Update(); void Send(int ClientID, const char *pLine); void Shutdown(); diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index f72d5466..1a5261f5 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -20,7 +20,7 @@ static int HostLookupThread(void *pUser) class CEngine : public IEngine { public: - IConfig *m_pConfig; + CConfig *m_pConfig; IConsole *m_pConsole; IStorage *m_pStorage; bool m_Logging; @@ -73,7 +73,7 @@ class CEngine : public IEngine void Init() { - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); @@ -88,15 +88,15 @@ class CEngine : public IEngine void InitLogfile() { // open logfile if needed - if(m_pConfig->Values()->m_Logfile[0]) + if(m_pConfig->m_Logfile[0]) { char aBuf[32]; - if(m_pConfig->Values()->m_LogfileTimestamp) + if(m_pConfig->m_LogfileTimestamp) str_timestamp(aBuf, sizeof(aBuf)); else aBuf[0] = 0; char aLogFilename[128]; - str_format(aLogFilename, sizeof(aLogFilename), "dumps/%s%s.txt", m_pConfig->Values()->m_Logfile, aBuf); + str_format(aLogFilename, sizeof(aLogFilename), "dumps/%s%s.txt", m_pConfig->m_Logfile, aBuf); IOHANDLE Handle = m_pStorage->OpenFile(aLogFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(Handle) dbg_logger_filehandle(Handle); @@ -114,7 +114,7 @@ class CEngine : public IEngine void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData) { - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("engine", "job added"); m_JobPool.Add(pJob, pfnFunc, pData); } diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 3a41a906..e769d1e5 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -70,7 +70,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) continue; // out of sequence, request resend - if(CNetBase::Config()->Values()->m_Debug) + if(CNetBase::Config()->m_Debug) dbg_msg("conn", "asking for resend %d %d", Header.m_Sequence, (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE); m_pConnection->SignalResend(); continue; // take the next chunk in the packet @@ -195,7 +195,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct // check the size if(Size < NET_PACKETHEADERSIZE || Size > NET_MAX_PACKETSIZE) { - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("network", "packet too small, size=%d", Size); return -1; } @@ -208,7 +208,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct { if(Size < NET_PACKETHEADERSIZE_CONNLESS) { - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("net", "connless packet too small, size=%d", Size); return -1; } @@ -233,7 +233,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct { if(Size - NET_PACKETHEADERSIZE > NET_MAX_PAYLOAD) { - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("network", "packet payload too big, size=%d", Size); return -1; } @@ -257,7 +257,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct // check for errors if(pPacket->m_DataSize < 0) { - if(m_pConfig->Values()->m_Debug) + if(m_pConfig->m_Debug) dbg_msg("network", "error during packet decoding"); return -1; } @@ -369,7 +369,7 @@ int CNetBase::IsSeqInBackroom(int Seq, int Ack) IOHANDLE CNetBase::ms_DataLogSent = 0; IOHANDLE CNetBase::ms_DataLogRecv = 0; CHuffman CNetBase::ms_Huffman; -IConfig *CNetBase::m_pConfig = 0; // todo: fix me +CConfig *CNetBase::m_pConfig = 0; // todo: fix me void CNetBase::OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv) { @@ -433,7 +433,7 @@ static const unsigned gs_aFreqTable[256+1] = { 12,18,18,27,20,18,15,19,11,17,33,12,18,15,19,18,16,26,17,18, 9,10,25,22,22,17,20,16,6,16,15,20,14,18,24,335,1517}; -void CNetBase::Init(IConfig *pConfig) +void CNetBase::Init(CConfig *pConfig) { m_pConfig = pConfig; ms_Huffman.Init(gs_aFreqTable); diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index e101c9ec..43bcc014 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -531,15 +531,15 @@ class CNetClient // TODO: both, fix these. This feels like a junk class for stuff that doesn't fit anywere class CNetBase { - static class IConfig *m_pConfig; + static class CConfig *m_pConfig; static IOHANDLE ms_DataLogSent; static IOHANDLE ms_DataLogRecv; static CHuffman ms_Huffman; public: - static IConfig *Config() { return m_pConfig; } + static CConfig *Config() { return m_pConfig; } static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv); static void CloseLog(); - static void Init(class IConfig *pConfig); + static void Init(class CConfig *pConfig); static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize); static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize); diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index 2697443f..8519b937 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -286,7 +286,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SetError(Str); } - if(CNetBase::Config()->Values()->m_Debug) + if(CNetBase::Config()->m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; @@ -304,7 +304,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SendControlWithToken(NET_CTRLMSG_CONNECT); dbg_msg("connection", "got token, replying, token=%x mytoken=%x", m_PeerToken, m_Token); } - else if(CNetBase::Config()->Values()->m_Debug) + else if(CNetBase::Config()->m_Debug) dbg_msg("connection", "got token, token=%x", m_PeerToken); } else @@ -325,7 +325,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); - if(CNetBase::Config()->Values()->m_Debug) + if(CNetBase::Config()->m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } @@ -337,7 +337,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; - if(CNetBase::Config()->Values()->m_Debug) + if(CNetBase::Config()->m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } @@ -350,7 +350,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; - if(CNetBase::Config()->Values()->m_Debug) + if(CNetBase::Config()->m_Debug) dbg_msg("connection", "connecting online"); } } @@ -410,7 +410,7 @@ int CNetConnection::Update() if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed { int NumFlushedChunks = Flush(); - if(NumFlushedChunks && CNetBase::Config()->Values()->m_Debug) + if(NumFlushedChunks && CNetBase::Config()->m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } diff --git a/src/game/client/component.h b/src/game/client/component.h index cbd0fb6f..071d3501 100644 --- a/src/game/client/component.h +++ b/src/game/client/component.h @@ -23,7 +23,7 @@ class CComponent class CUI *UI() const { return m_pClient->UI(); } class ISound *Sound() const { return m_pClient->Sound(); } class CRenderTools *RenderTools() const { return m_pClient->RenderTools(); } - class IConfig *Config() const { return m_pClient->Config(); } + class CConfig *Config() const { return m_pClient->Config(); } class IConsole *Console() const { return m_pClient->Console(); } class IDemoPlayer *DemoPlayer() const { return m_pClient->DemoPlayer(); } class IDemoRecorder *DemoRecorder() const { return m_pClient->DemoRecorder(); } diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 4782ea43..cea50b34 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -264,9 +264,9 @@ void CBinds::SetDefaults() void CBinds::OnConsoleInit() { // bindings - IConfig *pConfig = Kernel()->RequestInterface(); - if(pConfig) - pConfig->RegisterCallback(ConfigSaveCallback, this); + IConfigManager *pConfigManager = Kernel()->RequestInterface(); + if(pConfigManager) + pConfigManager->RegisterCallback(ConfigSaveCallback, this); Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); @@ -398,7 +398,7 @@ const char *CBinds::GetModifierName(int m) } } -void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) +void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) { CBinds *pSelf = (CBinds *)pUserData; @@ -426,7 +426,7 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) *pDst++ = '"'; *pDst++ = 0; - pConfig->WriteLine(aBuffer); + pConfigManager->WriteLine(aBuffer); } } @@ -438,7 +438,7 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) { // explicitly unbind keys that were unbound by the user str_format(aBuffer, sizeof(aBuffer), "unbind %s%s ", GetModifierName(Modifier), pSelf->Input()->KeyName(Key)); - pConfig->WriteLine(aBuffer); + pConfigManager->WriteLine(aBuffer); } } } diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index df7a27b8..fc30ee5c 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -15,7 +15,7 @@ class CBinds : public CComponent static void ConDumpBinds(IConsole::IResult *pResult, void *pUserData); class IConsole *GetConsole() const { return Console(); } - static void ConfigSaveCallback(class IConfig *pConfig, void *pUserData); + static void ConfigSaveCallback(class IConfigManager *pConfigManager, void *pUserData); public: CBinds(); diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index aacf83b3..d9dc1c78 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -41,10 +41,10 @@ inline bool IsCharWhitespace(char c) void CBroadcast::RenderServerBroadcast() { - if(!Config()->Values()->m_ClShowServerBroadcast || m_pClient->m_MuteServerBroadcast) + if(!Config()->m_ClShowServerBroadcast || m_pClient->m_MuteServerBroadcast) return; - const bool ColoredBroadcastEnabled = Config()->Values()->m_ClColoredBroadcast; + const bool ColoredBroadcastEnabled = Config()->m_ClColoredBroadcast; const float Height = 300; const float Width = Height*Graphics()->ScreenAspect(); @@ -259,7 +259,7 @@ void CBroadcast::OnReset() void CBroadcast::OnMessage(int MsgType, void* pRawMsg) { // process server broadcast message - if(MsgType == NETMSGTYPE_SV_BROADCAST && Config()->Values()->m_ClShowServerBroadcast && + if(MsgType == NETMSGTYPE_SV_BROADCAST && Config()->m_ClShowServerBroadcast && !m_pClient->m_MuteServerBroadcast) { CNetMsg_Sv_Broadcast *pMsg = (CNetMsg_Sv_Broadcast *)pRawMsg; diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp index 6ead7e6c..63bb8f04 100644 --- a/src/game/client/components/camera.cpp +++ b/src/game/client/components/camera.cpp @@ -63,10 +63,10 @@ void CCamera::OnRender() vec2 CameraOffset(0, 0); float l = length(m_pClient->m_pControls->m_MousePos); - if(Config()->Values()->m_ClDynamicCamera && l > 0.0001f) // make sure that this isn't 0 + if(Config()->m_ClDynamicCamera && l > 0.0001f) // make sure that this isn't 0 { - float DeadZone = Config()->Values()->m_ClMouseDeadzone; - float FollowFactor = Config()->Values()->m_ClMouseFollowfactor/100.0f; + float DeadZone = Config()->m_ClMouseDeadzone; + float FollowFactor = Config()->m_ClMouseFollowfactor/100.0f; float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor; CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount; @@ -83,22 +83,22 @@ void CCamera::OnRender() m_Zoom = 0.7f; static vec2 Dir = vec2(1.0f, 0.0f); - if(distance(m_Center, m_RotationCenter) <= (float)Config()->Values()->m_ClRotationRadius+0.5f) + if(distance(m_Center, m_RotationCenter) <= (float)Config()->m_ClRotationRadius+0.5f) { // do little rotation - float RotPerTick = 360.0f/(float)Config()->Values()->m_ClRotationSpeed * Client()->RenderFrameTime(); + float RotPerTick = 360.0f/(float)Config()->m_ClRotationSpeed * Client()->RenderFrameTime(); Dir = rotate(Dir, RotPerTick); - m_Center = m_RotationCenter+Dir*(float)Config()->Values()->m_ClRotationRadius; + m_Center = m_RotationCenter+Dir*(float)Config()->m_ClRotationRadius; } else { // positions for the animation Dir = normalize(m_AnimationStartPos - m_RotationCenter); - vec2 TargetPos = m_RotationCenter + Dir * (float)Config()->Values()->m_ClRotationRadius; + vec2 TargetPos = m_RotationCenter + Dir * (float)Config()->m_ClRotationRadius; float Distance = distance(m_AnimationStartPos, TargetPos); // move time - m_MoveTime += Client()->RenderFrameTime()*Config()->Values()->m_ClCameraSpeed / 10.0f; + m_MoveTime += Client()->RenderFrameTime()*Config()->m_ClCameraSpeed / 10.0f; float XVal = 1 - m_MoveTime; XVal = pow(XVal, 7.0f); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 91a32cab..d42053cc 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -535,10 +535,10 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) { - if(*pLine == 0 || (ClientID >= 0 && (!Config()->Values()->m_ClShowsocial || !m_pClient->m_aClients[ClientID].m_Active || // unknown client + if(*pLine == 0 || (ClientID >= 0 && (!Config()->m_ClShowsocial || !m_pClient->m_aClients[ClientID].m_Active || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore || - Config()->Values()->m_ClFilterchat == 2 || - (m_pClient->m_LocalClientID != ClientID && Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[ClientID].m_Friend)))) + Config()->m_ClFilterchat == 2 || + (m_pClient->m_LocalClientID != ClientID && Config()->m_ClFilterchat == 1 && !m_pClient->m_aClients[ClientID].m_Friend)))) return; if(Mode == CHAT_WHISPER) @@ -550,8 +550,8 @@ void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) if(ClientID != m_pClient->m_LocalClientID && TargetID != m_pClient->m_LocalClientID) return; // ignore and chat filter - if(m_pClient->m_aClients[TargetID].m_ChatIgnore || Config()->Values()->m_ClFilterchat == 2 || - (m_pClient->m_LocalClientID != TargetID && Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[TargetID].m_Friend)) + if(m_pClient->m_aClients[TargetID].m_ChatIgnore || Config()->m_ClFilterchat == 2 || + (m_pClient->m_LocalClientID != TargetID && Config()->m_ClFilterchat == 1 && !m_pClient->m_aClients[TargetID].m_Friend)) return; } diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 91c31259..ad9e845f 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -374,7 +374,7 @@ void CGameConsole::OnRender() Progress = 1.0f; } - if (m_ConsoleState == CONSOLE_OPEN && Config()->Values()->m_ClEditor) + if (m_ConsoleState == CONSOLE_OPEN && Config()->m_ClEditor) Toggle(CONSOLETYPE_LOCAL); if (m_ConsoleState == CONSOLE_CLOSED) @@ -743,7 +743,7 @@ void CGameConsole::OnConsoleInit() m_pConsole = Kernel()->RequestInterface(); // - m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->Values()->m_ConsoleOutputLevel, ClientConsolePrintCallback, this); + m_PrintCBIndex = Console()->RegisterPrintCallback(Config()->m_ConsoleOutputLevel, ClientConsolePrintCallback, this); Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console"); Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console"); diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 28ab8aeb..041832f4 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -102,7 +102,7 @@ void CControls::OnMessage(int Msg, void *pRawMsg) if(Msg == NETMSGTYPE_SV_WEAPONPICKUP) { CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; - if(Config()->Values()->m_ClAutoswitchWeapons) + if(Config()->m_ClAutoswitchWeapons) m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; } } @@ -155,7 +155,7 @@ int CControls::SnapInput(int *pData) m_InputData.m_Direction = 1; // stress testing - if(Config()->Values()->m_DbgStress) + if(Config()->m_DbgStress) { float t = Client()->LocalTime(); mem_zero(&m_InputData, sizeof(m_InputData)); @@ -228,14 +228,14 @@ void CControls::ClampMousePos() else { float MouseMax; - if(Config()->Values()->m_ClDynamicCamera) + if(Config()->m_ClDynamicCamera) { float CameraMaxDistance = 200.0f; - float FollowFactor = Config()->Values()->m_ClMouseFollowfactor/100.0f; - MouseMax = min(CameraMaxDistance/FollowFactor + Config()->Values()->m_ClMouseDeadzone, (float)Config()->Values()->m_ClMouseMaxDistanceDynamic); + float FollowFactor = Config()->m_ClMouseFollowfactor/100.0f; + MouseMax = min(CameraMaxDistance/FollowFactor + Config()->m_ClMouseDeadzone, (float)Config()->m_ClMouseMaxDistanceDynamic); } else - MouseMax = (float)Config()->Values()->m_ClMouseMaxDistanceStatic; + MouseMax = (float)Config()->m_ClMouseMaxDistanceStatic; if(length(m_MousePos) > MouseMax) m_MousePos = normalize(m_MousePos)*MouseMax; diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index 0d6b88c9..40e80e2f 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -73,7 +73,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() CCountryFlag CountryFlag; CountryFlag.m_CountryCode = CountryCode; str_copy(CountryFlag.m_aCountryCodeString, pCountryName, sizeof(CountryFlag.m_aCountryCodeString)); - if(Config()->Values()->m_ClLoadCountryFlags) + if(Config()->m_ClLoadCountryFlags) { // load the graphic file CImageInfo Info; @@ -96,7 +96,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() m_aCountryFlags.add_unsorted(CountryFlag); // print message - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", pCountryName); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); diff --git a/src/game/client/components/debughud.cpp b/src/game/client/components/debughud.cpp index b65bfd0e..0b5a0452 100644 --- a/src/game/client/components/debughud.cpp +++ b/src/game/client/components/debughud.cpp @@ -19,7 +19,7 @@ void CDebugHud::RenderNetCorrections() { - if(!Config()->Values()->m_Debug || Config()->Values()->m_DbgGraphs || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) + if(!Config()->m_Debug || Config()->m_DbgGraphs || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) return; float Width = 300*Graphics()->ScreenAspect(); @@ -76,7 +76,7 @@ void CDebugHud::RenderNetCorrections() void CDebugHud::RenderTuning() { // render tuning debugging - if(!Config()->Values()->m_DbgTuning) + if(!Config()->m_DbgTuning) return; CTuningParams StandardTuning; diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 982a43c5..f999ca54 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -213,7 +213,7 @@ void CHud::RenderScoreHud() // draw name of the flag holder int ID = FlagCarrier[t]%MAX_CLIENTS; char aName[64]; - str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; @@ -312,7 +312,7 @@ void CHud::RenderScoreHud() // draw name int ID = aPlayerInfo[t].m_ClientID; char aName[64]; - str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; @@ -408,7 +408,7 @@ void CHud::RenderWarmupTimer() void CHud::RenderFps() { - if(Config()->Values()->m_ClShowfps) + if(Config()->m_ClShowfps) { // calculate avg. fps float FPS = 1.0f / Client()->RenderFrameTime(); @@ -432,7 +432,7 @@ void CHud::RenderConnectionWarning() void CHud::RenderTeambalanceWarning() { // render prompt about team-balance - if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS && Config()->Values()->m_ClWarningTeambalance && m_pClient->m_ServerSettings.m_TeamBalance && + if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS && Config()->m_ClWarningTeambalance && m_pClient->m_ServerSettings.m_TeamBalance && absolute(m_pClient->m_GameInfo.m_aTeamSize[TEAM_RED]-m_pClient->m_GameInfo.m_aTeamSize[TEAM_BLUE]) >= NUM_TEAMS) { bool Flash = time_get()/(time_freq()/2)%2 == 0; @@ -655,7 +655,7 @@ void CHud::RenderSpectatorHud() char aName[64]; const int SpecID = m_pClient->m_Snap.m_SpecInfo.m_SpectatorID; const int SpecMode = m_pClient->m_Snap.m_SpecInfo.m_SpecMode; - str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : ""); + str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : ""); char aBuf[128]; CTextCursor Cursor; @@ -809,7 +809,7 @@ void CHud::OnRender() m_Height = 300.0f; Graphics()->MapScreen(0.0f, 0.0f, m_Width, m_Height); - if(Config()->Values()->m_ClShowhud) + if(Config()->m_ClShowhud) { if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) { diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index f5478a43..6ee3ac0b 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -43,13 +43,13 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) // unpack messages CInfoMsg Kill; Kill.m_Player1ID = pMsg->m_Victim; - str_format(Kill.m_aPlayer1Name, sizeof(Kill.m_aPlayer1Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player1ID].m_aName : ""); + str_format(Kill.m_aPlayer1Name, sizeof(Kill.m_aPlayer1Name), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player1ID].m_aName : ""); Kill.m_Player1RenderInfo = m_pClient->m_aClients[Kill.m_Player1ID].m_RenderInfo; Kill.m_Player2ID = pMsg->m_Killer; if (Kill.m_Player2ID >= 0) { - str_format(Kill.m_aPlayer2Name, sizeof(Kill.m_aPlayer2Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player2ID].m_aName : ""); + str_format(Kill.m_aPlayer2Name, sizeof(Kill.m_aPlayer2Name), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[Kill.m_Player2ID].m_aName : ""); Kill.m_Player2RenderInfo = m_pClient->m_aClients[Kill.m_Player2ID].m_RenderInfo; } else @@ -127,7 +127,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) { CInfoMsg Finish; Finish.m_Player1ID = pMsg->m_ClientID; - str_format(Finish.m_aPlayer1Name, sizeof(Finish.m_aPlayer1Name), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[pMsg->m_ClientID].m_aName : ""); + str_format(Finish.m_aPlayer1Name, sizeof(Finish.m_aPlayer1Name), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[pMsg->m_ClientID].m_aName : ""); Finish.m_Player1RenderInfo = m_pClient->m_aClients[Finish.m_Player1ID].m_RenderInfo; Finish.m_Time = pMsg->m_Time; @@ -141,7 +141,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) void CInfoMessages::OnRender() { - if(!Config()->Values()->m_ClShowhud) + if(!Config()->m_ClShowhud) return; float Width = 400*3.0f*Graphics()->ScreenAspect(); diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 02b5ab7e..37c330bd 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -39,31 +39,31 @@ void CMapLayers::OnStateChange(int NewState, int OldState) void CMapLayers::LoadBackgroundMap() { - if(!Config()->Values()->m_ClShowMenuMap) + if(!Config()->m_ClShowMenuMap) return; int HourOfTheDay = time_houroftheday(); char aBuf[128]; // check for the appropriate day/night map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->Values()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on generic map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", Config()->Values()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", Config()->m_ClMenuMap); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on day/night alternative map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->Values()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { - str_format(aBuf, sizeof(aBuf), "map '%s' not found", Config()->Values()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "map '%s' not found", Config()->m_ClMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); return; } } } - str_format(aBuf, sizeof(aBuf), "loaded map '%s'", Config()->Values()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "loaded map '%s'", Config()->m_ClMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); m_pMenuLayers->Init(Kernel(), m_pMenuMap); @@ -373,7 +373,7 @@ void CMapLayers::OnRender() { CMapItemGroup *pGroup = pLayers->GetGroup(g); - if(!Config()->Values()->m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) + if(!Config()->m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) { // set clipping float Points[4]; @@ -423,7 +423,7 @@ void CMapLayers::OnRender() continue; // skip rendering if detail layers is not wanted - if(!(pLayer->m_Flags&LAYERFLAG_DETAIL && !Config()->Values()->m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK))) + if(!(pLayer->m_Flags&LAYERFLAG_DETAIL && !Config()->m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK))) { if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0)) { @@ -495,11 +495,11 @@ void CMapLayers::OnRender() } } } - if(!Config()->Values()->m_GfxNoclip) + if(!Config()->m_GfxNoclip) Graphics()->ClipDisable(); } - if(!Config()->Values()->m_GfxNoclip) + if(!Config()->m_GfxNoclip) Graphics()->ClipDisable(); // reset the screen like it was before diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 16b24da7..f4e86f45 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -255,7 +255,7 @@ int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Ch float Fade = ButtonFade(pBC, Seconds, Checked); float FadeVal = (Fade/Seconds)*FontAlpha; - RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, Config()->Values()->m_ClMenuAlpha/100.0f*Alpha+FadeVal*0.5f), Corners, r); + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, Config()->m_ClMenuAlpha/100.0f*Alpha+FadeVal*0.5f), Corners, r); CUIRect Temp; pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp); @@ -1020,8 +1020,8 @@ void CMenus::RenderMenubar(CUIRect Rect) CUIRect Left, Right; Box.VSplitLeft(ButtonWidth*4.0f + Spacing*3.0f, &Left, 0); Box.VSplitRight(ButtonWidth*1.5f + Spacing, 0, &Right); - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); - RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Left.HSplitBottom(25.0f, 0, &Left); Right.HSplitBottom(25.0f, 0, &Right); @@ -1074,28 +1074,28 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header background if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Box.HSplitBottom(25.0f, 0, &Box); Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_GeneralButton; - if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_GENERAL, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_GENERAL ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage==SETTINGS_GENERAL, &Button, + Config()->m_UiSettingsPage == SETTINGS_GENERAL ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GENERAL); - Config()->Values()->m_UiSettingsPage = SETTINGS_GENERAL; + Config()->m_UiSettingsPage = SETTINGS_GENERAL; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); { static CButtonContainer s_PlayerButton; - if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_PLAYER, &Button, + Config()->m_UiSettingsPage == SETTINGS_PLAYER ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_PLAYER); - Config()->Values()->m_UiSettingsPage = SETTINGS_PLAYER; + Config()->m_UiSettingsPage = SETTINGS_PLAYER; } } @@ -1103,11 +1103,11 @@ void CMenus::RenderMenubar(CUIRect Rect) Box.VSplitLeft(ButtonWidth, &Button, &Box); { static CButtonContainer s_TeeButton; - if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage == SETTINGS_TEE, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_TEE ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_TEE, &Button, + Config()->m_UiSettingsPage == SETTINGS_TEE ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TEE); - Config()->Values()->m_UiSettingsPage = SETTINGS_TEE; + Config()->m_UiSettingsPage = SETTINGS_TEE; } } @@ -1115,31 +1115,31 @@ void CMenus::RenderMenubar(CUIRect Rect) Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_ControlsButton; - if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_CONTROLS, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_CONTROLS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage==SETTINGS_CONTROLS, &Button, + Config()->m_UiSettingsPage == SETTINGS_CONTROLS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_CONTROLS); - Config()->Values()->m_UiSettingsPage = SETTINGS_CONTROLS; + Config()->m_UiSettingsPage = SETTINGS_CONTROLS; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_GraphicsButton; - if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_GRAPHICS, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_GRAPHICS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage==SETTINGS_GRAPHICS, &Button, + Config()->m_UiSettingsPage == SETTINGS_GRAPHICS ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GRAPHICS); - Config()->Values()->m_UiSettingsPage = SETTINGS_GRAPHICS; + Config()->m_UiSettingsPage = SETTINGS_GRAPHICS; } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); static CButtonContainer s_SoundButton; - if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), Client()->State() == IClient::STATE_OFFLINE && Config()->Values()->m_UiSettingsPage==SETTINGS_SOUND, &Button, - Config()->Values()->m_UiSettingsPage == SETTINGS_SOUND ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage==SETTINGS_SOUND, &Button, + Config()->m_UiSettingsPage == SETTINGS_SOUND ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_SOUND); - Config()->Values()->m_UiSettingsPage = SETTINGS_SOUND; + Config()->m_UiSettingsPage = SETTINGS_SOUND; } } else if((Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_INTERNET && m_MenuPage <= PAGE_LAN) || (Client()->State() == IClient::STATE_ONLINE && m_GamePage >= PAGE_INTERNET && m_GamePage <= PAGE_LAN)) @@ -1154,7 +1154,7 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header backgrounds if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Left.HSplitBottom(25.0f, 0, &Left); @@ -1166,7 +1166,7 @@ void CMenus::RenderMenubar(CUIRect Rect) m_pClient->m_pCamera->ChangePosition(CCamera::POS_INTERNET); ServerBrowser()->SetType(IServerBrowser::TYPE_INTERNET); NewPage = PAGE_INTERNET; - Config()->Values()->m_UiBrowserPage = PAGE_INTERNET; + Config()->m_UiBrowserPage = PAGE_INTERNET; } Left.VSplitLeft(Spacing, 0, &Left); // little space @@ -1178,7 +1178,7 @@ void CMenus::RenderMenubar(CUIRect Rect) m_pClient->m_pCamera->ChangePosition(CCamera::POS_LAN); ServerBrowser()->SetType(IServerBrowser::TYPE_LAN); NewPage = PAGE_LAN; - Config()->Values()->m_UiBrowserPage = PAGE_LAN; + Config()->m_UiBrowserPage = PAGE_LAN; } if(Client()->State() == IClient::STATE_OFFLINE) @@ -1194,7 +1194,7 @@ void CMenus::RenderMenubar(CUIRect Rect) if(m_MenuPage == PAGE_DEMOS) { // render header background - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); Box.HSplitBottom(25.0f, 0, &Box); @@ -1286,7 +1286,7 @@ void CMenus::RenderBackButton(CUIRect MainView) // render background MainView.HSplitBottom(60.0f, 0, &MainView); MainView.VSplitLeft(ButtonWidth, &MainView, 0); - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); // back to main menu CUIRect Button; @@ -1462,14 +1462,14 @@ void CMenus::UpdatedFilteredVideoModes() void CMenus::UpdateVideoModeSettings() { - m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS, Config()->Values()->m_GfxScreen); + m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS, Config()->m_GfxScreen); UpdateVideoFormats(); bool Found = false; for(int i = 0; i < m_NumVideoFormats; i++) { - int G = gcd(Config()->Values()->m_GfxScreenWidth, Config()->Values()->m_GfxScreenHeight); - if(m_aVideoFormats[i].m_WidthValue == Config()->Values()->m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == Config()->Values()->m_GfxScreenHeight/G) + int G = gcd(Config()->m_GfxScreenWidth, Config()->m_GfxScreenHeight); + if(m_aVideoFormats[i].m_WidthValue == Config()->m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == Config()->m_GfxScreenHeight/G) { m_CurrentVideoFormat = i; Found = true; @@ -1498,11 +1498,11 @@ void CMenus::OnInit() // clear filter lists //m_lFilters.clear(); - if(Config()->Values()->m_ClShowWelcome) + if(Config()->m_ClShowWelcome) m_Popup = POPUP_LANGUAGE; - Config()->Values()->m_ClShowWelcome = 0; - if(Config()->Values()->m_ClSkipStartMenu) - SetMenuPage(Config()->Values()->m_UiBrowserPage); + Config()->m_ClShowWelcome = 0; + if(Config()->m_ClSkipStartMenu) + SetMenuPage(Config()->m_UiBrowserPage); Console()->Chain("br_filter_string", ConchainServerbrowserUpdate, this); Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this); @@ -1518,7 +1518,7 @@ void CMenus::OnInit() // setup load amount m_LoadCurrent = 0; m_LoadTotal = g_pData->m_NumImages; - if(!Config()->Values()->m_SndAsyncLoading) + if(!Config()->m_SndAsyncLoading) m_LoadTotal += g_pData->m_NumSounds; } @@ -1546,7 +1546,7 @@ int CMenus::Render() // refresh server browser before we are in browser menu to save time m_pClient->m_pCamera->ChangePosition(CCamera::POS_START); ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); - ServerBrowser()->SetType(Config()->Values()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); + ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); s_First = false; @@ -1582,7 +1582,7 @@ int CMenus::Render() else if(Client()->State() == IClient::STATE_ONLINE && m_GamePage >= PAGE_INTERNET && m_GamePage <= PAGE_LAN) BarHeight += 3.0f + 25.0f; float VMargin = Screen.w/2-365.0f; - if(Config()->Values()->m_UiWideview) + if(Config()->m_UiWideview) VMargin = min(VMargin, 60.0f); Screen.VMargin(VMargin, &MainView); @@ -1632,8 +1632,8 @@ int CMenus::Render() Row.VSplitRight(5.0f, &Row, 0); Row.VSplitRight(TopOffset, &Row, &Button); static CButtonContainer s_WideButton; - if((m_MenuPage == PAGE_INTERNET || m_MenuPage == PAGE_LAN || m_MenuPage == PAGE_DEMOS) && DoButton_MenuTabTop(&s_WideButton, Config()->Values()->m_UiWideview ? "\xe2\x96\xaa" : "\xe2\x96\xac", false, &Button, 1.0f, 1.0f, CUI::CORNER_B)) - Config()->Values()->m_UiWideview ^= 1; + if((m_MenuPage == PAGE_INTERNET || m_MenuPage == PAGE_LAN || m_MenuPage == PAGE_DEMOS) && DoButton_MenuTabTop(&s_WideButton, Config()->m_UiWideview ? "\xe2\x96\xaa" : "\xe2\x96\xac", false, &Button, 1.0f, 1.0f, CUI::CORNER_B)) + Config()->m_UiWideview ^= 1; } // render current page @@ -1862,7 +1862,7 @@ int CMenus::Render() Box.HSplitTop(20.0f, &EditBox, &Box); static float s_OffsetPassword = 0.0f; - DoEditBoxOption(Config()->Values()->m_Password, Config()->Values()->m_Password, sizeof(Config()->Values()->m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); + DoEditBoxOption(Config()->m_Password, Config()->m_Password, sizeof(Config()->m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); Box.HSplitTop(2.0f, 0, &Box); Box.HSplitTop(20.0f, &Save, &Box); @@ -1872,8 +1872,8 @@ int CMenus::Render() const bool Favorite = ServerInfo.m_Favorite; const int OnValue = Favorite ? 1 : 2; const char *pSaveText = Favorite ? Localize("Save password") : Localize("Save password and server as favorite"); - if(DoButton_CheckBox(&Config()->Values()->m_ClSaveServerPasswords, pSaveText, Config()->Values()->m_ClSaveServerPasswords == OnValue, &Save)) - Config()->Values()->m_ClSaveServerPasswords = Config()->Values()->m_ClSaveServerPasswords == OnValue ? 0 : OnValue; + if(DoButton_CheckBox(&Config()->m_ClSaveServerPasswords, pSaveText, Config()->m_ClSaveServerPasswords == OnValue, &Save)) + Config()->m_ClSaveServerPasswords = Config()->m_ClSaveServerPasswords == OnValue ? 0 : OnValue; // buttons BottomBar.VSplitMid(&Abort, &TryAgain); @@ -2267,13 +2267,13 @@ int CMenus::Render() Box.HSplitTop(ButtonHeight, &EditBox, &Box); static float s_OffsetName = 0.0f; - DoEditBoxOption(Config()->Values()->m_PlayerName, Config()->Values()->m_PlayerName, sizeof(Config()->Values()->m_PlayerName), &EditBox, Localize("Nickname"), ButtonWidth, &s_OffsetName); + DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &EditBox, Localize("Nickname"), ButtonWidth, &s_OffsetName); // button static CButtonContainer s_EnterButton; if(DoButton_Menu(&s_EnterButton, pButtonText, 0, &BottomBar) || m_EnterPressed) { - if(Config()->Values()->m_PlayerName[0]) + if(Config()->m_PlayerName[0]) m_Popup = POPUP_NONE; else PopupMessage(Localize("Error"), Localize("Nickname is empty."), Localize("Ok"), POPUP_FIRST_LAUNCH); @@ -2449,8 +2449,8 @@ void CMenus::OnStateChange(int NewState, int OldState) if(str_find(Client()->ErrorString(), "password")) { m_Popup = POPUP_PASSWORD; - UI()->SetHotItem(&Config()->Values()->m_Password); - UI()->SetActiveItem(&Config()->Values()->m_Password); + UI()->SetHotItem(&Config()->m_Password); + UI()->SetActiveItem(&Config()->m_Password); } else m_Popup = POPUP_DISCONNECTED; @@ -2548,7 +2548,7 @@ void CMenus::OnRender() Graphics()->WrapNormal(); // render debug information - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); @@ -2643,9 +2643,9 @@ void CMenus::ToggleMusic() { if(Client()->State() == IClient::STATE_OFFLINE) { - if(Config()->Values()->m_SndMusic && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + if(Config()->m_SndMusic && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); - else if(!Config()->Values()->m_SndMusic && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + else if(!Config()->m_SndMusic && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) m_pClient->m_pSounds->Stop(SOUND_MENU); } } @@ -2665,7 +2665,7 @@ void CMenus::SetMenuPage(int NewPage) { case PAGE_START: CameraPos = CCamera::POS_START; break; case PAGE_DEMOS: CameraPos = CCamera::POS_DEMOS; break; - case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS_GENERAL+Config()->Values()->m_UiSettingsPage; break; + case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS_GENERAL+Config()->m_UiSettingsPage; break; case PAGE_INTERNET: CameraPos = CCamera::POS_INTERNET; break; case PAGE_LAN: CameraPos = CCamera::POS_LAN; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 70ee1b48..9d498965 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -690,8 +690,8 @@ class CMenus : public CComponent void RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); void RenderBackButton(CUIRect MainView); - inline float GetListHeaderHeight() const { return ms_ListheaderHeight + (Config()->Values()->m_UiWideview ? 3.0f : 0.0f); } - inline float GetListHeaderHeightFactor() const { return 1.0f + (Config()->Values()->m_UiWideview ? (3.0f/ms_ListheaderHeight) : 0.0f); } + inline float GetListHeaderHeight() const { return ms_ListheaderHeight + (Config()->m_UiWideview ? 3.0f : 0.0f); } + inline float GetListHeaderHeightFactor() const { return 1.0f + (Config()->m_UiWideview ? (3.0f/ms_ListheaderHeight) : 0.0f); } // found in menus_demo.cpp void RenderDemoPlayer(CUIRect MainView); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 5ac3e0b2..5727ae5e 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -474,17 +474,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) + if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aName, Config()->Values()->m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aName, Config()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aName, (int)(pStr-pEntry->m_aName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aName, -1); @@ -506,17 +506,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) + if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aMap, Config()->Values()->m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aMap, Config()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aMap, (int)(pStr-pEntry->m_aMap)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aMap, -1); @@ -557,7 +557,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max); - if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) + if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); Button.y += 2.0f; @@ -621,17 +621,17 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Cursor.m_LineWidth = Button.w; TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - if(Config()->Values()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) + if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) { // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aGameType, Config()->Values()->m_BrFilterString); + const char *pStr = str_find_nocase(pEntry->m_aGameType, Config()->m_BrFilterString); if(pStr) { TextRender()->TextEx(&Cursor, pEntry->m_aGameType, (int)(pStr-pEntry->m_aGameType)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); @@ -883,17 +883,17 @@ void CMenus::RenderServerbrowserOverlay() TextRender()->SetCursor(&Cursor, Name.x, Name.y+(Name.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Name.w; const char *pName = pInfo->m_aClients[i].m_aName; - if(Config()->Values()->m_BrFilterString[0]) + if(Config()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pName, Config()->Values()->m_BrFilterString); + const char *s = str_find_nocase(pName, Config()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s+str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pName, -1); @@ -905,17 +905,17 @@ void CMenus::RenderServerbrowserOverlay() TextRender()->SetCursor(&Cursor, Clan.x, Clan.y+(Clan.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Clan.w; const char *pClan = pInfo->m_aClients[i].m_aClan; - if(Config()->Values()->m_BrFilterString[0]) + if(Config()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pClan, Config()->Values()->m_BrFilterString); + const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s+str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pClan, -1); @@ -974,7 +974,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) const float HeightFactor = GetListHeaderHeightFactor(); // background - RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), (Client()->State() == IClient::STATE_OFFLINE) ? CUI::CORNER_ALL : CUI::CORNER_B|CUI::CORNER_TR, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), (Client()->State() == IClient::STATE_OFFLINE) ? CUI::CORNER_ALL : CUI::CORNER_B|CUI::CORNER_TR, 5.0f); // make room for scrollbar { @@ -1022,15 +1022,15 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(i == COL_BROWSER_FLAG) continue; - if(DoButton_GridHeader(ms_aBrowserCols[i].m_Caption, ms_aBrowserCols[i].m_Caption, Config()->Values()->m_BrSort == ms_aBrowserCols[i].m_Sort, ms_aBrowserCols[i].m_Align, &ms_aBrowserCols[i].m_Rect)) + if(DoButton_GridHeader(ms_aBrowserCols[i].m_Caption, ms_aBrowserCols[i].m_Caption, Config()->m_BrSort == ms_aBrowserCols[i].m_Sort, ms_aBrowserCols[i].m_Align, &ms_aBrowserCols[i].m_Rect)) { if(ms_aBrowserCols[i].m_Sort != -1) { - if(Config()->Values()->m_BrSort == ms_aBrowserCols[i].m_Sort) - Config()->Values()->m_BrSortOrder ^= 1; + if(Config()->m_BrSort == ms_aBrowserCols[i].m_Sort) + Config()->m_BrSortOrder ^= 1; else - Config()->Values()->m_BrSortOrder = 0; - Config()->Values()->m_BrSort = ms_aBrowserCols[i].m_Sort; + Config()->m_BrSortOrder = 0; + Config()->m_BrSort = ms_aBrowserCols[i].m_Sort; } ServerBrowserSortingOnUpdate(); } @@ -1040,7 +1040,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); { int Column = COL_BROWSER_PING; - switch(Config()->Values()->m_BrSort) + switch(Config()->m_BrSort) { case IServerBrowser::SORT_NAME: Column = COL_BROWSER_NAME; @@ -1283,7 +1283,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_aSelectedFilters[BrowserType] = FilterIndex; m_aSelectedServers[BrowserType] = ServerIndex; m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); - if(Config()->Values()->m_UiAutoswitchInfotab) + if(Config()->m_UiAutoswitchInfotab) m_SidebarTab = 0; UpdateServerBrowserAddress(); // update now instead of using flag because of connect if(Input()->MouseDoubleClick()) @@ -1329,7 +1329,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) UI()->DoLabel(&Label, Localize("Search:"), FontSize, CUI::ALIGN_LEFT); EditBox.VSplitRight(EditBox.h, &EditBox, &Button); static float s_ClearOffset = 0.0f; - if(DoEditBox(&Config()->Values()->m_BrFilterString, &EditBox, Config()->Values()->m_BrFilterString, sizeof(Config()->Values()->m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->m_BrFilterString, &EditBox, Config()->m_BrFilterString, sizeof(Config()->m_BrFilterString), FontSize, &s_ClearOffset, false, CUI::CORNER_ALL)) { Client()->ServerBrowserUpdate(); ServerBrowserFilterOnUpdate(); @@ -1340,8 +1340,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) static CButtonContainer s_ClearButton; if(DoButton_SpriteID(&s_ClearButton, IMAGE_TOOLICONS, SPRITE_TOOL_X_A, false, &Button, CUI::CORNER_ALL, 5.0f, true)) { - Config()->Values()->m_BrFilterString[0] = 0; - UI()->SetActiveItem(&Config()->Values()->m_BrFilterString); + Config()->m_BrFilterString[0] = 0; + UI()->SetActiveItem(&Config()->m_BrFilterString); Client()->ServerBrowserUpdate(); } } @@ -1356,7 +1356,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(BrowserType == IServerBrowser::TYPE_INTERNET) { static float s_InternetAddressOffset = 0.0f; - if(DoEditBox(&Config()->Values()->m_UiServerAddress, &EditBox, Config()->Values()->m_UiServerAddress, sizeof(Config()->Values()->m_UiServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->m_UiServerAddress, &EditBox, Config()->m_UiServerAddress, sizeof(Config()->m_UiServerAddress), FontSize, &s_InternetAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -1364,7 +1364,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) else if(BrowserType == IServerBrowser::TYPE_LAN) { static float s_LanAddressOffset = 0.0f; - if(DoEditBox(&Config()->Values()->m_UiServerAddressLan, &EditBox, Config()->Values()->m_UiServerAddressLan, sizeof(Config()->Values()->m_UiServerAddressLan), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) + if(DoEditBox(&Config()->m_UiServerAddressLan, &EditBox, Config()->m_UiServerAddressLan, sizeof(Config()->m_UiServerAddressLan), FontSize, &s_LanAddressOffset, false, CUI::CORNER_ALL)) { m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; } @@ -1426,7 +1426,7 @@ void CMenus::RenderServerbrowserSidebar(CUIRect View) CUIRect Header, Button; // background - RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // handle Tab key if(m_TabPressed) @@ -2158,17 +2158,17 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Name.w; const char *pName = pInfo->m_aClients[i].m_aName; - if(Config()->Values()->m_BrFilterString[0]) + if(Config()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pName, Config()->Values()->m_BrFilterString); + const char *s = str_find_nocase(pName, Config()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s + str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pName, -1); @@ -2180,17 +2180,17 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int TextRender()->SetCursor(&Cursor, Clan.x, Clan.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Clan.w; const char *pClan = pInfo->m_aClients[i].m_aClan; - if(Config()->Values()->m_BrFilterString[0]) + if(Config()->m_BrFilterString[0]) { // highlight the part that matches - const char *s = str_find_nocase(pClan, Config()->Values()->m_BrFilterString); + const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->Values()->m_BrFilterString)); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s + str_length(Config()->Values()->m_BrFilterString), -1); + TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pClan, -1); @@ -2242,7 +2242,7 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView) float ButtonWidth = MainView.w/2.0f-Spacing/2.0f; // render background - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); // back to main menu CUIRect Button; @@ -2395,9 +2395,9 @@ const char *CMenus::GetServerBrowserAddress() { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - return Config()->Values()->m_UiServerAddress; + return Config()->m_UiServerAddress; else if(Type == IServerBrowser::TYPE_LAN) - return Config()->Values()->m_UiServerAddressLan; + return Config()->m_UiServerAddressLan; return 0; } @@ -2405,9 +2405,9 @@ void CMenus::SetServerBrowserAddress(const char *pAddress) { const int Type = ServerBrowser()->GetType(); if(Type == IServerBrowser::TYPE_INTERNET) - str_copy(Config()->Values()->m_UiServerAddress, pAddress, sizeof(Config()->Values()->m_UiServerAddress)); + str_copy(Config()->m_UiServerAddress, pAddress, sizeof(Config()->m_UiServerAddress)); else if(Type == IServerBrowser::TYPE_LAN) - str_copy(Config()->Values()->m_UiServerAddressLan, pAddress, sizeof(Config()->Values()->m_UiServerAddressLan)); + str_copy(Config()->m_UiServerAddressLan, pAddress, sizeof(Config()->m_UiServerAddressLan)); } void CMenus::ServerBrowserFilterOnUpdate() diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 36897bc5..898f0191 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -139,16 +139,16 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonInpGrab = 0; - if(DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !Config()->Values()->m_InpGrab, &Button)) + if(DoButton_CheckBox(&s_ButtonInpGrab, Localize("Use OS mouse acceleration"), !Config()->m_InpGrab, &Button)) { - Config()->Values()->m_InpGrab ^= 1; + Config()->m_InpGrab ^= 1; } View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->Values()->m_InpMousesens, &Config()->Values()->m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_InpMousesens, &Config()->m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->Values()->m_UiMousesens, &Config()->Values()->m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_UiMousesens, &Config()->m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); return BackgroundHeight; } @@ -157,7 +157,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) { UpdateBindKeys(m_pClient->m_pBinds); - bool JoystickEnabled = Config()->Values()->m_JoystickEnable; + bool JoystickEnabled = Config()->m_JoystickEnable; int NumJoysticks = m_pClient->Input()->NumJoysticks(); int NumOptions = 2; // expandable header & message if(JoystickEnabled && NumJoysticks > 0) @@ -180,9 +180,9 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); static int s_ButtonJoystickEnable = 0; - if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), Config()->Values()->m_JoystickEnable, &Button)) + if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), Config()->m_JoystickEnable, &Button)) { - Config()->Values()->m_JoystickEnable ^= 1; + Config()->m_JoystickEnable ^= 1; } if(JoystickEnabled) { @@ -204,11 +204,11 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->Values()->m_JoystickSens, &Config()->Values()->m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_JoystickSens, &Config()->m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->Values()->m_JoystickTolerance, &Config()->Values()->m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); + DoScrollbarOption(&Config()->m_JoystickTolerance, &Config()->m_JoystickTolerance, &Button, Localize("Joystick jitter tolerance"), 0, 50); // shrink view and draw background View.HSplitTop(Spacing, 0, &View); @@ -387,7 +387,7 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) static int s_aActive[g_MaxJoystickAxes][2]; for(int i = 0; i < min(m_pClient->Input()->GetJoystickNumAxes(), g_MaxJoystickAxes); i++) { - bool Active = Config()->Values()->m_JoystickX == i || Config()->Values()->m_JoystickY == i; + bool Active = Config()->m_JoystickX == i || Config()->m_JoystickY == i; View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Row, &View); @@ -407,16 +407,16 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) Row.VSplitLeft(StatusMargin, 0, &Row); Row.VSplitLeft(StatusWidth, &Button, &Row); Button.HMargin((ButtonHeight-14.0f)/2.0f, &Button); - DoJoystickBar(&Button, (m_pClient->Input()->GetJoystickAxisValue(i)+1.0f)/2.0f, Config()->Values()->m_JoystickTolerance/50.0f, Active); + DoJoystickBar(&Button, (m_pClient->Input()->GetJoystickAxisValue(i)+1.0f)/2.0f, Config()->m_JoystickTolerance/50.0f, Active); // Bind to X,Y Row.VSplitLeft(2*StatusMargin, 0, &Row); Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][0], "X", Config()->Values()->m_JoystickX == i, &Button, Config()->Values()->m_JoystickY == i)) - Config()->Values()->m_JoystickX = i; + if(DoButton_CheckBox(&s_aActive[i][0], "X", Config()->m_JoystickX == i, &Button, Config()->m_JoystickY == i)) + Config()->m_JoystickX = i; Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][1], "Y", Config()->Values()->m_JoystickY == i, &Button, Config()->Values()->m_JoystickX == i)) - Config()->Values()->m_JoystickY = i; + if(DoButton_CheckBox(&s_aActive[i][1], "Y", Config()->m_JoystickY == i, &Button, Config()->m_JoystickX == i)) + Config()->m_JoystickY = i; Row.VSplitLeft(StatusMargin, 0, &Row); } } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index ce727213..aca7e7df 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -50,7 +50,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) MainView.VSplitRight(450.0f, &MainView, 0); if (m_SeekBarActive || m_MenuActive) // only draw the background if SeekBar or Menu is active - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_T, 10.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_T, 10.0f); MainView.Margin(5.0f, &MainView); @@ -331,7 +331,7 @@ void CMenus::RenderDemoList(CUIRect MainView) // cut view MainView.HSplitBottom(80.0f, &MainView, &BottomView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); BottomView.HSplitTop(20.f, 0, &BottomView); static int s_Inited = 0; @@ -443,7 +443,7 @@ void CMenus::RenderDemoList(CUIRect MainView) float BackgroundWidth = ButtonWidth*(float)NumButtons+(float)(NumButtons-1)*Spacing; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 99dd070a..7d9e46b3 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -64,7 +64,7 @@ void CMenus::RenderGame(CUIRect MainView) MainView.HSplitTop(20.0f, 0, &MainView); float NoteHeight = !Info.m_aNotification[0] ? 0.0f : 45.0f; MainView.HSplitTop(20.0f+20.0f+2*Spacing+ NoteHeight, &MainView, 0); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // game options MainView.HSplitTop(20.0f, &Label, &MainView); @@ -214,7 +214,7 @@ void CMenus::RenderPlayers(CUIRect MainView) CUIRect Label, Row; MainView.HSplitBottom(80.0f, &MainView, 0); MainView.HSplitTop(20.0f, 0, &MainView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); // player options MainView.HSplitTop(ButtonHeight, &Label, &MainView); @@ -294,7 +294,7 @@ void CMenus::RenderPlayers(CUIRect MainView) Row.VSplitLeft(2*Spacing, 0, &Row); Row.VSplitLeft(NameWidth, &Label, &Row); Label.y += 2.0f; - if(Config()->Values()->m_ClShowUserId) + if(Config()->m_ClShowUserId) { CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Label.x, Label.y, ButtonHeight*ms_FontmodHeight*0.8f, TEXTFLAG_RENDER); @@ -302,18 +302,18 @@ void CMenus::RenderPlayers(CUIRect MainView) Label.VSplitLeft(ButtonHeight, 0, &Label); } char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Row.VSplitLeft(Spacing, 0, &Row); Row.VSplitLeft(ClanWidth, &Label, &Row); Label.y += 2.0f; - str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aClan : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aClan : ""); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); // ignore button Row.VSplitRight(ButtonHeight/2, &Row, 0); Row.VSplitRight(ButtonHeight, &Row, &Label); - if(Config()->Values()->m_ClFilterchat == 2 || (Config()->Values()->m_ClFilterchat == 1 && !m_pClient->m_aClients[i].m_Friend)) + if(Config()->m_ClFilterchat == 2 || (Config()->m_ClFilterchat == 1 && !m_pClient->m_aClients[i].m_Friend)) DoButton_Toggle(&s_aPlayerIDs[i][0], 1, &Label, false); else if(DoButton_Toggle(&s_aPlayerIDs[i][0], m_pClient->m_aClients[i].m_ChatIgnore, &Label, true)) @@ -355,7 +355,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) // render background MainView.HSplitBottom(80.0f, &MainView, 0); MainView.HSplitTop(20.0f, 0, &MainView); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); CUIRect ServerInfo, GameInfo, Motd, Label; @@ -573,7 +573,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Label.x + Label.h / 2, Label.y + Label.h / 2)); Row.VSplitLeft(2*Spacing, 0, &Row); - if(Config()->Values()->m_ClShowUserId) + if(Config()->m_ClShowUserId) { Row.VSplitLeft(Row.h, &Label, &Row); Label.y += 2.0f; @@ -586,12 +586,12 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) Row.VSplitLeft(NameWidth, &Label, &Row); Label.y += 2.0f; char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : ""); UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Row.VSplitLeft(Spacing, 0, &Row); Row.VSplitLeft(ClanWidth, &Label, &Row); Label.y += 2.0f; - str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aClan : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aClan : ""); UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } } @@ -663,7 +663,7 @@ void CMenus::RenderServerControl(CUIRect MainView) // only print notice CUIRect Bar; MainView.HSplitTop(45.0f, &Bar, &MainView); - RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_ALL, 5.0f); Bar.HMargin(15.0f, &Bar); UI()->DoLabel(&Bar, pNotification, 14.0f, CUI::ALIGN_CENTER); return; @@ -708,7 +708,7 @@ void CMenus::RenderServerControl(CUIRect MainView) { MainView.HSplitTop(20.0f+45.0f, &MainView, 0); } - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); if(pNotification && !Authed) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 791c04b5..bf284852 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -329,7 +329,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) *CSkins::ms_apColorVariables[p] = NewVal; } if(UseAlpha) - Config()->Values()->m_PlayerColorMarking = (Alp << 24) + NewVal; + Config()->m_PlayerColorMarking = (Alp << 24) + NewVal; m_SkinModified = true; } } @@ -364,7 +364,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) const CSkins::CSkin *s = s_paSkinList[i]; if(s == 0) continue; - if(!str_comp(s->m_aName, Config()->Values()->m_PlayerSkin)) + if(!str_comp(s->m_aName, Config()->m_PlayerSkin)) { m_pSelectedSkin = s; OldSelected = i; @@ -398,7 +398,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) if(NewSelected != -1 && NewSelected != OldSelected) { m_pSelectedSkin = s_paSkinList[NewSelected]; - mem_copy(Config()->Values()->m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(Config()->Values()->m_PlayerSkin)); + mem_copy(Config()->m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(Config()->m_PlayerSkin)); for(int p = 0; p < NUM_SKINPARTS; p++) { mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, 24); @@ -488,7 +488,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, 24); - Config()->Values()->m_PlayerSkin[0] = 0; + Config()->m_PlayerSkin[0] = 0; m_SkinModified = true; } OldSelected = NewSelected; @@ -698,7 +698,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) LoadLanguageIndexfile(Storage(), Console(), &s_Languages); for(int i = 0; i < s_Languages.size(); i++) { - if(str_comp(s_Languages[i].m_FileName, Config()->Values()->m_ClLanguagefile) == 0) + if(str_comp(s_Languages[i].m_FileName, Config()->m_ClLanguagefile) == 0) { s_SelectedLanguage = i; break; @@ -746,7 +746,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) if(OldSelected != s_SelectedLanguage) { m_ActiveListBox = ACTLB_LANG; - str_copy(Config()->Values()->m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(Config()->Values()->m_ClLanguagefile)); + str_copy(Config()->m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(Config()->m_ClLanguagefile)); g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console()); } } @@ -758,13 +758,13 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) if(m_lThemes.size() == 0) // not loaded yet { - if(!Config()->Values()->m_ClShowMenuMap) - str_copy(Config()->Values()->m_ClMenuMap, "", sizeof(Config()->Values()->m_ClMenuMap)); // cl_menu_map otherwise resets to default on loading + if(!Config()->m_ClShowMenuMap) + str_copy(Config()->m_ClMenuMap, "", sizeof(Config()->m_ClMenuMap)); // cl_menu_map otherwise resets to default on loading m_lThemes.add(CTheme("", false, false)); // no theme Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeScan, (CMenus*)this); Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeIconScan, (CMenus*)this); for(int i = 0; i < m_lThemes.size(); i++) - if(str_comp(m_lThemes[i].m_Name, Config()->Values()->m_ClMenuMap) == 0) + if(str_comp(m_lThemes[i].m_Name, Config()->m_ClMenuMap) == 0) { s_SelectedTheme = i; break; @@ -837,11 +837,11 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) if(OldSelected != s_SelectedTheme) { m_ActiveListBox = ACTLB_THEME; - str_copy(Config()->Values()->m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(Config()->Values()->m_ClMenuMap)); + str_copy(Config()->m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(Config()->m_ClMenuMap)); if(m_lThemes[s_SelectedTheme].m_Name[0]) - Config()->Values()->m_ClShowMenuMap = 1; + Config()->m_ClShowMenuMap = 1; else - Config()->Values()->m_ClShowMenuMap = 0; + Config()->m_ClShowMenuMap = 0; m_pClient->m_pMapLayersBackGround->BackgroundMapUpdate(); } } @@ -855,7 +855,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) BottomView.HSplitTop(20.f, 0, &BottomView); // render game menu backgrounds - int NumOptions = max(Config()->Values()->m_ClNameplates ? 6 : 3, Config()->Values()->m_ClShowsocial ? 5 : 4); + int NumOptions = max(Config()->m_ClNameplates ? 6 : 3, Config()->m_ClShowsocial ? 5 : 4); float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; @@ -864,15 +864,15 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), this->Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), this->Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Game, &MainView); RenderTools()->DrawUIRect(&Game, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // render client menu background NumOptions = 4; - if(Config()->Values()->m_ClAutoDemoRecord) NumOptions += 1; - if(Config()->Values()->m_ClAutoScreenshot) NumOptions += 1; + if(Config()->m_ClAutoDemoRecord) NumOptions += 1; + if(Config()->m_ClAutoScreenshot) NumOptions += 1; BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; MainView.HSplitTop(10.0f, 0, &MainView); @@ -893,81 +893,81 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_DynamicCameraButton = 0; - if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), Config()->Values()->m_ClDynamicCamera, &Button)) + if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), Config()->m_ClDynamicCamera, &Button)) { - if(Config()->Values()->m_ClDynamicCamera) + if(Config()->m_ClDynamicCamera) { - Config()->Values()->m_ClDynamicCamera = 0; + Config()->m_ClDynamicCamera = 0; // force to defaults when using the GUI - Config()->Values()->m_ClMouseMaxDistanceStatic = 400; - // Config()->Values()->m_ClMouseFollowfactor = 0; - // Config()->Values()->m_ClMouseDeadzone = 0; + Config()->m_ClMouseMaxDistanceStatic = 400; + // Config()->m_ClMouseFollowfactor = 0; + // Config()->m_ClMouseDeadzone = 0; } else { - Config()->Values()->m_ClDynamicCamera = 1; + Config()->m_ClDynamicCamera = 1; // force to defaults when using the GUI - Config()->Values()->m_ClMouseMaxDistanceDynamic = 1000; - Config()->Values()->m_ClMouseFollowfactor = 60; - Config()->Values()->m_ClMouseDeadzone = 300; + Config()->m_ClMouseMaxDistanceDynamic = 1000; + Config()->m_ClMouseFollowfactor = 60; + Config()->m_ClMouseDeadzone = 300; } } GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_AutoswitchWeapons = 0; - if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), Config()->Values()->m_ClAutoswitchWeapons, &Button)) - Config()->Values()->m_ClAutoswitchWeapons ^= 1; + if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), Config()->m_ClAutoswitchWeapons, &Button)) + Config()->m_ClAutoswitchWeapons ^= 1; GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); static int s_Nameplates = 0; - if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), Config()->Values()->m_ClNameplates, &Button)) - Config()->Values()->m_ClNameplates ^= 1; + if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), Config()->m_ClNameplates, &Button)) + Config()->m_ClNameplates ^= 1; - if(Config()->Values()->m_ClNameplates) + if(Config()->m_ClNameplates) { GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_NameplatesAlways = 0; - if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), Config()->Values()->m_ClNameplatesAlways, &Button)) - Config()->Values()->m_ClNameplatesAlways ^= 1; + if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), Config()->m_ClNameplatesAlways, &Button)) + Config()->m_ClNameplatesAlways ^= 1; GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&Config()->Values()->m_ClNameplatesSize, &Config()->Values()->m_ClNameplatesSize, &Button, Localize("Size"), 0, 100); + DoScrollbarOption(&Config()->m_ClNameplatesSize, &Config()->m_ClNameplatesSize, &Button, Localize("Size"), 0, 100); GameLeft.HSplitTop(Spacing, 0, &GameLeft); GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_NameplatesTeamcolors = 0; - if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), Config()->Values()->m_ClNameplatesTeamcolors, &Button)) - Config()->Values()->m_ClNameplatesTeamcolors ^= 1; + if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), Config()->m_ClNameplatesTeamcolors, &Button)) + Config()->m_ClNameplatesTeamcolors ^= 1; } // right side GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_Showhud = 0; - if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), Config()->Values()->m_ClShowhud, &Button)) - Config()->Values()->m_ClShowhud ^= 1; + if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), Config()->m_ClShowhud, &Button)) + Config()->m_ClShowhud ^= 1; GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_ShowUserId = 0; - if(DoButton_CheckBox(&s_ShowUserId, Localize("Show user IDs"), Config()->Values()->m_ClShowUserId, &Button)) - Config()->Values()->m_ClShowUserId ^= 1; + if(DoButton_CheckBox(&s_ShowUserId, Localize("Show user IDs"), Config()->m_ClShowUserId, &Button)) + Config()->m_ClShowUserId ^= 1; GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_Showsocial = 0; - if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), Config()->Values()->m_ClShowsocial, &Button)) - Config()->Values()->m_ClShowsocial ^= 1; + if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), Config()->m_ClShowsocial, &Button)) + Config()->m_ClShowsocial ^= 1; // show chat messages button - if(Config()->Values()->m_ClShowsocial) + if(Config()->m_ClShowsocial) { GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); @@ -983,23 +983,23 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(119.0f, &Button, 0); - if(Config()->Values()->m_ClFilterchat == 0) + if(Config()->m_ClFilterchat == 0) str_format(aBuf, sizeof(aBuf), Localize("everyone", "Show chat messages from:")); - else if(Config()->Values()->m_ClFilterchat == 1) + else if(Config()->m_ClFilterchat == 1) str_format(aBuf, sizeof(aBuf), Localize("friends only", "Show chat messages from:")); - else if(Config()->Values()->m_ClFilterchat == 2) + else if(Config()->m_ClFilterchat == 2) str_format(aBuf, sizeof(aBuf), Localize("no one", "Show chat messages from:")); static CButtonContainer s_ButtonFilterchat; if(DoButton_Menu(&s_ButtonFilterchat, aBuf, 0, &Button)) - Config()->Values()->m_ClFilterchat = (Config()->Values()->m_ClFilterchat + 1) % 3; + Config()->m_ClFilterchat = (Config()->m_ClFilterchat + 1) % 3; } GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_EnableColoredBroadcasts = 0; if(DoButton_CheckBox(&s_EnableColoredBroadcasts, Localize("Enable colored server broadcasts"), - Config()->Values()->m_ClColoredBroadcast, &Button)) - Config()->Values()->m_ClColoredBroadcast ^= 1; + Config()->m_ClColoredBroadcast, &Button)) + Config()->m_ClColoredBroadcast ^= 1; // render client menu Client.HSplitTop(ButtonHeight, &Label, &Client); @@ -1009,39 +1009,39 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_SkipMainMenu = 0; - if(DoButton_CheckBox(&s_SkipMainMenu, Localize("Skip the main menu"), Config()->Values()->m_ClSkipStartMenu, &Button)) - Config()->Values()->m_ClSkipStartMenu ^= 1; + if(DoButton_CheckBox(&s_SkipMainMenu, Localize("Skip the main menu"), Config()->m_ClSkipStartMenu, &Button)) + Config()->m_ClSkipStartMenu ^= 1; Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); - DoScrollbarOption(&Config()->Values()->m_ClMenuAlpha, &Config()->Values()->m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); + DoScrollbarOption(&Config()->m_ClMenuAlpha, &Config()->m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_AutoDemoRecord = 0; - if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), Config()->Values()->m_ClAutoDemoRecord, &Button)) - Config()->Values()->m_ClAutoDemoRecord ^= 1; + if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), Config()->m_ClAutoDemoRecord, &Button)) + Config()->m_ClAutoDemoRecord ^= 1; - if(Config()->Values()->m_ClAutoDemoRecord) + if(Config()->m_ClAutoDemoRecord) { Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&Config()->Values()->m_ClAutoDemoMax, &Config()->Values()->m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); + DoScrollbarOption(&Config()->m_ClAutoDemoMax, &Config()->m_ClAutoDemoMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); static int s_AutoScreenshot = 0; - if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), Config()->Values()->m_ClAutoScreenshot, &Button)) - Config()->Values()->m_ClAutoScreenshot ^= 1; + if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), Config()->m_ClAutoScreenshot, &Button)) + Config()->m_ClAutoScreenshot ^= 1; - if(Config()->Values()->m_ClAutoScreenshot) + if(Config()->m_ClAutoScreenshot) { Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); Button.VSplitLeft(ButtonHeight, 0, &Button); - DoScrollbarOption(&Config()->Values()->m_ClAutoScreenshotMax, &Config()->Values()->m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); + DoScrollbarOption(&Config()->m_ClAutoScreenshotMax, &Config()->m_ClAutoScreenshotMax, &Button, Localize("Max"), 0, 1000, &LogarithmicScrollbarScale, true); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -1059,41 +1059,41 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->Values()->m_ClDynamicCamera = 0; - Config()->Values()->m_ClMouseMaxDistanceStatic = 400; - Config()->Values()->m_ClMouseMaxDistanceDynamic = 1000; - Config()->Values()->m_ClMouseFollowfactor = 60; - Config()->Values()->m_ClMouseDeadzone = 300; - Config()->Values()->m_ClAutoswitchWeapons = 1; - Config()->Values()->m_ClShowhud = 1; - Config()->Values()->m_ClFilterchat = 0; - Config()->Values()->m_ClNameplates = 1; - Config()->Values()->m_ClNameplatesAlways = 1; - Config()->Values()->m_ClNameplatesSize = 50; - Config()->Values()->m_ClNameplatesTeamcolors = 1; - Config()->Values()->m_ClAutoDemoRecord = 0; - Config()->Values()->m_ClAutoDemoMax = 10; - Config()->Values()->m_ClAutoScreenshot = 0; - Config()->Values()->m_ClAutoScreenshotMax = 10; + Config()->m_ClDynamicCamera = 0; + Config()->m_ClMouseMaxDistanceStatic = 400; + Config()->m_ClMouseMaxDistanceDynamic = 1000; + Config()->m_ClMouseFollowfactor = 60; + Config()->m_ClMouseDeadzone = 300; + Config()->m_ClAutoswitchWeapons = 1; + Config()->m_ClShowhud = 1; + Config()->m_ClFilterchat = 0; + Config()->m_ClNameplates = 1; + Config()->m_ClNameplatesAlways = 1; + Config()->m_ClNameplatesSize = 50; + Config()->m_ClNameplatesTeamcolors = 1; + Config()->m_ClAutoDemoRecord = 0; + Config()->m_ClAutoDemoMax = 10; + Config()->m_ClAutoScreenshot = 0; + Config()->m_ClAutoScreenshotMax = 10; } } void CMenus::RenderSettingsPlayer(CUIRect MainView) { - static int s_PlayerCountry = Config()->Values()->m_PlayerCountry; + static int s_PlayerCountry = Config()->m_PlayerCountry; static char s_aPlayerName[256] = {0}; static char s_aPlayerClan[256] = {0}; if(!s_aPlayerName[0]) - str_copy(s_aPlayerName, Config()->Values()->m_PlayerName, sizeof(s_aPlayerName)); + str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); if(!s_aPlayerClan[0]) - str_copy(s_aPlayerClan, Config()->Values()->m_PlayerClan, sizeof(s_aPlayerClan)); + str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); CUIRect Button, Left, Right, TopView, Label, Background; @@ -1107,7 +1107,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1126,12 +1126,12 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) // left menu Left.HSplitTop(ButtonHeight, &Button, &Left); static float s_OffsetName = 0.0f; - DoEditBoxOption(Config()->Values()->m_PlayerName, Config()->Values()->m_PlayerName, sizeof(Config()->Values()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); + DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); // right menu Right.HSplitTop(ButtonHeight, &Button, &Right); static float s_OffsetClan = 0.0f; - DoEditBoxOption(Config()->Values()->m_PlayerClan, Config()->Values()->m_PlayerClan, sizeof(Config()->Values()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); + DoEditBoxOption(Config()->m_PlayerClan, Config()->m_PlayerClan, sizeof(Config()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); // country flag selector MainView.HSplitTop(10.0f, 0, &MainView); @@ -1145,7 +1145,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->GetByIndex(i); if(pEntry->m_Blocked) continue; - if(pEntry->m_CountryCode == Config()->Values()->m_PlayerCountry) + if(pEntry->m_CountryCode == Config()->m_PlayerCountry) OldSelected = i; CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); @@ -1178,14 +1178,14 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) const int NewSelected = s_ListBox.DoEnd(); if(OldSelected != NewSelected) - Config()->Values()->m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; + Config()->m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; // check if the new settings require a server reload m_NeedRestartPlayer = !( - s_PlayerCountry == Config()->Values()->m_PlayerCountry && - !str_comp(s_aPlayerClan, Config()->Values()->m_PlayerClan) && - !str_comp(s_aPlayerName, Config()->Values()->m_PlayerName) + s_PlayerCountry == Config()->m_PlayerCountry && + !str_comp(s_aPlayerClan, Config()->m_PlayerClan) && + !str_comp(s_aPlayerName, Config()->m_PlayerName) ); } @@ -1245,7 +1245,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) static bool s_CustomSkinMenu = false; static char s_aPlayerSkin[256] = {0}; if(!s_aPlayerSkin[0]) - str_copy(s_aPlayerSkin, Config()->Values()->m_PlayerSkin, sizeof(s_aPlayerSkin)); + str_copy(s_aPlayerSkin, Config()->m_PlayerSkin, sizeof(s_aPlayerSkin)); CUIRect Button, Label, BottomView, Preview, Background; @@ -1266,7 +1266,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Preview, &MainView); RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1401,7 +1401,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); Preview.y += 2.0f; - UI()->DoLabel(&Preview, Config()->Values()->m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Preview, Config()->m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -1416,7 +1416,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) float BackgroundWidth = s_CustomSkinMenu||(m_pSelectedSkin && (m_pSelectedSkin->m_Flags&CSkins::SKINFLAG_STANDARD) == 0) ? ButtonWidth*2.0f+SpacingW : ButtonWidth; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); if(s_CustomSkinMenu) @@ -1447,8 +1447,6 @@ void CMenus::RenderSettingsTee(CUIRect MainView) } } -//typedef void (*pfnAssignFuncCallback)(CConfiguration *pConfig, int Value); - void CMenus::RenderSettingsControls(CUIRect MainView) { // cut view @@ -1458,7 +1456,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); BottomView.HSplitTop(20.f, 0, &BottomView); @@ -1528,7 +1526,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; @@ -1542,48 +1540,48 @@ float CMenus::RenderSettingsControlsStats(CUIRect View) CUIRect Button; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos, Localize("Frags"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FRAGS; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos, Localize("Frags"), Config()->m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_FRAGS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+1, Localize("Deaths"), Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_DEATHS; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+1, Localize("Deaths"), Config()->m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_DEATHS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+2, Localize("Suicides"), Config()->Values()->m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_SUICIDES; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+2, Localize("Suicides"), Config()->m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_SUICIDES; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+3, Localize("Ratio"), Config()->Values()->m_ClStatboardInfos & TC_STATS_RATIO, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_RATIO; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+3, Localize("Ratio"), Config()->m_ClStatboardInfos & TC_STATS_RATIO, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_RATIO; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+4, Localize("Net score"), Config()->Values()->m_ClStatboardInfos & TC_STATS_NET, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_NET; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+4, Localize("Net score"), Config()->m_ClStatboardInfos & TC_STATS_NET, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_NET; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+5, Localize("Frags per minute"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FPM, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FPM; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+5, Localize("Frags per minute"), Config()->m_ClStatboardInfos & TC_STATS_FPM, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_FPM; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+6, Localize("Current spree"), Config()->Values()->m_ClStatboardInfos & TC_STATS_SPREE, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_SPREE; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+6, Localize("Current spree"), Config()->m_ClStatboardInfos & TC_STATS_SPREE, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_SPREE; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+7, Localize("Best spree"), Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_BESTSPREE; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+7, Localize("Best spree"), Config()->m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_BESTSPREE; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+9, Localize("Weapons stats"), Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_WEAPS; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+9, Localize("Weapons stats"), Config()->m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_WEAPS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+8, Localize("Flag grabs"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+8, Localize("Flag grabs"), Config()->m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; View.HSplitTop(20.0f, &Button, &View); - if(DoButton_CheckBox(&Config()->Values()->m_ClStatboardInfos+10, Localize("Flag captures"), Config()->Values()->m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) - Config()->Values()->m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; + if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+10, Localize("Flag captures"), Config()->m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) + Config()->m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; return 11*20.0f; } @@ -1598,8 +1596,8 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, for(int i = 0; i < lModes.size(); ++i) { - if(Config()->Values()->m_GfxScreenWidth == lModes[i].m_Width && - Config()->Values()->m_GfxScreenHeight == lModes[i].m_Height) + if(Config()->m_GfxScreenWidth == lModes[i].m_Width && + Config()->m_GfxScreenHeight == lModes[i].m_Height) { OldSelected = i; } @@ -1637,8 +1635,8 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, const int NewSelected = pListBox->DoEnd(); if(OldSelected != NewSelected) { - Config()->Values()->m_GfxScreenWidth = lModes[NewSelected].m_Width; - Config()->Values()->m_GfxScreenHeight = lModes[NewSelected].m_Height; + Config()->m_GfxScreenWidth = lModes[NewSelected].m_Width; + Config()->m_GfxScreenHeight = lModes[NewSelected].m_Height; return true; } return false; @@ -1648,11 +1646,11 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) { bool CheckSettings = false; - static int s_GfxScreenWidth = Config()->Values()->m_GfxScreenWidth; - static int s_GfxScreenHeight = Config()->Values()->m_GfxScreenHeight; - static int s_GfxFsaaSamples = Config()->Values()->m_GfxFsaaSamples; - static int s_GfxTextureQuality = Config()->Values()->m_GfxTextureQuality; - static int s_GfxTextureCompression = Config()->Values()->m_GfxTextureCompression; + static int s_GfxScreenWidth = Config()->m_GfxScreenWidth; + static int s_GfxScreenHeight = Config()->m_GfxScreenHeight; + static int s_GfxFsaaSamples = Config()->m_GfxFsaaSamples; + static int s_GfxTextureQuality = Config()->m_GfxTextureQuality; + static int s_GfxTextureCompression = Config()->m_GfxTextureCompression; CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView, Background; @@ -1662,7 +1660,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) // render screen menu background int NumOptions = 3; - if(Graphics()->GetNumScreens() > 1 && !Config()->Values()->m_GfxFullscreen) + if(Graphics()->GetNumScreens() > 1 && !Config()->m_GfxFullscreen) ++NumOptions; float ButtonHeight = 20.0f; float Spacing = 2.0f; @@ -1672,7 +1670,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &ScreenLeft, &MainView); RenderTools()->DrawUIRect(&ScreenLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1697,16 +1695,16 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft); ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); static int s_ButtonGfxFullscreen = 0; - if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), Config()->Values()->m_GfxFullscreen, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), Config()->m_GfxFullscreen, &Button)) Client()->ToggleFullscreen(); - if(!Config()->Values()->m_GfxFullscreen) + if(!Config()->m_GfxFullscreen) { ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft); ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonGfxBorderless = 0; - if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), Config()->Values()->m_GfxBorderless, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), Config()->m_GfxBorderless, &Button)) Client()->ToggleWindowBordered(); } @@ -1724,12 +1722,12 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(120.0f, &Button, 0); - str_format(aBuf, sizeof(aBuf), "#%d (%dx%d)", Config()->Values()->m_GfxScreen+1, Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); + str_format(aBuf, sizeof(aBuf), "#%d (%dx%d)", Config()->m_GfxScreen+1, Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); static CButtonContainer s_ButtonScreenId; if(DoButton_Menu(&s_ButtonScreenId, aBuf, 0, &Button)) { - Config()->Values()->m_GfxScreen = (Config()->Values()->m_GfxScreen + 1) % Graphics()->GetNumScreens(); - Client()->SwitchWindowScreen(Config()->Values()->m_GfxScreen); + Config()->m_GfxScreen = (Config()->m_GfxScreen + 1) % Graphics()->GetNumScreens(); + Client()->SwitchWindowScreen(Config()->m_GfxScreen); } } @@ -1748,16 +1746,16 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); Button.VSplitLeft(70.0f, &Button, 0); - str_format(aBuf, sizeof(aBuf), "%dx", Config()->Values()->m_GfxFsaaSamples); + str_format(aBuf, sizeof(aBuf), "%dx", Config()->m_GfxFsaaSamples); static CButtonContainer s_ButtonGfxFsaaSamples; if(DoButton_Menu(&s_ButtonGfxFsaaSamples, aBuf, 0, &Button)) { - if(!Config()->Values()->m_GfxFsaaSamples) - Config()->Values()->m_GfxFsaaSamples = 2; - else if(Config()->Values()->m_GfxFsaaSamples == 16) - Config()->Values()->m_GfxFsaaSamples = 0; + if(!Config()->m_GfxFsaaSamples) + Config()->m_GfxFsaaSamples = 2; + else if(Config()->m_GfxFsaaSamples == 16) + Config()->m_GfxFsaaSamples = 0; else - Config()->Values()->m_GfxFsaaSamples *= 2; + Config()->m_GfxFsaaSamples *= 2; CheckSettings = true; } } @@ -1765,26 +1763,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); static int s_ButtonGfxVsync = 0; - if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), Config()->Values()->m_GfxVsync, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), Config()->m_GfxVsync, &Button)) Client()->ToggleWindowVSync(); ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); // TODO: greyed out checkbox (not clickable) - if(!Config()->Values()->m_GfxVsync) + if(!Config()->m_GfxVsync) { static int s_ButtonGfxCapFps = 0; - if(DoButton_CheckBox(&s_ButtonGfxCapFps, Localize("Limit Fps"), Config()->Values()->m_GfxLimitFps, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxCapFps, Localize("Limit Fps"), Config()->m_GfxLimitFps, &Button)) { - Config()->Values()->m_GfxLimitFps ^= 1; + Config()->m_GfxLimitFps ^= 1; } - if(Config()->Values()->m_GfxLimitFps > 0) + if(Config()->m_GfxLimitFps > 0) { ScreenRight.HSplitTop(Spacing, 0, &ScreenRight); ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight); - DoScrollbarOption(&Config()->Values()->m_GfxMaxFps, &Config()->Values()->m_GfxMaxFps, + DoScrollbarOption(&Config()->m_GfxMaxFps, &Config()->m_GfxMaxFps, &Button, Localize("Max fps"), 30, 300); } } @@ -1797,26 +1795,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureQuality = 0; - if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), Config()->Values()->m_GfxTextureQuality, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), Config()->m_GfxTextureQuality, &Button)) { - Config()->Values()->m_GfxTextureQuality ^= 1; + Config()->m_GfxTextureQuality ^= 1; CheckSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureCompression = 0; - if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), Config()->Values()->m_GfxTextureCompression, &Button)) + if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), Config()->m_GfxTextureCompression, &Button)) { - Config()->Values()->m_GfxTextureCompression ^= 1; + Config()->m_GfxTextureCompression ^= 1; CheckSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxHighDetail = 0; - if(DoButton_CheckBox(&s_ButtonGfxHighDetail, Localize("High Detail"), Config()->Values()->m_GfxHighDetail, &Button)) - Config()->Values()->m_GfxHighDetail ^= 1; + if(DoButton_CheckBox(&s_ButtonGfxHighDetail, Localize("High Detail"), Config()->m_GfxHighDetail, &Button)) + Config()->m_GfxHighDetail ^= 1; // render screen modes MainView.HSplitTop(10.0f, 0, &MainView); @@ -1881,26 +1879,26 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->Values()->m_GfxScreenWidth = Graphics()->DesktopWidth(); - Config()->Values()->m_GfxScreenHeight = Graphics()->DesktopHeight(); - Config()->Values()->m_GfxBorderless = 0; - Config()->Values()->m_GfxFullscreen = 1; - Config()->Values()->m_GfxVsync = 1; - Config()->Values()->m_GfxFsaaSamples = 0; - Config()->Values()->m_GfxTextureQuality = 1; - Config()->Values()->m_GfxTextureCompression = 0; - Config()->Values()->m_GfxHighDetail = 1; - - if(Config()->Values()->m_GfxDisplayAllModes) + Config()->m_GfxScreenWidth = Graphics()->DesktopWidth(); + Config()->m_GfxScreenHeight = Graphics()->DesktopHeight(); + Config()->m_GfxBorderless = 0; + Config()->m_GfxFullscreen = 1; + Config()->m_GfxVsync = 1; + Config()->m_GfxFsaaSamples = 0; + Config()->m_GfxTextureQuality = 1; + Config()->m_GfxTextureCompression = 0; + Config()->m_GfxHighDetail = 1; + + if(Config()->m_GfxDisplayAllModes) { - Config()->Values()->m_GfxDisplayAllModes = 0; + Config()->m_GfxDisplayAllModes = 0; UpdateVideoModeSettings(); } @@ -1910,11 +1908,11 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) // check if the new settings require a restart if(CheckSettings) { - if(s_GfxScreenWidth == Config()->Values()->m_GfxScreenWidth && - s_GfxScreenHeight == Config()->Values()->m_GfxScreenHeight && - s_GfxFsaaSamples == Config()->Values()->m_GfxFsaaSamples && - s_GfxTextureQuality == Config()->Values()->m_GfxTextureQuality && - s_GfxTextureCompression == Config()->Values()->m_GfxTextureCompression) + if(s_GfxScreenWidth == Config()->m_GfxScreenWidth && + s_GfxScreenHeight == Config()->m_GfxScreenHeight && + s_GfxFsaaSamples == Config()->m_GfxFsaaSamples && + s_GfxTextureQuality == Config()->m_GfxTextureQuality && + s_GfxTextureCompression == Config()->m_GfxTextureCompression) m_NeedRestartGraphics = false; else m_NeedRestartGraphics = true; @@ -1926,12 +1924,12 @@ void CMenus::RenderSettingsSound(CUIRect MainView) CUIRect Label, Button, Sound, Detail, BottomView, Background; // render sound menu background - int NumOptions = Config()->Values()->m_SndEnable ? 3 : 2; + int NumOptions = Config()->m_SndEnable ? 3 : 2; float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; float TotalHeight = BackgroundHeight; - if(Config()->Values()->m_SndEnable) + if(Config()->m_SndEnable) TotalHeight += 10.0f+2.0f*ButtonHeight+Spacing; MainView.HSplitBottom(MainView.h-TotalHeight-20.0f, &MainView, &BottomView); @@ -1939,13 +1937,13 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Background = MainView; else MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(BackgroundHeight, &Sound, &MainView); RenderTools()->DrawUIRect(&Sound, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // render detail menu background - if(Config()->Values()->m_SndEnable) + if(Config()->m_SndEnable) { BackgroundHeight = 2.0f*ButtonHeight+Spacing; @@ -1954,8 +1952,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) RenderTools()->DrawUIRect(&Detail, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); } - static int s_SndInit = Config()->Values()->m_SndInit; - static int s_SndRate = Config()->Values()->m_SndRate; + static int s_SndInit = Config()->m_SndInit; + static int s_SndRate = Config()->m_SndRate; // render sound menu Sound.HSplitTop(ButtonHeight, &Label, &Sound); @@ -1966,15 +1964,15 @@ void CMenus::RenderSettingsSound(CUIRect MainView) CUIRect UseSoundButton; Sound.HSplitTop(ButtonHeight, &UseSoundButton, &Sound); - if(Config()->Values()->m_SndEnable) + if(Config()->m_SndEnable) { Sound.HSplitTop(Spacing, 0, &Sound); Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonSndMusic = 0; - if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), Config()->Values()->m_SndMusic, &Button)) + if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), Config()->m_SndMusic, &Button)) { - Config()->Values()->m_SndMusic ^= 1; + Config()->m_SndMusic ^= 1; ToggleMusic(); } @@ -1982,8 +1980,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonSndNonactiveMute = 0; - if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), Config()->Values()->m_SndNonactiveMute, &Button)) - Config()->Values()->m_SndNonactiveMute ^= 1; + if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), Config()->m_SndNonactiveMute, &Button)) + Config()->m_SndNonactiveMute ^= 1; // render detail menu Detail.HSplitTop(ButtonHeight, &Label, &Detail); @@ -2014,26 +2012,26 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Unit.y += 2.0f; UI()->DoLabel(&Unit, "kHz", Unit.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - if(Config()->Values()->m_SndRate != 48000 && Config()->Values()->m_SndRate != 44100) - Config()->Values()->m_SndRate = 48000; - if(Config()->Values()->m_SndRate == 48000) + if(Config()->m_SndRate != 48000 && Config()->m_SndRate != 44100) + Config()->m_SndRate = 48000; + if(Config()->m_SndRate == 48000) str_copy(aBuf, "48.0", sizeof(aBuf)); else str_copy(aBuf, "44.1", sizeof(aBuf)); static CButtonContainer s_SampleRateButton; if(DoButton_Menu(&s_SampleRateButton, aBuf, 0, &Value)) { - if(Config()->Values()->m_SndRate == 48000) - Config()->Values()->m_SndRate = 44100; + if(Config()->m_SndRate == 48000) + Config()->m_SndRate = 44100; else - Config()->Values()->m_SndRate = 48000; + Config()->m_SndRate = 48000; } - m_NeedRestartSound = Config()->Values()->m_SndInit && (!s_SndInit || s_SndRate != Config()->Values()->m_SndRate); + m_NeedRestartSound = Config()->m_SndInit && (!s_SndInit || s_SndRate != Config()->m_SndRate); } Right.HSplitTop(ButtonHeight, &Button, &Right); - DoScrollbarOption(&Config()->Values()->m_SndVolume, &Config()->Values()->m_SndVolume, &Button, Localize("Volume"), 0, 100, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_SndVolume, &Config()->m_SndVolume, &Button, Localize("Volume"), 0, 100, &LogarithmicScrollbarScale); } else { @@ -2041,21 +2039,21 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Sound.HSplitTop(ButtonHeight, &Button, &Sound); Button.VSplitLeft(ButtonHeight, 0, &Button); static int s_ButtonInitSounds = 0; - if(DoButton_CheckBox(&s_ButtonInitSounds, Localize("Load the sound system"), Config()->Values()->m_SndInit, &Button)) + if(DoButton_CheckBox(&s_ButtonInitSounds, Localize("Load the sound system"), Config()->m_SndInit, &Button)) { - Config()->Values()->m_SndInit ^= 1; - m_NeedRestartSound = Config()->Values()->m_SndInit && (!s_SndInit || s_SndRate != Config()->Values()->m_SndRate); + Config()->m_SndInit ^= 1; + m_NeedRestartSound = Config()->m_SndInit && (!s_SndInit || s_SndRate != Config()->m_SndRate); } } static int s_ButtonSndEnable = 0; - if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), Config()->Values()->m_SndEnable, &UseSoundButton)) + if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), Config()->m_SndEnable, &UseSoundButton)) { - Config()->Values()->m_SndEnable ^= 1; - if(Config()->Values()->m_SndEnable) + Config()->m_SndEnable ^= 1; + if(Config()->m_SndEnable) { - Config()->Values()->m_SndInit = 1; - if(Config()->Values()->m_SndMusic) + Config()->m_SndInit = 1; + if(Config()->m_SndMusic) m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } else @@ -2069,40 +2067,40 @@ void CMenus::RenderSettingsSound(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->Values()->m_SndEnable = 1; - Config()->Values()->m_SndInit = 1; - if(!Config()->Values()->m_SndMusic) + Config()->m_SndEnable = 1; + Config()->m_SndInit = 1; + if(!Config()->m_SndMusic) { - Config()->Values()->m_SndMusic = 1; + Config()->m_SndMusic = 1; m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } - Config()->Values()->m_SndNonactiveMute = 0; - Config()->Values()->m_SndRate = 48000; - Config()->Values()->m_SndVolume = 100; + Config()->m_SndNonactiveMute = 0; + Config()->m_SndRate = 48000; + Config()->m_SndVolume = 100; } } void CMenus::RenderSettings(CUIRect MainView) { // handle which page should be rendered - if(Config()->Values()->m_UiSettingsPage == SETTINGS_GENERAL) + if(Config()->m_UiSettingsPage == SETTINGS_GENERAL) RenderSettingsGeneral(MainView); - else if(Config()->Values()->m_UiSettingsPage == SETTINGS_PLAYER) + else if(Config()->m_UiSettingsPage == SETTINGS_PLAYER) RenderSettingsPlayer(MainView); - else if(Config()->Values()->m_UiSettingsPage == SETTINGS_TEE) + else if(Config()->m_UiSettingsPage == SETTINGS_TEE) RenderSettingsTee(MainView); - else if(Config()->Values()->m_UiSettingsPage == SETTINGS_CONTROLS) + else if(Config()->m_UiSettingsPage == SETTINGS_CONTROLS) RenderSettingsControls(MainView); - else if(Config()->Values()->m_UiSettingsPage == SETTINGS_GRAPHICS) + else if(Config()->m_UiSettingsPage == SETTINGS_GRAPHICS) RenderSettingsGraphics(MainView); - else if(Config()->Values()->m_UiSettingsPage == SETTINGS_SOUND) + else if(Config()->m_UiSettingsPage == SETTINGS_SOUND) RenderSettingsSound(MainView); MainView.HSplitBottom(32.0f, 0, &MainView); @@ -2120,7 +2118,7 @@ void CMenus::RenderSettings(CUIRect MainView) // background CUIRect RestartWarning; MainView.HSplitTop(25.0f, &RestartWarning, 0); - RestartWarning.VMargin(Config()->Values()->m_UiWideview ? 210.0f : 140.0f, &RestartWarning); + RestartWarning.VMargin(Config()->m_UiWideview ? 210.0f : 140.0f, &RestartWarning); RenderTools()->DrawUIRect(&RestartWarning, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // text diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index 2dfa2599..36e178cc 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -28,7 +28,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) MainView.VMargin(MainView.w/2-190.0f, &TopMenu); TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); - RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 10.0f); + RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 10.0f); TopMenu.HSplitTop(145.0f, 0, &TopMenu); @@ -37,13 +37,13 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_SettingsButton; - if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_S)) + if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, Config()->m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_S)) NewPage = PAGE_SETTINGS; /*TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Bottom); static int s_LocalServerButton = 0; - if(Config()->Values()->m_ClShowStartMenuImages) + if(Config()->m_ClShowStartMenuImages) { if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", 10.0f, 0.5f)) { @@ -59,7 +59,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_DemoButton; - if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_D)) + if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, Config()->m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_D)) { NewPage = PAGE_DEMOS; DemolistPopulate(); @@ -71,9 +71,9 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_MapEditorButton; - if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) + if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, Config()->m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) { - Config()->Values()->m_ClEditor = 1; + Config()->m_ClEditor = 1; Input()->MouseModeRelative(); EditorHotkeyWasPressed = true; } @@ -86,11 +86,11 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_PlayButton; - if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, Config()->Values()->m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) - NewPage = Config()->Values()->m_UiBrowserPage; + if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, Config()->m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) + NewPage = Config()->m_UiBrowserPage; BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); - RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->Values()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); + RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static CButtonContainer s_QuitButton; diff --git a/src/game/client/components/motd.cpp b/src/game/client/components/motd.cpp index 2c5d19a4..870c2738 100644 --- a/src/game/client/components/motd.cpp +++ b/src/game/client/components/motd.cpp @@ -83,8 +83,8 @@ void CMotd::OnMessage(int MsgType, void *pRawMsg) } } - if(m_aServerMotd[0] && Config()->Values()->m_ClMotdTime) - m_ServerMotdTime = time_get()+time_freq()*Config()->Values()->m_ClMotdTime; + if(m_aServerMotd[0] && Config()->m_ClMotdTime) + m_ServerMotdTime = time_get()+time_freq()*Config()->m_ClMotdTime; else m_ServerMotdTime = 0; } diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index c6166bd6..7220c4f8 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -22,17 +22,17 @@ void CNamePlates::RenderNameplate( vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick); - float FontSize = 18.0f + 20.0f * Config()->Values()->m_ClNameplatesSize / 100.0f; + float FontSize = 18.0f + 20.0f * Config()->m_ClNameplatesSize / 100.0f; // render name plate if(m_pClient->m_LocalClientID != ClientID) { float a = 1; - if(Config()->Values()->m_ClNameplatesAlways == 0) + if(Config()->m_ClNameplatesAlways == 0) a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); char aName[64]; - str_format(aName, sizeof(aName), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: ""); + str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: ""); CTextCursor Cursor; float tw = TextRender()->TextWidth(0, FontSize, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(FontSize); @@ -40,7 +40,7 @@ void CNamePlates::RenderNameplate( TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a); TextRender()->TextColor(1.0f, 1.0f, 1.0f, a); - if(Config()->Values()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) TextRender()->TextColor(1.0f, 0.5f, 0.5f, a); @@ -50,7 +50,7 @@ void CNamePlates::RenderNameplate( const vec4 IdTextColor(0.1f, 0.1f, 0.1f, a); vec4 BgIdColor(1.0f, 1.0f, 1.0f, a * 0.5f); - if(Config()->Values()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) BgIdColor = vec4(1.0f, 0.5f, 0.5f, a * 0.5f); @@ -71,7 +71,7 @@ void CNamePlates::RenderNameplate( void CNamePlates::OnRender() { - if (!Config()->Values()->m_ClNameplates) + if (!Config()->m_ClNameplates) return; for(int i = 0; i < MAX_CLIENTS; i++) diff --git a/src/game/client/components/notifications.cpp b/src/game/client/components/notifications.cpp index b93e70e1..163cfd16 100644 --- a/src/game/client/components/notifications.cpp +++ b/src/game/client/components/notifications.cpp @@ -26,7 +26,7 @@ void CNotifications::Con_SndToggle(IConsole::IResult *pResult, void *pUserData) { CNotifications *pSelf = (CNotifications *)pUserData; - pSelf->Config()->Values()->m_SndEnable ^= 1; + pSelf->Config()->m_SndEnable ^= 1; pSelf->m_SoundToggleTime = pSelf->Client()->LocalTime(); } @@ -53,14 +53,14 @@ void CNotifications::RenderSoundNotification() const float Fade = min(1.0f, RemainingDisplayTime / FadeTime); // 0.0 ≤ Fade ≤ 1.0 - vec4 Color = (Config()->Values()->m_SndEnable == 0) ? vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.55f) : vec4(1.f/0xff*0x2b, 1.f/0xff*0xf9, 1.f/0xff*0x2b, 0.55f); + vec4 Color = (Config()->m_SndEnable == 0) ? vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.55f) : vec4(1.f/0xff*0x2b, 1.f/0xff*0xf9, 1.f/0xff*0x2b, 0.55f); Color = mix(vec4(Color.r, Color.g, Color.b, 0.0f), Color, 0.8*Fade); RenderTools()->DrawUIRect(&Area, Color, CUI::CORNER_ALL, 3.0f); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_SOUNDICONS].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f*Fade, 1.0f*Fade, 1.0f*Fade, 1.0f*Fade); - RenderTools()->SelectSprite(Config()->Values()->m_SndEnable ? SPRITE_SOUNDICON_ON : SPRITE_SOUNDICON_MUTE); + RenderTools()->SelectSprite(Config()->m_SndEnable ? SPRITE_SOUNDICON_ON : SPRITE_SOUNDICON_MUTE); IGraphics::CQuadItem QuadItem(Area.x, Area.y, Area.w, Area.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index f19b0fcd..a28f28bc 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -59,7 +59,7 @@ void CPlayers::RenderHook( // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -196,7 +196,7 @@ void CPlayers::RenderPlayer( } // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -426,7 +426,7 @@ void CPlayers::RenderPlayer( } // render the "shadow" tee - if(m_pClient->m_LocalClientID == ClientID && Config()->Values()->m_Debug) + if(m_pClient->m_LocalClientID == ClientID && Config()->m_Debug) { vec2 GhostPosition = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick()); CTeeRenderInfo Ghost = RenderInfo; diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 063d2d97..32568cab 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -118,7 +118,7 @@ float CScoreboard::RenderSpectators(float x, float y, float w) if(Multiple) TextRender()->TextEx(&Cursor, ", ", -1); - if(Config()->Values()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) + if(Config()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) { Cursor.m_X += Cursor.m_FontSize; } @@ -156,7 +156,7 @@ float CScoreboard::RenderSpectators(float x, float y, float w) if(Multiple) TextRender()->TextEx(&Cursor, ", ", -1); - if(Config()->Values()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) + if(Config()->m_ClShowUserId && Cursor.m_LineCount <= Cursor.m_MaxLines) { RenderTools()->DrawClientID(TextRender(), &Cursor, i); } @@ -194,7 +194,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c float Spacing = 2.0f; float PingOffset = x+Spacing, PingLength = 35.0f; float CountryFlagOffset = PingOffset+PingLength, CountryFlagLength = 20.f; - float IdSize = Config()->Values()->m_ClShowUserId ? LineHeight : 0.0f; + float IdSize = Config()->m_ClShowUserId ? LineHeight : 0.0f; float ReadyLength = ReadyMode ? 10.f : 0.f; float TeeOffset = CountryFlagOffset+CountryFlagLength+4.0f, TeeLength = 25*TeeSizeMod; float NameOffset = CountryFlagOffset+CountryFlagLength+IdSize, NameLength = 128.0f-IdSize/2-ReadyLength; @@ -569,7 +569,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c TextRender()->TextColor(1.0f, 1.0f, 0.0f, ColorAlpha); // id - if(Config()->Values()->m_ClShowUserId) + if(Config()->m_ClShowUserId) { TextRender()->SetCursor(&Cursor, NameOffset+TeeLength-IdSize+Spacing, y+Spacing, FontSize, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, pInfo->m_ClientID); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 5e782256..b6c16108 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -92,7 +92,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) if(DirType != IStorage::TYPE_SAVE) Part.m_Flags |= SKINFLAG_STANDARD; str_truncate(Part.m_aName, sizeof(Part.m_aName), pName, str_length(pName) - 4); - if(pSelf->Config()->Values()->m_Debug) + if(pSelf->Config()->m_Debug) { str_format(aBuf, sizeof(aBuf), "load skin part %s", Part.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins", aBuf); @@ -199,7 +199,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) Skin.m_Flags = SpecialSkin ? SKINFLAG_SPECIAL : 0; if(DirType != IStorage::TYPE_SAVE) Skin.m_Flags |= SKINFLAG_STANDARD; - if(pSelf->Config()->Values()->m_Debug) + if(pSelf->Config()->m_Debug) { str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins", aBuf); @@ -212,24 +212,24 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) void CSkins::OnInit() { - ms_apSkinVariables[SKINPART_BODY] = Config()->Values()->m_PlayerSkinBody; - ms_apSkinVariables[SKINPART_MARKING] = Config()->Values()->m_PlayerSkinMarking; - ms_apSkinVariables[SKINPART_DECORATION] = Config()->Values()->m_PlayerSkinDecoration; - ms_apSkinVariables[SKINPART_HANDS] = Config()->Values()->m_PlayerSkinHands; - ms_apSkinVariables[SKINPART_FEET] = Config()->Values()->m_PlayerSkinFeet; - ms_apSkinVariables[SKINPART_EYES] = Config()->Values()->m_PlayerSkinEyes; - ms_apUCCVariables[SKINPART_BODY] = &Config()->Values()->m_PlayerUseCustomColorBody; - ms_apUCCVariables[SKINPART_MARKING] = &Config()->Values()->m_PlayerUseCustomColorMarking; - ms_apUCCVariables[SKINPART_DECORATION] = &Config()->Values()->m_PlayerUseCustomColorDecoration; - ms_apUCCVariables[SKINPART_HANDS] = &Config()->Values()->m_PlayerUseCustomColorHands; - ms_apUCCVariables[SKINPART_FEET] = &Config()->Values()->m_PlayerUseCustomColorFeet; - ms_apUCCVariables[SKINPART_EYES] = &Config()->Values()->m_PlayerUseCustomColorEyes; - ms_apColorVariables[SKINPART_BODY] = &Config()->Values()->m_PlayerColorBody; - ms_apColorVariables[SKINPART_MARKING] = &Config()->Values()->m_PlayerColorMarking; - ms_apColorVariables[SKINPART_DECORATION] = &Config()->Values()->m_PlayerColorDecoration; - ms_apColorVariables[SKINPART_HANDS] = &Config()->Values()->m_PlayerColorHands; - ms_apColorVariables[SKINPART_FEET] = &Config()->Values()->m_PlayerColorFeet; - ms_apColorVariables[SKINPART_EYES] = &Config()->Values()->m_PlayerColorEyes; + ms_apSkinVariables[SKINPART_BODY] = Config()->m_PlayerSkinBody; + ms_apSkinVariables[SKINPART_MARKING] = Config()->m_PlayerSkinMarking; + ms_apSkinVariables[SKINPART_DECORATION] = Config()->m_PlayerSkinDecoration; + ms_apSkinVariables[SKINPART_HANDS] = Config()->m_PlayerSkinHands; + ms_apSkinVariables[SKINPART_FEET] = Config()->m_PlayerSkinFeet; + ms_apSkinVariables[SKINPART_EYES] = Config()->m_PlayerSkinEyes; + ms_apUCCVariables[SKINPART_BODY] = &Config()->m_PlayerUseCustomColorBody; + ms_apUCCVariables[SKINPART_MARKING] = &Config()->m_PlayerUseCustomColorMarking; + ms_apUCCVariables[SKINPART_DECORATION] = &Config()->m_PlayerUseCustomColorDecoration; + ms_apUCCVariables[SKINPART_HANDS] = &Config()->m_PlayerUseCustomColorHands; + ms_apUCCVariables[SKINPART_FEET] = &Config()->m_PlayerUseCustomColorFeet; + ms_apUCCVariables[SKINPART_EYES] = &Config()->m_PlayerUseCustomColorEyes; + ms_apColorVariables[SKINPART_BODY] = &Config()->m_PlayerColorBody; + ms_apColorVariables[SKINPART_MARKING] = &Config()->m_PlayerColorMarking; + ms_apColorVariables[SKINPART_DECORATION] = &Config()->m_PlayerColorDecoration; + ms_apColorVariables[SKINPART_HANDS] = &Config()->m_PlayerColorHands; + ms_apColorVariables[SKINPART_FEET] = &Config()->m_PlayerColorFeet; + ms_apColorVariables[SKINPART_EYES] = &Config()->m_PlayerColorEyes; for(int p = 0; p < NUM_SKINPARTS; p++) { diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 983537c3..0acb9c56 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -37,7 +37,7 @@ static int LoadSoundsThread(void *pUser) ISound::CSampleHandle CSounds::GetSampleId(int SetId) { - if(!Config()->Values()->m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + if(!Config()->m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) return ISound::CSampleHandle(); CDataSoundset *pSet = &g_pData->m_aSounds[SetId]; @@ -71,7 +71,7 @@ void CSounds::OnInit() ClearQueue(); // load sounds - if(Config()->Values()->m_SndAsyncLoading) + if(Config()->m_SndAsyncLoading) { g_UserData.m_pGameClient = m_pClient; g_UserData.m_Render = false; @@ -143,7 +143,7 @@ void CSounds::Enqueue(int Channel, int SetId) // add sound to the queue if(m_QueuePos < QUEUE_SIZE) { - if(Channel == CHN_MUSIC || !Config()->Values()->m_ClEditor) + if(Channel == CHN_MUSIC || !Config()->m_ClEditor) { m_aQueue[m_QueuePos].m_Channel = Channel; m_aQueue[m_QueuePos++].m_SetId = SetId; @@ -153,7 +153,7 @@ void CSounds::Enqueue(int Channel, int SetId) void CSounds::Play(int Chn, int SetId, float Vol) { - if(Chn == CHN_MUSIC && !Config()->Values()->m_SndMusic) + if(Chn == CHN_MUSIC && !Config()->m_SndMusic) return; ISound::CSampleHandle SampleId = GetSampleId(SetId); @@ -169,7 +169,7 @@ void CSounds::Play(int Chn, int SetId, float Vol) void CSounds::PlayAt(int Chn, int SetId, float Vol, vec2 Pos) { - if(Chn == CHN_MUSIC && !Config()->Values()->m_SndMusic) + if(Chn == CHN_MUSIC && !Config()->m_SndMusic) return; ISound::CSampleHandle SampleId = GetSampleId(SetId); diff --git a/src/game/client/components/spectator.cpp b/src/game/client/components/spectator.cpp index d55d0740..8f558d78 100644 --- a/src/game/client/components/spectator.cpp +++ b/src/game/client/components/spectator.cpp @@ -308,7 +308,7 @@ void CSpectator::OnRender() } TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f); char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s", Config()->Values()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); + str_format(aBuf, sizeof(aBuf), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : ""); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Width/2.0f+x+50.0f, Height/2.0f+y+5.0f, FontSize, TEXTFLAG_RENDER); diff --git a/src/game/client/components/stats.cpp b/src/game/client/components/stats.cpp index b8e168cc..9fa1359f 100644 --- a/src/game/client/components/stats.cpp +++ b/src/game/client/components/stats.cpp @@ -49,7 +49,7 @@ void CStats::OnReset() bool CStats::IsActive() const { // force statboard after three seconds of game over if autostatscreenshot is on - if(Config()->Values()->m_ClAutoStatScreenshot && m_ScreenshotTime > -1 && m_ScreenshotTime < time_get()) + if(Config()->m_ClAutoStatScreenshot && m_ScreenshotTime > -1 && m_ScreenshotTime < time_get()) return true; return m_Active; @@ -113,7 +113,7 @@ void CStats::OnMessage(int MsgType, void *pRawMsg) void CStats::OnRender() { // auto stat screenshot stuff - if(Config()->Values()->m_ClAutoStatScreenshot) + if(Config()->m_ClAutoStatScreenshot) { // on game over, wait three seconds if(m_ScreenshotTime < 0 && m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) @@ -161,16 +161,16 @@ void CStats::OnRender() } for(int i=0; i<9; i++) - if(Config()->Values()->m_ClStatboardInfos & (1<m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & TC_STATS_FRAGS) + if((1<m_ClStatboardInfos & TC_STATS_FRAGS) { w += 60; // some extra for the merge continue; } else if((1<Values()->m_ClStatboardInfos & TC_STATS_SPREE)) + if(!(Config()->m_ClStatboardInfos & TC_STATS_SPREE)) w += 140; // Best spree is a long column name, add a bit more else w += 40; // The combined colunms are a bit long, add some extra @@ -181,12 +181,12 @@ void CStats::OnRender() w += 100; } - if((m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS) && (Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES)) + if((m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS) && (Config()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES)) w += 100; bool aDisplayWeapon[NUM_WEAPONS] = {false}; bool NoDisplayedWeapon = true; - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->m_ClStatboardInfos & TC_STATS_WEAPS) { for(i=0; iText(0, x+10, y-5, 20.0f, Localize("Name"), -1.0f); const char *apHeaders[] = { "K", "D", Localize("Suicides"), Localize("Ratio"), Localize("Net", "Net score"), Localize("FPM"), Localize("Spree"), Localize("Best spree"), Localize("Grabs", "Flag grabs") }; for(i=0; i<9; i++) - if(Config()->Values()->m_ClStatboardInfos & (1<m_ClStatboardInfos & (1<Values()->m_ClStatboardInfos & TC_STATS_DEATHS) + if(1<m_ClStatboardInfos & TC_STATS_DEATHS) { pText = "K:D"; px += 60.0f; // some extra for the merge } - else if(1<Values()->m_ClStatboardInfos & TC_STATS_FRAGS) + else if(1<m_ClStatboardInfos & TC_STATS_FRAGS) continue; // handle spree columns merge if(1<Values()->m_ClStatboardInfos & TC_STATS_SPREE) + if(Config()->m_ClStatboardInfos & TC_STATS_SPREE) continue; px += 40.0f; // some extra for the long name } - else if(1<Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) + else if(1<m_ClStatboardInfos & TC_STATS_BESTSPREE) px += 40.0f; // some extra for the merge if(1<m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS)) continue; @@ -249,7 +249,7 @@ void CStats::OnRender() } // sprite headers now - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->m_ClStatboardInfos & TC_STATS_WEAPS) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); @@ -270,7 +270,7 @@ void CStats::OnRender() px += 10; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) { px -= 40; Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); @@ -334,9 +334,9 @@ void CStats::OnRender() TextRender()->TextEx(&Cursor, m_pClient->m_aClients[apPlayers[j]].m_aName, -1); px = 325; - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_FRAGS) + if(Config()->m_ClStatboardInfos & TC_STATS_FRAGS) { - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS) + if(Config()->m_ClStatboardInfos & TC_STATS_DEATHS) { px += 60; str_format(aBuf, sizeof(aBuf), "%d:%d", pStats->m_Frags, pStats->m_Deaths); @@ -347,21 +347,21 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - else if(Config()->Values()->m_ClStatboardInfos & TC_STATS_DEATHS) + else if(Config()->m_ClStatboardInfos & TC_STATS_DEATHS) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_Deaths); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_SUICIDES) + if(Config()->m_ClStatboardInfos & TC_STATS_SUICIDES) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_Suicides); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_RATIO) + if(Config()->m_ClStatboardInfos & TC_STATS_RATIO) { if(pStats->m_Deaths == 0) str_format(aBuf, sizeof(aBuf), "--"); @@ -371,14 +371,14 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_NET) + if(Config()->m_ClStatboardInfos & TC_STATS_NET) { str_format(aBuf, sizeof(aBuf), "%+d", pStats->m_Frags-pStats->m_Deaths); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_FPM) + if(Config()->m_ClStatboardInfos & TC_STATS_FPM) { float Fpm = pStats->m_IngameTicks > 0 ? (float)(pStats->m_Frags * Client()->GameTickSpeed() * 60) / pStats->m_IngameTicks : 0.f; str_format(aBuf, sizeof(aBuf), "%.1f", Fpm); @@ -386,9 +386,9 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_SPREE) + if(Config()->m_ClStatboardInfos & TC_STATS_SPREE) { - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) + if(Config()->m_ClStatboardInfos & TC_STATS_BESTSPREE) { px += 40; // extra space str_format(aBuf, sizeof(aBuf), "%d (%d)", pStats->m_CurrentSpree, pStats->m_BestSpree); @@ -399,7 +399,7 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - else if(Config()->Values()->m_ClStatboardInfos & TC_STATS_BESTSPREE) + else if(Config()->m_ClStatboardInfos & TC_STATS_BESTSPREE) { px += 40; str_format(aBuf, sizeof(aBuf), "%d", pStats->m_BestSpree); @@ -407,7 +407,7 @@ void CStats::OnRender() TextRender()->Text(0, x-tw+px, y, FontSize, aBuf, -1.0f); px += 100; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGGRABS) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->m_ClStatboardInfos&TC_STATS_FLAGGRABS) { str_format(aBuf, sizeof(aBuf), "%d", pStats->m_FlagGrabs); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); @@ -415,7 +415,7 @@ void CStats::OnRender() px += 100; } px -= 40; - if(Config()->Values()->m_ClStatboardInfos & TC_STATS_WEAPS) + if(Config()->m_ClStatboardInfos & TC_STATS_WEAPS) { const float BarHeight = 0.3f*LineHeight; const float Offset = 40.0f; @@ -462,7 +462,7 @@ void CStats::OnRender() px += 10; } - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->Values()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) + if(m_pClient->m_Snap.m_pGameData && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && Config()->m_ClStatboardInfos&TC_STATS_FLAGCAPTURES) { if(pStats->m_FlagCaptures <= 0) { diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index c4398ca3..e2b75b34 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -191,20 +191,20 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) case VOTE_START_KICK: { char aName[4]; - if(!Config()->Values()->m_ClShowsocial) + if(!Config()->m_ClShowsocial) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); - str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to kick '%s' (%s)"), aLabel, Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); - str_format(m_aDescription, sizeof(m_aDescription), "Kick '%s'", Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName); + str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to kick '%s' (%s)"), aLabel, Config()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); + str_format(m_aDescription, sizeof(m_aDescription), "Kick '%s'", Config()->m_ClShowsocial ? pMsg->m_pDescription : aName); m_pClient->m_pChat->AddLine(aBuf); break; } case VOTE_START_SPEC: { char aName[4]; - if(!Config()->Values()->m_ClShowsocial) + if(!Config()->m_ClShowsocial) str_copy(aName, pMsg->m_pDescription, sizeof(aName)); - str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to move '%s' to spectators (%s)"), aLabel, Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); - str_format(m_aDescription, sizeof(m_aDescription), "Move '%s' to spectators", Config()->Values()->m_ClShowsocial ? pMsg->m_pDescription : aName); + str_format(aBuf, sizeof(aBuf), Localize("'%s' called for vote to move '%s' to spectators (%s)"), aLabel, Config()->m_ClShowsocial ? pMsg->m_pDescription : aName, pMsg->m_pReason); + str_format(m_aDescription, sizeof(m_aDescription), "Move '%s' to spectators", Config()->m_ClShowsocial ? pMsg->m_pDescription : aName); m_pClient->m_pChat->AddLine(aBuf); } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 69c2fae0..5d294c40 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -131,8 +131,8 @@ const char *CGameClient::NetVersionHashUsed() const { return GAME_NETVERSION_HAS const char *CGameClient::NetVersionHashReal() const{ return GAME_NETVERSION_HASH; } int CGameClient::ClientVersion() const { return CLIENT_VERSION; } const char *CGameClient::GetItemName(int Type) const { return m_NetObjHandler.GetObjName(Type); } -bool CGameClient::IsXmas() const { return Config()->Values()->m_ClShowXmasHats == 2 || (Config()->Values()->m_ClShowXmasHats == 1 && m_IsXmasDay); } -bool CGameClient::IsEaster() const { return Config()->Values()->m_ClShowEasterEggs == 2 || (Config()->Values()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } +bool CGameClient::IsXmas() const { return Config()->m_ClShowXmasHats == 2 || (Config()->m_ClShowXmasHats == 1 && m_IsXmasDay); } +bool CGameClient::IsEaster() const { return Config()->m_ClShowEasterEggs == 2 || (Config()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } enum { @@ -159,9 +159,9 @@ static int GetStrTeam(int Team, bool Teamplay) void CGameClient::GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName) { - if(!Config()->Values()->m_ClShowsocial) + if(!Config()->m_ClShowsocial) str_format(aBuf, BufferSize, "%2d:", ClientID); - else if(Config()->Values()->m_ClShowUserId) + else if(Config()->m_ClShowUserId) str_format(aBuf, BufferSize, "%2d: %s", ClientID, ClientName); else str_format(aBuf, BufferSize, "%s", ClientName); @@ -210,7 +210,7 @@ void CGameClient::OnConsoleInit() m_pTextRender = Kernel()->RequestInterface(); m_pSound = Kernel()->RequestInterface(); m_pInput = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); m_pDemoPlayer = Kernel()->RequestInterface(); @@ -345,7 +345,7 @@ void CGameClient::OnInit() int64 Start = time_get(); // set the language - g_Localization.Load(Config()->Values()->m_ClLanguagefile, Storage(), Console()); + g_Localization.Load(Config()->m_ClLanguagefile, Storage(), Console()); // TODO: this should be different // setup item sizes @@ -357,7 +357,7 @@ void CGameClient::OnInit() // load default font char aFontName[256]; - str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->Values()->m_ClFontfile); + str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->m_ClFontfile); char aFilename[512]; IOHANDLE File = Storage()->OpenFile(aFontName, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); if(File) @@ -477,7 +477,7 @@ void CGameClient::OnReset() void CGameClient::UpdatePositions() { // local character position - if(Config()->Values()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + if(Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) @@ -760,7 +760,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { if(m_LocalClientID != -1) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid local clientinfo"); return; } @@ -771,7 +771,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { if(m_aClients[pMsg->m_ClientID].m_Active) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientinfo"); return; } @@ -832,7 +832,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(m_LocalClientID == pMsg->m_ClientID || !m_aClients[pMsg->m_ClientID].m_Active) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop"); return; } @@ -863,7 +863,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(!m_aClients[pMsg->m_ClientID].m_Active) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid skin info"); return; } @@ -977,7 +977,7 @@ void CGameClient::OnEnterGame() {} void CGameClient::OnGameOver() { - if(Client()->State() != IClient::STATE_DEMOPLAYBACK && Config()->Values()->m_ClEditor == 0) + if(Client()->State() != IClient::STATE_DEMOPLAYBACK && Config()->m_ClEditor == 0) Client()->AutoScreenshot_Start(); } @@ -1088,7 +1088,7 @@ void CGameClient::OnNewSnapshot() const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID); @@ -1101,7 +1101,7 @@ void CGameClient::OnNewSnapshot() ProcessEvents(); - if(Config()->Values()->m_DbgStress) + if(Config()->m_DbgStress) { if((Client()->GameTick()%100) == 0) { @@ -1536,7 +1536,7 @@ void CGameClient::OnPredict() m_PredictedChar = *World.m_apCharacters[m_LocalClientID]; } - if(Config()->Values()->m_Debug && Config()->Values()->m_ClPredict && m_PredictedTick == Client()->PredGameTick()) + if(Config()->m_Debug && Config()->m_ClPredict && m_PredictedTick == Client()->PredGameTick()) { CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; BeforeChar.Write(&Before); @@ -1744,9 +1744,9 @@ void CGameClient::SendSwitchTeam(int Team) void CGameClient::SendStartInfo() { CNetMsg_Cl_StartInfo Msg; - Msg.m_pName = Config()->Values()->m_PlayerName; - Msg.m_pClan = Config()->Values()->m_PlayerClan; - Msg.m_Country = Config()->Values()->m_PlayerCountry; + Msg.m_pName = Config()->m_PlayerName; + Msg.m_pClan = Config()->m_PlayerClan; + Msg.m_Country = Config()->m_PlayerCountry; for(int p = 0; p < NUM_SKINPARTS; p++) { Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 533608ef..99fbd25a 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -37,7 +37,7 @@ class CGameClient : public IGameClient class ITextRender *m_pTextRender; class IClient *m_pClient; class ISound *m_pSound; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; class IStorage *m_pStorage; class IDemoPlayer *m_pDemoPlayer; @@ -81,7 +81,7 @@ class CGameClient : public IGameClient class ISound *Sound() const { return m_pSound; } class IInput *Input() const { return m_pInput; } class IStorage *Storage() const { return m_pStorage; } - class IConfig *Config() const { return m_pConfig; } + class CConfig *Config() const { return m_pConfig; } class IConsole *Console() { return m_pConsole; } class ITextRender *TextRender() const { return m_pTextRender; } class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; } diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index c6ae574b..25bf511d 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -16,7 +16,7 @@ static float gs_SpriteWScale; static float gs_SpriteHScale; -void CRenderTools::Init(IConfig *pConfig, IGraphics *pGraphics, CUI *pUI) +void CRenderTools::Init(CConfig *pConfig, IGraphics *pGraphics, CUI *pUI) { m_pConfig = pConfig; m_pGraphics = pGraphics; @@ -531,7 +531,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, const CTeeRenderInfo *pInfo, int } else { - bool Indicate = !pInfo->m_GotAirJump && m_pConfig->Values()->m_ClAirjumpindicator; + bool Indicate = !pInfo->m_GotAirJump && m_pConfig->m_ClAirjumpindicator; float cs = 1.0f; // color scale if(Indicate) cs = 0.5f; @@ -667,7 +667,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) void CRenderTools::DrawClientID(ITextRender* pTextRender, CTextCursor* pCursor, int ID, const vec4& BgColor, const vec4& TextColor) { - if(!m_pConfig->Values()->m_ClShowUserId) return; + if(!m_pConfig->m_ClShowUserId) return; char aBuff[4]; str_format(aBuff, sizeof(aBuff), "%2d ", ID); @@ -712,6 +712,6 @@ void CRenderTools::DrawClientID(ITextRender* pTextRender, CTextCursor* pCursor, float CRenderTools::GetClientIdRectSize(float FontSize) { - if(!m_pConfig->Values()->m_ClShowUserId) return 0; + if(!m_pConfig->m_ClShowUserId) return 0; return 1.4f * FontSize + 0.2f * FontSize; } diff --git a/src/game/client/render.h b/src/game/client/render.h index 55d43646..2eaac606 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -52,7 +52,7 @@ class CRenderTools void DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners); - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IGraphics *m_pGraphics; class CUI *m_pUI; public: @@ -60,7 +60,7 @@ class CRenderTools class IGraphics *Graphics() const { return m_pGraphics; } class CUI *UI() const { return m_pUI; } - void Init(class IConfig *pConfig, class IGraphics *pGraphics, class CUI *pUI); + void Init(class CConfig *pConfig, class IGraphics *pGraphics, class CUI *pUI); void SelectSprite(struct CDataSprite *pSprite, int Flags=0, int sx=0, int sy=0); void SelectSprite(int id, int Flags=0, int sx=0, int sy=0); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index eca8d6fe..4271d9e0 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -63,7 +63,7 @@ bool CUI::MouseInsideClip() const void CUI::ConvertMouseMove(float *x, float *y) const { - float Fac = (float)(m_pConfig->Values()->m_UiMousesens)/m_pConfig->Values()->m_InpMousesens; + float Fac = (float)(m_pConfig->m_UiMousesens)/m_pConfig->m_InpMousesens; *x = *x*Fac; *y = *y*Fac; } diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 655e1b44..1bb3fd17 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -44,14 +44,14 @@ class CUI unsigned m_NumClips; void UpdateClipping(); - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; public: // TODO: Refactor: Fill this in - void Init(class IConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } - class IConfig *Config() const { return m_pConfig; } + void Init(class CConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } + class CConfig *Config() const { return m_pConfig; } class IGraphics *Graphics() const { return m_pGraphics; } class ITextRender *TextRender() const { return m_pTextRender; } diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 7dcd64c9..8247ad6b 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -253,7 +253,7 @@ void CEditorImage::LoadAutoMapper() // clean up json_value_free(pJsonData); - if(m_pAutoMapper && m_pEditor->Config()->Values()->m_Debug) + if(m_pAutoMapper && m_pEditor->Config()->m_Debug) { str_format(aBuf, sizeof(aBuf),"loaded %s.json (%s)", m_aName, IAutoMapper::GetTypeName(m_pAutoMapper->GetType())); m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "editor", aBuf); @@ -666,18 +666,18 @@ void CEditor::RenderGrid(CLayerGroup *pGroup) for(int i = 0; i < (int)w; i++) { if((i+YGridOffset) % m_GridFactor == 0) - GridColor = HexToRgba(Config()->Values()->m_EdColorGridOuter); + GridColor = HexToRgba(Config()->m_EdColorGridOuter); else - GridColor = HexToRgba(Config()->Values()->m_EdColorGridInner); + GridColor = HexToRgba(Config()->m_EdColorGridInner); Graphics()->SetColor(GridColor.r, GridColor.g, GridColor.b, GridColor.a); IGraphics::CLineItem Line = IGraphics::CLineItem(LineDistance*XOffset, LineDistance*i+LineDistance*YOffset, w+aGroupPoints[2], LineDistance*i+LineDistance*YOffset); Graphics()->LinesDraw(&Line, 1); if((i+XGridOffset) % m_GridFactor == 0) - GridColor = HexToRgba(Config()->Values()->m_EdColorGridOuter); + GridColor = HexToRgba(Config()->m_EdColorGridOuter); else - GridColor = HexToRgba(Config()->Values()->m_EdColorGridInner); + GridColor = HexToRgba(Config()->m_EdColorGridInner); Graphics()->SetColor(GridColor.r, GridColor.g, GridColor.b, GridColor.a); Line = IGraphics::CLineItem(LineDistance*i+LineDistance*XOffset, LineDistance*YOffset, LineDistance*i+LineDistance*XOffset, h+aGroupPoints[3]); @@ -1301,13 +1301,13 @@ void CEditor::DoQuad(CQuad *q, int Index) } } - PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivotActive); + PivotColor = HexToRgba(Config()->m_EdColorQuadPivotActive); } else if(UI()->HotItem() == pID) { ms_pUiGotContext = pID; - PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivotHover); + PivotColor = HexToRgba(Config()->m_EdColorQuadPivotHover); m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. Hold alt to ignore grid."; if(UI()->MouseButton(0)) @@ -1345,7 +1345,7 @@ void CEditor::DoQuad(CQuad *q, int Index) } } else - PivotColor = HexToRgba(Config()->Values()->m_EdColorQuadPivot); + PivotColor = HexToRgba(Config()->m_EdColorQuadPivot); Graphics()->SetColor(PivotColor.r, PivotColor.g, PivotColor.b, PivotColor.a); IGraphics::CQuadItem QuadItem(CenterX, CenterY, 5.0f*m_WorldZoom, 5.0f*m_WorldZoom); @@ -1482,13 +1482,13 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) } } - pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPointActive); + pointColor = HexToRgba(Config()->m_EdColorQuadPointActive); } else if(UI()->HotItem() == pID) { ms_pUiGotContext = pID; - pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPointHover); + pointColor = HexToRgba(Config()->m_EdColorQuadPointHover); m_pTooltip = "Left mouse button to move. Hold shift to move the texture. Hold alt to ignore grid."; if(UI()->MouseButton(0)) @@ -1530,7 +1530,7 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) } } else - pointColor = HexToRgba(Config()->Values()->m_EdColorQuadPoint); + pointColor = HexToRgba(Config()->m_EdColorQuadPoint); Graphics()->SetColor(pointColor.r, pointColor.g, pointColor.b, pointColor.a); IGraphics::CQuadItem QuadItem(px, py, 5.0f*m_WorldZoom, 5.0f*m_WorldZoom); @@ -4260,7 +4260,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) pEditor->m_PopupEventActivated = true; } else - pEditor->Config()->Values()->m_ClEditor = 0; + pEditor->Config()->m_ClEditor = 0; return 1; } @@ -4294,7 +4294,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar) ExitButton.VSplitRight(13.f, 0, &ExitButton); if(DoButton_Editor(&s_ExitButton, "\xE2\x9C\x95", 1, &ExitButton, 0, "[ctrl+shift+e] Exit")) { - Config()->Values()->m_ClEditor ^= 1; + Config()->m_ClEditor ^= 1; Input()->MouseModeRelative(); } } @@ -4368,7 +4368,7 @@ void CEditor::Render() { float OldLevel = m_ZoomLevel; m_ZoomLevel = clamp(m_ZoomLevel + Zoom * 20, 50, 2000); - if(Config()->Values()->m_EdZoomTarget) + if(Config()->m_EdZoomTarget) ZoomMouseTarget((float)m_ZoomLevel / OldLevel); } } @@ -4441,7 +4441,7 @@ void CEditor::Render() RenderStatusbar(StatusBar); // todo: fix this - if(Config()->Values()->m_EdShowkeys) + if(Config()->m_EdShowkeys) { Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); CTextCursor Cursor; @@ -4663,7 +4663,7 @@ void CEditor::Init() { m_pInput = Kernel()->RequestInterface(); m_pClient = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); m_pGraphics = Kernel()->RequestInterface(); m_pTextRender = Kernel()->RequestInterface(); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index c0e5dc64..3a6228bc 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -502,7 +502,7 @@ class CEditor : public IEditor { class IInput *m_pInput; class IClient *m_pClient; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; @@ -512,7 +512,7 @@ class CEditor : public IEditor public: class IInput *Input() { return m_pInput; }; class IClient *Client() { return m_pClient; }; - class IConfig *Config() { return m_pConfig; } + class CConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; }; class IGraphics *Graphics() { return m_pGraphics; }; class ITextRender *TextRender() { return m_pTextRender; }; diff --git a/src/game/editor/layer_quads.cpp b/src/game/editor/layer_quads.cpp index f60b902e..5a94fb3a 100644 --- a/src/game/editor/layer_quads.cpp +++ b/src/game/editor/layer_quads.cpp @@ -81,7 +81,7 @@ CQuad *CLayerQuads::NewQuad() void CLayerQuads::BrushSelecting(CUIRect Rect) { // draw selection rectangle - vec4 RectColor = HexToRgba(m_pEditor->Config()->Values()->m_EdColorSelectionQuad); + vec4 RectColor = HexToRgba(m_pEditor->Config()->m_EdColorSelectionQuad); IGraphics::CLineItem Array[4] = { IGraphics::CLineItem(Rect.x, Rect.y, Rect.x+Rect.w, Rect.y), IGraphics::CLineItem(Rect.x+Rect.w, Rect.y, Rect.x+Rect.w, Rect.y+Rect.h), diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 7f560ae4..0174ab58 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -216,7 +216,7 @@ void CLayerTiles::Clamp(RECTi *pRect) void CLayerTiles::BrushSelecting(CUIRect Rect) { - vec4 FillColor = HexToRgba(m_pEditor->Config()->Values()->m_EdColorSelectionTile); + vec4 FillColor = HexToRgba(m_pEditor->Config()->m_EdColorSelectionTile); Graphics()->TextureClear(); m_pEditor->Graphics()->QuadsBegin(); diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 34f73515..91010066 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -795,7 +795,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) if(pEditor->DoButton_Editor(&s_OkButton, "Ok", 0, &Label, 0, 0)) { if(pEditor->m_PopupEventType == POPEVENT_EXIT) - pEditor->Config()->Values()->m_ClEditor = 0; + pEditor->Config()->m_ClEditor = 0; else if(pEditor->m_PopupEventType == POPEVENT_LOAD) pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", pEditor->CallbackOpenMap, pEditor); else if(pEditor->m_PopupEventType == POPEVENT_LOAD_CURRENT) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 8da2865d..4d170dac 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -288,7 +288,7 @@ void CCharacter::FireWeapon() vec2 ProjStartPos = m_Pos+Direction*GetProximityRadius()*0.75f; - if(GameServer()->Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "shot player='%d:%s' team=%d weapon=%d", m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), m_pPlayer->GetTeam(), m_ActiveWeapon); @@ -845,7 +845,7 @@ void CCharacter::Snap(int SnappingClient) pCharacter->m_Direction = m_Input.m_Direction; if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 || - (!GameServer()->Config()->Values()->m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID())) + (!Config()->m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID())) { pCharacter->m_Health = m_Health; pCharacter->m_Armor = m_Armor; diff --git a/src/game/server/entity.h b/src/game/server/entity.h index abe3b2c7..12c63cc4 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -59,6 +59,7 @@ class CEntity /* Objects */ class CGameWorld *GameWorld() { return m_pGameWorld; } + class CConfig *Config() { return m_pGameWorld->Config(); } class CGameContext *GameServer() { return m_pGameWorld->GameServer(); } class IServer *Server() { return m_pGameWorld->Server(); } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 017baff4..21c5b4f9 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -264,19 +264,19 @@ void CGameContext::SendWeaponPickup(int ClientID, int Weapon) void CGameContext::SendMotd(int ClientID) { CNetMsg_Sv_Motd Msg; - Msg.m_pMessage = Config()->Values()->m_SvMotd; + Msg.m_pMessage = Config()->m_SvMotd; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } void CGameContext::SendSettings(int ClientID) { CNetMsg_Sv_ServerSettings Msg; - Msg.m_KickVote = Config()->Values()->m_SvVoteKick; - Msg.m_KickMin = Config()->Values()->m_SvVoteKickMin; - Msg.m_SpecVote = Config()->Values()->m_SvVoteSpectate; + Msg.m_KickVote = Config()->m_SvVoteKick; + Msg.m_KickMin = Config()->m_SvVoteKickMin; + Msg.m_SpecVote = Config()->m_SvVoteSpectate; Msg.m_TeamLock = m_LockTeams != 0; - Msg.m_TeamBalance = Config()->Values()->m_SvTeambalanceTime != 0; - Msg.m_PlayerSlots = Config()->Values()->m_SvPlayerSlots; + Msg.m_TeamBalance = Config()->m_SvTeambalanceTime != 0; + Msg.m_PlayerSlots = Config()->m_SvPlayerSlots; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } @@ -571,7 +571,7 @@ void CGameContext::OnClientDirectInput(int ClientID, void *pInput) int NumFailures = m_NetObjHandler.NumObjFailures(); if(m_NetObjHandler.ValidateObj(NETOBJTYPE_PLAYERINPUT, pInput, sizeof(CNetObj_PlayerInput)) == -1) { - if(Config()->Values()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) + if(Config()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "NETOBJTYPE_PLAYERINPUT failed on '%s'", m_NetObjHandler.FailedObjOn()); @@ -589,7 +589,7 @@ void CGameContext::OnClientPredictedInput(int ClientID, void *pInput) int NumFailures = m_NetObjHandler.NumObjFailures(); if(m_NetObjHandler.ValidateObj(NETOBJTYPE_PLAYERINPUT, pInput, sizeof(CNetObj_PlayerInput)) == -1) { - if(Config()->Values()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) + if(Config()->m_Debug && NumFailures != m_NetObjHandler.NumObjFailures()) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "NETOBJTYPE_PLAYERINPUT corrected on '%s'", m_NetObjHandler.FailedObjOn()); @@ -617,7 +617,7 @@ void CGameContext::OnClientEnter(int ClientID) NewClientInfoMsg.m_Country = Server()->ClientCountry(ClientID); NewClientInfoMsg.m_Silent = false; - if(Config()->Values()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) + if(Config()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) NewClientInfoMsg.m_Silent = true; for(int p = 0; p < NUM_SKINPARTS; p++) @@ -727,7 +727,7 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason) Msg.m_ClientID = ClientID; Msg.m_pReason = pReason; Msg.m_Silent = false; - if(Config()->Values()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) + if(Config()->m_SvSilentSpectatorMode && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS) Msg.m_Silent = true; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, -1); } @@ -753,7 +753,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) if(!pRawMsg) { - if(Config()->Values()->m_Debug) + if(Config()->m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgID), MsgID, m_NetObjHandler.FailedMsgOn()); @@ -766,7 +766,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { if(MsgID == NETMSGTYPE_CL_SAY) { - if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) + if(Config()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) return; CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg; @@ -798,14 +798,14 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) *(const_cast(pEnd)) = 0; // drop empty and autocreated spam messages (more than 20 characters per second) - if(Length == 0 || (Config()->Values()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat + Server()->TickSpeed()*(Length/20) > Server()->Tick())) + if(Length == 0 || (Config()->m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat + Server()->TickSpeed()*(Length/20) > Server()->Tick())) return; pPlayer->m_LastChat = Server()->Tick(); // don't allow spectators to disturb players during a running game in tournament mode int Mode = pMsg->m_Mode; - if((Config()->Values()->m_SvTournamentMode == 2) && + if((Config()->m_SvTournamentMode == 2) && pPlayer->GetTeam() == TEAM_SPECTATORS && m_pController->IsGameRunning() && !Server()->IsAuthed(ClientID)) @@ -831,7 +831,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else { - if((Config()->Values()->m_SvSpamprotection && ((pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry+Server()->TickSpeed()*3 > Now) || + if((Config()->m_SvSpamprotection && ((pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry+Server()->TickSpeed()*3 > Now) || (pPlayer->m_LastVoteCall && pPlayer->m_LastVoteCall+Server()->TickSpeed()*VOTE_COOLDOWN > Now))) || pPlayer->GetTeam() == TEAM_SPECTATORS || m_VoteCloseTime) return; @@ -880,7 +880,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else if(str_comp_nocase(pMsg->m_Type, "kick") == 0) { - if(!Config()->Values()->m_SvVoteKick || m_pController->GetRealPlayerNum() < Config()->Values()->m_SvVoteKickMin) + if(!Config()->m_SvVoteKick || m_pController->GetRealPlayerNum() < Config()->m_SvVoteKickMin) return; int KickID = str_toint(pMsg->m_Value); @@ -888,13 +888,13 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; str_format(aDesc, sizeof(aDesc), "%2d: %s", KickID, Server()->ClientName(KickID)); - if (!Config()->Values()->m_SvVoteKickBantime) + if (!Config()->m_SvVoteKickBantime) str_format(aCmd, sizeof(aCmd), "kick %d Kicked by vote", KickID); else { char aAddrStr[NETADDR_MAXSTRSIZE] = {0}; Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr)); - str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, Config()->Values()->m_SvVoteKickBantime); + str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, Config()->m_SvVoteKickBantime); } char aBuf[128]; str_format(aBuf, sizeof(aBuf), @@ -915,7 +915,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0) { - if(!Config()->Values()->m_SvVoteSpectate) + if(!Config()->m_SvVoteSpectate) return; int SpectateID = str_toint(pMsg->m_Value); @@ -923,7 +923,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; str_format(aDesc, sizeof(aDesc), "%2d: %s", SpectateID, Server()->ClientName(SpectateID)); - str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, Config()->Values()->m_SvVoteSpectateRejoindelay); + str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, Config()->m_SvVoteSpectateRejoindelay); char aBuf[128]; str_format(aBuf, sizeof(aBuf), "'%d:%s' voted %s '%d:%s' reason='%s' cmd='%s' force=%d", @@ -981,7 +981,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg; if(pPlayer->GetTeam() == pMsg->m_Team || - (Config()->Values()->m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick()) || + (Config()->m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick()) || (pMsg->m_Team != TEAM_SPECTATORS && m_LockTeams) || pPlayer->m_TeamChangeTick > Server()->Tick()) return; @@ -1000,7 +1000,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg; - if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed() > Server()->Tick()) + if(Config()->m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed() > Server()->Tick()) return; pPlayer->m_LastSetSpectatorMode = Server()->Tick(); @@ -1011,7 +1011,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg; - if(Config()->Values()->m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick()) + if(Config()->m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick()) return; pPlayer->m_LastEmote = Server()->Tick(); @@ -1476,7 +1476,7 @@ void CGameContext::ConchainGameinfoUpdate(IConsole::IResult *pResult, void *pUse void CGameContext::OnConsoleInit() { m_pServer = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); @@ -1505,7 +1505,7 @@ void CGameContext::OnInit() { // init everything m_pServer = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); m_World.SetGameServer(this); m_Events.SetGameServer(this); @@ -1520,15 +1520,15 @@ void CGameContext::OnInit() m_Collision.Init(&m_Layers); // select gametype - if(str_comp_nocase(Config()->Values()->m_SvGametype, "mod") == 0) + if(str_comp_nocase(Config()->m_SvGametype, "mod") == 0) m_pController = new CGameControllerMOD(this); - else if(str_comp_nocase(Config()->Values()->m_SvGametype, "ctf") == 0) + else if(str_comp_nocase(Config()->m_SvGametype, "ctf") == 0) m_pController = new CGameControllerCTF(this); - else if(str_comp_nocase(Config()->Values()->m_SvGametype, "lms") == 0) + else if(str_comp_nocase(Config()->m_SvGametype, "lms") == 0) m_pController = new CGameControllerLMS(this); - else if(str_comp_nocase(Config()->Values()->m_SvGametype, "lts") == 0) + else if(str_comp_nocase(Config()->m_SvGametype, "lts") == 0) m_pController = new CGameControllerLTS(this); - else if(str_comp_nocase(Config()->Values()->m_SvGametype, "tdm") == 0) + else if(str_comp_nocase(Config()->m_SvGametype, "tdm") == 0) m_pController = new CGameControllerTDM(this); else m_pController = new CGameControllerDM(this); @@ -1564,16 +1564,16 @@ void CGameContext::OnInit() Console()->Chain("sv_matches_per_map", ConchainGameinfoUpdate, this); // clamp sv_player_slots to 0..MaxClients - if(Config()->Values()->m_SvMaxClients < Config()->Values()->m_SvPlayerSlots) - Config()->Values()->m_SvPlayerSlots = Config()->Values()->m_SvMaxClients; + if(Config()->m_SvMaxClients < Config()->m_SvPlayerSlots) + Config()->m_SvPlayerSlots = Config()->m_SvMaxClients; #ifdef CONF_DEBUG // clamp dbg_dummies to 0..MAX_CLIENTS-1 - if(MAX_CLIENTS <= Config()->Values()->m_DbgDummies) - Config()->Values()->m_DbgDummies = MAX_CLIENTS; - if(Config()->Values()->m_DbgDummies) + if(MAX_CLIENTS <= Config()->m_DbgDummies) + Config()->m_DbgDummies = MAX_CLIENTS; + if(Config()->m_DbgDummies) { - for(int i = 0; i < Config()->Values()->m_DbgDummies ; i++) + for(int i = 0; i < Config()->m_DbgDummies ; i++) OnClientConnected(MAX_CLIENTS -i-1, true, false); } #endif diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 451c5633..a7a9f713 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -36,7 +36,7 @@ class CGameContext : public IGameServer { IServer *m_pServer; - class IConfig *m_pConfig; + class CConfig *m_pConfig; class IConsole *m_pConsole; CLayers m_Layers; CCollision m_Collision; @@ -71,7 +71,7 @@ class CGameContext : public IGameServer bool m_Resetting; public: IServer *Server() const { return m_pServer; } - class IConfig *Config() { return m_pConfig; } + class CConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; } CCollision *Collision() { return &m_Collision; } CTuningParams *Tuning() { return &m_Tuning; } diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index aa3a5a71..497ea96a 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -14,6 +14,7 @@ IGameController::IGameController(CGameContext *pGameServer) { m_pGameServer = pGameServer; + m_pConfig = m_pGameServer->Config(); m_pServer = m_pGameServer->Server(); // balancing @@ -30,8 +31,8 @@ IGameController::IGameController(CGameContext *pGameServer) m_SuddenDeath = 0; m_aTeamscore[TEAM_RED] = 0; m_aTeamscore[TEAM_BLUE] = 0; - if(GameServer()->Config()->Values()->m_SvWarmup) - SetGameState(IGS_WARMUP_USER, GameServer()->Config()->Values()->m_SvWarmup); + if(Config()->m_SvWarmup) + SetGameState(IGS_WARMUP_USER, Config()->m_SvWarmup); else SetGameState(IGS_WARMUP_GAME, TIMER_INFINITE); @@ -39,9 +40,9 @@ IGameController::IGameController(CGameContext *pGameServer) m_GameFlags = 0; m_pGameType = "unknown"; m_GameInfo.m_MatchCurrent = m_MatchCount+1; - m_GameInfo.m_MatchNum = (str_length(GameServer()->Config()->Values()->m_SvMaprotation) && GameServer()->Config()->Values()->m_SvMatchesPerMap) ? GameServer()->Config()->Values()->m_SvMatchesPerMap : 0; - m_GameInfo.m_ScoreLimit = GameServer()->Config()->Values()->m_SvScorelimit; - m_GameInfo.m_TimeLimit = GameServer()->Config()->Values()->m_SvTimelimit; + m_GameInfo.m_MatchNum = (str_length(Config()->m_SvMaprotation) && Config()->m_SvMatchesPerMap) ? Config()->m_SvMatchesPerMap : 0; + m_GameInfo.m_ScoreLimit = Config()->m_SvScorelimit; + m_GameInfo.m_TimeLimit = Config()->m_SvTimelimit; // map m_aMapWish[0] = 0; @@ -58,22 +59,22 @@ IGameController::IGameController(CGameContext *pGameServer) //activity void IGameController::DoActivityCheck() { - if(GameServer()->Config()->Values()->m_SvInactiveKickTime == 0) + if(Config()->m_SvInactiveKickTime == 0) return; for(int i = 0; i < MAX_CLIENTS; ++i) { - if(GameServer()->m_apPlayers[i] && !GameServer()->m_apPlayers[i]->IsDummy() && (GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS || GameServer()->Config()->Values()->m_SvInactiveKick > 0) && - !Server()->IsAuthed(i) && (GameServer()->m_apPlayers[i]->m_InactivityTickCounter > GameServer()->Config()->Values()->m_SvInactiveKickTime*Server()->TickSpeed()*60)) + if(GameServer()->m_apPlayers[i] && !GameServer()->m_apPlayers[i]->IsDummy() && (GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS || Config()->m_SvInactiveKick > 0) && + !Server()->IsAuthed(i) && (GameServer()->m_apPlayers[i]->m_InactivityTickCounter > Config()->m_SvInactiveKickTime*Server()->TickSpeed()*60)) { if(GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS) { - if(GameServer()->Config()->Values()->m_SvInactiveKickSpec) + if(Config()->m_SvInactiveKickSpec) Server()->Kick(i, "Kicked for inactivity"); } else { - switch(GameServer()->Config()->Values()->m_SvInactiveKick) + switch(Config()->m_SvInactiveKick) { case 1: { @@ -88,7 +89,7 @@ void IGameController::DoActivityCheck() for(int j = 0; j < MAX_CLIENTS; ++j) if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS) ++Spectators; - if(Spectators >= GameServer()->Config()->Values()->m_SvMaxClients - GameServer()->Config()->Values()->m_SvPlayerSlots) + if(Spectators >= Config()->m_SvMaxClients - Config()->m_SvPlayerSlots) Server()->Kick(i, "Kicked for inactivity"); else DoTeamChange(GameServer()->m_apPlayers[i], TEAM_SPECTATORS); @@ -135,7 +136,7 @@ bool IGameController::CanBeMovedOnBalance(int ClientID) const void IGameController::CheckTeamBalance() { - if(!IsTeamplay() || !GameServer()->Config()->Values()->m_SvTeambalanceTime) + if(!IsTeamplay() || !Config()->m_SvTeambalanceTime) { m_UnbalancedTick = TBALANCE_OK; return; @@ -159,7 +160,7 @@ void IGameController::CheckTeamBalance() void IGameController::DoTeamBalance() { - if(!IsTeamplay() || !GameServer()->Config()->Values()->m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS) + if(!IsTeamplay() || !Config()->m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS) return; GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); @@ -298,7 +299,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos) Type = PICKUP_LASER; break; case ENTITY_POWERUP_NINJA: - if(GameServer()->Config()->Values()->m_SvPowerups) + if(Config()->m_SvPowerups) Type = PICKUP_NINJA; } @@ -353,7 +354,7 @@ void IGameController::OnPlayerInfoChange(CPlayer *pPlayer) void IGameController::OnPlayerReadyChange(CPlayer *pPlayer) { - if(GameServer()->Config()->Values()->m_SvPlayerReadyMode && pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_DeadSpecMode) + if(Config()->m_SvPlayerReadyMode && pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_DeadSpecMode) { // change players ready state pPlayer->m_IsReadyToPlay ^= 1; @@ -371,7 +372,7 @@ void IGameController::OnPlayerReadyChange(CPlayer *pPlayer) // to be called when a player changes state, spectates or disconnects void IGameController::CheckReadyStates(int WithoutID) { - if(GameServer()->Config()->Values()->m_SvPlayerReadyMode) + if(Config()->m_SvPlayerReadyMode) { switch(m_GameState) { @@ -524,7 +525,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) { m_GameState = GameState; m_GameStateTimer = TIMER_INFINITE; - if(GameServer()->Config()->Values()->m_SvPlayerReadyMode) + if(Config()->m_SvPlayerReadyMode) { // run warmup till all players are ready SetPlayersReadyState(false); @@ -556,17 +557,17 @@ void IGameController::SetGameState(EGameState GameState, int Timer) // only possible when game, pause or start countdown is running if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_START_COUNTDOWN) { - if(GameServer()->Config()->Values()->m_SvCountdown == 0 && m_GameFlags&GAMEFLAG_SURVIVAL) + if(Config()->m_SvCountdown == 0 && m_GameFlags&GAMEFLAG_SURVIVAL) { m_GameState = GameState; m_GameStateTimer = 3*Server()->TickSpeed(); GameServer()->m_World.m_Paused = true; } - else if(GameServer()->Config()->Values()->m_SvCountdown > 0) + else if(Config()->m_SvCountdown > 0) { m_GameState = GameState; - m_GameStateTimer = GameServer()->Config()->Values()->m_SvCountdown*Server()->TickSpeed(); + m_GameStateTimer = Config()->m_SvCountdown*Server()->TickSpeed(); GameServer()->m_World.m_Paused = true; } else @@ -773,7 +774,7 @@ void IGameController::Tick() if(m_MatchCount >= m_GameInfo.m_MatchNum-1) CycleMap(); - if(GameServer()->Config()->Values()->m_SvMatchSwap) + if(Config()->m_SvMatchSwap) GameServer()->SwapTeams(); m_MatchCount++; StartMatch(); @@ -791,7 +792,7 @@ void IGameController::Tick() { case IGS_WARMUP_USER: // check if player ready mode was disabled and it waits that all players are ready -> end warmup - if(!GameServer()->Config()->Values()->m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE) + if(!Config()->m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE) SetGameState(IGS_WARMUP_USER, 0); else if(m_GameStateTimer == 3 * Server()->TickSpeed()) StartMatch(); @@ -822,7 +823,7 @@ void IGameController::Tick() case TBALANCE_OK: break; default: - if(Server()->Tick() > m_UnbalancedTick+GameServer()->Config()->Values()->m_SvTeambalanceTime*Server()->TickSpeed()*60) + if(Server()->Tick() > m_UnbalancedTick+Config()->m_SvTeambalanceTime*Server()->TickSpeed()*60) DoTeamBalance(); } } @@ -843,15 +844,15 @@ void IGameController::Tick() // info void IGameController::CheckGameInfo() { - int MatchNum = (str_length(GameServer()->Config()->Values()->m_SvMaprotation) && GameServer()->Config()->Values()->m_SvMatchesPerMap) ? GameServer()->Config()->Values()->m_SvMatchesPerMap : 0; + int MatchNum = (str_length(Config()->m_SvMaprotation) && Config()->m_SvMatchesPerMap) ? Config()->m_SvMatchesPerMap : 0; if(MatchNum == 0) m_MatchCount = 0; bool GameInfoChanged = (m_GameInfo.m_MatchCurrent != m_MatchCount + 1) || (m_GameInfo.m_MatchNum != MatchNum) || - (m_GameInfo.m_ScoreLimit != GameServer()->Config()->Values()->m_SvScorelimit) || (m_GameInfo.m_TimeLimit != GameServer()->Config()->Values()->m_SvTimelimit); + (m_GameInfo.m_ScoreLimit != Config()->m_SvScorelimit) || (m_GameInfo.m_TimeLimit != Config()->m_SvTimelimit); m_GameInfo.m_MatchCurrent = m_MatchCount + 1; m_GameInfo.m_MatchNum = MatchNum; - m_GameInfo.m_ScoreLimit = GameServer()->Config()->Values()->m_SvScorelimit; - m_GameInfo.m_TimeLimit = GameServer()->Config()->Values()->m_SvTimelimit; + m_GameInfo.m_ScoreLimit = Config()->m_SvScorelimit; + m_GameInfo.m_TimeLimit = Config()->m_SvTimelimit; if(GameInfoChanged) UpdateGameInfo(-1); } @@ -866,7 +867,7 @@ bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) const if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2]) return false; - if(!GameServer()->Config()->Values()->m_SvTeamdamage && GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) + if(!Config()->m_SvTeamdamage && GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) return true; } @@ -875,12 +876,12 @@ bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) const bool IGameController::IsFriendlyTeamFire(int Team1, int Team2) const { - return IsTeamplay() && !GameServer()->Config()->Values()->m_SvTeamdamage && Team1 == Team2; + return IsTeamplay() && !Config()->m_SvTeamdamage && Team1 == Team2; } bool IGameController::IsPlayerReadyMode() const { - return GameServer()->Config()->Values()->m_SvPlayerReadyMode != 0 && (m_GameStateTimer == TIMER_INFINITE && (m_GameState == IGS_WARMUP_USER || m_GameState == IGS_GAME_PAUSED)); + return Config()->m_SvPlayerReadyMode != 0 && (m_GameStateTimer == TIMER_INFINITE && (m_GameState == IGS_WARMUP_USER || m_GameState == IGS_GAME_PAUSED)); } bool IGameController::IsTeamChangeAllowed() const @@ -944,17 +945,17 @@ void IGameController::CycleMap() char aBuf[256]; str_format(aBuf, sizeof(aBuf), "rotating map to %s", m_aMapWish); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(GameServer()->Config()->Values()->m_SvMap, m_aMapWish, sizeof(GameServer()->Config()->Values()->m_SvMap)); + str_copy(Config()->m_SvMap, m_aMapWish, sizeof(Config()->m_SvMap)); m_aMapWish[0] = 0; m_MatchCount = 0; return; } - if(!str_length(GameServer()->Config()->Values()->m_SvMaprotation)) + if(!str_length(Config()->m_SvMaprotation)) return; // handle maprotation - const char *pMapRotation = GameServer()->Config()->Values()->m_SvMaprotation; - const char *pCurrentMap = GameServer()->Config()->Values()->m_SvMap; + const char *pMapRotation = Config()->m_SvMaprotation; + const char *pCurrentMap = Config()->m_SvMap; int CurrentMapLen = str_length(pCurrentMap); const char *pNextMap = pMapRotation; @@ -1003,7 +1004,7 @@ void IGameController::CycleMap() char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(GameServer()->Config()->Values()->m_SvMap, &aBuf[i], sizeof(GameServer()->Config()->Values()->m_SvMap)); + str_copy(Config()->m_SvMap, &aBuf[i], sizeof(Config()->m_SvMap)); } // spawn @@ -1110,7 +1111,7 @@ bool IGameController::GetStartRespawnState() const // team bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) const { - if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !GameServer()->Config()->Values()->m_SvTeambalanceTime) + if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !Config()->m_SvTeambalanceTime) return true; // simulate what would happen if the player changes team @@ -1130,7 +1131,7 @@ bool IGameController::CanJoinTeam(int Team, int NotThisID) const // check if there're enough player slots left int TeamMod = GameServer()->m_apPlayers[NotThisID] && GameServer()->m_apPlayers[NotThisID]->GetTeam() != TEAM_SPECTATORS ? -1 : 0; - return TeamMod+m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < GameServer()->Config()->Values()->m_SvPlayerSlots; + return TeamMod+m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < Config()->m_SvPlayerSlots; } int IGameController::ClampTeam(int Team) const @@ -1192,19 +1193,19 @@ void IGameController::DoTeamChange(CPlayer *pPlayer, int Team, bool DoChatMsg) int IGameController::GetStartTeam() { - if(GameServer()->Config()->Values()->m_SvTournamentMode) + if(Config()->m_SvTournamentMode) return TEAM_SPECTATORS; // determine new team int Team = TEAM_RED; if(IsTeamplay()) { - if(!GameServer()->Config()->Values()->m_DbgStress) // this will force the auto balancer to work overtime aswell + if(!Config()->m_DbgStress) // this will force the auto balancer to work overtime aswell Team = m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED; } // check if there're enough player slots left - if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < GameServer()->Config()->Values()->m_SvPlayerSlots) + if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < Config()->m_SvPlayerSlots) { ++m_aTeamSize[Team]; m_UnbalancedTick = TBALANCE_CHECK; diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 2a2056b9..0a66d151 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -16,6 +16,7 @@ class IGameController { class CGameContext *m_pGameServer; + class CConfig *m_pConfig; class IServer *m_pServer; // activity @@ -95,6 +96,7 @@ class IGameController protected: CGameContext *GameServer() const { return m_pGameServer; } + CConfig *Config() const { return m_pConfig; } IServer *Server() const { return m_pServer; } // game diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp index f8cf6482..c2312680 100644 --- a/src/game/server/gamemodes/tdm.cpp +++ b/src/game/server/gamemodes/tdm.cpp @@ -28,7 +28,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye m_aTeamscore[pKiller->GetTeam()&1]++; // good shit } - pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*GameServer()->Config()->Values()->m_SvRespawnDelayTDM); + pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*GameServer()->Config()->m_SvRespawnDelayTDM); return 0; } diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index ffc65a55..932f6082 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -14,6 +14,7 @@ CGameWorld::CGameWorld() { m_pGameServer = 0x0; + m_pConfig = 0x0; m_pServer = 0x0; m_Paused = false; @@ -33,6 +34,7 @@ CGameWorld::~CGameWorld() void CGameWorld::SetGameServer(CGameContext *pGameServer) { m_pGameServer = pGameServer; + m_pConfig = m_pGameServer->Config(); m_pServer = m_pGameServer->Server(); } diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 6eb24a38..03ced191 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -34,10 +34,12 @@ class CGameWorld CEntity *m_apFirstEntityTypes[NUM_ENTTYPES]; class CGameContext *m_pGameServer; + class CConfig *m_pConfig; class IServer *m_pServer; public: class CGameContext *GameServer() { return m_pGameServer; } + class CConfig *Config() { return m_pConfig; } class IServer *Server() { return m_pServer; } bool m_ResetRequested; diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 3f3fcae8..78f179a0 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -294,25 +294,26 @@ int main(int argc, const char **argv) // ignore_convention int FlagMask = CFGFLAG_MASTER; IKernel *pKernel = IKernel::Create(); IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); - IConfig *pConfig = CreateConfig(); + IConfigManager *pConfigManager = CreateConfigManager(); + CConfig *pConfig = pConfigManager->Values(); m_pConsole = CreateConsole(FlagMask); CNetBase::Init(pConfig); bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(m_pConsole); - RegisterFail |= !pKernel->RegisterInterface(pConfig); + RegisterFail |= !pKernel->RegisterInterface(pConfigManager); if(RegisterFail) return -1; - pConfig->Init(FlagMask); + pConfigManager->Init(FlagMask); m_pConsole->Init(); m_NetBan.Init(m_pConsole, pStorage); if(argc > 1) // ignore_convention m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention - if(pConfig->Values()->m_Bindaddr[0] && net_host_lookup(pConfig->Values()->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) + if(pConfig->m_Bindaddr[0] && net_host_lookup(pConfig->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0) { // got bindaddr BindAddr.type = NETTYPE_ALL; diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index a7da0bd7..952d5625 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -89,18 +89,18 @@ int main(int argc, const char **argv) // ignore_convention int FlagMask = 0; IKernel *pKernel = IKernel::Create(); IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); - IConfig *pConfig = CreateConfig(); + IConfigManager *pConfigManager = CreateConfigManager(); IConsole *pConsole = CreateConsole(FlagMask); - CNetBase::Init(pConfig); + CNetBase::Init(pConfigManager->Values()); bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(pConsole); - RegisterFail |= !pKernel->RegisterInterface(pConfig); + RegisterFail |= !pKernel->RegisterInterface(pConfigManager); if(RegisterFail) return -1; - pConfig->Init(FlagMask); + pConfigManager->Init(FlagMask); pConsole->Init(); mem_zero(&BindAddr, sizeof(BindAddr)); From 3f35f4127c116ee246f74e8b4b859e094ad770d4 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 22:17:31 +0100 Subject: [PATCH 137/479] Only print the bad path message for paths starting with a slash Also generate an extra warning for paths containing '..'. --- src/base/system.c | 2 +- src/base/system.h | 8 ++++---- src/engine/shared/console.cpp | 8 +++++++- src/engine/shared/storage.cpp | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index da552384..a5f48d81 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1932,7 +1932,7 @@ void str_sanitize_cc(char *str_in) } /* check if the string contains '..' (parent directory) paths */ -int str_check_pathname(const char* str) +int str_path_unsafe(const char *str) { // State machine. 0 means that we're at the beginning // of a new directory/filename, and a positive number represents the number of diff --git a/src/base/system.h b/src/base/system.h index a57b4bc1..a56a79ff 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -942,22 +942,22 @@ void str_sanitize(char *str); Remarks: - The strings are treated as zero-terminated strings. */ -char* str_sanitize_filename(char* aName); +char *str_sanitize_filename(char *name); /* - Function: str_check_pathname + Function: str_path_unsafe Check if the string contains '..' (parent directory) paths. Parameters: str - String to check. Returns: - Returns 0 if the path is valid, -1 otherwise. + Returns 0 if the path is safe, -1 otherwise. Remarks: - The strings are treated as zero-terminated strings. */ -int str_check_pathname(const char* str); +int str_path_unsafe(const char *str); /* Function: str_clean_whitespaces diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index c95d180b..93276396 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -439,7 +439,13 @@ bool CConsole::ExecuteFile(const char *pFilename) { str_format(aBuf, sizeof(aBuf), "failed to open '%s'", pFilename); Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf); - Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", "Info: only relative paths starting from the ones you specify in 'storage.cfg' are allowed"); + bool AbsHeur = false; + AbsHeur = AbsHeur || (pFilename[0] == '/' || pFilename[0] == '\\'); + AbsHeur = AbsHeur || (pFilename[0] && pFilename[1] == ':' && (pFilename[2] == '/' || pFilename[2] == '\\')); + if(AbsHeur) + { + Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", "Info: only relative paths starting from the ones you specify in 'storage.cfg' are allowed"); + } } m_pFirstExec = pPrev; diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 4a5fce6e..84cebef5 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -333,9 +333,9 @@ class CStorage : public IStorage // // E. g. "/etc/passwd" => "/path/to/storage//etc/passwd", which // is safe. - if(str_check_pathname(pFilename) != 0) + if(str_path_unsafe(pFilename) != 0) { - pBuffer[0] = 0; + dbg_msg("storage", "refusing to open path which looks like it could escape those specified in 'storage.cfg': %s", pFilename); return 0; } From fd9782708a585803b4495afd45d38ec7073554c5 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 28 Jan 2020 22:20:32 +0100 Subject: [PATCH 138/479] Add tests for `str_path_unsafe` --- src/test/str.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/str.cpp b/src/test/str.cpp index 46f08c19..f09582e5 100644 --- a/src/test/str.cpp +++ b/src/test/str.cpp @@ -100,3 +100,27 @@ TEST(StrFormat, Positional) str_format(aBuf, sizeof(aBuf), "%1$s %1$s %2$d %1$s %2$d", "str", 1); EXPECT_STREQ(aBuf, "str str 1 str 1"); } + +TEST(Str, PathUnsafe) +{ + EXPECT_TRUE(str_path_unsafe("..")); + EXPECT_TRUE(str_path_unsafe("/..")); + EXPECT_TRUE(str_path_unsafe("/../")); + EXPECT_TRUE(str_path_unsafe("../")); + + EXPECT_TRUE(str_path_unsafe("/../foobar")); + EXPECT_TRUE(str_path_unsafe("../foobar")); + EXPECT_TRUE(str_path_unsafe("foobar/../foobar")); + EXPECT_TRUE(str_path_unsafe("foobar/..")); + EXPECT_TRUE(str_path_unsafe("foobar/../")); + + EXPECT_FALSE(str_path_unsafe("abc")); + EXPECT_FALSE(str_path_unsafe("abc/")); + EXPECT_FALSE(str_path_unsafe("abc/def")); + EXPECT_FALSE(str_path_unsafe("abc/def.txt")); + EXPECT_FALSE(str_path_unsafe("abc\\")); + EXPECT_FALSE(str_path_unsafe("abc\\def")); + EXPECT_FALSE(str_path_unsafe("abc\\def.txt")); + EXPECT_FALSE(str_path_unsafe("abc/def\\ghi.txt")); + EXPECT_FALSE(str_path_unsafe("любовь")); +} From 165ab18cd230a1450832bef11835234d1627094f Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sat, 1 Feb 2020 21:02:21 +0100 Subject: [PATCH 139/479] Clean up chat commands --- CMakeLists.txt | 1 + datasrc/network.py | 42 ++-- src/base/system.c | 7 + src/base/system.h | 6 + src/engine/console.h | 2 + src/engine/shared/console.cpp | 18 ++ src/engine/shared/console.h | 2 + src/game/client/components/chat.cpp | 376 +++++++++++----------------- src/game/client/components/chat.h | 64 ++--- src/game/client/gameclient.cpp | 14 ++ src/game/client/gameclient.h | 2 + src/game/commands.h | 175 +++++++++++++ src/game/server/gamecontext.cpp | 46 +++- src/game/server/gamecontext.h | 11 + src/game/server/gamecontroller.cpp | 106 +------- src/game/server/gamecontroller.h | 53 +--- 16 files changed, 484 insertions(+), 441 deletions(-) create mode 100644 src/game/commands.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d20f90d..210abf2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1360,6 +1360,7 @@ set(ENGINE_GENERATED_SHARED src/generated/nethash.cpp src/generated/protocol.cpp set_src(GAME_SHARED GLOB src/game collision.cpp collision.h + commands.h gamecore.cpp gamecore.h layers.cpp diff --git a/datasrc/network.py b/datasrc/network.py index 8b77f903..f59d3dc1 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -14,11 +14,11 @@ RaceFlags = Flags("RACEFLAG", ["HIDE_KILLMSG", "FINISHMSG_AS_CHAT", "KEEP_WANTED_WEAPON"]) GameMsgIDs = Enum("GAMEMSG", ["TEAM_SWAP", "SPEC_INVALIDID", "TEAM_SHUFFLE", "TEAM_BALANCE", "CTF_DROP", "CTF_RETURN", - + "TEAM_ALL", "TEAM_BALANCE_VICTIM", "CTF_GRAB", - + "CTF_CAPTURE", - + "GAME_PAUSED"]) # todo 0.8: sort (1 para) @@ -212,7 +212,7 @@ NetObject("De_GameInfo", [ NetFlag("m_GameFlags", GameFlags), - + NetIntRange("m_ScoreLimit", 0, 'max_int'), NetIntRange("m_TimeLimit", 0, 'max_int'), @@ -362,7 +362,7 @@ NetMessage("Sv_GameInfo", [ NetFlag("m_GameFlags", GameFlags), - + NetIntRange("m_ScoreLimit", 0, 'max_int'), NetIntRange("m_TimeLimit", 0, 'max_int'), @@ -460,20 +460,20 @@ NetMessage("Sv_Checkpoint", [ NetIntAny("m_Diff"), ]), - - NetMessage("Sv_CommandInfo", [ - NetStringStrict("m_pName"), - NetStringStrict("m_ArgsFormat"), - NetStringStrict("m_HelpText") - ]), - - NetMessage("Sv_CommandInfoRemove", [ - NetStringStrict("m_pName") - ]), - - NetMessage("Cl_Command", [ - NetStringStrict("m_Name"), - NetStringStrict("m_Arguments") - ]), - + + NetMessage("Sv_CommandInfo", [ + NetStringStrict("m_Name"), + NetStringStrict("m_ArgsFormat"), + NetStringStrict("m_HelpText") + ]), + + NetMessage("Sv_CommandInfoRemove", [ + NetStringStrict("m_Name") + ]), + + NetMessage("Cl_Command", [ + NetStringStrict("m_Name"), + NetStringStrict("m_Arguments") + ]), + ] diff --git a/src/base/system.c b/src/base/system.c index da552384..fd3a066b 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2084,6 +2084,13 @@ char *str_skip_whitespaces(char *str) return str; } +const char *str_skip_whitespaces_const(const char *str) +{ + while(*str && (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r')) + str++; + return str; +} + /* case */ int str_comp_nocase(const char *a, const char *b) { diff --git a/src/base/system.h b/src/base/system.h index a57b4bc1..35841567 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1021,6 +1021,12 @@ const char *str_skip_to_whitespace_const(const char *str); */ char *str_skip_whitespaces(char *str); +/* + Function: str_skip_whitespaces_const + See str_skip_whitespaces. +*/ +const char *str_skip_whitespaces_const(const char *str); + /* Function: str_comp_nocase Compares to strings case insensitive. diff --git a/src/engine/console.h b/src/engine/console.h index f6f0bd04..c5915313 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -93,6 +93,8 @@ class IConsole : public IInterface virtual void SetPrintOutputLevel(int Index, int OutputLevel) = 0; virtual void Print(int Level, const char *pFrom, const char *pStr, bool Highlighted=false) = 0; + virtual int ParseCommandArgs(const char *pArgs, const char *pFormat, FCommandCallback pfnCallback, void *pContext) = 0; + virtual void SetAccessLevel(int AccessLevel) = 0; }; diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index c95d180b..6924aaae 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -165,6 +165,8 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) pStr = str_skip_to_whitespace(pStr); else if(Command == 's') // validate string pStr = str_skip_to_whitespace(pStr); + else if(Command == 'p') + pStr = str_skip_to_whitespace(pStr); if(pStr[0] != 0) // check for end of string { @@ -178,6 +180,22 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) return Error; } +int CConsole::ParseCommandArgs(const char *pArgs, const char *pFormat, FCommandCallback pfnCallback, void *pContext) +{ + CResult Result; + str_copy(Result.m_aStringStorage, pArgs, sizeof(Result.m_aStringStorage)); + Result.m_pArgsStart = Result.m_aStringStorage; + + int Error = ParseArgs(&Result, pFormat); + if(Error) + return Error; + + if(pfnCallback) + pfnCallback(&Result, pContext); + + return 0; +} + int CConsole::RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData) { if(m_NumPrintCB == MAX_PRINT_CB) diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index 3252130e..e9390622 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -197,6 +197,8 @@ class CConsole : public IConsole virtual void SetPrintOutputLevel(int Index, int OutputLevel); virtual void Print(int Level, const char *pFrom, const char *pStr, bool Highlighted=false); + virtual int ParseCommandArgs(const char *pArgs, const char *pFormat, FCommandCallback pfnCallback, void *pContext); + void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_MOD)); } }; diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 91a32cab..1d7bc160 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -50,8 +50,13 @@ void CChat::OnReset() m_pHistoryEntry = 0x0; m_PendingChatCounter = 0; m_LastChatSend = 0; + m_IgnoreCommand = false; - m_Commands.Reset(); + m_SelectedCommand = 0; + if(m_pFilter) + free(m_pFilter); + m_pFilter = 0; + m_FilteredCount = 0; for(int i = 0; i < CHAT_NUM; ++i) m_aLastSoundPlayed[i] = 0; @@ -67,15 +72,15 @@ void CChat::OnReset() m_CurrentLineWidth = -1.0f; // init chat commands (must be in alphabetical order) - m_Commands.ClearCommands(); - m_Commands.AddCommand("all", "", "Switch to all chat", &Com_All); - m_Commands.AddCommand("friend", "p", "Add player as friend", &Com_Befriend); - m_Commands.AddCommand("m", "p", "Mute a player", &Com_Mute); - m_Commands.AddCommand("mute", "p", "Mute a player", &Com_Mute); - m_Commands.AddCommand("r", "", "Reply to a whisper", &Com_Reply); - m_Commands.AddCommand("team", "", "Switch to team chat", &Com_Team); - m_Commands.AddCommand("w", "p", "Whisper another player", &Com_Whisper); - m_Commands.AddCommand("whisper", "p", "Whisper another player", &Com_Whisper); + m_CommandManager.ClearCommands(); + m_CommandManager.AddCommand("all", "Switch to all chat", "?r", &Com_All, this); + m_CommandManager.AddCommand("friend", "Add player as friend", "p", &Com_Befriend, this); + m_CommandManager.AddCommand("m", "Mute a player", "p", &Com_Mute, this); + m_CommandManager.AddCommand("mute", "Mute a player", "p", &Com_Mute, this); + m_CommandManager.AddCommand("r", "Reply to a whisper", "", &Com_Reply, this); + m_CommandManager.AddCommand("team", "Switch to team chat", "", &Com_Team, this); + m_CommandManager.AddCommand("w", "Whisper another player", "p", &Com_Whisper, this); + m_CommandManager.AddCommand("whisper", "Whisper another player", "p", &Com_Whisper, this); } void CChat::OnMapLoad() @@ -190,6 +195,7 @@ void CChat::ConShowChat(IConsole::IResult *pResult, void *pUserData) void CChat::OnInit() { + m_CommandManager.Init(Console()); m_Input.Init(Input()); } @@ -420,7 +426,7 @@ bool CChat::OnInput(IInput::CEvent Event) { if(IsTypingCommand()) { - m_Commands.SelectPreviousCommand(); + PreviousActiveCommand(&m_SelectedCommand); } else { @@ -442,7 +448,7 @@ bool CChat::OnInput(IInput::CEvent Event) { if(IsTypingCommand()) { - m_Commands.SelectNextCommand(); + NextActiveCommand(&m_SelectedCommand); } else { @@ -500,7 +506,26 @@ void CChat::ClearInput() m_CompletionChosen = -1; m_IgnoreCommand = false; - m_Commands.Reset(); + m_SelectedCommand = 0; + + if(m_pFilter) + free(m_pFilter); + m_pFilter = 0; + m_FilteredCount = 0; +} + +void CChat::ServerCommandCallback(IConsole::IResult *pResult, void *pContext) +{ + CCommandManager::SCommandContext *pComContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pComContext->m_pContext; + + CNetMsg_Cl_Command Msg; + Msg.m_Name = pComContext->m_pCommand; + Msg.m_Arguments = pComContext->m_pArgs; + pChatData->Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + + pChatData->m_Mode = CHAT_NONE; + pChatData->m_pClient->OnRelease(); } void CChat::OnMessage(int MsgType, void *pRawMsg) @@ -513,22 +538,16 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) else if(MsgType == NETMSGTYPE_SV_COMMANDINFO) { CNetMsg_Sv_CommandInfo *pMsg = (CNetMsg_Sv_CommandInfo *)pRawMsg; - if(!m_Commands.GetCommandByName(pMsg->m_pName)) - { - dbg_msg("chat_commands", "adding server chat command: name='%s' args='%s' help='%s'", pMsg->m_pName, pMsg->m_ArgsFormat, pMsg->m_HelpText); - m_Commands.AddCommand(pMsg->m_pName, pMsg->m_ArgsFormat, pMsg->m_HelpText, 0); - } + if(!m_CommandManager.AddCommand(pMsg->m_Name, pMsg->m_HelpText, pMsg->m_ArgsFormat, ServerCommandCallback, this)) + dbg_msg("chat_commands", "adding server chat command: name='%s' args='%s' help='%s'", pMsg->m_Name, pMsg->m_ArgsFormat, pMsg->m_HelpText); } else if(MsgType == NETMSGTYPE_SV_COMMANDINFOREMOVE) { CNetMsg_Sv_CommandInfoRemove *pMsg = (CNetMsg_Sv_CommandInfoRemove *)pRawMsg; - - CChatCommand *pCommand = m_Commands.GetCommandByName(pMsg->m_pName); - if(pCommand) + if(!m_CommandManager.RemoveCommand(pMsg->m_Name)) { - mem_zero(pCommand, sizeof(CChatCommand)); - dbg_msg("chat_commands", "removed chat command: name='%s'", pMsg->m_pName); + dbg_msg("chat_commands", "removed chat command: name='%s'", pMsg->m_Name); } } } @@ -917,7 +936,7 @@ void CChat::OnRender() //Check if key exists with bind int KeyID, Modifier; m_pClient->m_pBinds->GetKeyID(GetCommandName(m_ChatBufferMode), KeyID, Modifier); - + if(KeyID < KEY_LAST) { //find keyname and format text @@ -941,13 +960,15 @@ void CChat::OnRender() TextRender()->TextEx(&Cursor, m_Input.GetString()+m_Input.GetCursorOffset(), -1); //Render command autocomplete option hint - if(IsTypingCommand() && m_Commands.CountActiveCommands()) - if(const CChat::CChatCommand* pCommand = m_Commands.GetSelectedCommand()) - if(str_length(pCommand->m_aName)+1 > str_length(m_Input.GetString())) - { - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); - TextRender()->TextEx(&Cursor, pCommand->m_aName + str_length(m_Input.GetString())-1, -1); - } + if(IsTypingCommand() && m_CommandManager.CommandCount() - m_FilteredCount && m_SelectedCommand >= 0) + { + const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(m_SelectedCommand); + if(str_length(pCommand->m_aName)+1 > str_length(m_Input.GetString())) + { + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextEx(&Cursor, pCommand->m_aName + str_length(m_Input.GetString())-1, -1); + } + } if(ChatMode == CHAT_WHISPER) { @@ -1308,6 +1329,7 @@ bool CChat::IsTypingCommand() const // chat commands handlers void CChat::HandleCommands(float x, float y, float w) { + //dbg_msg("DEBUG", "%d", m_SelectedCommand); // render commands menu if(m_Mode != CHAT_NONE && IsTypingCommand()) { @@ -1315,8 +1337,14 @@ void CChat::HandleCommands(float x, float y, float w) const float LineWidth = w; const float LineHeight = 8.0f; - m_Commands.Filter(m_Input.GetString()); // flag active commands, update selected command - const int ActiveCount = m_Commands.CountActiveCommands(); + FilterChatCommands(m_Input.GetString()); // flag active commands, update selected command + const int ActiveCount = m_CommandManager.CommandCount() - m_FilteredCount; + + if(ActiveCount && m_pFilter[m_SelectedCommand]) + { + m_SelectedCommand = -1; + NextActiveCommand(&m_SelectedCommand); + } if(ActiveCount > 0) // at least one command to display { @@ -1329,26 +1357,31 @@ void CChat::HandleCommands(float x, float y, float w) CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Rect.x + 5.0f, y, 5.0f, TEXTFLAG_RENDER); TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); - if(m_Commands.GetSelectedCommand() && str_startswith(m_Input.GetString() + 1, m_Commands.GetSelectedCommand()->m_aName)) + if(m_SelectedCommand >= 0 && str_startswith(m_Input.GetString() + 1, m_CommandManager.GetCommand(m_SelectedCommand)->m_aName)) TextRender()->TextEx(&Cursor, Localize("Press Enter to confirm or Esc to cancel"), -1); else TextRender()->TextEx(&Cursor, Localize("Press Tab to select or Esc to cancel"), -1); } // render commands - for(int i = ActiveCount - 1; i >= 0; i--) + for(int i = m_CommandManager.CommandCount() - 1; i >= 0; i--) { + if(m_pFilter[i]) + continue; + + const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(i); + if(!pCommand) + continue; + y -= LineHeight; CUIRect HighlightRect = {Rect.x, y, LineWidth, LineHeight-1}; - // retrieve command - const CChatCommand* pCommand = m_Commands.GetCommand(i); - - if(!pCommand->m_pfnCallback) - RenderTools()->DrawUIRect(&HighlightRect, vec4(0.0f, 0.6f, 0.6f, 0.2f), CUI::CORNER_ALL, 0); + //TODO: Fix this + //if(!pCommand->m_pfnCallback) + //RenderTools()->DrawUIRect(&HighlightRect, vec4(0.0f, 0.6f, 0.6f, 0.2f), CUI::CORNER_ALL, 0); // draw selection box - if(pCommand == m_Commands.GetSelectedCommand()) + if(i == m_SelectedCommand) RenderTools()->DrawUIRect(&HighlightRect, vec4(0.25f, 0.25f, 0.6f, Alpha), CUI::CORNER_ALL, 2.0f); // print command @@ -1392,30 +1425,17 @@ void CChat::HandleCommands(float x, float y, float w) bool CChat::ExecuteCommand(bool Execute) { - if(m_Commands.CountActiveCommands() == 0) + if(!Execute && m_CommandManager.CommandCount() - m_FilteredCount == 0) return false; - const char* pCommandStr = m_Input.GetString(); - const CChatCommand* pCommand = m_Commands.GetSelectedCommand(); - dbg_assert(pCommand != 0, "selected command does not exist"); + const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(m_SelectedCommand); + const char *pCommandStr = m_Input.GetString(); bool IsFullMatch = str_find(pCommandStr + 1, pCommand->m_aName); // if the command text is fully inside pCommandStr (aka, not a shortcut) if(IsFullMatch && Execute) { // execute command - if(pCommand->m_pfnCallback) - pCommand->m_pfnCallback(this, pCommandStr); - else - { - // Send server-side command. - CNetMsg_Cl_Command Msg; - Msg.m_Name = pCommand->m_aName; - Msg.m_Arguments = pCommandStr; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); - m_Mode = CHAT_NONE; - m_pClient->OnRelease(); - } - return true; + return !m_CommandManager.OnCommand(pCommand->m_aName, str_skip_whitespaces_const(str_skip_to_whitespace_const(pCommandStr)), -1); } else if(!IsFullMatch && !Execute) { @@ -1433,87 +1453,62 @@ bool CChat::ExecuteCommand(bool Execute) return false; } -// returns -1 if not found or duplicate -int CChat::IdentifyNameParameter(const char* pCommand) const -{ - // retrieve name parameter - const char* pParameter = str_skip_to_whitespace_const(pCommand); - if(!pParameter) - return -1; - - // do not count leading and trailing whitespaces - char aName[MAX_NAME_LENGTH]; - str_copy(aName, pParameter+1, sizeof(aName)); - str_clean_whitespaces_simple(aName); - - int TargetID = -1; - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(!m_pClient->m_aClients[i].m_Active || i == m_pClient->m_LocalClientID) // skip local user - continue; - if(str_length(m_pClient->m_aClients[i].m_aName) == str_length(aName) && str_comp(m_pClient->m_aClients[i].m_aName, aName) == 0) - { - // name strictly matches - if(TargetID != -1) - { - // duplicate; be conservative - dbg_msg("chat", "name duplicate found, aborting command"); - return -1; - } - TargetID = i; - } - } - return TargetID; -} - - // callback functions for commands -void CChat::Com_All(CChat *pChatData, const char* pCommand) +void CChat::Com_All(IConsole::IResult *pResult, void *pContext) { - const char* pParameter = str_skip_to_whitespace_const(pCommand); + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + pChatData->m_ChatCmdBuffer[0] = 0; - if(pParameter++ && *pParameter) // skip the first space + if(pResult->NumArguments()) { // save the parameter in a buffer before EnableMode clears it - str_copy(pChatData->m_ChatCmdBuffer, pParameter, sizeof(pChatData->m_ChatCmdBuffer)); + str_copy(pChatData->m_ChatCmdBuffer, pResult->GetString(0), sizeof(pChatData->m_ChatCmdBuffer)); } pChatData->EnableMode(CHAT_ALL, pChatData->m_ChatCmdBuffer); } -void CChat::Com_Team(CChat *pChatData, const char* pCommand) +void CChat::Com_Team(IConsole::IResult *pResult, void *pContext) { - const char* pParameter = str_skip_to_whitespace_const(pCommand); + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + pChatData->m_ChatCmdBuffer[0] = 0; - if(pParameter++ && *pParameter) // skip the first space + if(pResult->NumArguments()) { // save the parameter in a buffer before EnableMode clears it - str_copy(pChatData->m_ChatCmdBuffer, pParameter, sizeof(pChatData->m_ChatCmdBuffer)); + str_copy(pChatData->m_ChatCmdBuffer, pResult->GetString(0), sizeof(pChatData->m_ChatCmdBuffer)); } pChatData->EnableMode(CHAT_TEAM, pChatData->m_ChatCmdBuffer); } -void CChat::Com_Reply(CChat *pChatData, const char* pCommand) +void CChat::Com_Reply(IConsole::IResult *pResult, void *pContext) { + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + if(pChatData->m_LastWhisperFrom == -1) pChatData->ClearInput(); // just reset the chat else { pChatData->m_WhisperTarget = pChatData->m_LastWhisperFrom; - const char* pParameter = str_skip_to_whitespace_const(pCommand); pChatData->m_ChatCmdBuffer[0] = 0; - if(pParameter++ && *pParameter) // skip the first space + if(pResult->NumArguments()) { // save the parameter in a buffer before EnableMode clears it - str_copy(pChatData->m_ChatCmdBuffer, pParameter, sizeof(pChatData->m_ChatCmdBuffer)); + str_copy(pChatData->m_ChatCmdBuffer, pResult->GetString(0), sizeof(pChatData->m_ChatCmdBuffer)); } pChatData->EnableMode(CHAT_WHISPER, pChatData->m_ChatCmdBuffer); } } -void CChat::Com_Whisper(CChat *pChatData, const char* pCommand) +void CChat::Com_Whisper(IConsole::IResult *pResult, void *pContext) { - int TargetID = pChatData->IdentifyNameParameter(pCommand); + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + + int TargetID = pChatData->m_pClient->GetClientID(pResult->GetString(0)); if(TargetID != -1) { pChatData->m_WhisperTarget = TargetID; @@ -1521,9 +1516,12 @@ void CChat::Com_Whisper(CChat *pChatData, const char* pCommand) } } -void CChat::Com_Mute(CChat *pChatData, const char* pCommand) +void CChat::Com_Mute(IConsole::IResult *pResult, void *pContext) { - int TargetID = pChatData->IdentifyNameParameter(pCommand); + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + + int TargetID = pChatData->m_pClient->GetClientID(pResult->GetString(0)); if(TargetID != -1) { bool isMuted = pChatData->m_pClient->m_aClients[TargetID].m_ChatIgnore; @@ -1543,9 +1541,12 @@ void CChat::Com_Mute(CChat *pChatData, const char* pCommand) pChatData->m_pClient->OnRelease(); } -void CChat::Com_Befriend(CChat *pChatData, const char* pCommand) +void CChat::Com_Befriend(IConsole::IResult *pResult, void *pContext) { - int TargetID = pChatData->IdentifyNameParameter(pCommand); + CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; + CChat *pChatData = (CChat *)pCommandContext->m_pContext; + + int TargetID = pChatData->m_pClient->GetClientID(pResult->GetString(0)); if(TargetID != -1) { bool isFriend = pChatData->m_pClient->m_aClients[TargetID].m_Friend; @@ -1566,147 +1567,58 @@ void CChat::Com_Befriend(CChat *pChatData, const char* pCommand) } -// CChatCommands methods -CChat::CChatCommands::CChatCommands() : m_pSelectedCommand(0) -{ - mem_zero(m_aCommands, sizeof(m_aCommands)); -} -CChat::CChatCommands::~CChatCommands() {} - -// selection -void CChat::CChatCommands::Reset() -{ - m_pSelectedCommand = 0; -} - -void CChat::CChatCommands::AddCommand(const char *pName, const char *pArgsFormat, const char *pHelpText, COMMAND_CALLBACK pfnCallback) +int CChat::FilterChatCommands(const char *pLine) { - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(!m_aCommands[i].m_Used) - { - mem_zero(&m_aCommands[i], sizeof(CChatCommand)); + if(m_pFilter) + free(m_pFilter); - str_copy(m_aCommands[i].m_aName, pName, sizeof(m_aCommands[i].m_aName)); - str_copy(m_aCommands[i].m_aHelpText, pHelpText, sizeof(m_aCommands[i].m_aHelpText)); - str_copy(m_aCommands[i].m_aArgsFormat, pArgsFormat, sizeof(m_aCommands[i].m_aArgsFormat)); - - m_aCommands[i].m_pfnCallback = pfnCallback; - m_aCommands[i].m_aFiltered = false; - m_aCommands[i].m_Used = true; - break; - } - } -} - -void CChat::CChatCommands::ClearCommands() -{ - mem_zero(m_aCommands, sizeof(m_aCommands)); -} - -// Example: /whisper command will match "/whi", "/whisper" and "/whisper tee" -void CChat::CChatCommands::Filter(const char* pLine) -{ - char aCommandStr[64]; - - // Ignore first char "/" when filtering. - str_copy(aCommandStr, pLine + 1, sizeof(aCommandStr)); - - // truncate the string at the first whitespace to get the command - char* pFirstWhitespace = str_skip_to_whitespace(aCommandStr); - if(pFirstWhitespace) - *pFirstWhitespace = 0; - - for(int i = 0; i < MAX_COMMANDS; i++) - if(m_aCommands[i].m_Used) - m_aCommands[i].m_aFiltered = (str_find_nocase(m_aCommands[i].m_aName, aCommandStr) != m_aCommands[i].m_aName); - - // also update selected command - if(!GetSelectedCommand() || GetSelectedCommand()->m_aFiltered) - { - if(CountActiveCommands() > 0) - m_pSelectedCommand = &m_aCommands[GetActiveIndex(0)]; // default to first command - else - m_pSelectedCommand = 0; - } -} - -// this will not return a correct value if we are not writing a command (m_Input.GetString()[0] == '/') -int CChat::CChatCommands::CountActiveCommands() const -{ - int n = 0; - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(m_aCommands[i].m_Used && !m_aCommands[i].m_aFiltered) - n++; - } - return n; -} + m_pFilter = (bool *)malloc(m_CommandManager.CommandCount() * sizeof(*m_pFilter)); + if(!m_pFilter) + return -1; -const CChat::CChatCommand* CChat::CChatCommands::GetCommand(int Index) const -{ - int RealIndex = GetActiveIndex(Index); - return RealIndex != -1 ? &m_aCommands[RealIndex] : 0; + m_FilteredCount = m_CommandManager.Filter(m_pFilter, pLine + 1); + return m_FilteredCount; } -CChat::CChatCommand *CChat::CChatCommands::GetCommandByName(const char *pName) +int CChat::GetFirstActiveCommand() { - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(m_aCommands[i].m_Used && str_comp(m_aCommands[i].m_aName, pName) == 0) - return &m_aCommands[i]; - } + if(!m_pFilter) + return 0; - return 0; -} + for(int i = 0; i < m_CommandManager.CommandCount(); i++) + if(!m_pFilter[i]) + return i; -const CChat::CChatCommand* CChat::CChatCommands::GetSelectedCommand() const -{ - return m_pSelectedCommand; + return -1; } -void CChat::CChatCommands::SelectPreviousCommand() +void CChat::NextActiveCommand(int *Index) { - CChatCommand* LastCommand = 0x0; - for(int i = 0; i < MAX_COMMANDS; i++) + int StartIndex = (*Index)++; + if(m_pFilter) { - if(!m_aCommands[i].m_Used || m_aCommands[i].m_aFiltered) - continue; - if(&m_aCommands[i] == m_pSelectedCommand) + while(*Index % m_CommandManager.CommandCount() != StartIndex && + m_pFilter[*Index % m_CommandManager.CommandCount()]) { - m_pSelectedCommand = LastCommand; - return; + (*Index)++; } - LastCommand = &m_aCommands[i]; } -} -void CChat::CChatCommands::SelectNextCommand() -{ - bool FoundSelected = false; - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(!m_aCommands[i].m_Used || m_aCommands[i].m_aFiltered) - continue; - if(FoundSelected) - { - m_pSelectedCommand = &m_aCommands[i]; - return; - } - if(&m_aCommands[i] == m_pSelectedCommand) - FoundSelected = true; - } + *Index %= m_CommandManager.CommandCount(); } -int CChat::CChatCommands::GetActiveIndex(int Index) const +void CChat::PreviousActiveCommand(int *Index) { - for(int i = 0; i < MAX_COMMANDS; i++) + int StartIndex = (*Index)--; + if(m_pFilter) { - if(!m_aCommands[i].m_Used || m_aCommands[i].m_aFiltered) - Index++; - if(i == Index) - return i; + while((*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount() != StartIndex && + m_pFilter[(*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount()]) + { + (*Index)--; + } } - - return -1; + + *Index += m_CommandManager.CommandCount(); + *Index %= m_CommandManager.CommandCount(); } diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 031e9d40..1ef2eaff 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -7,6 +7,7 @@ #include #include #include +#include class CChat : public CComponent { @@ -79,59 +80,27 @@ class CChat : public CComponent typedef void (*COMMAND_CALLBACK)(CChat *pChatData, const char *pArgs); // chat commands - struct CChatCommand - { - char m_aName[32]; - char m_aHelpText[64]; - char m_aArgsFormat[16]; - // If callback is null, then it's a server-side command. - COMMAND_CALLBACK m_pfnCallback; - bool m_aFiltered; // 0 = shown, 1 = hidden - bool m_Used; - }; + bool m_IgnoreCommand; + int m_SelectedCommand; - class CChatCommands - { - enum - { - // 8 is the number of vanilla commands, 14 the number of commands left to fill the chat. - MAX_COMMANDS = 8 + 14 - }; - - CChatCommand m_aCommands[MAX_COMMANDS]; - CChatCommand *m_pSelectedCommand; - - private: - int GetActiveIndex(int index) const; - public: - CChatCommands(); - ~CChatCommands(); - - void AddCommand(const char *pName, const char *pArgsFormat, const char *pHelpText, COMMAND_CALLBACK pfnCallback); - void ClearCommands(); - CChatCommand *GetCommandByName(const char *pName); - void Reset(); - void Filter(const char* pLine); - int CountActiveCommands() const; - const CChatCommand* GetCommand(int index) const; - const CChatCommand* GetSelectedCommand() const; - void SelectPreviousCommand(); - void SelectNextCommand(); - }; + bool *m_pFilter; + int m_FilteredCount; + int FilterChatCommands(const char *pLine); + int GetFirstActiveCommand(); + void NextActiveCommand(int *Index); + void PreviousActiveCommand(int *Index); - CChatCommands m_Commands; - bool m_IgnoreCommand; + CCommandManager m_CommandManager; bool IsTypingCommand() const; void HandleCommands(float x, float y, float w); bool ExecuteCommand(bool Execute); - int IdentifyNameParameter(const char* pCommand) const; - static void Com_All(CChat *pChatData, const char* pCommand); - static void Com_Team(CChat *pChatData, const char* pCommand); - static void Com_Reply(CChat *pChatData, const char* pCommand); - static void Com_Whisper(CChat *pChatData, const char* pCommand); - static void Com_Mute(CChat *pChatData, const char* pCommand); - static void Com_Befriend(CChat *pChatData, const char* pCommand); + static void Com_All(IConsole::IResult *pResult, void *pContext); + static void Com_Team(IConsole::IResult *pResult, void *pContext); + static void Com_Reply(IConsole::IResult *pResult, void *pContext); + static void Com_Whisper(IConsole::IResult *pResult, void *pContext); + static void Com_Mute(IConsole::IResult *pResult, void *pContext); + static void Com_Befriend(IConsole::IResult *pResult, void *pContext); void ClearInput(); @@ -141,6 +110,7 @@ class CChat : public CComponent static void ConWhisper(IConsole::IResult *pResult, void *pUserData); static void ConChat(IConsole::IResult *pResult, void *pUserData); static void ConShowChat(IConsole::IResult *pResult, void *pUserData); + static void ServerCommandCallback(IConsole::IResult *pResult, void *pContext); public: // client IDs for special messages diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 69c2fae0..5d28a8b6 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1781,6 +1781,20 @@ void CGameClient::SendSkinChange() m_LastSkinChangeTime = Client()->LocalTime(); } +int CGameClient::GetClientID(const char *pName) +{ + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_aClients[i].m_Active || i == m_LocalClientID) // skip local user + continue; + + if(!str_comp(m_aClients[i].m_aName, pName)) + return i; + } + + return -1; +} + void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData) { CGameClient *pClient = static_cast(pUserData); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 533608ef..32575d29 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -278,6 +278,8 @@ class CGameClient : public IGameClient void DoLeaveMessage(const char *pName, int ClientID, const char *pReason); void DoTeamChangeMessage(const char *pName, int ClientID, int Team); + int GetClientID(const char *pName); + // actions // TODO: move these void SendSwitchTeam(int Team); diff --git a/src/game/commands.h b/src/game/commands.h new file mode 100644 index 00000000..69564003 --- /dev/null +++ b/src/game/commands.h @@ -0,0 +1,175 @@ +#ifndef GAME_COMMANDS_H +#define GAME_COMMANDS_H + +#include +#include +#include + +class CCommandManager +{ +public: + class CCommand + { + public: + char m_aName[16]; + char m_aHelpText[64]; + char m_aArgsFormat[16]; + + IConsole::FCommandCallback m_pfnCallback; + void *m_pContext; + + CCommand() + { + m_aName[0] = '\0'; + m_aHelpText[0] = '\0'; + m_aArgsFormat[0] = '\0'; + + m_pfnCallback = 0; + m_pContext = 0; + } + + CCommand(const char *pName, const char *pHelpText, const char *pArgsFormat, IConsole::FCommandCallback pfnCallback, void *pContext) + { + str_copy(m_aName, pName, sizeof(m_aName)); + str_copy(m_aHelpText, pHelpText, sizeof(m_aHelpText)); + str_copy(m_aArgsFormat, pArgsFormat, sizeof(m_aArgsFormat)); + m_pfnCallback = pfnCallback; + m_pContext = pContext; + } + }; + + typedef void (*FNewCommandHook)(const CCommand *pCommand, void *pContext); + typedef void (*FRemoveCommandHook)(const CCommand *pCommand, void *pContext); + +private: + array m_aCommands; + + IConsole *m_pConsole; + void *m_pHookContext; + FNewCommandHook m_pfnNewCommandHook; + FRemoveCommandHook m_pfnRemoveCommandHook; + +public: + CCommandManager() + { + m_pConsole = 0; + m_aCommands.clear(); + } + + void Init(IConsole *pConsole, void *pHookContext = 0, FNewCommandHook pfnNewCommandHook = 0, FRemoveCommandHook pfnRemoveCommandHook = 0) + { + m_pConsole = pConsole; + m_pHookContext = pHookContext; + m_pfnNewCommandHook = pfnNewCommandHook; + m_pfnRemoveCommandHook = pfnRemoveCommandHook; + } + + const CCommand *GetCommand(const char *pCommand) + { + for(int i = 0; i < m_aCommands.size(); i++) + if(!str_comp(m_aCommands[i].m_aName, pCommand)) + return &m_aCommands[i]; + + return 0; + } + + const CCommand *GetCommand(int Index) + { + if(Index < 0 || Index >= m_aCommands.size()) + return 0; + + return &m_aCommands[Index]; + } + + int AddCommand(const char *pCommand, const char *pHelpText, const char *pArgsFormat, IConsole::FCommandCallback pfnCallback, void *pContext) + { + const CCommand *pCom = GetCommand(pCommand); + if(pCom) + return 1; + + int Index = m_aCommands.add(CCommand(pCommand, pHelpText, pArgsFormat, pfnCallback, pContext)); + if(m_pfnNewCommandHook) + m_pfnNewCommandHook(&m_aCommands[Index], m_pHookContext); + + return 0; + } + + int RemoveCommand(const char *pCommand) + { + for(int i = 0; i < m_aCommands.size(); i++) + { + if(!str_comp(m_aCommands[i].m_aName, pCommand)) + { + if(m_pfnRemoveCommandHook) + m_pfnRemoveCommandHook(&m_aCommands[i], m_pHookContext); + + m_aCommands.remove_index(i); + return 0; + } + } + + return 1; + } + + void ClearCommands() + { + m_aCommands.clear(); + } + + int CommandCount() + { + return m_aCommands.size(); + } + + struct SCommandContext + { + const char *m_pCommand; + const char *m_pArgs; + int m_ClientID; + void *m_pContext; + }; + + int OnCommand(const char *pCommand, const char *pArgs, int ClientID) + { + dbg_msg("DEBUG", "calling '%s' with args '%s'", pCommand, pArgs); + const CCommand *pCom = GetCommand(pCommand); + if(!pCom) + return 1; + + SCommandContext Context = {pCom->m_aName, pArgs, ClientID, pCom->m_pContext}; + return m_pConsole->ParseCommandArgs(pArgs, pCom->m_aArgsFormat, pCom->m_pfnCallback, &Context); + } + + int Filter(bool *pFilter, const char *pStr) + { + if(!*pStr) + { + mem_zero(pFilter, m_aCommands.size() * sizeof(*pFilter)); + return 0; + } + + int Filtered = 0; + for(int i = 0; i < m_aCommands.size(); i++) + { + /*if(str_find_nocase(m_aCommands[i].m_aName, pStr)) + dbg_msg("DEBUG", "'%s' found in '%s' '%p' '%p' '%s'", pStr, m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr), m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName ? "true" : "false"); + else + dbg_msg("DEBUJG", "'%s' not found in '%s' '%s'", pStr, m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName ? "true" : "false");*/ + + Filtered += (pFilter[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); + } + + /*char aBuf[64] = ""; + for(int i = 0; i < m_aCommands.size(); i++) + { + char test[5]; + str_format(test, sizeof(test), "%d ", pFilter[i]); + str_append(aBuf, test, sizeof(aBuf)); + } + dbg_msg("DEBUG", "%s", aBuf);*/ + + return Filtered; + } +}; + +#endif //GAME_COMMANDS_H diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 017baff4..b37e8509 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -318,6 +318,32 @@ void CGameContext::SendGameMsg(int GameMsgID, int ParaI1, int ParaI2, int ParaI3 Server()->SendMsg(&Msg, MSGFLAG_VITAL, ClientID); } +void CGameContext::SendChatCommand(const CCommandManager::CCommand *pCommand, int ClientID) +{ + CNetMsg_Sv_CommandInfo Msg; + Msg.m_Name = pCommand->m_aName; + Msg.m_HelpText = pCommand->m_aHelpText; + Msg.m_ArgsFormat = pCommand->m_aArgsFormat; + + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); +} + +void CGameContext::SendChatCommands(int ClientID) +{ + for(int i = 0; i < CommandManager()->CommandCount(); i++) + { + SendChatCommand(CommandManager()->GetCommand(i), ClientID); + } +} + +void CGameContext::SendRemoveChatCommand(const CCommandManager::CCommand *pCommand, int ClientID) +{ + CNetMsg_Sv_CommandInfoRemove Msg; + Msg.m_Name = pCommand->m_aName; + + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); +} + // void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason) { @@ -603,6 +629,9 @@ void CGameContext::OnClientPredictedInput(int ClientID, void *pInput) void CGameContext::OnClientEnter(int ClientID) { + // send chat commands + SendChatCommands(ClientID); + m_pController->OnPlayerConnect(m_apPlayers[ClientID]); m_VoteUpdate = true; @@ -1063,7 +1092,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) else if (MsgID == NETMSGTYPE_CL_COMMAND) { CNetMsg_Cl_Command *pMsg = (CNetMsg_Cl_Command*)pRawMsg; - m_pController->OnPlayerCommand(pPlayer, pMsg->m_Name, pMsg->m_Arguments); + CommandManager()->OnCommand(pMsg->m_Name, pMsg->m_Arguments, ClientID); } } else @@ -1501,6 +1530,18 @@ void CGameContext::OnConsoleInit() Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, "Force a vote to yes/no"); } +void CGameContext::NewCommandHook(const CCommandManager::CCommand *pCommand, void *pContext) +{ + CGameContext *pSelf = (CGameContext *)pContext; + pSelf->SendChatCommand(pCommand, -1); +} + +void CGameContext::RemoveCommandHook(const CCommandManager::CCommand *pCommand, void *pContext) +{ + CGameContext *pSelf = (CGameContext *)pContext; + pSelf->SendRemoveChatCommand(pCommand, -1); +} + void CGameContext::OnInit() { // init everything @@ -1509,6 +1550,7 @@ void CGameContext::OnInit() m_pConsole = Kernel()->RequestInterface(); m_World.SetGameServer(this); m_Events.SetGameServer(this); + m_CommandManager.Init(m_pConsole, this, NewCommandHook, RemoveCommandHook); // HACK: only set static size for items, which were available in the first 0.7 release // so new items don't break the snapshot delta @@ -1533,6 +1575,8 @@ void CGameContext::OnInit() else m_pController = new CGameControllerDM(this); + m_pController->RegisterChatCommands(CommandManager()); + // create all entities from the game layer CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer(); CTile *pTiles = (CTile *)Kernel()->RequestInterface()->GetData(pTileMap->m_Data); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 451c5633..887d4922 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -65,6 +66,9 @@ class CGameContext : public IGameServer static void ConchainSettingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainGameinfoUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + static void NewCommandHook(const CCommandManager::CCommand *pCommand, void *pContext); + static void RemoveCommandHook(const CCommandManager::CCommand *pCommand, void *pContext); + CGameContext(int Resetting); void Construct(int Resetting); @@ -86,6 +90,9 @@ class CGameContext : public IGameServer class IGameController *m_pController; CGameWorld m_World; + CCommandManager m_CommandManager; + + CCommandManager *CommandManager() { return &m_CommandManager; } // helper functions class CCharacter *GetPlayerChar(int ClientID); @@ -150,6 +157,10 @@ class CGameContext : public IGameServer void SendGameMsg(int GameMsgID, int ParaI1, int ClientID); void SendGameMsg(int GameMsgID, int ParaI1, int ParaI2, int ParaI3, int ClientID); + void SendChatCommand(const CCommandManager::CCommand *pCommand, int ClientID); + void SendChatCommands(int ClientID); + void SendRemoveChatCommand(const CCommandManager::CCommand *pCommand, int ClientID); + // void CheckPureTuning(); void SendTuningParams(int ClientID); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index aa3a5a71..da780527 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -50,9 +50,6 @@ IGameController::IGameController(CGameContext *pGameServer) m_aNumSpawnPoints[0] = 0; m_aNumSpawnPoints[1] = 0; m_aNumSpawnPoints[2] = 0; - - // commands - CommandsManager()->OnInit(); } //activity @@ -322,8 +319,6 @@ void IGameController::OnPlayerConnect(CPlayer *pPlayer) // update game info UpdateGameInfo(ClientID); - - CommandsManager()->OnPlayerConnect(Server(), pPlayer); } void IGameController::OnPlayerDisconnect(CPlayer *pPlayer) @@ -472,7 +467,7 @@ void IGameController::ResetGame() { // reset the game GameServer()->m_World.m_ResetRequested = true; - + SetGameState(IGS_GAME_RUNNING); m_GameStartTick = Server()->Tick(); m_SuddenDeath = 0; @@ -497,7 +492,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) // run warmup till there're enough players m_GameState = GameState; m_GameStateTimer = TIMER_INFINITE; - + // enable respawning in survival when activating warmup if(m_GameFlags&GAMEFLAG_SURVIVAL) { @@ -536,7 +531,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) m_GameState = GameState; m_GameStateTimer = Timer*Server()->TickSpeed(); } - + // enable respawning in survival when activating warmup if(m_GameFlags&GAMEFLAG_SURVIVAL) { @@ -929,7 +924,7 @@ void IGameController::ChangeMap(const char *pToMap) if(m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER) SetGameState(IGS_GAME_RUNNING); EndMatch(); - + if(m_GameState != IGS_END_MATCH) { // game could not been ended, force cycle @@ -1215,96 +1210,15 @@ int IGameController::GetStartTeam() return TEAM_SPECTATORS; } -IGameController::CChatCommands::CChatCommands() -{ - mem_zero(m_aCommands, sizeof(m_aCommands)); -} - -void IGameController::CChatCommands::AddCommand(const char *pName, const char *pArgsFormat, const char *pHelpText, COMMAND_CALLBACK pfnCallback) -{ - if(GetCommand(pName)) - return; - - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(!m_aCommands[i].m_Used) - { - mem_zero(&m_aCommands[i], sizeof(CChatCommand)); - - str_copy(m_aCommands[i].m_aName, pName, sizeof(m_aCommands[i].m_aName)); - str_copy(m_aCommands[i].m_aHelpText, pHelpText, sizeof(m_aCommands[i].m_aHelpText)); - str_copy(m_aCommands[i].m_aArgsFormat, pArgsFormat, sizeof(m_aCommands[i].m_aArgsFormat)); - - m_aCommands[i].m_pfnCallback = pfnCallback; - m_aCommands[i].m_Used = true; - break; - } - } -} - -void IGameController::CChatCommands::SendRemoveCommand(IServer *pServer, const char *pName, int ID) -{ - CNetMsg_Sv_CommandInfoRemove Msg; - Msg.m_pName = pName; - - pServer->SendPackMsg(&Msg, MSGFLAG_VITAL, ID); -} - -void IGameController::CChatCommands::RemoveCommand(const char *pName) +void IGameController::Com_Example(IConsole::IResult *pResult, void *pContext) { - CChatCommand *pCommand = GetCommand(pName); + CCommandManager::SCommandContext *pComContext = (CCommandManager::SCommandContext *)pContext; + IGameController *pSelf = (IGameController *)pComContext->m_pContext; - if(pCommand) - { - mem_zero(pCommand, sizeof(CChatCommand)); - } + pSelf->GameServer()->SendBroadcast(pResult->GetString(0), -1); } -IGameController::CChatCommand *IGameController::CChatCommands::GetCommand(const char *pName) +void IGameController::RegisterChatCommands(CCommandManager *pManager) { - for(int i = 0; i < MAX_COMMANDS; i++) - { - if(m_aCommands[i].m_Used && str_comp(m_aCommands[i].m_aName, pName) == 0) - { - return &m_aCommands[i]; - } - } - return 0; + pManager->AddCommand("test", "Test the command system", "r", Com_Example, this); } - -void IGameController::CChatCommands::OnPlayerConnect(IServer *pServer, CPlayer *pPlayer) -{ - for(int i = 0; i < MAX_COMMANDS; i++) - { - CChatCommand *pCommand = &m_aCommands[i]; - - if(pCommand->m_Used) - { - CNetMsg_Sv_CommandInfo Msg; - Msg.m_pName = pCommand->m_aName; - Msg.m_HelpText = pCommand->m_aHelpText; - Msg.m_ArgsFormat = pCommand->m_aArgsFormat; - - pServer->SendPackMsg(&Msg, MSGFLAG_VITAL, pPlayer->GetCID()); - } - } -} - -void IGameController::OnPlayerCommand(CPlayer *pPlayer, const char *pCommandName, const char *pCommandArgs) -{ - // TODO: Add a argument parser? - CChatCommand *pCommand = CommandsManager()->GetCommand(pCommandName); - - if(pCommand) - pCommand->m_pfnCallback(pPlayer, pCommandArgs); -} - -void IGameController::CChatCommands::OnInit() -{ - //AddCommand("example", "si", "I am a description", Com_Example); -} - -/*void IGameController::Com_Example(class CPlayer *pPlayer, const char *pArgs) -{ - // Do something with the player here -}*/ diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 2a2056b9..42dcad6b 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -6,6 +6,8 @@ #include #include +#include + #include /* @@ -48,7 +50,7 @@ class IGameController IGS_GAME_PAUSED, // game paused (infinite or tick timer) IGS_GAME_RUNNING, // game running (infinite) - + IGS_END_MATCH, // match is over (tick timer) IGS_END_ROUND, // round is over (tick timer) }; @@ -65,7 +67,7 @@ class IGameController // map char m_aMapWish[128]; - + void CycleMap(); // spawn @@ -86,7 +88,7 @@ class IGameController }; vec2 m_aaSpawnPoints[3][64]; int m_aNumSpawnPoints[3]; - + float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) const; void EvaluateSpawnType(CSpawnEval *pEval, int Type) const; @@ -120,46 +122,6 @@ class IGameController void UpdateGameInfo(int ClientID); - typedef void (*COMMAND_CALLBACK)(class CPlayer *pPlayer, const char *pArgs); - - //static void Com_Example(class CPlayer *pPlayer, const char *pArgs); - - struct CChatCommand - { - char m_aName[32]; - char m_aHelpText[64]; - char m_aArgsFormat[16]; - COMMAND_CALLBACK m_pfnCallback; - bool m_Used; - }; - - class CChatCommands - { - enum - { - // 8 is the number of vanilla commands, 14 the number of commands left to fill the chat. - MAX_COMMANDS = 8 + 14 - }; - - CChatCommand m_aCommands[MAX_COMMANDS]; - public: - CChatCommands(); - - // Format: i = int, s = string, p = playername, c = subcommand - void AddCommand(const char *pName, const char *pArgsFormat, const char *pHelpText, COMMAND_CALLBACK pfnCallback); - void RemoveCommand(const char *pName); - void SendRemoveCommand(class IServer *pServer, const char *pName, int ID); - CChatCommand *GetCommand(const char *pName); - - void OnPlayerConnect(class IServer *pServer, class CPlayer *pPlayer); - - void OnInit(); - }; - - CChatCommands m_Commands; - - CChatCommands *CommandsManager() { return &m_Commands; } - public: IGameController(class CGameContext *pGameServer); virtual ~IGameController() {}; @@ -256,9 +218,12 @@ class IGameController void DoTeamChange(class CPlayer *pPlayer, int Team, bool DoChatMsg=true); void ForceTeamBalance() { if(!(m_GameFlags&GAMEFLAG_SURVIVAL)) DoTeamBalance(); } - + int GetRealPlayerNum() const { return m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE]; } int GetStartTeam(); + + static void Com_Example(IConsole::IResult *pResult, void *pContext); + virtual void RegisterChatCommands(CCommandManager *pManager); }; #endif From 43a247e24d5fa40aa4d6e0ea89c34a53c5a84042 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 2 Feb 2020 12:05:25 +0100 Subject: [PATCH 140/479] stripped off huffman usage --- src/engine/shared/demo.cpp | 6 ++++-- src/engine/shared/demo.h | 3 +++ src/engine/shared/huffman.cpp | 22 +++++++++++++++++++--- src/engine/shared/huffman.h | 2 +- src/engine/shared/network.cpp | 32 +++----------------------------- src/engine/shared/network.h | 4 +--- 6 files changed, 31 insertions(+), 38 deletions(-) diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index d5276bca..e76f2755 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -24,6 +24,7 @@ CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta) m_File = 0; m_LastTickMarker = -1; m_pSnapshotDelta = pSnapshotDelta; + m_Huffman.Init(); } // Record @@ -203,7 +204,7 @@ void CDemoRecorder::Write(int Type, const void *pData, int Size) m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_recorder", "error during intpack compression"); return; } - Size = CNetBase::Compress(aBuffer, Size, aBuffer2, sizeof(aBuffer2)); // buffer -> buffer2 + Size = m_Huffman.Compress(aBuffer, Size, aBuffer2, sizeof(aBuffer2)); // buffer -> buffer2 if(Size < 0) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_recorder", "error during network compression"); @@ -336,6 +337,7 @@ void CDemoRecorder::AddDemoMarker() CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta) { + m_Huffman.Init(); m_File = 0; m_aErrorMsg[0] = 0; m_pKeyFrames = 0; @@ -506,7 +508,7 @@ void CDemoPlayer::DoTick() break; } - DataSize = CNetBase::Decompress(aCompresseddata, ChunkSize, aDecompressed, sizeof(aDecompressed)); + DataSize = m_Huffman.Decompress(aCompresseddata, ChunkSize, aDecompressed, sizeof(aDecompressed)); if(DataSize < 0) { // stop on error or eof diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h index 8d3671da..c8a43ba4 100644 --- a/src/engine/shared/demo.h +++ b/src/engine/shared/demo.h @@ -6,11 +6,13 @@ #include #include +#include "huffman.h" #include "snapshot.h" class CDemoRecorder : public IDemoRecorder { class IConsole *m_pConsole; + CHuffman m_Huffman; IOHANDLE m_File; int m_LastTickMarker; int m_LastKeyFrame; @@ -84,6 +86,7 @@ class CDemoPlayer : public IDemoPlayer }; class IConsole *m_pConsole; + CHuffman m_Huffman; IOHANDLE m_File; char m_aFilename[256]; char m_aErrorMsg[256]; diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index d08c39c1..cce241bb 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -3,6 +3,22 @@ #include #include "huffman.h" + +static const unsigned gs_aFreqTable[256 + 1] = { + 1 << 30,4545,2657,431,1950,919,444,482,2244,617,838,542,715,1814,304,240,754,212,647,186, + 283,131,146,166,543,164,167,136,179,859,363,113,157,154,204,108,137,180,202,176, + 872,404,168,134,151,111,113,109,120,126,129,100,41,20,16,22,18,18,17,19, + 16,37,13,21,362,166,99,78,95,88,81,70,83,284,91,187,77,68,52,68, + 59,66,61,638,71,157,50,46,69,43,11,24,13,19,10,12,12,20,14,9, + 20,20,10,10,15,15,12,12,7,19,15,14,13,18,35,19,17,14,8,5, + 15,17,9,15,14,18,8,10,2173,134,157,68,188,60,170,60,194,62,175,71, + 148,67,167,78,211,67,156,69,1674,90,174,53,147,89,181,51,174,63,163,80, + 167,94,128,122,223,153,218,77,200,110,190,73,174,69,145,66,277,143,141,60, + 136,53,180,57,142,57,158,61,166,112,152,92,26,22,21,28,20,26,30,21, + 32,27,20,17,23,21,30,22,22,21,27,25,17,27,23,18,39,26,15,21, + 12,18,18,27,20,18,15,19,11,17,33,12,18,15,19,18,16,26,17,18, + 9,10,25,22,22,17,20,16,6,16,15,20,14,18,24,335,1517 }; + struct CHuffmanConstructNode { unsigned short m_NodeId; @@ -96,16 +112,16 @@ void CHuffman::ConstructTree(const unsigned *pFrequencies) void CHuffman::Init(const unsigned *pFrequencies) { - int i; - // make sure to cleanout every thing mem_zero(this, sizeof(*this)); // construct the tree + if(!pFrequencies) + pFrequencies = gs_aFreqTable; ConstructTree(pFrequencies); // build decode LUT - for(i = 0; i < HUFFMAN_LUTSIZE; i++) + for(int i = 0; i < HUFFMAN_LUTSIZE; i++) { unsigned Bits = i; int k; diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h index 0d15ed99..96628db9 100644 --- a/src/engine/shared/huffman.h +++ b/src/engine/shared/huffman.h @@ -53,7 +53,7 @@ class CHuffman - Does no allocation what so ever. - You don't have to call any cleanup functions when you are done with it */ - void Init(const unsigned *pFrequencies); + void Init(const unsigned *pFrequencies = 0); /* Function: huffman_compress diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index e769d1e5..d291d799 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -133,7 +133,7 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons // compress if not ctrl msg if(!(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)) - CompressedSize = Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); + CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); // check if the compression was enabled, successful and good enough if(CompressedSize > 0 && CompressedSize < pPacket->m_DataSize) @@ -249,7 +249,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct pPacket->m_ResponseToken = NET_TOKEN_NONE; if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION) - pPacket->m_DataSize = Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); + pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); else mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize); } @@ -407,34 +407,8 @@ void CNetBase::CloseLog() } } -int CNetBase::Compress(const void *pData, int DataSize, void *pOutput, int OutputSize) -{ - return ms_Huffman.Compress(pData, DataSize, pOutput, OutputSize); -} - -int CNetBase::Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize) -{ - return ms_Huffman.Decompress(pData, DataSize, pOutput, OutputSize); -} - - -static const unsigned gs_aFreqTable[256+1] = { - 1<<30,4545,2657,431,1950,919,444,482,2244,617,838,542,715,1814,304,240,754,212,647,186, - 283,131,146,166,543,164,167,136,179,859,363,113,157,154,204,108,137,180,202,176, - 872,404,168,134,151,111,113,109,120,126,129,100,41,20,16,22,18,18,17,19, - 16,37,13,21,362,166,99,78,95,88,81,70,83,284,91,187,77,68,52,68, - 59,66,61,638,71,157,50,46,69,43,11,24,13,19,10,12,12,20,14,9, - 20,20,10,10,15,15,12,12,7,19,15,14,13,18,35,19,17,14,8,5, - 15,17,9,15,14,18,8,10,2173,134,157,68,188,60,170,60,194,62,175,71, - 148,67,167,78,211,67,156,69,1674,90,174,53,147,89,181,51,174,63,163,80, - 167,94,128,122,223,153,218,77,200,110,190,73,174,69,145,66,277,143,141,60, - 136,53,180,57,142,57,158,61,166,112,152,92,26,22,21,28,20,26,30,21, - 32,27,20,17,23,21,30,22,22,21,27,25,17,27,23,18,39,26,15,21, - 12,18,18,27,20,18,15,19,11,17,33,12,18,15,19,18,16,26,17,18, - 9,10,25,22,22,17,20,16,6,16,15,20,14,18,24,335,1517}; - void CNetBase::Init(CConfig *pConfig) { m_pConfig = pConfig; - ms_Huffman.Init(gs_aFreqTable); + ms_Huffman.Init(); } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 43bcc014..8811b6dd 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -540,9 +540,7 @@ class CNetBase static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv); static void CloseLog(); static void Init(class CConfig *pConfig); - static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize); - static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize); - + static void SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize); static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended); static void SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize); From 4b070e2e60408b1d2e17df0a60500d969cc2fe74 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 2 Feb 2020 12:20:09 +0100 Subject: [PATCH 141/479] distinguish network logging of the server --- src/engine/server/server.cpp | 2 +- src/engine/shared/engine.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index a015a58d..b3235593 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1830,7 +1830,7 @@ int main(int argc, const char **argv) // ignore_convention // create the components int FlagMask = CFGFLAG_SERVER|CFGFLAG_ECON; - IEngine *pEngine = CreateEngine("Teeworlds"); + IEngine *pEngine = CreateEngine("Teeworlds_Server"); IEngineMap *pEngineMap = CreateEngineMap(); IGameServer *pGameServer = CreateGameServer(); IConsole *pConsole = CreateConsole(CFGFLAG_SERVER|CFGFLAG_ECON); diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index 1a5261f5..b819a3a9 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -24,6 +24,7 @@ class CEngine : public IEngine IConsole *m_pConsole; IStorage *m_pStorage; bool m_Logging; + const char *m_pAppname; static void Con_DbgLognetwork(IConsole::IResult *pResult, void *pUserData) { @@ -39,8 +40,8 @@ class CEngine : public IEngine char aBuf[32]; str_timestamp(aBuf, sizeof(aBuf)); char aFilenameSent[128], aFilenameRecv[128]; - str_format(aFilenameSent, sizeof(aFilenameSent), "dumps/network_sent_%s.txt", aBuf); - str_format(aFilenameRecv, sizeof(aFilenameRecv), "dumps/network_recv_%s.txt", aBuf); + str_format(aFilenameSent, sizeof(aFilenameSent), "dumps/%s_network_sent_%s.txt", pEngine->m_pAppname, aBuf); + str_format(aFilenameRecv, sizeof(aFilenameRecv), "dumps/%s_network_recv_%s.txt", pEngine->m_pAppname, aBuf); CNetBase::OpenLog(pEngine->m_pStorage->OpenFile(aFilenameSent, IOFLAG_WRITE, IStorage::TYPE_SAVE), pEngine->m_pStorage->OpenFile(aFilenameRecv, IOFLAG_WRITE, IStorage::TYPE_SAVE)); pEngine->m_Logging = true; @@ -69,6 +70,7 @@ class CEngine : public IEngine m_JobPool.Init(1); m_Logging = false; + m_pAppname = pAppname; } void Init() From ce9717f75ec52fa9d49de4186f033a0e58ebfce0 Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 16:18:52 +0100 Subject: [PATCH 142/479] Decrease dynamic allocations --- src/game/client/components/chat.cpp | 57 ++++++++++------------------- src/game/client/components/chat.h | 2 +- src/game/commands.h | 24 +++--------- 3 files changed, 27 insertions(+), 56 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 1d7bc160..5d502590 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -53,9 +53,11 @@ void CChat::OnReset() m_IgnoreCommand = false; m_SelectedCommand = 0; - if(m_pFilter) - free(m_pFilter); - m_pFilter = 0; + + m_aFilter.set_size(8); //Should help decrease allocations + for(int i = 0; i < m_aFilter.size(); i++) + m_aFilter[i] = false; + m_FilteredCount = 0; for(int i = 0; i < CHAT_NUM; ++i) @@ -77,8 +79,8 @@ void CChat::OnReset() m_CommandManager.AddCommand("friend", "Add player as friend", "p", &Com_Befriend, this); m_CommandManager.AddCommand("m", "Mute a player", "p", &Com_Mute, this); m_CommandManager.AddCommand("mute", "Mute a player", "p", &Com_Mute, this); - m_CommandManager.AddCommand("r", "Reply to a whisper", "", &Com_Reply, this); - m_CommandManager.AddCommand("team", "Switch to team chat", "", &Com_Team, this); + m_CommandManager.AddCommand("r", "Reply to a whisper", "?r", &Com_Reply, this); + m_CommandManager.AddCommand("team", "Switch to team chat", "?r", &Com_Team, this); m_CommandManager.AddCommand("w", "Whisper another player", "p", &Com_Whisper, this); m_CommandManager.AddCommand("whisper", "Whisper another player", "p", &Com_Whisper, this); } @@ -507,11 +509,6 @@ void CChat::ClearInput() m_IgnoreCommand = false; m_SelectedCommand = 0; - - if(m_pFilter) - free(m_pFilter); - m_pFilter = 0; - m_FilteredCount = 0; } void CChat::ServerCommandCallback(IConsole::IResult *pResult, void *pContext) @@ -1340,7 +1337,7 @@ void CChat::HandleCommands(float x, float y, float w) FilterChatCommands(m_Input.GetString()); // flag active commands, update selected command const int ActiveCount = m_CommandManager.CommandCount() - m_FilteredCount; - if(ActiveCount && m_pFilter[m_SelectedCommand]) + if(ActiveCount && m_aFilter[m_SelectedCommand]) { m_SelectedCommand = -1; NextActiveCommand(&m_SelectedCommand); @@ -1366,7 +1363,7 @@ void CChat::HandleCommands(float x, float y, float w) // render commands for(int i = m_CommandManager.CommandCount() - 1; i >= 0; i--) { - if(m_pFilter[i]) + if(m_aFilter[i]) continue; const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(i); @@ -1569,24 +1566,16 @@ void CChat::Com_Befriend(IConsole::IResult *pResult, void *pContext) int CChat::FilterChatCommands(const char *pLine) { - if(m_pFilter) - free(m_pFilter); - - m_pFilter = (bool *)malloc(m_CommandManager.CommandCount() * sizeof(*m_pFilter)); - if(!m_pFilter) - return -1; + m_aFilter.set_size(m_CommandManager.CommandCount()); - m_FilteredCount = m_CommandManager.Filter(m_pFilter, pLine + 1); + m_FilteredCount = m_CommandManager.Filter(&m_aFilter, pLine + 1); return m_FilteredCount; } int CChat::GetFirstActiveCommand() { - if(!m_pFilter) - return 0; - for(int i = 0; i < m_CommandManager.CommandCount(); i++) - if(!m_pFilter[i]) + if(!m_aFilter[i]) return i; return -1; @@ -1595,13 +1584,10 @@ int CChat::GetFirstActiveCommand() void CChat::NextActiveCommand(int *Index) { int StartIndex = (*Index)++; - if(m_pFilter) + while(*Index % m_CommandManager.CommandCount() != StartIndex && + m_aFilter[*Index % m_CommandManager.CommandCount()]) { - while(*Index % m_CommandManager.CommandCount() != StartIndex && - m_pFilter[*Index % m_CommandManager.CommandCount()]) - { - (*Index)++; - } + (*Index)++; } *Index %= m_CommandManager.CommandCount(); @@ -1610,14 +1596,11 @@ void CChat::NextActiveCommand(int *Index) void CChat::PreviousActiveCommand(int *Index) { int StartIndex = (*Index)--; - if(m_pFilter) - { - while((*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount() != StartIndex && - m_pFilter[(*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount()]) - { - (*Index)--; - } - } + while((*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount() != StartIndex && + m_aFilter[(*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount()]) + { + (*Index)--; + } *Index += m_CommandManager.CommandCount(); *Index %= m_CommandManager.CommandCount(); diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 1ef2eaff..b9c4d11e 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -83,7 +83,7 @@ class CChat : public CComponent bool m_IgnoreCommand; int m_SelectedCommand; - bool *m_pFilter; + array m_aFilter; int m_FilteredCount; int FilterChatCommands(const char *pLine); int GetFirstActiveCommand(); diff --git a/src/game/commands.h b/src/game/commands.h index 69564003..e5a04d93 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -131,7 +131,7 @@ class CCommandManager int OnCommand(const char *pCommand, const char *pArgs, int ClientID) { - dbg_msg("DEBUG", "calling '%s' with args '%s'", pCommand, pArgs); + dbg_msg("chat-command", "calling '%s' with args '%s'", pCommand, pArgs); const CCommand *pCom = GetCommand(pCommand); if(!pCom) return 1; @@ -140,33 +140,21 @@ class CCommandManager return m_pConsole->ParseCommandArgs(pArgs, pCom->m_aArgsFormat, pCom->m_pfnCallback, &Context); } - int Filter(bool *pFilter, const char *pStr) + int Filter(array *paFilter, const char *pStr) { + dbg_assert((*paFilter).size() == m_aCommands.size(), "filter size must match command count"); if(!*pStr) { - mem_zero(pFilter, m_aCommands.size() * sizeof(*pFilter)); + for(int i = 0; i < (*paFilter).size(); i++) + (*paFilter)[i] = false; return 0; } int Filtered = 0; for(int i = 0; i < m_aCommands.size(); i++) { - /*if(str_find_nocase(m_aCommands[i].m_aName, pStr)) - dbg_msg("DEBUG", "'%s' found in '%s' '%p' '%p' '%s'", pStr, m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr), m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName ? "true" : "false"); - else - dbg_msg("DEBUJG", "'%s' not found in '%s' '%s'", pStr, m_aCommands[i].m_aName, str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName ? "true" : "false");*/ - - Filtered += (pFilter[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); - } - - /*char aBuf[64] = ""; - for(int i = 0; i < m_aCommands.size(); i++) - { - char test[5]; - str_format(test, sizeof(test), "%d ", pFilter[i]); - str_append(aBuf, test, sizeof(aBuf)); + Filtered += ((*paFilter)[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); } - dbg_msg("DEBUG", "%s", aBuf);*/ return Filtered; } From e28143a1309bb3e2b9e8e0ca57c44196ee7f359d Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 16:21:49 +0100 Subject: [PATCH 143/479] References are cleaner --- src/game/client/components/chat.cpp | 2 +- src/game/commands.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 5d502590..03a1a001 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1568,7 +1568,7 @@ int CChat::FilterChatCommands(const char *pLine) { m_aFilter.set_size(m_CommandManager.CommandCount()); - m_FilteredCount = m_CommandManager.Filter(&m_aFilter, pLine + 1); + m_FilteredCount = m_CommandManager.Filter(m_aFilter, pLine + 1); return m_FilteredCount; } diff --git a/src/game/commands.h b/src/game/commands.h index e5a04d93..766c3cf8 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -140,20 +140,20 @@ class CCommandManager return m_pConsole->ParseCommandArgs(pArgs, pCom->m_aArgsFormat, pCom->m_pfnCallback, &Context); } - int Filter(array *paFilter, const char *pStr) + int Filter(array &aFilter, const char *pStr) { - dbg_assert((*paFilter).size() == m_aCommands.size(), "filter size must match command count"); + dbg_assert(aFilter.size() == m_aCommands.size(), "filter size must match command count"); if(!*pStr) { - for(int i = 0; i < (*paFilter).size(); i++) - (*paFilter)[i] = false; + for(int i = 0; i < aFilter.size(); i++) + aFilter[i] = false; return 0; } int Filtered = 0; for(int i = 0; i < m_aCommands.size(); i++) { - Filtered += ((*paFilter)[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); + Filtered += (aFilter[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); } return Filtered; From 03f93dea75117fcc7ff4f1e92038d29709756124 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 2 Feb 2020 18:15:26 +0100 Subject: [PATCH 144/479] shortened a config value path --- src/game/server/gamemodes/tdm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp index c2312680..1af4f7fc 100644 --- a/src/game/server/gamemodes/tdm.cpp +++ b/src/game/server/gamemodes/tdm.cpp @@ -28,7 +28,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye m_aTeamscore[pKiller->GetTeam()&1]++; // good shit } - pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*GameServer()->Config()->m_SvRespawnDelayTDM); + pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*Config()->m_SvRespawnDelayTDM); return 0; } From d670fdef4716a6447f5f7f951f6e3e0f6aa49ffd Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 18:20:04 +0100 Subject: [PATCH 145/479] Make the UI capable of n-commands --- src/game/client/components/chat.cpp | 95 ++++++++++++++++++----------- src/game/client/components/chat.h | 5 +- src/game/server/gamecontroller.cpp | 29 +++++++++ 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 03a1a001..222f224f 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -53,6 +53,7 @@ void CChat::OnReset() m_IgnoreCommand = false; m_SelectedCommand = 0; + m_CommandStart = 0; m_aFilter.set_size(8); //Should help decrease allocations for(int i = 0; i < m_aFilter.size(); i++) @@ -429,6 +430,8 @@ bool CChat::OnInput(IInput::CEvent Event) if(IsTypingCommand()) { PreviousActiveCommand(&m_SelectedCommand); + if(m_SelectedCommand < 0) + m_SelectedCommand = 0; } else { @@ -451,6 +454,8 @@ bool CChat::OnInput(IInput::CEvent Event) if(IsTypingCommand()) { NextActiveCommand(&m_SelectedCommand); + if(m_SelectedCommand >= m_CommandManager.CommandCount()) + m_SelectedCommand = m_CommandManager.CommandCount() - 1; } else { @@ -1335,33 +1340,47 @@ void CChat::HandleCommands(float x, float y, float w) const float LineHeight = 8.0f; FilterChatCommands(m_Input.GetString()); // flag active commands, update selected command - const int ActiveCount = m_CommandManager.CommandCount() - m_FilteredCount; + const int DisplayCount = min(m_CommandManager.CommandCount() - m_FilteredCount, 16); - if(ActiveCount && m_aFilter[m_SelectedCommand]) + if(DisplayCount && m_aFilter[m_SelectedCommand]) { m_SelectedCommand = -1; NextActiveCommand(&m_SelectedCommand); } + if(DisplayCount && m_aFilter[m_CommandStart]) + { + NextActiveCommand(&m_CommandStart); + } - if(ActiveCount > 0) // at least one command to display + //dbg_msg("DEBUG", "as%d c%d", m_CommandStart, m_SelectedCommand); + if(DisplayCount > 0) // at least one command to display { - CUIRect Rect = {x, y-(ActiveCount+1)*LineHeight, LineWidth, (ActiveCount+1)*LineHeight}; + CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth, (DisplayCount+1)*LineHeight}; RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_ALL, 3.0f); - // render notification + int End = m_CommandStart; + for(int i = 0; i < DisplayCount - 1; i++) + NextActiveCommand(&End); + + if(End >= m_CommandManager.CommandCount()) + for(int i = End - m_CommandManager.CommandCount(); i >= 0; i--) + PreviousActiveCommand(&m_CommandStart); + + if(m_SelectedCommand < m_CommandStart) { - y -= LineHeight; - CTextCursor Cursor; - TextRender()->SetCursor(&Cursor, Rect.x + 5.0f, y, 5.0f, TEXTFLAG_RENDER); - TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); - if(m_SelectedCommand >= 0 && str_startswith(m_Input.GetString() + 1, m_CommandManager.GetCommand(m_SelectedCommand)->m_aName)) - TextRender()->TextEx(&Cursor, Localize("Press Enter to confirm or Esc to cancel"), -1); - else - TextRender()->TextEx(&Cursor, Localize("Press Tab to select or Esc to cancel"), -1); + //dbg_msg("DEBUG", "Decrementing Start"); + PreviousActiveCommand(&m_CommandStart); + } + else if(m_SelectedCommand > End) + { + //dbg_msg("DEBUG", "Incrementing Start"); + NextActiveCommand(&m_CommandStart); + NextActiveCommand(&End); } - // render commands - for(int i = m_CommandManager.CommandCount() - 1; i >= 0; i--) + //dbg_msg("DEBUG", "bs%d c%d", m_CommandStart, m_SelectedCommand); + y -= (DisplayCount+2)*LineHeight; + for(int i = m_CommandStart, j = 0; j < DisplayCount && i < m_CommandManager.CommandCount(); i++) { if(m_aFilter[i]) continue; @@ -1370,12 +1389,13 @@ void CChat::HandleCommands(float x, float y, float w) if(!pCommand) continue; - y -= LineHeight; + j++; + + y += LineHeight; CUIRect HighlightRect = {Rect.x, y, LineWidth, LineHeight-1}; - //TODO: Fix this - //if(!pCommand->m_pfnCallback) - //RenderTools()->DrawUIRect(&HighlightRect, vec4(0.0f, 0.6f, 0.6f, 0.2f), CUI::CORNER_ALL, 0); + if(pCommand->m_pfnCallback == ServerCommandCallback) + RenderTools()->DrawUIRect(&HighlightRect, vec4(0.0f, 0.6f, 0.6f, 0.2f), CUI::CORNER_ALL, 0); // draw selection box if(i == m_SelectedCommand) @@ -1416,6 +1436,18 @@ void CChat::HandleCommands(float x, float y, float w) TextRender()->TextEx(&Cursor, pCommand->m_aHelpText, -1); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } + + // render notification + { + y += LineHeight; + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Rect.x + 5.0f, y, 5.0f, TEXTFLAG_RENDER); + TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); + if(m_SelectedCommand >= 0 && str_startswith(m_Input.GetString() + 1, m_CommandManager.GetCommand(m_SelectedCommand)->m_aName)) + TextRender()->TextEx(&Cursor, Localize("Press Enter to confirm or Esc to cancel"), -1); + else + TextRender()->TextEx(&Cursor, Localize("Press Tab to select or Esc to cancel"), -1); + } } } } @@ -1581,27 +1613,20 @@ int CChat::GetFirstActiveCommand() return -1; } -void CChat::NextActiveCommand(int *Index) +int CChat::NextActiveCommand(int *Index) { - int StartIndex = (*Index)++; - while(*Index % m_CommandManager.CommandCount() != StartIndex && - m_aFilter[*Index % m_CommandManager.CommandCount()]) - { + (*Index)++; + while(*Index < m_aFilter.size() && m_aFilter[*Index]) (*Index)++; - } - *Index %= m_CommandManager.CommandCount(); + return *Index; } -void CChat::PreviousActiveCommand(int *Index) +int CChat::PreviousActiveCommand(int *Index) { - int StartIndex = (*Index)--; - while((*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount() != StartIndex && - m_aFilter[(*Index + m_CommandManager.CommandCount()) % m_CommandManager.CommandCount()]) - { - (*Index)--; - } + (*Index)--; + while(*Index >= 0 && m_aFilter[*Index]) + (*Index)--; - *Index += m_CommandManager.CommandCount(); - *Index %= m_CommandManager.CommandCount(); + return *Index; } diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index b9c4d11e..bd513534 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -82,13 +82,14 @@ class CChat : public CComponent // chat commands bool m_IgnoreCommand; int m_SelectedCommand; + int m_CommandStart; array m_aFilter; int m_FilteredCount; int FilterChatCommands(const char *pLine); int GetFirstActiveCommand(); - void NextActiveCommand(int *Index); - void PreviousActiveCommand(int *Index); + int NextActiveCommand(int *Index); + int PreviousActiveCommand(int *Index); CCommandManager m_CommandManager; bool IsTypingCommand() const; diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index da780527..f55dc53f 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -1221,4 +1221,33 @@ void IGameController::Com_Example(IConsole::IResult *pResult, void *pContext) void IGameController::RegisterChatCommands(CCommandManager *pManager) { pManager->AddCommand("test", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test2", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("call", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test4", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test5", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("call2", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test7", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test8", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("toast", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test10", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test11", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test12", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("toast2", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test14", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock2", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock3", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock4", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test19", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("toast3", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test21", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test22", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock5", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test24", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test25", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test26", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("sock6", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test28", "Test the command system", "r", Com_Example, this); + pManager->AddCommand("test29", "Test the command system", "r", Com_Example, this); + /*pManager->AddCommand("test30", "Test the command system", "r", Com_Example, this);*/ } From fbced6ff6c371a4ba79d1efa0d5e0d67c5269969 Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 19:12:56 +0100 Subject: [PATCH 146/479] Add a scrollbar --- src/game/client/components/chat.cpp | 37 ++++++++++++++++++++++------- src/game/client/components/chat.h | 1 + 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 222f224f..e8e86f21 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1331,16 +1331,17 @@ bool CChat::IsTypingCommand() const // chat commands handlers void CChat::HandleCommands(float x, float y, float w) { - //dbg_msg("DEBUG", "%d", m_SelectedCommand); // render commands menu if(m_Mode != CHAT_NONE && IsTypingCommand()) { const float Alpha = 0.90f; - const float LineWidth = w; + const float ScrollBarW = 6.0f; + const float LineWidth = w - ScrollBarW; const float LineHeight = 8.0f; FilterChatCommands(m_Input.GetString()); // flag active commands, update selected command - const int DisplayCount = min(m_CommandManager.CommandCount() - m_FilteredCount, 16); + const int ActiveCount = m_CommandManager.CommandCount() - m_FilteredCount; + const int DisplayCount = min(ActiveCount, 16); if(DisplayCount && m_aFilter[m_SelectedCommand]) { @@ -1352,10 +1353,9 @@ void CChat::HandleCommands(float x, float y, float w) NextActiveCommand(&m_CommandStart); } - //dbg_msg("DEBUG", "as%d c%d", m_CommandStart, m_SelectedCommand); if(DisplayCount > 0) // at least one command to display { - CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth, (DisplayCount+1)*LineHeight}; + CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth + ScrollBarW, (DisplayCount+1)*LineHeight}; RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_ALL, 3.0f); int End = m_CommandStart; @@ -1368,17 +1368,25 @@ void CChat::HandleCommands(float x, float y, float w) if(m_SelectedCommand < m_CommandStart) { - //dbg_msg("DEBUG", "Decrementing Start"); PreviousActiveCommand(&m_CommandStart); } else if(m_SelectedCommand > End) { - //dbg_msg("DEBUG", "Incrementing Start"); NextActiveCommand(&m_CommandStart); NextActiveCommand(&End); } - //dbg_msg("DEBUG", "bs%d c%d", m_CommandStart, m_SelectedCommand); + // render worlds most inefficient "scrollbar" + { + CUIRect K = {x + LineWidth, y - (DisplayCount + 1) * LineHeight, ScrollBarW, (DisplayCount+1)*LineHeight}; + RenderTools()->DrawUIRect(&K, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_R, 3.0f); + + float h = K.h; + K.h *= (float)DisplayCount/ActiveCount; + K.y += h * (float)(GetActiveCountRange(GetFirstActiveCommand(), m_CommandStart))/ActiveCount; + RenderTools()->DrawUIRect(&K, vec4(0.5f, 0.5f, 0.5f, Alpha), CUI::CORNER_R, 3.0f); + } + y -= (DisplayCount+2)*LineHeight; for(int i = m_CommandStart, j = 0; j < DisplayCount && i < m_CommandManager.CommandCount(); i++) { @@ -1630,3 +1638,16 @@ int CChat::PreviousActiveCommand(int *Index) return *Index; } + +int CChat::GetActiveCountRange(int i, int j) +{ + int Count = 0; + + while(i < j) + { + if(!m_aFilter[i++]) + Count++; + } + + return Count; +} diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index bd513534..7c041126 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -90,6 +90,7 @@ class CChat : public CComponent int GetFirstActiveCommand(); int NextActiveCommand(int *Index); int PreviousActiveCommand(int *Index); + int GetActiveCountRange(int i, int j); CCommandManager m_CommandManager; bool IsTypingCommand() const; From ef4ffb378432030a60c1fcd87119d07c5255b0b3 Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 20:02:50 +0100 Subject: [PATCH 147/479] Show scrollbar when needed --- src/game/client/components/chat.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index e8e86f21..89395573 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1336,7 +1336,7 @@ void CChat::HandleCommands(float x, float y, float w) { const float Alpha = 0.90f; const float ScrollBarW = 6.0f; - const float LineWidth = w - ScrollBarW; + float LineWidth = w; const float LineHeight = 8.0f; FilterChatCommands(m_Input.GetString()); // flag active commands, update selected command @@ -1355,7 +1355,7 @@ void CChat::HandleCommands(float x, float y, float w) if(DisplayCount > 0) // at least one command to display { - CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth + ScrollBarW, (DisplayCount+1)*LineHeight}; + CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth, (DisplayCount+1)*LineHeight}; RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_ALL, 3.0f); int End = m_CommandStart; @@ -1377,14 +1377,17 @@ void CChat::HandleCommands(float x, float y, float w) } // render worlds most inefficient "scrollbar" + if(ActiveCount > DisplayCount) { - CUIRect K = {x + LineWidth, y - (DisplayCount + 1) * LineHeight, ScrollBarW, (DisplayCount+1)*LineHeight}; - RenderTools()->DrawUIRect(&K, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_R, 3.0f); + LineWidth -= ScrollBarW; - float h = K.h; - K.h *= (float)DisplayCount/ActiveCount; - K.y += h * (float)(GetActiveCountRange(GetFirstActiveCommand(), m_CommandStart))/ActiveCount; - RenderTools()->DrawUIRect(&K, vec4(0.5f, 0.5f, 0.5f, Alpha), CUI::CORNER_R, 3.0f); + CUIRect Rect = {x + LineWidth, y - (DisplayCount + 1) * LineHeight, ScrollBarW, (DisplayCount+1)*LineHeight}; + RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_R, 3.0f); + + float h = Rect.h; + Rect.h *= (float)DisplayCount/ActiveCount; + Rect.y += h * (float)(GetActiveCountRange(GetFirstActiveCommand(), m_CommandStart))/ActiveCount; + RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 0.5f, 0.5f, Alpha), CUI::CORNER_R, 3.0f); } y -= (DisplayCount+2)*LineHeight; From 971d7b79a558f07ab7fbb6971bed66cf35fb8882 Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 2 Feb 2020 20:05:40 +0100 Subject: [PATCH 148/479] Comment out examples --- src/game/server/gamecontroller.cpp | 35 +++--------------------------- src/game/server/gamecontroller.h | 2 +- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index f55dc53f..9996a006 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -1210,44 +1210,15 @@ int IGameController::GetStartTeam() return TEAM_SPECTATORS; } -void IGameController::Com_Example(IConsole::IResult *pResult, void *pContext) +/*void IGameController::Com_Example(IConsole::IResult *pResult, void *pContext) { CCommandManager::SCommandContext *pComContext = (CCommandManager::SCommandContext *)pContext; IGameController *pSelf = (IGameController *)pComContext->m_pContext; pSelf->GameServer()->SendBroadcast(pResult->GetString(0), -1); -} +}*/ void IGameController::RegisterChatCommands(CCommandManager *pManager) { - pManager->AddCommand("test", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test2", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("call", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test4", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test5", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("call2", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test7", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test8", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("toast", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test10", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test11", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test12", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("toast2", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test14", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock2", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock3", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock4", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test19", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("toast3", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test21", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test22", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock5", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test24", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test25", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test26", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("sock6", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test28", "Test the command system", "r", Com_Example, this); - pManager->AddCommand("test29", "Test the command system", "r", Com_Example, this); - /*pManager->AddCommand("test30", "Test the command system", "r", Com_Example, this);*/ + //pManager->AddCommand("test", "Test the command system", "r", Com_Example, this); } diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 42dcad6b..2be5f2ca 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -222,7 +222,7 @@ class IGameController int GetRealPlayerNum() const { return m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE]; } int GetStartTeam(); - static void Com_Example(IConsole::IResult *pResult, void *pContext); + //static void Com_Example(IConsole::IResult *pResult, void *pContext); virtual void RegisterChatCommands(CCommandManager *pManager); }; From ff8fec0455b5b8958b6af4eb9a1ea523e6207d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 2 Feb 2020 21:39:50 +0100 Subject: [PATCH 149/479] move tilemap skip init to CLayers --- src/game/client/components/maplayers.cpp | 1 - src/game/client/gameclient.cpp | 2 -- src/game/client/render.cpp | 35 ----------------------- src/game/client/render.h | 3 -- src/game/layers.cpp | 36 ++++++++++++++++++++++++ src/game/layers.h | 1 + 6 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 37c330bd..2ac70de4 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -67,7 +67,6 @@ void CMapLayers::LoadBackgroundMap() Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); m_pMenuLayers->Init(Kernel(), m_pMenuMap); - RenderTools()->RenderTilemapGenerateSkip(m_pMenuLayers); m_pClient->m_pMapimages->OnMenuMapLoad(m_pMenuMap); LoadEnvPoints(m_pMenuLayers, m_lEnvPointsMenu); } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 5d294c40..c047293b 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -434,8 +434,6 @@ void CGameClient::OnConnected() m_Layers.Init(Kernel()); m_Collision.Init(Layers()); - RenderTools()->RenderTilemapGenerateSkip(Layers()); - for(int i = 0; i < m_All.m_Num; i++) { m_All.m_paComponents[i]->OnMapLoad(); diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 25bf511d..7b777cf3 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -629,41 +629,6 @@ void CRenderTools::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup Graphics()->MapScreen(aPoints[0], aPoints[1], aPoints[2], aPoints[3]); } -void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) -{ - - for(int g = 0; g < pLayers->NumGroups(); g++) - { - CMapItemGroup *pGroup = pLayers->GetGroup(g); - - for(int l = 0; l < pGroup->m_NumLayers; l++) - { - CMapItemLayer *pLayer = pLayers->GetLayer(pGroup->m_StartLayer+l); - - if(pLayer->m_Type == LAYERTYPE_TILES) - { - CMapItemLayerTilemap *pTmap = (CMapItemLayerTilemap *)pLayer; - CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data); - for(int y = 0; y < pTmap->m_Height; y++) - { - for(int x = 1; x < pTmap->m_Width;) - { - int sx; - for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++) - { - if(pTiles[y*pTmap->m_Width+x+sx].m_Index) - break; - } - - pTiles[y*pTmap->m_Width+x].m_Skip = sx-1; - x += sx; - } - } - } - } - } -} - void CRenderTools::DrawClientID(ITextRender* pTextRender, CTextCursor* pCursor, int ID, const vec4& BgColor, const vec4& TextColor) { diff --git a/src/game/client/render.h b/src/game/client/render.h index 2eaac606..e721ca38 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -73,9 +73,6 @@ class CRenderTools void DrawUIRect(const CUIRect *pRect, vec4 Color, int Corners, float Rounding); void DrawUIRect4(const CUIRect *pRect, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, int Corners, float Rounding); - // larger rendering methods - void RenderTilemapGenerateSkip(class CLayers *pLayers); - // object render methods (gc_render_obj.cpp) void RenderTee(class CAnimState *pAnim, const CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos); void RenderTeeHand(const CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, diff --git a/src/game/layers.cpp b/src/game/layers.cpp index 4e499df7..a3cca222 100644 --- a/src/game/layers.cpp +++ b/src/game/layers.cpp @@ -54,6 +54,42 @@ void CLayers::Init(class IKernel *pKernel, IMap *pMap) } } } + + InitTilemapSkip(); +} + +void CLayers::InitTilemapSkip() +{ + for(int g = 0; g < NumGroups(); g++) + { + CMapItemGroup *pGroup = GetGroup(g); + + for(int l = 0; l < pGroup->m_NumLayers; l++) + { + CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l); + + if(pLayer->m_Type == LAYERTYPE_TILES) + { + CMapItemLayerTilemap *pTmap = (CMapItemLayerTilemap *)pLayer; + CTile *pTiles = (CTile *)Map()->GetData(pTmap->m_Data); + for(int y = 0; y < pTmap->m_Height; y++) + { + for(int x = 1; x < pTmap->m_Width;) + { + int sx; + for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++) + { + if(pTiles[y*pTmap->m_Width+x+sx].m_Index) + break; + } + + pTiles[y*pTmap->m_Width+x].m_Skip = sx-1; + x += sx; + } + } + } + } + } } CMapItemGroup *CLayers::GetGroup(int Index) const diff --git a/src/game/layers.h b/src/game/layers.h index 9b94305e..465cbbf8 100644 --- a/src/game/layers.h +++ b/src/game/layers.h @@ -15,6 +15,7 @@ class CLayers CMapItemGroup *m_pGameGroup; CMapItemLayerTilemap *m_pGameLayer; class IMap *m_pMap; + void InitTilemapSkip(); public: CLayers(); From fb0cf570f3bf61b203c937451e5efb927e643d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 2 Feb 2020 21:54:08 +0100 Subject: [PATCH 150/479] add optional spacing parameter to VSplitMid/HSplitMid --- src/game/client/components/menus.cpp | 34 ++++----------- src/game/client/components/menus_browser.cpp | 7 ++-- src/game/client/components/menus_ingame.cpp | 4 +- src/game/client/components/menus_settings.cpp | 41 +++++-------------- src/game/client/ui.cpp | 22 +++++----- src/game/client/ui.h | 5 +-- src/game/editor/editor.cpp | 4 +- 7 files changed, 39 insertions(+), 78 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index f4e86f45..c6e7613e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -748,7 +748,7 @@ void CMenus::DoInfoBox(const CUIRect *pRect, const char *pLabel, const char *pVa RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Label, Value; - pRect->VSplitMid(&Label, &Value); + pRect->VSplitMid(&Label, &Value, 2.0f); RenderTools()->DrawUIRect(&Value, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1839,9 +1839,7 @@ int CMenus::Render() } // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonAbort; if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed) @@ -1876,9 +1874,7 @@ int CMenus::Render() Config()->m_ClSaveServerPasswords = Config()->m_ClSaveServerPasswords == OnValue ? 0 : OnValue; // buttons - BottomBar.VSplitMid(&Abort, &TryAgain); - Abort.VSplitRight(SpacingW/2.0f, &Abort, 0); - TryAgain.VSplitLeft(SpacingW/2.0f, 0, &TryAgain); + BottomBar.VSplitMid(&Abort, &TryAgain, SpacingW); static CButtonContainer s_ButtonAbort; if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed) @@ -2042,9 +2038,7 @@ int CMenus::Render() UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) @@ -2084,9 +2078,7 @@ int CMenus::Render() DoEditBoxOption(m_aCurrentDemoFile, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), &EditBox, Localize("Name"), ButtonWidth, &s_OffsetRenameDemo); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) @@ -2132,9 +2124,7 @@ int CMenus::Render() ButtonHeight*ms_FontmodHeight*1.2f, CUI::ALIGN_CENTER, NameLabel.w); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) @@ -2165,9 +2155,7 @@ int CMenus::Render() UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, Box.w); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW / 2.0f, &No, 0); - Yes.VSplitLeft(SpacingW / 2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) @@ -2199,9 +2187,7 @@ int CMenus::Render() DoEditBoxOption(m_aSaveSkinName, m_aSaveSkinName, sizeof(m_aSaveSkinName), &EditBox, Localize("Name"), ButtonWidth, &s_OffsetSaveSkin); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonAbort; if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed) @@ -2227,9 +2213,7 @@ int CMenus::Render() UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); // buttons - BottomBar.VSplitMid(&No, &Yes); - No.VSplitRight(SpacingW/2.0f, &No, 0); - Yes.VSplitLeft(SpacingW/2.0f, 0, &Yes); + BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 5727ae5e..0910b1e9 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -788,14 +788,15 @@ void CMenus::RenderServerbrowserOverlay() RenderTools()->DrawUIRect(&View, vec4(0.25f, 0.25f, 0.25f, 1.0f), CUI::CORNER_ALL, 6.0f); View.Margin(2.0f, &View); + CUIRect NumServers, NumPlayers; + View.HSplitMid(&NumServers, &NumPlayers); char aBuf[128]; str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Servers"), pFilter->NumSortedServers()); - UI()->DoLabel(&View, aBuf, 12.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&NumServers, aBuf, 12.0f, CUI::ALIGN_CENTER); - View.HSplitMid(0, &View); str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Players"), pFilter->NumPlayers()); - UI()->DoLabel(&View, aBuf, 12.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&NumPlayers, aBuf, 12.0f, CUI::ALIGN_CENTER); } else if(Type == CInfoOverlay::OVERLAY_SERVERINFO) { diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 7d9e46b3..dc9080f4 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -364,8 +364,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) // serverinfo MainView.HSplitBottom(250.0f, &ServerInfo, &Motd); - ServerInfo.VSplitMid(&ServerInfo, &GameInfo); - ServerInfo.VSplitRight(1.0f, &ServerInfo, 0); + ServerInfo.VSplitMid(&ServerInfo, &GameInfo, 2.0f); RenderTools()->DrawUIRect(&ServerInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f); ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo); @@ -421,7 +420,6 @@ void CMenus::RenderServerInfo(CUIRect MainView) } // gameinfo - GameInfo.VSplitLeft(1.0f, 0, &GameInfo); RenderTools()->DrawUIRect(&GameInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f); GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index bf284852..1530f4a9 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -885,9 +885,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Label.y += 2.0f; UI()->DoLabel(&Label, Localize("Game"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - Game.VSplitMid(&GameLeft, &GameRight); - GameLeft.VSplitRight(Spacing * 0.5f, &GameLeft, 0); - GameRight.VSplitLeft(Spacing * 0.5f, 0, &GameRight); + Game.VSplitMid(&GameLeft, &GameRight, Spacing); // left side GameLeft.HSplitTop(Spacing, 0, &GameLeft); @@ -1048,9 +1046,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) // render language and theme selection CUIRect LanguageView, ThemeView; - MainView.VSplitMid(&LanguageView, &ThemeView); - LanguageView.VSplitRight(1, &LanguageView, 0); - ThemeView.VSplitLeft(1, 0, &ThemeView); + MainView.VSplitMid(&LanguageView, &ThemeView, 2.0f); RenderLanguageSelection(LanguageView); RenderThemeSelection(ThemeView); @@ -1119,9 +1115,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) // split menu TopView.HSplitTop(Spacing, 0, &TopView); - TopView.VSplitMid(&Left, &Right); - Left.VSplitRight(1.5f, &Left, 0); - Right.VSplitLeft(1.5f, 0, &Right); + TopView.VSplitMid(&Left, &Right, 3.0f); // left menu Left.HSplitTop(ButtonHeight, &Button, &Left); @@ -1228,9 +1222,7 @@ void CMenus::RenderSettingsTeeCustom(CUIRect MainView) } MainView.HSplitTop(SpacingH, 0, &MainView); - MainView.VSplitMid(&Left, &Right); - Left.VSplitRight(SpacingW/2.0f, &Left, 0); - Right.VSplitLeft(SpacingW/2.0f, 0, &Right); + MainView.VSplitMid(&Left, &Right, SpacingW); // part selection RenderSkinPartSelection(Left); @@ -1282,9 +1274,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) Preview.HSplitTop(SkinHeight, &Left, &Preview); // split the menu in 2 parts - Left.VSplitMid(&Left, &Right); - Left.VSplitRight(SpacingW/2.0f, &Left, 0); - Right.VSplitLeft(SpacingW/2.0f, 0, &Right); + Left.VSplitMid(&Left, &Right, SpacingW); // handle left @@ -1372,9 +1362,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) Label.y += 17.0f; UI()->DoLabel(&Label, Localize("Team:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - Right.VSplitMid(&Left, &Right); - Left.VSplitRight(SpacingW/2.0f, &Left, 0); - Right.VSplitLeft(SpacingW/2.0f, 0, &Right); + Right.VSplitMid(&Left, &Right, SpacingW); RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1688,9 +1676,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Label.y += 2.0f; UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - ScreenLeft.VSplitMid(&ScreenLeft, &ScreenRight); - ScreenLeft.VSplitRight(Spacing * 0.5f, &ScreenLeft, 0); - ScreenRight.VSplitLeft(Spacing * 0.5f, 0, &ScreenRight); + ScreenLeft.VSplitMid(&ScreenLeft, &ScreenRight, Spacing); ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft); ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); @@ -1836,9 +1822,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) MainView.HSplitTop(Spacing, 0, &MainView); MainView.HSplitTop(ButtonHeight, &Button, &MainView); CUIRect HeaderLeft, HeaderRight; - Button.VSplitMid(&HeaderLeft, &HeaderRight); - HeaderLeft.VSplitRight(1.5f, &HeaderLeft, 0); - HeaderRight.VSplitLeft(1.5f, 0, &HeaderRight); + Button.VSplitMid(&HeaderLeft, &HeaderRight, 3.0f); RenderTools()->DrawUIRect(&HeaderLeft, vec4(0.30f, 0.4f, 1.0f, 0.5f), CUI::CORNER_T, 5.0f); RenderTools()->DrawUIRect(&HeaderRight, vec4(0.0f, 0.0f, 0.0f, 0.5f), CUI::CORNER_T, 5.0f); @@ -1855,7 +1839,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) MainView.HSplitTop(Spacing, 0, &MainView); CUIRect ListRec, ListOth; - MainView.VSplitMid(&ListRec, &ListOth); + MainView.VSplitMid(&ListRec, &ListOth, 3.0f); ListRec.HSplitBottom(ButtonHeight, &ListRec, &Button); ListRec.HSplitBottom(Spacing, &ListRec, 0); @@ -1865,9 +1849,6 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Button.y += 2; UI()->DoLabel(&Button, aBuf, Button.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - ListRec.VSplitRight(1.5f, &ListRec, 0); - ListOth.VSplitLeft(1.5f, 0, &ListOth); - static CListBox s_RecListBox; static CListBox s_OthListBox; CheckSettings |= DoResolutionList(&ListRec, &s_RecListBox, m_lRecommendedVideoModes); @@ -1991,9 +1972,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) // split menu CUIRect Left, Right; Detail.HSplitTop(Spacing, 0, &Detail); - Detail.VSplitMid(&Left, &Right); - Left.VSplitRight(1.5f, &Left, 0); - Right.VSplitLeft(1.5f, 0, &Right); + Detail.VSplitMid(&Left, &Right, 3.0f); // sample rate thingy { diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 4271d9e0..f07113b0 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -136,25 +136,26 @@ void CUI::UpdateClipping() } } -void CUIRect::HSplitMid(CUIRect *pTop, CUIRect *pBottom) const +void CUIRect::HSplitMid(CUIRect *pTop, CUIRect *pBottom, float Spacing) const { CUIRect r = *this; - float Cut = r.h/2; + const float Cut = r.h/2; + const float HalfSpacing = Spacing/2; if(pTop) { pTop->x = r.x; pTop->y = r.y; pTop->w = r.w; - pTop->h = Cut; + pTop->h = Cut - HalfSpacing; } if(pBottom) { pBottom->x = r.x; - pBottom->y = r.y + Cut; + pBottom->y = r.y + Cut + HalfSpacing; pBottom->w = r.w; - pBottom->h = r.h - Cut; + pBottom->h = r.h - Cut - HalfSpacing; } } @@ -201,24 +202,25 @@ void CUIRect::HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const } -void CUIRect::VSplitMid(CUIRect *pLeft, CUIRect *pRight) const +void CUIRect::VSplitMid(CUIRect *pLeft, CUIRect *pRight, float Spacing) const { CUIRect r = *this; - float Cut = r.w/2; + const float Cut = r.w/2; + const float HalfSpacing = Spacing/2; if (pLeft) { pLeft->x = r.x; pLeft->y = r.y; - pLeft->w = Cut; + pLeft->w = Cut - HalfSpacing; pLeft->h = r.h; } if (pRight) { - pRight->x = r.x + Cut; + pRight->x = r.x + Cut + HalfSpacing; pRight->y = r.y; - pRight->w = r.w - Cut; + pRight->w = r.w - Cut - HalfSpacing; pRight->h = r.h; } } diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 1bb3fd17..382881d5 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -8,17 +8,16 @@ class CUIRect public: float x, y, w, h; - void HSplitMid(CUIRect *pTop, CUIRect *pBottom) const; + void HSplitMid(CUIRect *pTop, CUIRect *pBottom, float Spacing = 0.0f) const; void HSplitTop(float Cut, CUIRect *pTop, CUIRect *pBottom) const; void HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const; - void VSplitMid(CUIRect *pLeft, CUIRect *pRight) const; + void VSplitMid(CUIRect *pLeft, CUIRect *pRight, float Spacing = 0.0f) const; void VSplitLeft(float Cut, CUIRect *pLeft, CUIRect *pRight) const; void VSplitRight(float Cut, CUIRect *pLeft, CUIRect *pRight) const; void Margin(float Cut, CUIRect *pOtherRect) const; void VMargin(float Cut, CUIRect *pOtherRect) const; void HMargin(float Cut, CUIRect *pOtherRect) const; - }; class CUI diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 8247ad6b..48e74af2 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -2520,9 +2520,7 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int * else if(pProps[i].m_Type == PROPTYPE_SHIFT) { CUIRect Left, Right, Up, Down; - Shifter.VSplitMid(&Left, &Up); - Left.VSplitRight(1.0f, &Left, 0); - Up.VSplitLeft(1.0f, 0, &Up); + Shifter.VSplitMid(&Left, &Up, 2.0f); Left.VSplitLeft(10.0f, &Left, &Shifter); Shifter.VSplitRight(10.0f, &Shifter, &Right); RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f); From 5f9dfaadd31e854d947541acc2ee6542a5f7cbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 2 Feb 2020 22:09:44 +0100 Subject: [PATCH 151/479] extract drawing menu button shadow into RenderBackgroundShadow --- src/game/client/components/menus.cpp | 22 ++++++++++++++----- src/game/client/components/menus.h | 4 +++- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_settings.cpp | 10 ++++----- src/game/client/components/menus_start.cpp | 4 ++-- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c6e7613e..78d79aaf 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1020,8 +1020,8 @@ void CMenus::RenderMenubar(CUIRect Rect) CUIRect Left, Right; Box.VSplitLeft(ButtonWidth*4.0f + Spacing*3.0f, &Left, 0); Box.VSplitRight(ButtonWidth*1.5f + Spacing, 0, &Right); - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); - RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderBackgroundShadow(&Left, false); + RenderBackgroundShadow(&Right, false); Left.HSplitBottom(25.0f, 0, &Left); Right.HSplitBottom(25.0f, 0, &Right); @@ -1074,7 +1074,7 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header background if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderBackgroundShadow(&Box, false); Box.HSplitBottom(25.0f, 0, &Box); @@ -1154,7 +1154,7 @@ void CMenus::RenderMenubar(CUIRect Rect) // render header backgrounds if(Client()->State() == IClient::STATE_OFFLINE) - RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderBackgroundShadow(&Left, false); Left.HSplitBottom(25.0f, 0, &Left); @@ -1194,7 +1194,7 @@ void CMenus::RenderMenubar(CUIRect Rect) if(m_MenuPage == PAGE_DEMOS) { // render header background - RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 5.0f); + RenderBackgroundShadow(&Box, false); Box.HSplitBottom(25.0f, 0, &Box); @@ -1286,7 +1286,7 @@ void CMenus::RenderBackButton(CUIRect MainView) // render background MainView.HSplitBottom(60.0f, 0, &MainView); MainView.VSplitLeft(ButtonWidth, &MainView, 0); - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&MainView, true); // back to main menu CUIRect Button; @@ -2613,6 +2613,16 @@ void CMenus::RenderBackground() Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);} } +void CMenus::RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom) +{ + const vec4 Transparent(0.0f, 0.0f, 0.0f, 0.0f); + const vec4 Background(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f); + if(TopToBottom) + RenderTools()->DrawUIRect4(pRect, Background, Background, Transparent, Transparent, CUI::CORNER_T, 5.0f); + else + RenderTools()->DrawUIRect4(pRect, Transparent, Transparent, Background, Background, CUI::CORNER_B, 5.0f); +} + void CMenus::ConchainToggleMusic(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 9d498965..6a9f00b0 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -780,6 +780,9 @@ class CMenus : public CComponent void SetMenuPage(int NewPage); bool CheckHotKey(int Key) const; + + void RenderBackground(); + void RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom); public: struct CSwitchTeamInfo { @@ -788,7 +791,6 @@ class CMenus : public CComponent int m_TimeLeft; }; void GetSwitchTeamInfo(CSwitchTeamInfo *pInfo); - void RenderBackground(); void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; } diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 0910b1e9..cd14610b 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2243,7 +2243,7 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView) float ButtonWidth = MainView.w/2.0f-Spacing/2.0f; // render background - RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&MainView, true); // back to main menu CUIRect Button; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index aca7e7df..c4a2b99f 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -443,7 +443,7 @@ void CMenus::RenderDemoList(CUIRect MainView) float BackgroundWidth = ButtonWidth*(float)NumButtons+(float)(NumButtons-1)*Spacing; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 1530f4a9..f8ba041f 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1055,7 +1055,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; @@ -1404,7 +1404,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) float BackgroundWidth = s_CustomSkinMenu||(m_pSelectedSkin && (m_pSelectedSkin->m_Flags&CSkins::SKINFLAG_STANDARD) == 0) ? ButtonWidth*2.0f+SpacingW : ButtonWidth; BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); if(s_CustomSkinMenu) @@ -1514,7 +1514,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; @@ -1860,7 +1860,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; @@ -2046,7 +2046,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; BottomView.VSplitRight(ButtonWidth, 0, &BottomView); - RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); Button = BottomView; diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index 36e178cc..2cd7d447 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -28,7 +28,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) MainView.VMargin(MainView.w/2-190.0f, &TopMenu); TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); - RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), CUI::CORNER_B, 10.0f); + RenderBackgroundShadow(&TopMenu, false); TopMenu.HSplitTop(145.0f, 0, &TopMenu); @@ -90,7 +90,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) NewPage = Config()->m_UiBrowserPage; BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); - RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); + RenderBackgroundShadow(&BottomMenu, true); BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static CButtonContainer s_QuitButton; From b31e4f80417b07670b94ca16437abc40e7ce0537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 2 Feb 2020 22:36:23 +0100 Subject: [PATCH 152/479] fix implicit delcaration of functions _stricmp and _strnicmp --- src/base/system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index a5f48d81..cd07bb53 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2087,7 +2087,7 @@ char *str_skip_whitespaces(char *str) /* case */ int str_comp_nocase(const char *a, const char *b) { -#if defined(CONF_FAMILY_WINDOWS) +#if defined(CONF_FAMILY_WINDOWS) && !defined(__GNUC__) return _stricmp(a,b); #else return strcasecmp(a,b); @@ -2096,7 +2096,7 @@ int str_comp_nocase(const char *a, const char *b) int str_comp_nocase_num(const char *a, const char *b, const int num) { -#if defined(CONF_FAMILY_WINDOWS) +#if defined(CONF_FAMILY_WINDOWS) && !defined(__GNUC__) return _strnicmp(a, b, num); #else return strncasecmp(a, b, num); From f7c24bb111c091f2edff794df9d1374b11629509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 3 Feb 2020 12:43:16 +0100 Subject: [PATCH 153/479] move popup callbacks from editor to popups --- src/game/editor/editor.cpp | 167 ------------------------------------ src/game/editor/popups.cpp | 168 +++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 167 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 8247ad6b..cbbbc93f 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -2813,66 +2813,6 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) pEditor->m_Dialog = DIALOG_NONE; } - -static int gs_ModifyIndexDeletedIndex; -static void ModifyIndexDeleted(int *pIndex) -{ - if(*pIndex == gs_ModifyIndexDeletedIndex) - *pIndex = -1; - else if(*pIndex > gs_ModifyIndexDeletedIndex) - *pIndex = *pIndex - 1; -} - -int CEditor::PopupImage(CEditor *pEditor, CUIRect View) -{ - static int s_ReplaceButton = 0; - static int s_RemoveButton = 0; - - CUIRect Slot; - View.HSplitTop(2.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage]; - - static int s_ExternalButton = 0; - if(pImg->m_External) - { - if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Embed", 0, &Slot, 0, "Embeds the image into the map file.")) - { - pImg->m_External = 0; - return 1; - } - } - else - { - if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file.")) - { - pImg->m_External = 1; - return 1; - } - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one")) - { - pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Replace Image", "Replace", "mapres", "", ReplaceImage, pEditor); - return 1; - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_RemoveButton, "Remove", 0, &Slot, 0, "Removes the image from the map")) - { - delete pImg; - pEditor->m_Map.m_lImages.remove_index(pEditor->m_SelectedImage); - gs_ModifyIndexDeletedIndex = pEditor->m_SelectedImage; - pEditor->m_Map.ModifyImageIndex(ModifyIndexDeleted); - return 1; - } - - return 0; -} - static int *gs_pSortedIndex = 0; static void ModifySortedIndex(int *pIndex) { @@ -4160,113 +4100,6 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) } } -int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) -{ - static int s_NewMapButton = 0; - static int s_SaveButton = 0; - static int s_SaveAsButton = 0; - static int s_OpenButton = 0; - static int s_OpenCurrentButton = 0; - static int s_AppendButton = 0; - static int s_ExitButton = 0; - - CUIRect Slot; - View.HSplitTop(2.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_NewMapButton, "New", 0, &Slot, 0, "Creates a new map")) - { - if(pEditor->HasUnsavedData()) - { - pEditor->m_PopupEventType = POPEVENT_NEW; - pEditor->m_PopupEventActivated = true; - } - else - { - pEditor->Reset(); - pEditor->m_aFileName[0] = 0; - } - return 1; - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_OpenButton, "Load", 0, &Slot, 0, "Opens a map for editing")) - { - if(pEditor->HasUnsavedData()) - { - pEditor->m_PopupEventType = POPEVENT_LOAD; - pEditor->m_PopupEventActivated = true; - } - else - pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", pEditor->CallbackOpenMap, pEditor); - return 1; - } - - if(pEditor->Client()->State() == IClient::STATE_ONLINE) - { - View.HSplitTop(2.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_OpenCurrentButton, "Load Current Map", 0, &Slot, 0, "Opens the current in game map for editing")) - { - if(pEditor->HasUnsavedData()) - { - pEditor->m_PopupEventType = POPEVENT_LOAD_CURRENT; - pEditor->m_PopupEventActivated = true; - } - else - pEditor->LoadCurrentMap(); - return 1; - } - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_AppendButton, "Append", 0, &Slot, 0, "Opens a map and adds everything from that map to the current one")) - { - pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Append map", "Append", "maps", "", pEditor->CallbackAppendMap, pEditor); - return 1; - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_SaveButton, "Save", 0, &Slot, 0, "Saves the current map")) - { - if(pEditor->m_aFileName[0] && pEditor->m_ValidSaveFilename) - { - str_copy(pEditor->m_aFileSaveName, pEditor->m_aFileName, sizeof(pEditor->m_aFileSaveName)); - pEditor->m_PopupEventType = POPEVENT_SAVE; - pEditor->m_PopupEventActivated = true; - } - else - pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor); - return 1; - } - - View.HSplitTop(2.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name")) - { - pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor); - return 1; - } - - View.HSplitTop(10.0f, &Slot, &View); - View.HSplitTop(12.0f, &Slot, &View); - if(pEditor->DoButton_MenuItem(&s_ExitButton, "Exit", 0, &Slot, 0, "Exits from the editor")) - { - if(pEditor->HasUnsavedData()) - { - pEditor->m_PopupEventType = POPEVENT_EXIT; - pEditor->m_PopupEventActivated = true; - } - else - pEditor->Config()->m_ClEditor = 0; - return 1; - } - - return 0; -} - void CEditor::RenderMenubar(CUIRect MenuBar) { CUIRect ExitButton; diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 91010066..5d93e134 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "editor.h" @@ -1171,3 +1172,170 @@ int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View) return 0; } + + +static int gs_ModifyIndexDeletedIndex; +static void ModifyIndexDeleted(int *pIndex) +{ + if(*pIndex == gs_ModifyIndexDeletedIndex) + *pIndex = -1; + else if(*pIndex > gs_ModifyIndexDeletedIndex) + *pIndex = *pIndex - 1; +} + +int CEditor::PopupImage(CEditor *pEditor, CUIRect View) +{ + static int s_ReplaceButton = 0; + static int s_RemoveButton = 0; + + CUIRect Slot; + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage]; + + static int s_ExternalButton = 0; + if(pImg->m_External) + { + if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Embed", 0, &Slot, 0, "Embeds the image into the map file.")) + { + pImg->m_External = 0; + return 1; + } + } + else + { + if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file.")) + { + pImg->m_External = 1; + return 1; + } + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one")) + { + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Replace Image", "Replace", "mapres", "", ReplaceImage, pEditor); + return 1; + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_RemoveButton, "Remove", 0, &Slot, 0, "Removes the image from the map")) + { + delete pImg; + pEditor->m_Map.m_lImages.remove_index(pEditor->m_SelectedImage); + gs_ModifyIndexDeletedIndex = pEditor->m_SelectedImage; + pEditor->m_Map.ModifyImageIndex(ModifyIndexDeleted); + return 1; + } + + return 0; +} + +int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) +{ + static int s_NewMapButton = 0; + static int s_SaveButton = 0; + static int s_SaveAsButton = 0; + static int s_OpenButton = 0; + static int s_OpenCurrentButton = 0; + static int s_AppendButton = 0; + static int s_ExitButton = 0; + + CUIRect Slot; + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_NewMapButton, "New", 0, &Slot, 0, "Creates a new map")) + { + if(pEditor->HasUnsavedData()) + { + pEditor->m_PopupEventType = POPEVENT_NEW; + pEditor->m_PopupEventActivated = true; + } + else + { + pEditor->Reset(); + pEditor->m_aFileName[0] = 0; + } + return 1; + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_OpenButton, "Load", 0, &Slot, 0, "Opens a map for editing")) + { + if(pEditor->HasUnsavedData()) + { + pEditor->m_PopupEventType = POPEVENT_LOAD; + pEditor->m_PopupEventActivated = true; + } + else + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", pEditor->CallbackOpenMap, pEditor); + return 1; + } + + if(pEditor->Client()->State() == IClient::STATE_ONLINE) + { + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_OpenCurrentButton, "Load Current Map", 0, &Slot, 0, "Opens the current in game map for editing")) + { + if(pEditor->HasUnsavedData()) + { + pEditor->m_PopupEventType = POPEVENT_LOAD_CURRENT; + pEditor->m_PopupEventActivated = true; + } + else + pEditor->LoadCurrentMap(); + return 1; + } + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_AppendButton, "Append", 0, &Slot, 0, "Opens a map and adds everything from that map to the current one")) + { + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Append map", "Append", "maps", "", pEditor->CallbackAppendMap, pEditor); + return 1; + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_SaveButton, "Save", 0, &Slot, 0, "Saves the current map")) + { + if(pEditor->m_aFileName[0] && pEditor->m_ValidSaveFilename) + { + str_copy(pEditor->m_aFileSaveName, pEditor->m_aFileName, sizeof(pEditor->m_aFileSaveName)); + pEditor->m_PopupEventType = POPEVENT_SAVE; + pEditor->m_PopupEventActivated = true; + } + else + pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor); + return 1; + } + + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name")) + { + pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor); + return 1; + } + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_ExitButton, "Exit", 0, &Slot, 0, "Exits from the editor")) + { + if(pEditor->HasUnsavedData()) + { + pEditor->m_PopupEventType = POPEVENT_EXIT; + pEditor->m_PopupEventActivated = true; + } + else + pEditor->Config()->m_ClEditor = 0; + return 1; + } + + return 0; +} From dcbeb3818267045d3aaa001d4536bdab69c6eb8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 3 Feb 2020 14:11:23 +0100 Subject: [PATCH 154/479] change name of tile layer to image name on change (closes #1202), extract some expressions into variables --- src/game/editor/layer_tiles.cpp | 11 ++++++++--- src/game/editor/popups.cpp | 13 +++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 0174ab58..f296f883 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -13,11 +13,12 @@ #include #include "editor.h" +const char *pDefaultLayerName = "Tiles"; CLayerTiles::CLayerTiles(int w, int h) { m_Type = LAYERTYPE_TILES; - str_copy(m_aName, "Tiles", sizeof(m_aName)); + str_copy(m_aName, pDefaultLayerName, sizeof(m_aName)); m_Width = w; m_Height = h; m_Image = -1; @@ -504,8 +505,9 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) { CUIRect Button; + bool IsGameLayer = m_pEditor->m_Map.m_pGameLayer == this; bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty(); - if(m_pEditor->m_Map.m_pGameLayer != this) + if(!IsGameLayer) { if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size() && m_pEditor->m_Map.m_lImages[m_Image]->m_pAutoMapper) { @@ -583,7 +585,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) {0}, }; - if(m_pEditor->m_Map.m_pGameLayer == this) // remove the image and color properties if this is the game layer + if(IsGameLayer) // remove the image and color properties if this is the game layer { aProps[3].m_pName = 0; aProps[4].m_pName = 0; @@ -610,9 +612,12 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) } else { + bool HasNameOfOldImage = m_Image != -1 && str_comp(m_aName, m_pEditor->m_Map.m_lImages[m_Image]->m_aName) == 0; m_Image = NewVal%m_pEditor->m_Map.m_lImages.size(); m_SelectedRuleSet = 0; m_LiveAutoMap = false; + if(str_comp(m_aName, pDefaultLayerName) == 0 || HasNameOfOldImage) + str_copy(m_aName, m_pEditor->m_Map.m_lImages[m_Image]->m_aName, sizeof(m_aName)); } } else if(Prop == PROP_COLOR) diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 5d93e134..6d1e7f76 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -252,35 +252,36 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) { + CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0); + bool IsGameLayer = pEditor->m_Map.m_pGameLayer == pCurrentLayer; + // remove layer button CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); static int s_DeleteButton = 0; // don't allow deletion of game layer - if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) && - pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer")) + if(!IsGameLayer && pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer")) { pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->DeleteLayer(pEditor->m_SelectedLayer); return 1; } // layer name - if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0)) + if(!IsGameLayer) { View.HSplitBottom(5.0f, &View, &Button); View.HSplitBottom(12.0f, &View, &Button); static float s_Name = 0; pEditor->UI()->DoLabel(&Button, "Name:", 10.0f, CUI::ALIGN_LEFT); Button.VSplitLeft(40.0f, 0, &Button); - if(pEditor->DoEditBox(&s_Name, &Button, pEditor->GetSelectedLayer(0)->m_aName, sizeof(pEditor->GetSelectedLayer(0)->m_aName), 10.0f, &s_Name)) + if(pEditor->DoEditBox(&s_Name, &Button, pCurrentLayer->m_aName, sizeof(pCurrentLayer->m_aName), 10.0f, &s_Name)) pEditor->m_Map.m_Modified = true; } View.HSplitBottom(10.0f, &View, 0); CLayerGroup *pCurrentGroup = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]; - CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0); enum { @@ -297,7 +298,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) {0}, }; - if(pEditor->m_Map.m_pGameLayer == pEditor->GetSelectedLayer(0)) // dont use Group and Detail from the selection if this is the game layer + if(IsGameLayer) // dont use Group and Detail from the selection if this is the game layer { aProps[0].m_Type = PROPTYPE_NULL; aProps[2].m_Type = PROPTYPE_NULL; From c5016fe87a1e735e83ff47b1e221a7c4d501e770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 4 Feb 2020 21:47:47 +0100 Subject: [PATCH 155/479] fix seekbar not working at edges, pause while seeking, various code style fixes --- src/engine/client/client.cpp | 2 +- src/engine/client/client.h | 2 +- src/engine/demo.h | 6 +- src/engine/shared/demo.cpp | 262 +++++++++------------- src/engine/shared/demo.h | 8 +- src/game/client/components/menus_demo.cpp | 30 ++- 6 files changed, 137 insertions(+), 173 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 277f7881..2d1af425 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2289,7 +2289,7 @@ const char *CClient::DemoPlayer_Play(const char *pFilename, int StorageType) m_NetClient.ResetErrorString(); // try to start playback - m_DemoPlayer.SetListner(this); + m_DemoPlayer.SetListener(this); const char *pError = m_DemoPlayer.Load(Storage(), m_pConsole, pFilename, StorageType, GameClient()->NetVersion()); if(pError) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index ea6002bb..390ad087 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -52,7 +52,7 @@ class CSmoothTime }; -class CClient : public IClient, public CDemoPlayer::IListner +class CClient : public IClient, public CDemoPlayer::IListener { // needed interfaces IEngine *m_pEngine; diff --git a/src/engine/demo.h b/src/engine/demo.h index 7b7365c7..74eb03de 100644 --- a/src/engine/demo.h +++ b/src/engine/demo.h @@ -19,10 +19,10 @@ struct CDemoHeader unsigned char m_aMapSize[4]; unsigned char m_aMapCrc[4]; char m_aType[8]; - char m_aLength[4]; + unsigned char m_aLength[4]; char m_aTimestamp[20]; - char m_aNumTimelineMarkers[4]; - char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][4]; + unsigned char m_aNumTimelineMarkers[4]; + unsigned char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][4]; }; class IDemoPlayer : public IInterface diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index e76f2755..9df3b87e 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -18,6 +18,18 @@ static const unsigned char gs_ActVersion = 4; static const int gs_LengthOffset = 152; static const int gs_NumMarkersOffset = 176; +static inline void EncodeUnsigned(unsigned char *pOut, unsigned Value) +{ + pOut[0] = (Value>>24)&0xff; + pOut[1] = (Value>>16)&0xff; + pOut[2] = (Value>>8)&0xff; + pOut[3] = Value&0xff; +} + +static inline unsigned DecodeUnsigned(const unsigned char *pIn) +{ + return ((pIn[0]<<24)&0xFF000000) | ((pIn[1]<<16)&0xFF0000) | ((pIn[2]<<8)&0xFF00) | (pIn[3]&0xFF); +} CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta) { @@ -89,14 +101,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con str_copy(Header.m_aNetversion, pNetVersion, sizeof(Header.m_aNetversion)); str_copy(Header.m_aMapName, pMap, sizeof(Header.m_aMapName)); unsigned MapSize = io_length(MapFile); - Header.m_aMapSize[0] = (MapSize>>24)&0xff; - Header.m_aMapSize[1] = (MapSize>>16)&0xff; - Header.m_aMapSize[2] = (MapSize>>8)&0xff; - Header.m_aMapSize[3] = (MapSize)&0xff; - Header.m_aMapCrc[0] = (Crc>>24)&0xff; - Header.m_aMapCrc[1] = (Crc>>16)&0xff; - Header.m_aMapCrc[2] = (Crc>>8)&0xff; - Header.m_aMapCrc[3] = (Crc)&0xff; + EncodeUnsigned(Header.m_aMapSize, MapSize); + EncodeUnsigned(Header.m_aMapCrc, Crc); 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)); @@ -105,9 +111,9 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con io_write(DemoFile, &Header, sizeof(Header)); // write map data + unsigned char aChunk[1024*64]; while(1) { - unsigned char aChunk[1024*64]; int Bytes = io_read(MapFile, &aChunk, sizeof(aChunk)); if(Bytes <= 0) break; @@ -162,10 +168,7 @@ void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe) { unsigned char aChunk[5]; aChunk[0] = CHUNKTYPEFLAG_TICKMARKER; - aChunk[1] = (Tick>>24)&0xff; - aChunk[2] = (Tick>>16)&0xff; - aChunk[3] = (Tick>>8)&0xff; - aChunk[4] = (Tick)&0xff; + EncodeUnsigned(aChunk+1, Tick); if(Keyframe) aChunk[0] |= CHUNKTICKFLAG_KEYFRAME; @@ -186,13 +189,12 @@ void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe) void CDemoRecorder::Write(int Type, const void *pData, int Size) { - char aBuffer[64*1024]; - char aBuffer2[64*1024]; - unsigned char aChunk[3]; - if(!m_File) return; + char aBuffer[64*1024]; + char aBuffer2[64*1024]; + /* pad the data with 0 so we get an alignment of 4, else the compression won't work and miss some bytes */ mem_copy(aBuffer2, pData, Size); @@ -211,6 +213,7 @@ void CDemoRecorder::Write(int Type, const void *pData, int Size) return; } + unsigned char aChunk[3]; aChunk[0] = ((Type&0x3)<<5); if(Size < 30) { @@ -281,30 +284,19 @@ int CDemoRecorder::Stop() // add the demo length to the header io_seek(m_File, gs_LengthOffset, IOSEEK_START); - int DemoLength = Length(); - char aLength[4]; - aLength[0] = (DemoLength>>24)&0xff; - aLength[1] = (DemoLength>>16)&0xff; - aLength[2] = (DemoLength>>8)&0xff; - aLength[3] = (DemoLength)&0xff; + unsigned char aLength[4]; + EncodeUnsigned(aLength, Length()); 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; + unsigned char aNumMarkers[4]; + EncodeUnsigned(aNumMarkers, m_NumTimelineMarkers); 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; + unsigned char aMarker[4]; + EncodeUnsigned(aMarker, m_aTimelineMarkers[i]); io_write(m_File, aMarker, sizeof(aMarker)); } @@ -346,9 +338,9 @@ CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta) m_LastSnapshotDataSize = -1; } -void CDemoPlayer::SetListner(IListner *pListner) +void CDemoPlayer::SetListener(IListener *pListener) { - m_pListner = pListner; + m_pListener = pListener; } @@ -370,16 +362,15 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) if(Tickdelta == 0) { - unsigned char aTickdata[4]; - if(io_read(m_File, aTickdata, sizeof(aTickdata)) != sizeof(aTickdata)) + unsigned char aTickData[4]; + if(io_read(m_File, aTickData, sizeof(aTickData)) != sizeof(aTickData)) return -1; - *pTick = (aTickdata[0]<<24) | (aTickdata[1]<<16) | (aTickdata[2]<<8) | aTickdata[3]; + *pTick = DecodeUnsigned(aTickData); } else { *pTick += Tickdelta; } - } else { @@ -389,18 +380,17 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) if(*pSize == 30) { - unsigned char aSizedata[1]; - if(io_read(m_File, aSizedata, sizeof(aSizedata)) != sizeof(aSizedata)) + unsigned char aSizeData[1]; + if(io_read(m_File, aSizeData, sizeof(aSizeData)) != sizeof(aSizeData)) return -1; - *pSize = aSizedata[0]; - + *pSize = aSizeData[0]; } else if(*pSize == 31) { - unsigned char aSizedata[2]; - if(io_read(m_File, aSizedata, sizeof(aSizedata)) != sizeof(aSizedata)) + unsigned char aSizeData[2]; + if(io_read(m_File, aSizeData, sizeof(aSizeData)) != sizeof(aSizeData)) return -1; - *pSize = (aSizedata[1]<<8) | aSizedata[0]; + *pSize = (aSizeData[1]<<8) | aSizeData[0]; } } @@ -409,21 +399,19 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) void CDemoPlayer::ScanFile() { - long StartPos; CHeap Heap; CKeyFrameSearch *pFirstKey = 0; CKeyFrameSearch *pCurrentKey = 0; - //DEMOREC_CHUNK chunk; - int ChunkSize, ChunkType, ChunkTick = 0; - int i; + int ChunkTick = 0; - StartPos = io_tell(m_File); + long StartPos = io_tell(m_File); m_Info.m_SeekablePoints = 0; while(1) { long CurrentPos = io_tell(m_File); + int ChunkSize, ChunkType; if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick)) break; @@ -432,10 +420,8 @@ void CDemoPlayer::ScanFile() { if(ChunkType&CHUNKTICKFLAG_KEYFRAME) { - CKeyFrameSearch *pKey; - // save the position - pKey = (CKeyFrameSearch *)Heap.Allocate(sizeof(CKeyFrameSearch)); + CKeyFrameSearch *pKey = (CKeyFrameSearch *)Heap.Allocate(sizeof(CKeyFrameSearch)); pKey->m_Frame.m_Filepos = CurrentPos; pKey->m_Frame.m_Tick = ChunkTick; pKey->m_pNext = 0; @@ -453,10 +439,10 @@ void CDemoPlayer::ScanFile() } else if(ChunkSize) io_skip(m_File, ChunkSize); - } // copy all the frames to an array instead for fast access + int i; m_pKeyFrames = (CKeyFrame*)mem_alloc(m_Info.m_SeekablePoints*sizeof(CKeyFrame), 1); for(pCurrentKey = pFirstKey, i = 0; pCurrentKey; pCurrentKey = pCurrentKey->m_pNext, i++) m_pKeyFrames[i] = pCurrentKey->m_Frame; @@ -467,22 +453,21 @@ void CDemoPlayer::ScanFile() void CDemoPlayer::DoTick() { - static char aCompresseddata[CSnapshot::MAX_SIZE]; + static char aCompressedData[CSnapshot::MAX_SIZE]; static char aDecompressed[CSnapshot::MAX_SIZE]; static char aData[CSnapshot::MAX_SIZE]; - static char aNewsnap[CSnapshot::MAX_SIZE]; - int ChunkType, ChunkTick, ChunkSize; - int DataSize = 0; - int GotSnapshot = 0; + static char aNewSnap[CSnapshot::MAX_SIZE]; + bool GotSnapshot = false; // update ticks m_Info.m_PreviousTick = m_Info.m_Info.m_CurrentTick; m_Info.m_Info.m_CurrentTick = m_Info.m_NextTick; - ChunkTick = m_Info.m_Info.m_CurrentTick; + int ChunkTick = m_Info.m_Info.m_CurrentTick; while(1) { - DataSize = 0; + int DataSize = 0; + int ChunkType, ChunkSize; if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick)) { // stop on error or eof @@ -500,7 +485,7 @@ void CDemoPlayer::DoTick() // read the chunk if(ChunkSize) { - if(io_read(m_File, aCompresseddata, ChunkSize) != (unsigned)ChunkSize) + if(io_read(m_File, aCompressedData, ChunkSize) != (unsigned)ChunkSize) { // stop on error or eof m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", "error reading chunk"); @@ -508,7 +493,7 @@ void CDemoPlayer::DoTick() break; } - DataSize = m_Huffman.Decompress(aCompresseddata, ChunkSize, aDecompressed, sizeof(aDecompressed)); + DataSize = m_Huffman.Decompress(aCompressedData, ChunkSize, aDecompressed, sizeof(aDecompressed)); if(DataSize < 0) { // stop on error or eof @@ -518,7 +503,6 @@ void CDemoPlayer::DoTick() } DataSize = CVariableInt::Decompress(aDecompressed, DataSize, aData, sizeof(aData)); - if(DataSize < 0) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", "error during intpack decompression"); @@ -530,25 +514,24 @@ void CDemoPlayer::DoTick() if(ChunkType == CHUNKTYPE_DELTA) { // process delta snapshot - GotSnapshot = 1; + GotSnapshot = true; // only unpack the delta if we have a valid snapshot if(m_LastSnapshotDataSize == -1) continue; - DataSize = m_pSnapshotDelta->UnpackDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)aNewsnap, aData, DataSize); - + DataSize = m_pSnapshotDelta->UnpackDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)aNewSnap, aData, DataSize); if(DataSize >= 0) { - if(m_pListner) - m_pListner->OnDemoPlayerSnapshot(aNewsnap, DataSize); + if(m_pListener) + m_pListener->OnDemoPlayerSnapshot(aNewSnap, DataSize); m_LastSnapshotDataSize = DataSize; - mem_copy(m_aLastSnapshotData, aNewsnap, DataSize); + mem_copy(m_aLastSnapshotData, aNewSnap, DataSize); } else { - char aBuf[256]; + char aBuf[64]; str_format(aBuf, sizeof(aBuf), "error during unpacking of delta, err=%d", DataSize); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf); } @@ -557,23 +540,23 @@ void CDemoPlayer::DoTick() { // process full snapshot CSnapshotBuilder Builder; - GotSnapshot = 1; + GotSnapshot = true; if(Builder.UnserializeSnap(aData, DataSize)) - DataSize = Builder.Finish(aNewsnap); + DataSize = Builder.Finish(aNewSnap); else DataSize = -1; - + if(DataSize >= 0) { m_LastSnapshotDataSize = DataSize; - mem_copy(m_aLastSnapshotData, aNewsnap, DataSize); - if(m_pListner) - m_pListner->OnDemoPlayerSnapshot(aNewsnap, DataSize); + mem_copy(m_aLastSnapshotData, aNewSnap, DataSize); + if(m_pListener) + m_pListener->OnDemoPlayerSnapshot(aNewSnap, DataSize); } else { - char aBuf[256]; + char aBuf[64]; str_format(aBuf, sizeof(aBuf), "error during unpacking of snapshot, err=%d", DataSize); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf); } @@ -581,10 +564,10 @@ void CDemoPlayer::DoTick() else { // if there were no snapshots in this tick, replay the last one - if(!GotSnapshot && m_pListner && m_LastSnapshotDataSize != -1) + if(!GotSnapshot && m_pListener && m_LastSnapshotDataSize != -1) { - GotSnapshot = 1; - m_pListner->OnDemoPlayerSnapshot(m_aLastSnapshotData, m_LastSnapshotDataSize); + GotSnapshot = true; + m_pListener->OnDemoPlayerSnapshot(m_aLastSnapshotData, m_LastSnapshotDataSize); } // check the remaining types @@ -595,8 +578,8 @@ void CDemoPlayer::DoTick() } else if(ChunkType == CHUNKTYPE_MESSAGE) { - if(m_pListner) - m_pListner->OnDemoPlayerMessage(aData, DataSize); + if(m_pListener) + m_pListener->OnDemoPlayerMessage(aData, DataSize); } } } @@ -604,17 +587,12 @@ void CDemoPlayer::DoTick() void CDemoPlayer::Pause() { - m_Info.m_Info.m_Paused = 1; + m_Info.m_Info.m_Paused = true; } void CDemoPlayer::Unpause() { - if(m_Info.m_Info.m_Paused) - { - /*m_Info.start_tick = m_Info.current_tick; - m_Info.start_time = time_get();*/ - m_Info.m_Info.m_Paused = 0; - } + m_Info.m_Info.m_Paused = false; } const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, int StorageType, const char *pNetversion) @@ -654,7 +632,7 @@ const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole return m_aErrorMsg; } - if(m_Info.m_Header.m_Version < gs_ActVersion) + if(m_Info.m_Header.m_Version != gs_ActVersion) { str_format(m_aErrorMsg, sizeof(m_aErrorMsg), "demo version %d is not supported", m_Info.m_Header.m_Version); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_player", m_aErrorMsg); @@ -681,11 +659,11 @@ const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole m_DemoType = DEMOTYPE_INVALID; // read map - unsigned MapSize = (m_Info.m_Header.m_aMapSize[0]<<24) | (m_Info.m_Header.m_aMapSize[1]<<16) | (m_Info.m_Header.m_aMapSize[2]<<8) | (m_Info.m_Header.m_aMapSize[3]); + unsigned MapSize = DecodeUnsigned(m_Info.m_Header.m_aMapSize); // check if we already have the map // TODO: improve map checking (maps folder, check crc) - unsigned Crc = (m_Info.m_Header.m_aMapCrc[0]<<24) | (m_Info.m_Header.m_aMapCrc[1]<<16) | (m_Info.m_Header.m_aMapCrc[2]<<8) | (m_Info.m_Header.m_aMapCrc[3]); + unsigned Crc = DecodeUnsigned(m_Info.m_Header.m_aMapCrc); char aMapFilename[128]; str_format(aMapFilename, sizeof(aMapFilename), "downloadedmaps/%s_%08x.map", m_Info.m_Header.m_aMapName, Crc); IOHANDLE MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_READ, IStorage::TYPE_ALL); @@ -711,17 +689,13 @@ const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole } // 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 = min(Num, int(MAX_TIMELINE_MARKERS)); + m_Info.m_Info.m_NumTimelineMarkers = min(DecodeUnsigned(m_Info.m_Header.m_aNumTimelineMarkers), unsigned(MAX_TIMELINE_MARKERS)); for(int i = 0; i < m_Info.m_Info.m_NumTimelineMarkers; 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); + m_Info.m_Info.m_aTimelineMarkers[i] = DecodeUnsigned(m_Info.m_Header.m_aTimelineMarkers[i]); } - // scan the file for interessting points + // scan the file for interesting points ScanFile(); // ready for playback @@ -741,8 +715,6 @@ int CDemoPlayer::Play() DoTick(); // set start info - /*m_Info.start_tick = m_Info.previous_tick; - m_Info.start_time = time_get();*/ m_Info.m_CurrentTime = m_Info.m_PreviousTick*time_freq()/SERVER_TICK_SPEED; m_Info.m_LastUpdate = time_get(); return 0; @@ -750,18 +722,13 @@ int CDemoPlayer::Play() int CDemoPlayer::SetPos(float Percent) { - int Keyframe; - int WantedTick; if(!m_File) return -1; // -5 because we have to have a current tick and previous tick when we do the playback - WantedTick = m_Info.m_Info.m_FirstTick + (int)((m_Info.m_Info.m_LastTick-m_Info.m_Info.m_FirstTick)*Percent) - 5; + int WantedTick = m_Info.m_Info.m_FirstTick + (int)((m_Info.m_Info.m_LastTick-m_Info.m_Info.m_FirstTick)*Percent) - 5; - Keyframe = (int)(m_Info.m_SeekablePoints*Percent); - - if(Keyframe < 0 || Keyframe >= m_Info.m_SeekablePoints) - return -1; + int Keyframe = clamp((int)(m_Info.m_SeekablePoints*Percent), 0, m_Info.m_SeekablePoints-1); // get correct key frame if(m_pKeyFrames[Keyframe].m_Tick < WantedTick) @@ -774,7 +741,6 @@ int CDemoPlayer::SetPos(float Percent) // seek to the correct keyframe io_seek(m_File, m_pKeyFrames[Keyframe].m_Filepos, IOSEEK_START); - //m_Info.start_tick = -1; m_Info.m_NextTick = -1; m_Info.m_Info.m_CurrentTick = -1; m_Info.m_PreviousTick = -1; @@ -799,49 +765,42 @@ int CDemoPlayer::Update() int64 Deltatime = Now-m_Info.m_LastUpdate; m_Info.m_LastUpdate = Now; - if(!IsPlaying()) + if(!IsPlaying() || m_Info.m_Info.m_Paused) return 0; - if(m_Info.m_Info.m_Paused) - { + int64 Freq = time_freq(); + m_Info.m_CurrentTime += (int64)(Deltatime*(double)m_Info.m_Info.m_Speed); - } - else + while(1) { - int64 Freq = time_freq(); - m_Info.m_CurrentTime += (int64)(Deltatime*(double)m_Info.m_Info.m_Speed); + int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; - while(1) - { - int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; - - // break if we are ready - if(CurtickStart > m_Info.m_CurrentTime) - break; + // break if we are ready + if(CurtickStart > m_Info.m_CurrentTime) + break; - // do one more tick - DoTick(); + // do one more tick + DoTick(); - if(m_Info.m_Info.m_Paused) - return 0; - } + if(m_Info.m_Info.m_Paused) + return 0; + } - // update intratick - { - int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; - int64 PrevtickStart = (m_Info.m_PreviousTick)*Freq/SERVER_TICK_SPEED; - m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart-PrevtickStart); - m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq; - } + // update intratick + { + int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; + int64 PrevtickStart = (m_Info.m_PreviousTick)*Freq/SERVER_TICK_SPEED; + m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart-PrevtickStart); + m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq; + } - if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick || - m_Info.m_Info.m_CurrentTick == m_Info.m_NextTick) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "tick error prev=%d cur=%d next=%d", - m_Info.m_PreviousTick, m_Info.m_Info.m_CurrentTick, m_Info.m_NextTick); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf); - } + if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick || + m_Info.m_Info.m_CurrentTick == m_Info.m_NextTick) + { + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "tick error prev=%d cur=%d next=%d", + m_Info.m_PreviousTick, m_Info.m_Info.m_CurrentTick, m_Info.m_NextTick); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf); } return 0; @@ -857,7 +816,7 @@ int CDemoPlayer::Stop() m_File = 0; mem_free(m_pKeyFrames); m_pKeyFrames = 0; - str_copy(m_aFilename, "", sizeof(m_aFilename)); + m_aFilename[0] = '\0'; return 0; } @@ -890,14 +849,9 @@ bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, i return false; io_read(File, pDemoHeader, sizeof(CDemoHeader)); - if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_ActVersion) - { - io_close(File); - return false; - } - + bool Valid = mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) == 0 && pDemoHeader->m_Version == gs_ActVersion; io_close(File); - return true; + return Valid; } int CDemoPlayer::GetDemoType() const diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h index c8a43ba4..a27907c8 100644 --- a/src/engine/shared/demo.h +++ b/src/engine/shared/demo.h @@ -42,10 +42,10 @@ class CDemoRecorder : public IDemoRecorder class CDemoPlayer : public IDemoPlayer { public: - class IListner + class IListener { public: - virtual ~IListner() {} + virtual ~IListener() {} virtual void OnDemoPlayerSnapshot(void *pData, int Size) = 0; virtual void OnDemoPlayerMessage(void *pData, int Size) = 0; }; @@ -69,7 +69,7 @@ class CDemoPlayer : public IDemoPlayer }; private: - IListner *m_pListner; + IListener *m_pListener; // Playback @@ -107,7 +107,7 @@ class CDemoPlayer : public IDemoPlayer CDemoPlayer(class CSnapshotDelta *m_pSnapshotDelta); - void SetListner(IListner *pListner); + void SetListener(IListener *pListner); const char *Load(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, int StorageType, const char *pNetversion); int Play(); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index c4a2b99f..142db77a 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -90,7 +90,8 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) if(m_SeekBarActive || m_MenuActive) { static int s_SeekBarID = 0; - void *id = &s_SeekBarID; + static bool s_PausedBeforeSeeking = false; + static float s_PrevAmount = -1.0f; char aBuffer[128]; const float Rounding = 5.0f; @@ -100,7 +101,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // draw filled bar float Amount = CurrentTick/(float)TotalTicks; CUIRect FilledBar = SeekBar; - FilledBar.w = max(2*Rounding, FilledBar.w*Amount); + FilledBar.w = (FilledBar.w-2*Rounding)*Amount + 2*Rounding; RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, Rounding); // draw markers @@ -124,17 +125,21 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // do the logic bool Inside = UI()->MouseInside(&SeekBar); - if(UI()->CheckActiveItem(id)) + if(UI()->CheckActiveItem(&s_SeekBarID)) { if(!UI()->MouseButton(0)) + { UI()->SetActiveItem(0); + if(!s_PausedBeforeSeeking) + DemoPlayer()->Unpause(); + s_PrevAmount = -1.0f; // so that the same position can be seeked again after releasing the mouse + } else { - static float PrevAmount = 0.0f; - float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w; - if(Amount > 0.0f && Amount < 1.0f && absolute(PrevAmount-Amount) >= (1.0f/UI()->Screen()->w)) + float Amount = clamp((UI()->MouseX()-SeekBar.x-Rounding)/(float)(SeekBar.w-2*Rounding), 0.0f, 1.0f); + if(absolute(s_PrevAmount-Amount) >= (0.1f/UI()->Screen()->w)) { - PrevAmount = Amount; + s_PrevAmount = Amount; m_pClient->OnReset(); m_pClient->m_SuppressEvents = true; DemoPlayer()->SetPos(Amount); @@ -144,14 +149,19 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == &s_SeekBarID) { if(UI()->MouseButton(0)) - UI()->SetActiveItem(id); + { + UI()->SetActiveItem(&s_SeekBarID); + s_PausedBeforeSeeking = pInfo->m_Paused; + if(!pInfo->m_Paused) + DemoPlayer()->Pause(); + } } if(Inside) - UI()->SetHotItem(id); + UI()->SetHotItem(&s_SeekBarID); } if(CurrentTick == TotalTicks) From 11d3d9cb11fe84121cd5e68f83adfe4422aefba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 5 Feb 2020 22:23:53 +0100 Subject: [PATCH 156/479] fix naming --- src/engine/client/backend_sdl.cpp | 9 ++++----- src/engine/client/backend_sdl.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 8dcf16ec..81c975af 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -646,7 +646,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer) // ------------ CGraphicsBackend_SDL_OpenGL -int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWindowWidth, int *pWindowHeight, int* pScreenWidth, int* pScreenHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) +int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWindowWidth, int *pWindowHeight, int* pScreenWidth, int* pScreenHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) { if(!SDL_WasInit(SDL_INIT_VIDEO)) { @@ -662,13 +662,12 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWind m_NumScreens = SDL_GetNumVideoDisplays(); if(m_NumScreens > 0) { - *Screen = clamp(*Screen, 0, m_NumScreens-1); - if(SDL_GetDisplayBounds(*Screen, &ScreenPos) != 0) + *pScreen = clamp(*pScreen, 0, m_NumScreens-1); + if(SDL_GetDisplayBounds(*pScreen, &ScreenPos) != 0) { dbg_msg("gfx", "unable to retrieve screen information: %s", SDL_GetError()); return -1; } - } else { @@ -677,7 +676,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWind } // store desktop resolution for settings reset button - if(!GetDesktopResolution(*Screen, pDesktopWidth, pDesktopHeight)) + if(!GetDesktopResolution(*pScreen, pDesktopWidth, pDesktopHeight)) { dbg_msg("gfx", "unable to get desktop resolution: %s", SDL_GetError()); return -1; diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h index 1f3647b8..ecf14261 100644 --- a/src/engine/client/backend_sdl.h +++ b/src/engine/client/backend_sdl.h @@ -198,7 +198,7 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded int m_NumScreens; int m_TextureArraySize; public: - virtual int Init(const char *pName, int *Screen, int *pWindowWidth, int *pWindowHeight, int *pScreenWidth, int *pScreenHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight); + virtual int Init(const char *pName, int *pScreen, int *pWindowWidth, int *pWindowHeight, int *pScreenWidth, int *pScreenHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight); virtual int Shutdown(); virtual int MemoryUsage() const; From dfb34021c3d43320fd511b74db1a771bf17b38b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 5 Feb 2020 23:24:28 +0100 Subject: [PATCH 157/479] remove IClient::GetDebugFont, use normal font in editor, load debug font lazily --- src/engine/client.h | 2 -- src/engine/client/client.cpp | 31 ++++++++++--------------------- src/engine/client/client.h | 6 ------ src/game/editor/layer_tiles.cpp | 9 +++------ 4 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index cd9f684e..a4ad4ff7 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -152,8 +152,6 @@ class IClient : public IInterface virtual bool ConnectionProblems() const = 0; virtual bool SoundInitFailed() const = 0; - - virtual IGraphics::CTextureHandle GetDebugFont() const = 0; // TODO: remove this function }; class IGameClient : public IInterface diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 277f7881..c58d462e 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -614,12 +614,6 @@ void CClient::GetServerInfo(CServerInfo *pServerInfo) m_ServerBrowser.UpdateFavoriteState(pServerInfo); } -int CClient::LoadData() -{ - m_DebugFont = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE); - return 1; -} - // --- const void *CClient::SnapGetItem(int SnapID, int Index, CSnapItem *pItem) const @@ -683,17 +677,18 @@ void CClient::SnapSetStaticsize(int ItemType, int Size) void CClient::DebugRender() { + if(!Config()->m_Debug) + return; + static NETSTATS Prev, Current; static int64 LastSnap = 0; static float FrameTimeAvg = 0; + static IGraphics::CTextureHandle Font = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE); + char aBuffer[256]; int64 Now = time_get(); - char aBuffer[512]; - - if(!Config()->m_Debug) - return; //m_pGraphics->BlendNormal(); - Graphics()->TextureSet(m_DebugFont); + Graphics()->TextureSet(Font); Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight()); Graphics()->QuadsBegin(); @@ -737,8 +732,7 @@ void CClient::DebugRender() // render rates { int y = 0; - int i; - for(i = 0; i < 256; i++) + for(int i = 0; i < 256; i++) { if(m_SnapshotDelta.GetDataRate(i)) { @@ -766,13 +760,13 @@ void CClient::DebugRender() m_FpsGraph.ScaleMax(); m_FpsGraph.ScaleMin(); - m_FpsGraph.Render(Graphics(), m_DebugFont, x, sp*5, w, h, "FPS"); + m_FpsGraph.Render(Graphics(), Font, x, sp*5, w, h, "FPS"); m_InputtimeMarginGraph.ScaleMin(); m_InputtimeMarginGraph.ScaleMax(); - m_InputtimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp, w, h, "Prediction Margin"); + m_InputtimeMarginGraph.Render(Graphics(), Font, x, sp*5+h+sp, w, h, "Prediction Margin"); m_GametimeMarginGraph.ScaleMin(); m_GametimeMarginGraph.ScaleMax(); - m_GametimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin"); + m_GametimeMarginGraph.Render(Graphics(), Font, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin"); } } @@ -1975,11 +1969,6 @@ void CClient::Run() // init the editor m_pEditor->Init(); - - // load data - if(!LoadData()) - return; - GameClient()->OnInit(); char aBuf[256]; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index ea6002bb..6892dcc9 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -89,8 +89,6 @@ class CClient : public IClient, public CDemoPlayer::IListner unsigned m_SnapshotParts; int64 m_LocalStartTime; - IGraphics::CTextureHandle m_DebugFont; - int64 m_LastRenderTime; int64 m_LastCpuTime; float m_LastAvgCpuFrameTime; @@ -223,8 +221,6 @@ class CClient : public IClient, public CDemoPlayer::IListner virtual bool SoundInitFailed() const { return m_SoundInitFailed; } - virtual IGraphics::CTextureHandle GetDebugFont() const { return m_DebugFont; } - void SendInput(); // TODO: OPT: do this alot smarter! @@ -248,8 +244,6 @@ class CClient : public IClient, public CDemoPlayer::IListner virtual void GetServerInfo(CServerInfo *pServerInfo); - int LoadData(); - // --- const void *SnapGetItem(int SnapID, int Index, CSnapItem *pItem) const; diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index f296f883..3fdf51f7 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -470,8 +470,6 @@ void CLayerTiles::ShowInfo() { float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); - Graphics()->TextureSet(m_pEditor->Client()->GetDebugFont()); - Graphics()->QuadsBegin(); int StartY = max(0, (int)(ScreenY0/32.0f)-1); int StartX = max(0, (int)(ScreenX0/32.0f)-1); @@ -484,20 +482,19 @@ void CLayerTiles::ShowInfo() int c = x + y*m_Width; if(m_pTiles[c].m_Index) { - char aBuf[64]; + char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%i", m_pTiles[c].m_Index); - m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, aBuf); + TextRender()->Text(0, x*32+4, y*32+4, 10.0f, aBuf, 32.0f); char aFlags[4] = { m_pTiles[c].m_Flags&TILEFLAG_VFLIP ? 'V' : ' ', m_pTiles[c].m_Flags&TILEFLAG_HFLIP ? 'H' : ' ', m_pTiles[c].m_Flags&TILEFLAG_ROTATE? 'R' : ' ', 0}; - m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, aFlags); + TextRender()->Text(0, x*32+4, y*32+18, 10.0f, aFlags, 32.0f); } x += m_pTiles[c].m_Skip; } - Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } From 7ecc1573aefe1f35fcea3a5f0bbf70a71d191f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Feb 2020 22:06:10 +0100 Subject: [PATCH 158/479] improve loading screen feedback during OnInit, move most loading to loading screen --- src/engine/client/client.cpp | 25 ++- src/game/client/component.h | 1 + src/game/client/components/countryflags.cpp | 8 + src/game/client/components/countryflags.h | 1 + src/game/client/components/maplayers.cpp | 17 +- src/game/client/components/maplayers.h | 1 + src/game/client/components/menus.cpp | 196 +++++-------------- src/game/client/components/menus.h | 22 +-- src/game/client/components/menus_browser.cpp | 57 ++++-- src/game/client/components/skins.cpp | 10 + src/game/client/components/skins.h | 2 +- src/game/client/components/sounds.cpp | 9 +- src/game/client/components/sounds.h | 1 + src/game/client/gameclient.cpp | 16 +- 14 files changed, 169 insertions(+), 197 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index c58d462e..04bd1aa8 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -782,10 +782,16 @@ const char *CClient::ErrorString() const void CClient::Render() { - if(Config()->m_GfxClear) - Graphics()->Clear(1,1,0); - - GameClient()->OnRender(); + if(m_EditorActive) + { + m_pEditor->UpdateAndRender(); + } + else + { + if(Config()->m_GfxClear) + Graphics()->Clear(1,1,0); + GameClient()->OnRender(); + } DebugRender(); } @@ -1966,9 +1972,6 @@ void CClient::Run() // start refreshing addresses while we load MasterServer()->RefreshAddresses(m_ContactClient.NetType()); - // init the editor - m_pEditor->Init(); - GameClient()->OnInit(); char aBuf[256]; @@ -2099,13 +2102,7 @@ void CClient::Run() // when we are stress testing only render every 10th frame if(!Config()->m_DbgStress || (m_RenderFrames%10) == 0 ) { - if(!m_EditorActive) - Render(); - else - { - m_pEditor->UpdateAndRender(); - DebugRender(); - } + Render(); m_pGraphics->Swap(); } } diff --git a/src/game/client/component.h b/src/game/client/component.h index 071d3501..c8349314 100644 --- a/src/game/client/component.h +++ b/src/game/client/component.h @@ -35,6 +35,7 @@ class CComponent virtual void OnStateChange(int NewState, int OldState) {}; virtual void OnConsoleInit() {}; + virtual int GetInitAmount() const { return 0; }; // Amount of progress reported by this component during OnInit virtual void OnInit() {}; virtual void OnShutdown() {}; virtual void OnReset() {}; diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index 40e80e2f..bf6a2401 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -10,6 +10,7 @@ #include #include +#include "menus.h" #include "countryflags.h" @@ -129,11 +130,17 @@ void CCountryFlags::LoadCountryflagsIndexfile() m_CodeIndexLUT[max(0, (m_aCountryFlags[i].m_CountryCode-CODE_LB)%CODE_RANGE)] = i; } +int CCountryFlags::GetInitAmount() const +{ + return 15; +} + void CCountryFlags::OnInit() { // load country flags m_aCountryFlags.clear(); LoadCountryflagsIndexfile(); + m_pClient->m_pMenus->RenderLoading(5); if(!m_aCountryFlags.size()) { Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "countryflags", "failed to load country flags. folder='countryflags/'"); @@ -143,6 +150,7 @@ void CCountryFlags::OnInit() mem_zero(DummyEntry.m_aCountryCodeString, sizeof(DummyEntry.m_aCountryCodeString)); m_aCountryFlags.add(DummyEntry); } + m_pClient->m_pMenus->RenderLoading(10); } int CCountryFlags::Num() const diff --git a/src/game/client/components/countryflags.h b/src/game/client/components/countryflags.h index 07e887e1..4f525b96 100644 --- a/src/game/client/components/countryflags.h +++ b/src/game/client/components/countryflags.h @@ -19,6 +19,7 @@ class CCountryFlags : public CComponent bool operator<(const CCountryFlag &Other) const { return str_comp(m_aCountryCodeString, Other.m_aCountryCodeString) < 0; } }; + int GetInitAmount() const; void OnInit(); int Num() const; diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 2ac70de4..dfa083a0 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -14,10 +14,9 @@ #include #include -#include -#include - - +#include "camera.h" +#include "mapimages.h" +#include "menus.h" #include "maplayers.h" CMapLayers::CMapLayers(int t) @@ -71,14 +70,22 @@ void CMapLayers::LoadBackgroundMap() LoadEnvPoints(m_pMenuLayers, m_lEnvPointsMenu); } +int CMapLayers::GetInitAmount() const +{ + if(m_Type == TYPE_BACKGROUND) + return 15; + return 0; +} + void CMapLayers::OnInit() { if(m_Type == TYPE_BACKGROUND) { m_pMenuLayers = new CLayers; m_pMenuMap = CreateEngineMap(); - + m_pClient->m_pMenus->RenderLoading(1); LoadBackgroundMap(); + m_pClient->m_pMenus->RenderLoading(14); } m_pEggTiles = 0; diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 83193337..9bee0fc3 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -37,6 +37,7 @@ class CMapLayers : public CComponent CMapLayers(int Type); virtual void OnStateChange(int NewState, int OldState); + virtual int GetInitAmount() const; virtual void OnInit(); virtual void OnShutdown(); virtual void OnRender(); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 78d79aaf..d9ff1c0c 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1224,19 +1224,30 @@ void CMenus::RenderMenubar(CUIRect Rect) } } -void CMenus::RenderLoading() +void CMenus::InitLoading(int TotalWorkAmount) { - // TODO: not supported right now due to separate render thread + m_LoadCurrent = 0; + m_LoadTotal = TotalWorkAmount; +} + +void CMenus::RenderLoading(int WorkedAmount) +{ + static int64 s_LastLoadRender = 0; + m_LoadCurrent += WorkedAmount; - static int64 LastLoadRender = 0; - float Percent = m_LoadCurrent++/(float)m_LoadTotal; + if(Config()->m_Debug) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "progress: %03d/%03d (+%02d) %dms", m_LoadCurrent, m_LoadTotal, WorkedAmount, s_LastLoadRender == 0 ? 0 : int((time_get()-s_LastLoadRender)*1000.0f/time_freq())); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "loading", aBuf); + } // make sure that we don't render for each little thing we load // because that will slow down loading if we have vsync - if(time_get()-LastLoadRender < time_freq()/60) + if(s_LastLoadRender > 0 && time_get()-s_LastLoadRender < time_freq()/60) return; - LastLoadRender = time_get(); + s_LastLoadRender = time_get(); CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); @@ -1252,19 +1263,20 @@ void CMenus::RenderLoading() Graphics()->BlendNormal(); RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 40.0f); - const char *pCaption = Localize("Loading"); - Rect.x = x; Rect.y = y+20; Rect.w = w; Rect.h = h; - UI()->DoLabel(&Rect, pCaption, 48.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Rect, Localize("Loading"), 48.0f, CUI::ALIGN_CENTER); - Rect.x = x+40.0f; + float Percent = m_LoadCurrent/(float)m_LoadTotal; + float Spacing = 40.0f; + float Rounding = 5.0f; + Rect.x = x+Spacing; Rect.y = y+h-75.0f; - Rect.w = (w-80.0f)*Percent; + Rect.w = (w-2*Spacing-2*Rounding)*Percent+2*Rounding; Rect.h = 25.0f; - RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 1.0f, 1.0f, 0.75f), 5.0f); + RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); Graphics()->Swap(); } @@ -1392,64 +1404,21 @@ const CMenus::CMenuImage *CMenus::FindMenuImage(const char *pName) return 0; } -void CMenus::UpdateVideoFormats() -{ - m_NumVideoFormats = 0; - for(int i = 0; i < m_NumModes; i++) - { - int G = gcd(m_aModes[i].m_Width, m_aModes[i].m_Height); - int Width = m_aModes[i].m_Width/G; - int Height = m_aModes[i].m_Height/G; - - // check if we already have the format - bool Found = false; - for(int j = 0; j < m_NumVideoFormats; j++) - { - if(Width == m_aVideoFormats[j].m_WidthValue && Height == m_aVideoFormats[j].m_HeightValue) - { - Found = true; - break; - } - } - - if(!Found) - { - m_aVideoFormats[m_NumVideoFormats].m_WidthValue = Width; - m_aVideoFormats[m_NumVideoFormats].m_HeightValue = Height; - m_NumVideoFormats++; - - // sort the array - for(int k = 0; k < m_NumVideoFormats-1; k++) // ffs, bubblesort - { - for(int j = 0; j < m_NumVideoFormats-k-1; j++) - { - if((float)m_aVideoFormats[j].m_WidthValue/(float)m_aVideoFormats[j].m_HeightValue > (float)m_aVideoFormats[j+1].m_WidthValue/(float)m_aVideoFormats[j+1].m_HeightValue) - { - CVideoFormat Tmp = m_aVideoFormats[j]; - m_aVideoFormats[j] = m_aVideoFormats[j+1]; - m_aVideoFormats[j+1] = Tmp; - } - } - } - } - } -} - void CMenus::UpdatedFilteredVideoModes() { // same format as desktop goes to recommended list m_lRecommendedVideoModes.clear(); m_lOtherVideoModes.clear(); - const int DeskTopG = gcd(Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); - const int DeskTopWidthG = Graphics()->DesktopWidth() / DeskTopG; - const int DeskTopHeightG = Graphics()->DesktopHeight() / DeskTopG; + const int DesktopG = gcd(Graphics()->DesktopWidth(), Graphics()->DesktopHeight()); + const int DesktopWidthG = Graphics()->DesktopWidth() / DesktopG; + const int DesktopHeightG = Graphics()->DesktopHeight() / DesktopG; for(int i = 0; i < m_NumModes; i++) { const int G = gcd(m_aModes[i].m_Width, m_aModes[i].m_Height); - if(m_aModes[i].m_Width/G == DeskTopWidthG && - m_aModes[i].m_Height/G == DeskTopHeightG) + if(m_aModes[i].m_Width/G == DesktopWidthG && + m_aModes[i].m_Height/G == DesktopHeightG) { m_lRecommendedVideoModes.add(m_aModes[i]); } @@ -1463,30 +1432,18 @@ void CMenus::UpdatedFilteredVideoModes() void CMenus::UpdateVideoModeSettings() { m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS, Config()->m_GfxScreen); - UpdateVideoFormats(); - - bool Found = false; - for(int i = 0; i < m_NumVideoFormats; i++) - { - int G = gcd(Config()->m_GfxScreenWidth, Config()->m_GfxScreenHeight); - if(m_aVideoFormats[i].m_WidthValue == Config()->m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == Config()->m_GfxScreenHeight/G) - { - m_CurrentVideoFormat = i; - Found = true; - break; - } - - } - - if(!Found) - m_CurrentVideoFormat = 0; - UpdatedFilteredVideoModes(); } +int CMenus::GetInitAmount() const +{ + return 10; +} + void CMenus::OnInit() { UpdateVideoModeSettings(); + RenderLoading(5); m_MousePos.x = Graphics()->ScreenWidth()/2; m_MousePos.y = Graphics()->ScreenHeight()/2; @@ -1494,10 +1451,19 @@ void CMenus::OnInit() // load menu images m_lMenuImages.clear(); Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageScan, this); + RenderLoading(2); + + // load filters + LoadFilters(); + // add standard filters in case they are missing + InitDefaultFilters(); + RenderLoading(1); - // clear filter lists - //m_lFilters.clear(); + // load game type icons + Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/gametypes", GameIconScan, this); + RenderLoading(1); + // initial launch preparations if(Config()->m_ClShowWelcome) m_Popup = POPUP_LANGUAGE; Config()->m_ClShowWelcome = 0; @@ -1513,13 +1479,7 @@ void CMenus::OnInit() Console()->Chain("remove_friend", ConchainFriendlistUpdate, this); Console()->Chain("snd_enable_music", ConchainToggleMusic, this); - m_TextureBlob = Graphics()->LoadTexture("ui/blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); - - // setup load amount - m_LoadCurrent = 0; - m_LoadTotal = g_pData->m_NumImages; - if(!Config()->m_SndAsyncLoading) - m_LoadTotal += g_pData->m_NumSounds; + RenderLoading(1); } void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton, int Next) @@ -2371,44 +2331,6 @@ bool CMenus::OnInput(IInput::CEvent e) void CMenus::OnConsoleInit() { - // load filters - LoadFilters(); - - // add standard filters in case they are missing - bool UseDefaultFilters = !m_lFilters.size(); - bool FilterStandard = false; - bool FilterFav = false; - bool FilterAll = false; - for(int i = 0; i < m_lFilters.size(); i++) - { - switch(m_lFilters[i].Custom()) - { - case CBrowserFilter::FILTER_STANDARD: - FilterStandard = true; - break; - case CBrowserFilter::FILTER_FAVORITES: - FilterFav = true; - break; - case CBrowserFilter::FILTER_ALL: - FilterAll = true; - } - } - if(!FilterStandard) - { - // put it on top - int Pos = m_lFilters.size(); - m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_STANDARD, "Teeworlds", ServerBrowser())); - for(; Pos > 0; --Pos) - Move(true, Pos); - } - if(!FilterFav) - m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_FAVORITES, Localize("Favorites"), ServerBrowser())); - if(!FilterAll) - m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_ALL, Localize("All"), ServerBrowser())); - // expand the all filter tab by default - if(UseDefaultFilters) - m_lFilters[m_lFilters.size()-1].Switch(); - CUIElementBase::Init(this); } @@ -2562,30 +2484,13 @@ bool CMenus::CheckHotKey(int Key) const void CMenus::RenderBackground() { - //Graphics()->Clear(1,1,1); - //render_sunrays(0,0); + // render background color + Graphics()->Clear(0.45f, 0.45f, 0.45f); float sw = 300*Graphics()->ScreenAspect(); float sh = 300; Graphics()->MapScreen(0, 0, sw, sh); - // render background color - Graphics()->TextureClear(); - Graphics()->QuadsBegin(); - //vec4 bottom(gui_color.r*0.3f, gui_color.g*0.3f, gui_color.b*0.3f, 1.0f); - //vec4 bottom(0, 0, 0, 1.0f); - vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); - vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); - IGraphics::CColorVertex Array[4] = { - IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), - IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a)}; - Graphics()->SetColorVertex(Array, 4); - IGraphics::CQuadItem QuadItem(0, 0, sw, sh); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - // render the tiles Graphics()->TextureClear(); Graphics()->QuadsBegin(); @@ -2601,10 +2506,11 @@ void CMenus::RenderBackground() Graphics()->QuadsEnd(); // render border fade + static IGraphics::CTextureHandle m_TextureBlob = Graphics()->LoadTexture("ui/blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); Graphics()->TextureSet(m_TextureBlob); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200); + IGraphics::CQuadItem QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 6a9f00b0..2fd359c4 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -400,10 +400,6 @@ class CMenus : public CComponent int64 m_LastInput; - // loading - int m_LoadCurrent; - int m_LoadTotal; - // char m_aMessageTopic[512]; char m_aMessageBody[512]; @@ -577,6 +573,7 @@ class CMenus : public CComponent void SaveFilters(); void RemoveFilter(int FilterIndex); void Move(bool Up, int Filter); + void InitDefaultFilters(); class CInfoOverlay { @@ -666,22 +663,15 @@ class CMenus : public CComponent { MAX_RESOLUTIONS=256, }; - CVideoMode m_aModes[MAX_RESOLUTIONS]; int m_NumModes; - struct CVideoFormat { int m_WidthValue; int m_HeightValue; }; - - CVideoFormat m_aVideoFormats[MAX_RESOLUTIONS]; sorted_array m_lRecommendedVideoModes; sorted_array m_lOtherVideoModes; - int m_NumVideoFormats; - int m_CurrentVideoFormat; - void UpdateVideoFormats(); void UpdatedFilteredVideoModes(); void UpdateVideoModeSettings(); @@ -773,7 +763,9 @@ class CMenus : public CComponent void InvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CMenus *pMenu, CUIRect Rect), void *pExtra=0); void DoPopupMenu(); - IGraphics::CTextureHandle m_TextureBlob; + // loading + int m_LoadCurrent; + int m_LoadTotal; void ToggleMusic(); @@ -784,6 +776,9 @@ class CMenus : public CComponent void RenderBackground(); void RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom); public: + void InitLoading(int TotalWorkAmount); + void RenderLoading(int WorkedAmount = 0); + struct CSwitchTeamInfo { char m_aNotification[128]; @@ -798,10 +793,9 @@ class CMenus : public CComponent CMenus(); - void RenderLoading(); - bool IsActive() const { return m_MenuActive; } + virtual int GetInitAmount() const; virtual void OnInit(); virtual void OnConsoleInit(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index cd14610b..8392b826 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -358,6 +358,43 @@ void CMenus::Move(bool Up, int Filter) } } +void CMenus::InitDefaultFilters() +{ + bool UseDefaultFilters = !m_lFilters.size(); + bool FilterStandard = false; + bool FilterFav = false; + bool FilterAll = false; + for(int i = 0; i < m_lFilters.size(); i++) + { + switch(m_lFilters[i].Custom()) + { + case CBrowserFilter::FILTER_STANDARD: + FilterStandard = true; + break; + case CBrowserFilter::FILTER_FAVORITES: + FilterFav = true; + break; + case CBrowserFilter::FILTER_ALL: + FilterAll = true; + } + } + if(!FilterStandard) + { + // put it on top + int Pos = m_lFilters.size(); + m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_STANDARD, "Teeworlds", ServerBrowser())); + for(; Pos > 0; --Pos) + Move(true, Pos); + } + if(!FilterFav) + m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_FAVORITES, Localize("Favorites"), ServerBrowser())); + if(!FilterAll) + m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_ALL, Localize("All"), ServerBrowser())); + // expand the all filter tab by default + if(UseDefaultFilters) + m_lFilters[m_lFilters.size()-1].Switch(); +} + void CMenus::SetOverlay(int Type, float x, float y, const void *pData) { if(!m_PopupActive && m_InfoOverlay.m_Reset) @@ -1697,8 +1734,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) Button.VSplitLeft(60.0f, &Icon, &Button); static char s_aFilterName[32] = { 0 }; static float s_FilterOffset = 0.0f; - static int s_EditFilter = 0; - DoEditBox(&s_EditFilter, &Icon, s_aFilterName, sizeof(s_aFilterName), FontSize, &s_FilterOffset, false, CUI::CORNER_L); + DoEditBox(&s_FilterOffset, &Icon, s_aFilterName, sizeof(s_aFilterName), FontSize, &s_FilterOffset, false, CUI::CORNER_L); RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_R, 5.0f); Button.VSplitLeft(Button.h, &Icon, &Label); Label.HMargin(2.0f, &Label); @@ -1841,10 +1877,9 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) Button.VSplitLeft(60.0f, &Button, &Icon); ServerFilter.HSplitTop(3.0f, 0, &ServerFilter); static char s_aGametype[16] = { 0 }; - static float s_Offset = 0.0f; - static int s_EditGametype = 0; + static float s_OffsetGametype = 0.0f; Button.VSplitRight(Button.h, &Label, &Button); - DoEditBox(&s_EditGametype, &Label, s_aGametype, sizeof(s_aGametype), FontSize, &s_Offset); + DoEditBox(&s_OffsetGametype, &Label, s_aGametype, sizeof(s_aGametype), FontSize, &s_OffsetGametype); RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_R, 5.0f); DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Button); static CButtonContainer s_AddGametype; @@ -1899,9 +1934,8 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); UI()->DoLabel(&Button, Localize("Server address:"), FontSize, CUI::ALIGN_LEFT); Button.VSplitRight(60.0f, 0, &Button); - static float OffsetAddr = 0.0f; - static int s_BrFilterServerAddress = 0; - if(DoEditBox(&s_BrFilterServerAddress, &Button, FilterInfo.m_aAddress, sizeof(FilterInfo.m_aAddress), FontSize, &OffsetAddr)) + static float s_OffsetAddr = 0.0f; + if(DoEditBox(&s_OffsetAddr, &Button, FilterInfo.m_aAddress, sizeof(FilterInfo.m_aAddress), FontSize, &s_OffsetAddr)) UpdateFilter = true; // player country @@ -1929,7 +1963,6 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) // level ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); - ServerFilter.HSplitTop(LineSize + 2, &Button, &ServerFilter); UI()->DoLabel(&Button, Localize("Difficulty:"), FontSize, CUI::ALIGN_LEFT); Button.VSplitRight(60.0f, 0, &Button); @@ -2337,12 +2370,6 @@ void CMenus::RenderServerbrowser(CUIRect MainView) | back | | bottom box | +------+ +------------+ */ - static bool s_Init = true; - if(s_Init) - { - Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/gametypes", GameIconScan, this); - s_Init = false; - } CUIRect ServerList, Sidebar, BottomBox, SidebarButton; diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index b6c16108..66b2b123 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -12,6 +12,7 @@ #include #include +#include "menus.h" #include "skins.h" @@ -209,6 +210,10 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) return 0; } +int CSkins::GetInitAmount() const +{ + return NUM_SKINPARTS*2 + 8; +} void CSkins::OnInit() { @@ -260,6 +265,7 @@ void CSkins::OnInit() DummySkinPart.m_BloodColor = vec3(1.0f, 1.0f, 1.0f); m_aaSkinParts[p].add(DummySkinPart); } + m_pClient->m_pMenus->RenderLoading(2); } // create dummy skin @@ -278,10 +284,12 @@ void CSkins::OnInit() m_DummySkin.m_aPartColors[p] = p==SKINPART_MARKING ? (255<<24)+65408 : 65408; m_DummySkin.m_aUseCustomColors[p] = 0; } + m_pClient->m_pMenus->RenderLoading(1); // load skins m_aSkins.clear(); Storage()->ListDirectory(IStorage::TYPE_ALL, "skins", SkinScan, this); + m_pClient->m_pMenus->RenderLoading(5); // add dummy skin if(!m_aSkins.size()) @@ -305,6 +313,7 @@ void CSkins::OnInit() m_XmasHatTexture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); } } + m_pClient->m_pMenus->RenderLoading(1); { // add bot decoration @@ -324,6 +333,7 @@ void CSkins::OnInit() m_BotTexture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); } } + m_pClient->m_pMenus->RenderLoading(1); } void CSkins::AddSkin(const char *pSkinName) diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index af703883..c28ebf41 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -55,7 +55,7 @@ class CSkins : public CComponent IGraphics::CTextureHandle m_XmasHatTexture; IGraphics::CTextureHandle m_BotTexture; - // + int GetInitAmount() const; void OnInit(); void AddSkin(const char *pSkinName); diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 0acb9c56..3573e7f8 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -29,7 +29,7 @@ static int LoadSoundsThread(void *pUser) } if(pData->m_Render) - pData->m_pGameClient->m_pMenus->RenderLoading(); + pData->m_pGameClient->m_pMenus->RenderLoading(1); } return 0; @@ -58,6 +58,13 @@ ISound::CSampleHandle CSounds::GetSampleId(int SetId) return pSet->m_aSounds[Id].m_Id; } +int CSounds::GetInitAmount() +{ + if(Config()->m_SndAsyncLoading) + return 0; + return g_pData->m_NumSounds; +} + void CSounds::OnInit() { // setup sound channels diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index 2389bb51..6853b9cd 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -35,6 +35,7 @@ class CSounds : public CComponent CHN_GLOBAL, }; + virtual int GetInitAmount(); virtual void OnInit(); virtual void OnReset(); virtual void OnStateChange(int NewState, int OldState); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 5e203c27..b8e6735f 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -371,17 +371,28 @@ void CGameClient::OnInit() } } + // determine total work for loading all components + int TotalWorkAmount = g_pData->m_NumImages + 2; // +2=editor + for(int i = m_All.m_Num-1; i >= 0; --i) + TotalWorkAmount += m_All.m_paComponents[i]->GetInitAmount(); + + m_pMenus->InitLoading(TotalWorkAmount); + m_pMenus->RenderLoading(); // render initial loading screen // init all components for(int i = m_All.m_Num-1; i >= 0; --i) m_All.m_paComponents[i]->OnInit(); - // setup load amount// load textures + // load textures for(int i = 0; i < g_pData->m_NumImages; i++) { g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, g_pData->m_aImages[i].m_Flag ? IGraphics::TEXLOAD_LINEARMIPMAPS : 0); - m_pMenus->RenderLoading(); + m_pMenus->RenderLoading(1); } + // init the editor + m_pEditor->Init(); + m_pMenus->RenderLoading(2); + OnReset(); int64 End = time_get(); @@ -393,6 +404,7 @@ void CGameClient::OnInit() m_IsXmasDay = time_isxmasday(); m_IsEasterDay = time_iseasterday(); + m_pMenus->RenderLoading(); } void CGameClient::OnUpdate() From 4d8f803ee0c326159974ff3dd278028ae51c381e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Feb 2020 22:18:14 +0100 Subject: [PATCH 159/479] draw full progress bar lightly behind filling progress bar --- src/game/client/components/menus.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index d9ff1c0c..57c59ad9 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1263,20 +1263,16 @@ void CMenus::RenderLoading(int WorkedAmount) Graphics()->BlendNormal(); RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 40.0f); - Rect.x = x; - Rect.y = y+20; - Rect.w = w; - Rect.h = h; + Rect.y += 20; UI()->DoLabel(&Rect, Localize("Loading"), 48.0f, CUI::ALIGN_CENTER); float Percent = m_LoadCurrent/(float)m_LoadTotal; float Spacing = 40.0f; float Rounding = 5.0f; - Rect.x = x+Spacing; - Rect.y = y+h-75.0f; - Rect.w = (w-2*Spacing-2*Rounding)*Percent+2*Rounding; - Rect.h = 25.0f; - RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); + CUIRect Bar = {x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f}; + RenderTools()->DrawRoundRect(&Bar, vec4(1.0f, 1.0f, 1.0f, 0.10f), Rounding); + Bar.w = (Bar.w-2*Rounding)*Percent+2*Rounding; + RenderTools()->DrawRoundRect(&Bar, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); Graphics()->Swap(); } From d61e75672bc65a2f818f5ff957324e3e65cf6bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Feb 2020 22:45:08 +0100 Subject: [PATCH 160/479] fix naming --- src/engine/client/client.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 04bd1aa8..b7526d0e 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -683,12 +683,12 @@ void CClient::DebugRender() static NETSTATS Prev, Current; static int64 LastSnap = 0; static float FrameTimeAvg = 0; - static IGraphics::CTextureHandle Font = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE); + static IGraphics::CTextureHandle s_Font = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE); char aBuffer[256]; int64 Now = time_get(); //m_pGraphics->BlendNormal(); - Graphics()->TextureSet(Font); + Graphics()->TextureSet(s_Font); Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight()); Graphics()->QuadsBegin(); @@ -760,13 +760,13 @@ void CClient::DebugRender() m_FpsGraph.ScaleMax(); m_FpsGraph.ScaleMin(); - m_FpsGraph.Render(Graphics(), Font, x, sp*5, w, h, "FPS"); + m_FpsGraph.Render(Graphics(), s_Font, x, sp*5, w, h, "FPS"); m_InputtimeMarginGraph.ScaleMin(); m_InputtimeMarginGraph.ScaleMax(); - m_InputtimeMarginGraph.Render(Graphics(), Font, x, sp*5+h+sp, w, h, "Prediction Margin"); + m_InputtimeMarginGraph.Render(Graphics(), s_Font, x, sp*5+h+sp, w, h, "Prediction Margin"); m_GametimeMarginGraph.ScaleMin(); m_GametimeMarginGraph.ScaleMax(); - m_GametimeMarginGraph.Render(Graphics(), Font, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin"); + m_GametimeMarginGraph.Render(Graphics(), s_Font, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin"); } } From 4a9ae47b571387542880572dd03f49c9a4b790c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Feb 2020 23:12:55 +0100 Subject: [PATCH 161/479] add missing const classifier --- src/game/client/components/sounds.cpp | 2 +- src/game/client/components/sounds.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 3573e7f8..b392560f 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -58,7 +58,7 @@ ISound::CSampleHandle CSounds::GetSampleId(int SetId) return pSet->m_aSounds[Id].m_Id; } -int CSounds::GetInitAmount() +int CSounds::GetInitAmount() const { if(Config()->m_SndAsyncLoading) return 0; diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index 6853b9cd..64561879 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -35,7 +35,7 @@ class CSounds : public CComponent CHN_GLOBAL, }; - virtual int GetInitAmount(); + virtual int GetInitAmount() const; virtual void OnInit(); virtual void OnReset(); virtual void OnStateChange(int NewState, int OldState); From efb0736060183e862b02362ca3dee172f6f7034f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 08:55:29 +0100 Subject: [PATCH 162/479] revert to using debug font in editor for now, but without the dependence on the engine client --- src/game/editor/layer_tiles.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 3fdf51f7..7cf524bb 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -470,6 +471,9 @@ void CLayerTiles::ShowInfo() { float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); + static IGraphics::CTextureHandle s_Font = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE); + Graphics()->TextureSet(s_Font); + Graphics()->QuadsBegin(); int StartY = max(0, (int)(ScreenY0/32.0f)-1); int StartX = max(0, (int)(ScreenX0/32.0f)-1); @@ -484,17 +488,26 @@ void CLayerTiles::ShowInfo() { char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%i", m_pTiles[c].m_Index); - TextRender()->Text(0, x*32+4, y*32+4, 10.0f, aBuf, 32.0f); + m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, aBuf); char aFlags[4] = { m_pTiles[c].m_Flags&TILEFLAG_VFLIP ? 'V' : ' ', m_pTiles[c].m_Flags&TILEFLAG_HFLIP ? 'H' : ' ', m_pTiles[c].m_Flags&TILEFLAG_ROTATE? 'R' : ' ', 0}; - TextRender()->Text(0, x*32+4, y*32+18, 10.0f, aFlags, 32.0f); + m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, aFlags); + + // TODO: Use text render instead, once it's optimized enough for this much text at once, and remove usage of debug font here + /*str_format(aBuf, sizeof(aBuf), + "%i\n%c%c%c", m_pTiles[c].m_Index, + m_pTiles[c].m_Flags&TILEFLAG_VFLIP ? 'V' : ' ', + m_pTiles[c].m_Flags&TILEFLAG_HFLIP ? 'H' : ' ', + m_pTiles[c].m_Flags&TILEFLAG_ROTATE? 'R' : ' '); + TextRender()->Text(0, x*32+4, y*32+4, 10.0f, aBuf, 32.0f);*/ } x += m_pTiles[c].m_Skip; } + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } From 3c9897659366fccb0e680d7411dad5f29d3a9fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 08:56:14 +0100 Subject: [PATCH 163/479] fix that one pFont logging call without a category --- src/engine/client/text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index 1987765d..a9018c7f 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -171,7 +171,7 @@ class CTextRender : public IEngineTextRender pSizeData->m_TextureHeight = Height; pSizeData->m_CurrentCharacter = 0; - dbg_msg("", "pFont memory usage: %d", FontMemoryUsage); + dbg_msg("pFont", "memory usage: %d", FontMemoryUsage); mem_free(pMem); } From 2b8b3365f2d8aa79774077aba11776e0a4e60ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 08:59:25 +0100 Subject: [PATCH 164/479] fix naming --- src/game/client/components/menus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 57c59ad9..3eba21b8 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2502,8 +2502,8 @@ void CMenus::RenderBackground() Graphics()->QuadsEnd(); // render border fade - static IGraphics::CTextureHandle m_TextureBlob = Graphics()->LoadTexture("ui/blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); - Graphics()->TextureSet(m_TextureBlob); + static IGraphics::CTextureHandle s_TextureBlob = Graphics()->LoadTexture("ui/blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); + Graphics()->TextureSet(s_TextureBlob); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); IGraphics::CQuadItem QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200); From c849eafeb9094d4b0950651b8a09fc60d6c01812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 09:35:45 +0100 Subject: [PATCH 165/479] add loading percentage --- src/game/client/components/menus.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 3eba21b8..779fce8f 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1264,15 +1264,25 @@ void CMenus::RenderLoading(int WorkedAmount) RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 40.0f); Rect.y += 20; + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); UI()->DoLabel(&Rect, Localize("Loading"), 48.0f, CUI::ALIGN_CENTER); float Percent = m_LoadCurrent/(float)m_LoadTotal; float Spacing = 40.0f; float Rounding = 5.0f; - CUIRect Bar = {x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f}; - RenderTools()->DrawRoundRect(&Bar, vec4(1.0f, 1.0f, 1.0f, 0.10f), Rounding); - Bar.w = (Bar.w-2*Rounding)*Percent+2*Rounding; - RenderTools()->DrawRoundRect(&Bar, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); + CUIRect FullBar = {x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f}; + RenderTools()->DrawRoundRect(&FullBar, vec4(1.0f, 1.0f, 1.0f, 0.10f), Rounding); + CUIRect FillingBar = FullBar; + FillingBar.w = (FullBar.w-2*Rounding)*Percent+2*Rounding; + RenderTools()->DrawRoundRect(&FillingBar, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); + + if(Percent > 0.5) + TextRender()->TextColor(0.2f, 0.2f, 0.2f, 1.0f); + else + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + char aBuf[8]; + str_format(aBuf, sizeof(aBuf), "%d%%", (int)(100*Percent)); + UI()->DoLabel(&FullBar, aBuf, 20.0f, CUI::ALIGN_CENTER); Graphics()->Swap(); } From e381f2c3beb6e16202d6b952b54466de198f5b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 09:37:03 +0100 Subject: [PATCH 166/479] change loading screen text to Teeworlds --- src/game/client/components/menus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 779fce8f..14e36cf8 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1265,7 +1265,7 @@ void CMenus::RenderLoading(int WorkedAmount) Rect.y += 20; TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - UI()->DoLabel(&Rect, Localize("Loading"), 48.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Rect, "Teeworlds", 48.0f, CUI::ALIGN_CENTER); float Percent = m_LoadCurrent/(float)m_LoadTotal; float Spacing = 40.0f; From ba1d1bd9d1e0d3e2369d19257fc936d28326e818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 7 Feb 2020 20:56:45 +0100 Subject: [PATCH 167/479] use white text outline color when loading above 50 percent --- src/game/client/components/menus.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 14e36cf8..6aec7377 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1264,6 +1264,7 @@ void CMenus::RenderLoading(int WorkedAmount) RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 40.0f); Rect.y += 20; + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); UI()->DoLabel(&Rect, "Teeworlds", 48.0f, CUI::ALIGN_CENTER); @@ -1271,15 +1272,16 @@ void CMenus::RenderLoading(int WorkedAmount) float Spacing = 40.0f; float Rounding = 5.0f; CUIRect FullBar = {x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f}; - RenderTools()->DrawRoundRect(&FullBar, vec4(1.0f, 1.0f, 1.0f, 0.10f), Rounding); + RenderTools()->DrawRoundRect(&FullBar, vec4(1.0f, 1.0f, 1.0f, 0.1f), Rounding); CUIRect FillingBar = FullBar; FillingBar.w = (FullBar.w-2*Rounding)*Percent+2*Rounding; RenderTools()->DrawRoundRect(&FillingBar, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); - if(Percent > 0.5) + if(Percent > 0.5f) + { + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.7f); TextRender()->TextColor(0.2f, 0.2f, 0.2f, 1.0f); - else - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + } char aBuf[8]; str_format(aBuf, sizeof(aBuf), "%d%%", (int)(100*Percent)); UI()->DoLabel(&FullBar, aBuf, 20.0f, CUI::ALIGN_CENTER); From cdb772d5c350397cdf5a3ef694f67f2a10c4e80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 8 Feb 2020 12:09:11 +0100 Subject: [PATCH 168/479] combine CGraph::ScaleMin/Max, encapsulation, remove base 2 restriction --- src/engine/client/client.cpp | 42 ++++++++++++------------------------ src/engine/client/client.h | 6 ++---- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b7526d0e..bb48a69f 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -61,31 +61,22 @@ void CGraph::Init(float Min, float Max) m_Index = 0; } -void CGraph::ScaleMax() +void CGraph::Scale() { - int i = 0; + m_Min = m_MinRange; m_Max = m_MaxRange; - for(i = 0; i < MAX_VALUES; i++) + for(int i = 0; i < MAX_VALUES; i++) { if(m_aValues[i] > m_Max) m_Max = m_aValues[i]; - } -} - -void CGraph::ScaleMin() -{ - int i = 0; - m_Min = m_MinRange; - for(i = 0; i < MAX_VALUES; i++) - { - if(m_aValues[i] < m_Min) + else if(m_aValues[i] < m_Min) m_Min = m_aValues[i]; } } void CGraph::Add(float v, float r, float g, float b) { - m_Index = (m_Index+1)&(MAX_VALUES-1); + m_Index = (m_Index+1)%MAX_VALUES; m_aValues[m_Index] = v; m_aColors[m_Index][0] = r; m_aColors[m_Index][1] = g; @@ -96,7 +87,6 @@ void CGraph::Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture, { //m_pGraphics->BlendNormal(); - pGraphics->TextureClear(); pGraphics->QuadsBegin(); @@ -110,24 +100,24 @@ void CGraph::Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture, IGraphics::CLineItem LineItem(x, y+h/2, x+w, y+h/2); pGraphics->LinesDraw(&LineItem, 1); pGraphics->SetColor(0.5f, 0.5f, 0.5f, 0.75f); - IGraphics::CLineItem Array[2] = { + IGraphics::CLineItem aLineItems[2] = { IGraphics::CLineItem(x, y+(h*3)/4, x+w, y+(h*3)/4), IGraphics::CLineItem(x, y+h/4, x+w, y+h/4)}; - pGraphics->LinesDraw(Array, 2); + pGraphics->LinesDraw(aLineItems, 2); for(int i = 1; i < MAX_VALUES; i++) { float a0 = (i-1)/(float)MAX_VALUES; float a1 = i/(float)MAX_VALUES; - int i0 = (m_Index+i-1)&(MAX_VALUES-1); - int i1 = (m_Index+i)&(MAX_VALUES-1); + int i0 = (m_Index+i-1)%MAX_VALUES; + int i1 = (m_Index+i)%MAX_VALUES; float v0 = (m_aValues[i0]-m_Min) / (m_Max-m_Min); float v1 = (m_aValues[i1]-m_Min) / (m_Max-m_Min); - IGraphics::CColorVertex Array[2] = { + IGraphics::CColorVertex aColorVertices[2] = { IGraphics::CColorVertex(0, m_aColors[i0][0], m_aColors[i0][1], m_aColors[i0][2], 0.75f), IGraphics::CColorVertex(1, m_aColors[i1][0], m_aColors[i1][1], m_aColors[i1][2], 0.75f)}; - pGraphics->SetColorVertex(Array, 2); + pGraphics->SetColorVertex(aColorVertices, 2); IGraphics::CLineItem LineItem(x+a0*w, y+h-v0*h, x+a1*w, y+h-v1*h); pGraphics->LinesDraw(&LineItem, 1); @@ -752,20 +742,16 @@ void CClient::DebugRender() // render graphs if(Config()->m_DbgGraphs) { - //Graphics()->MapScreen(0,0,400.0f,300.0f); float w = Graphics()->ScreenWidth()/4.0f; float h = Graphics()->ScreenHeight()/6.0f; float sp = Graphics()->ScreenWidth()/100.0f; float x = Graphics()->ScreenWidth()-w-sp; - m_FpsGraph.ScaleMax(); - m_FpsGraph.ScaleMin(); + m_FpsGraph.Scale(); m_FpsGraph.Render(Graphics(), s_Font, x, sp*5, w, h, "FPS"); - m_InputtimeMarginGraph.ScaleMin(); - m_InputtimeMarginGraph.ScaleMax(); + m_InputtimeMarginGraph.Scale(); m_InputtimeMarginGraph.Render(Graphics(), s_Font, x, sp*5+h+sp, w, h, "Prediction Margin"); - m_GametimeMarginGraph.ScaleMin(); - m_GametimeMarginGraph.ScaleMax(); + m_GametimeMarginGraph.Scale(); m_GametimeMarginGraph.Render(Graphics(), s_Font, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin"); } } diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 6892dcc9..a3a5ba9a 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -7,7 +7,6 @@ class CGraph { -public: enum { // restrictions: Must be power of two @@ -20,11 +19,10 @@ class CGraph float m_aColors[MAX_VALUES][3]; int m_Index; +public: void Init(float Min, float Max); - void ScaleMax(); - void ScaleMin(); - + void Scale(); void Add(float v, float r, float g, float b); void Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture, float x, float y, float w, float h, const char *pDescription); }; From 74a95f084408aab47b30b40ef5710e332259456b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 8 Feb 2020 14:29:21 +0100 Subject: [PATCH 169/479] remove obsolete comment --- src/engine/client/client.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index a3a5ba9a..57b0fd47 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -9,7 +9,6 @@ class CGraph { enum { - // restrictions: Must be power of two MAX_VALUES=128, }; From bef666642338efde2a9b29b8e64b184714eacc96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 8 Feb 2020 14:50:26 +0100 Subject: [PATCH 170/479] fix incorrect menu music states and duplicated playback (closes #2460) --- src/game/client/components/menus.cpp | 25 +++++++++---------- src/game/client/components/menus.h | 5 ++-- src/game/client/components/menus_settings.cpp | 14 +++-------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 6aec7377..a38099c2 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1485,7 +1485,8 @@ void CMenus::OnInit() Console()->Chain("br_sort_order", ConchainServerbrowserSortingUpdate, this); Console()->Chain("add_friend", ConchainFriendlistUpdate, this); Console()->Chain("remove_friend", ConchainFriendlistUpdate, this); - Console()->Chain("snd_enable_music", ConchainToggleMusic, this); + Console()->Chain("snd_enable", ConchainUpdateMusicState, this); + Console()->Chain("snd_enable_music", ConchainUpdateMusicState, this); RenderLoading(1); } @@ -1516,7 +1517,7 @@ int CMenus::Render() ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); - m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); + UpdateMusicState(); s_First = false; } @@ -2356,7 +2357,7 @@ void CMenus::OnStateChange(int NewState, int OldState) if(NewState == IClient::STATE_OFFLINE) { if(OldState >= IClient::STATE_ONLINE && NewState < IClient::STATE_QUITING) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); + UpdateMusicState(); m_Popup = POPUP_NONE; if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) { @@ -2537,25 +2538,23 @@ void CMenus::RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom) RenderTools()->DrawUIRect4(pRect, Transparent, Transparent, Background, Background, CUI::CORNER_B, 5.0f); } -void CMenus::ConchainToggleMusic(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +void CMenus::ConchainUpdateMusicState(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); CMenus *pSelf = (CMenus *)pUserData; if(pResult->NumArguments()) { - pSelf->ToggleMusic(); + pSelf->UpdateMusicState(); } } -void CMenus::ToggleMusic() +void CMenus::UpdateMusicState() { - if(Client()->State() == IClient::STATE_OFFLINE) - { - if(Config()->m_SndMusic && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); - else if(!Config()->m_SndMusic && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) - m_pClient->m_pSounds->Stop(SOUND_MENU); - } + bool ShouldPlay = Client()->State() == IClient::STATE_OFFLINE && Config()->m_SndEnable && Config()->m_SndMusic; + if(ShouldPlay && !m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); + else if(!ShouldPlay && m_pClient->m_pSounds->IsPlaying(SOUND_MENU)) + m_pClient->m_pSounds->Stop(SOUND_MENU); } void CMenus::SetMenuPage(int NewPage) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 2fd359c4..c4aad0a1 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -682,6 +682,8 @@ class CMenus : public CComponent void RenderBackButton(CUIRect MainView); inline float GetListHeaderHeight() const { return ms_ListheaderHeight + (Config()->m_UiWideview ? 3.0f : 0.0f); } inline float GetListHeaderHeightFactor() const { return 1.0f + (Config()->m_UiWideview ? (3.0f/ms_ListheaderHeight) : 0.0f); } + static void ConchainUpdateMusicState(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + void UpdateMusicState(); // found in menus_demo.cpp void RenderDemoPlayer(CUIRect MainView); @@ -719,7 +721,6 @@ class CMenus : public CComponent 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); static void ConchainServerbrowserSortingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); - static void ConchainToggleMusic(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); void DoFriendListEntry(CUIRect *pView, CFriendItem *pFriend, const void *pID, const CContactInfo *pFriendInfo, const CServerInfo *pServerInfo, bool Checked, bool Clan = false); void SetOverlay(int Type, float x, float y, const void *pData); void UpdateFriendCounter(const CServerInfo *pEntry); @@ -767,8 +768,6 @@ class CMenus : public CComponent int m_LoadCurrent; int m_LoadTotal; - void ToggleMusic(); - void SetMenuPage(int NewPage); bool CheckHotKey(int Key) const; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index f8ba041f..e2286f07 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1954,7 +1954,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), Config()->m_SndMusic, &Button)) { Config()->m_SndMusic ^= 1; - ToggleMusic(); + UpdateMusicState(); } Sound.HSplitTop(Spacing, 0, &Sound); @@ -2032,11 +2032,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) if(Config()->m_SndEnable) { Config()->m_SndInit = 1; - if(Config()->m_SndMusic) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } - else - m_pClient->m_pSounds->Stop(SOUND_MENU); + UpdateMusicState(); } // reset button @@ -2055,14 +2052,11 @@ void CMenus::RenderSettingsSound(CUIRect MainView) { Config()->m_SndEnable = 1; Config()->m_SndInit = 1; - if(!Config()->m_SndMusic) - { - Config()->m_SndMusic = 1; - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); - } + Config()->m_SndMusic = 1; Config()->m_SndNonactiveMute = 0; Config()->m_SndRate = 48000; Config()->m_SndVolume = 100; + UpdateMusicState(); } } From d716201687fce903613fcadc3f2f75e77e0df4c0 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 8 Feb 2020 18:12:08 +0100 Subject: [PATCH 171/479] reworked CNetBase --- src/engine/client/client.cpp | 4 +- src/engine/client/client.h | 1 + src/engine/engine.h | 1 + src/engine/server/server.cpp | 5 +- src/engine/shared/engine.cpp | 67 ++++++++-- src/engine/shared/network.cpp | 185 +++++++++++++-------------- src/engine/shared/network.h | 100 ++++++++------- src/engine/shared/network_client.cpp | 29 +++-- src/engine/shared/network_conn.cpp | 45 +++++-- src/engine/shared/network_server.cpp | 39 +++--- src/engine/shared/network_token.cpp | 22 ++-- src/mastersrv/mastersrv.cpp | 7 +- src/versionsrv/versionsrv.cpp | 5 +- 13 files changed, 287 insertions(+), 223 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 277f7881..c35dd878 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1950,13 +1950,13 @@ void CClient::Run() mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; } - if(!m_NetClient.Open(BindAddr, BindAddr.port ? 0 : NETCREATE_FLAG_RANDOMPORT)) + if(!m_NetClient.Open(BindAddr, Config(), Console(), Engine(), BindAddr.port ? 0 : NETCREATE_FLAG_RANDOMPORT)) { dbg_msg("client", "couldn't open socket(net)"); return; } BindAddr.port = 0; - if(!m_ContactClient.Open(BindAddr, 0)) + if(!m_ContactClient.Open(BindAddr, Config(), Console(), Engine(), 0)) { dbg_msg("client", "couldn't open socket(contact)"); return; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index ea6002bb..b279243d 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -203,6 +203,7 @@ class CClient : public IClient, public CDemoPlayer::IListner IEngineMasterServer *MasterServer() { return m_pMasterServer; } IConfigManager *ConfigManager() { return m_pConfigManager; } CConfig *Config() { return m_pConfig; } + IConsole *Console() { return m_pConsole; } IStorage *Storage() { return m_pStorage; } CClient(); diff --git a/src/engine/engine.h b/src/engine/engine.h index f4b6864c..b8fab029 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -25,6 +25,7 @@ class IEngine : public IInterface public: virtual void Init() = 0; virtual void InitLogfile() = 0; + virtual void QueryNetLogHandles(IOHANDLE *pHDLSend, IOHANDLE *pHDLRecv) = 0; virtual void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype) = 0; virtual void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData) = 0; }; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index b3235593..1e6fb8d0 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1319,7 +1319,8 @@ int CServer::Run() BindAddr.port = Config()->m_SvPort; } - if(!m_NetServer.Open(BindAddr, &m_ServerBan, Config()->m_SvMaxClients, Config()->m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) + if(!m_NetServer.Open(BindAddr, Config(), Console(), Kernel()->RequestInterface(), &m_ServerBan, + Config()->m_SvMaxClients, Config()->m_SvMaxClientsPerIP, NewClientCallback, DelClientCallback, this)) { dbg_msg("server", "couldn't open socket. port %d might already be in use", Config()->m_SvPort); return -1; @@ -1465,7 +1466,7 @@ int CServer::Run() } // wait for incomming data - net_socket_read_wait(m_NetServer.Socket(), 5); + m_NetServer.Wait(5); } } // disconnect all clients on shutdown diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index b819a3a9..9c04e6b3 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -24,6 +24,8 @@ class CEngine : public IEngine IConsole *m_pConsole; IStorage *m_pStorage; bool m_Logging; + IOHANDLE m_DataLogSent; + IOHANDLE m_DataLogRecv; const char *m_pAppname; static void Con_DbgLognetwork(IConsole::IResult *pResult, void *pUserData) @@ -32,8 +34,7 @@ class CEngine : public IEngine if(pEngine->m_Logging) { - CNetBase::CloseLog(); - pEngine->m_Logging = false; + pEngine->StopLogging(); } else { @@ -42,9 +43,8 @@ class CEngine : public IEngine char aFilenameSent[128], aFilenameRecv[128]; str_format(aFilenameSent, sizeof(aFilenameSent), "dumps/%s_network_sent_%s.txt", pEngine->m_pAppname, aBuf); str_format(aFilenameRecv, sizeof(aFilenameRecv), "dumps/%s_network_recv_%s.txt", pEngine->m_pAppname, aBuf); - CNetBase::OpenLog(pEngine->m_pStorage->OpenFile(aFilenameSent, IOFLAG_WRITE, IStorage::TYPE_SAVE), - pEngine->m_pStorage->OpenFile(aFilenameRecv, IOFLAG_WRITE, IStorage::TYPE_SAVE)); - pEngine->m_Logging = true; + pEngine->StartLogging(pEngine->m_pStorage->OpenFile(aFilenameSent, IOFLAG_WRITE, IStorage::TYPE_SAVE), + pEngine->m_pStorage->OpenFile(aFilenameRecv, IOFLAG_WRITE, IStorage::TYPE_SAVE)); } } @@ -64,15 +64,20 @@ class CEngine : public IEngine dbg_msg("engine", "unknown endian"); #endif - // init the network - net_init(); - + m_JobPool.Init(1); + m_DataLogSent = 0; + m_DataLogRecv = 0; m_Logging = false; m_pAppname = pAppname; } + ~CEngine() + { + StopLogging(); + } + void Init() { m_pConfig = Kernel()->RequestInterface()->Values(); @@ -82,8 +87,6 @@ class CEngine : public IEngine if(!m_pConsole || !m_pStorage) return; - CNetBase::Init(m_pConfig); - m_pConsole->Register("dbg_lognetwork", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_DbgLognetwork, this, "Log the network"); } @@ -107,6 +110,50 @@ class CEngine : public IEngine } } + void QueryNetLogHandles(IOHANDLE *pHDLSend, IOHANDLE *pHDLRecv) + { + *pHDLSend = m_DataLogSent; + *pHDLRecv = m_DataLogRecv; + } + + void StartLogging(IOHANDLE DataLogSent, IOHANDLE DataLogRecv) + { + if(DataLogSent) + { + m_DataLogSent = DataLogSent; + dbg_msg("engine", "logging network sent packages"); + } + else + dbg_msg("engine", "failed to start logging network sent packages"); + + if(DataLogRecv) + { + m_DataLogRecv = DataLogRecv; + dbg_msg("engine", "logging network recv packages"); + } + else + dbg_msg("engine", "failed to start logging network recv packages"); + + m_Logging = true; + } + + void StopLogging() + { + if(m_DataLogSent) + { + dbg_msg("engine", "stopped logging network sent packages"); + io_close(m_DataLogSent); + m_DataLogSent = 0; + } + if(m_DataLogRecv) + { + dbg_msg("engine", "stopped logging network recv packages"); + io_close(m_DataLogRecv); + m_DataLogRecv = 0; + } + m_Logging = false; + } + void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype) { str_copy(pLookup->m_aHostname, pHostname, sizeof(pLookup->m_aHostname)); diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index d291d799..dd0e46ec 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -1,12 +1,22 @@ /* (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 "config.h" +#include "console.h" #include "network.h" #include "huffman.h" + +static void ConchainDbgLognetwork(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + ((CNetBase *)pUserData)->UpdateLogHandles(); +} + void CNetRecvUnpacker::Clear() { m_Valid = false; @@ -66,11 +76,11 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) else { // old packet that we already got - if(CNetBase::IsSeqInBackroom(Header.m_Sequence, m_pConnection->m_Ack)) + if(m_pConnection->IsSeqInBackroom(Header.m_Sequence, m_pConnection->m_Ack)) continue; // out of sequence, request resend - if(CNetBase::Config()->m_Debug) + if(m_pConnection->Config()->m_Debug) dbg_msg("conn", "asking for resend %d %d", Header.m_Sequence, (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE); m_pConnection->SignalResend(); continue; // take the next chunk in the packet @@ -86,9 +96,46 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) return 1; } } +CNetBase::CNetInitializer CNetBase::m_NetInitializer; + +CNetBase::CNetBase() +{ + m_Socket = { NETTYPE_INVALID, -1, -1 }; + m_pConfig = 0; + m_pEngine = 0; + m_DataLogSent = 0; + m_DataLogRecv = 0; +} + +CNetBase::~CNetBase() +{ + if(m_Socket.type != NETTYPE_INVALID) + Shutdown(); +} + +void CNetBase::Init(NETSOCKET Socket, CConfig *pConfig, IConsole *pConsole, IEngine *pEngine) +{ + m_Socket = Socket; + m_pConfig = pConfig; + m_pEngine = pEngine; + m_Huffman.Init(); + if(pEngine) + pConsole->Chain("dbg_lognetwork", ConchainDbgLognetwork, this); +} + +void CNetBase::Shutdown() +{ + net_udp_close(m_Socket); + m_Socket = { NETTYPE_INVALID, -1, -1 }; +} + +void CNetBase::Wait(int Time) +{ + net_socket_read_wait(m_Socket, Time); +} // packs the data tight and sends it -void CNetBase::SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize) +void CNetBase::SendPacketConnless(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize) { unsigned char aBuffer[NET_MAX_PACKETSIZE]; @@ -110,30 +157,30 @@ void CNetBase::SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN dbg_assert(i == NET_PACKETHEADERSIZE_CONNLESS, "inconsistency"); mem_copy(&aBuffer[i], pData, DataSize); - net_udp_send(Socket, pAddr, aBuffer, i+DataSize); + net_udp_send(m_Socket, pAddr, aBuffer, i+DataSize); } -void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketConstruct *pPacket) +void CNetBase::SendPacket(const NETADDR *pAddr, CNetPacketConstruct *pPacket) { unsigned char aBuffer[NET_MAX_PACKETSIZE]; int CompressedSize = -1; int FinalSize = -1; // log the data - if(ms_DataLogSent) + if(m_DataLogSent) { int Type = 1; - io_write(ms_DataLogSent, &Type, sizeof(Type)); - io_write(ms_DataLogSent, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize)); - io_write(ms_DataLogSent, &pPacket->m_aChunkData, pPacket->m_DataSize); - io_flush(ms_DataLogSent); + io_write(m_DataLogSent, &Type, sizeof(Type)); + io_write(m_DataLogSent, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize)); + io_write(m_DataLogSent, &pPacket->m_aChunkData, pPacket->m_DataSize); + io_flush(m_DataLogSent); } dbg_assert((pPacket->m_Token&~NET_TOKEN_MASK) == 0, "token out of range"); // compress if not ctrl msg if(!(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)) - CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); + CompressedSize = m_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[NET_PACKETHEADERSIZE], NET_MAX_PAYLOAD); // check if the compression was enabled, successful and good enough if(CompressedSize > 0 && CompressedSize < pPacket->m_DataSize) @@ -165,31 +212,36 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons dbg_assert(i == NET_PACKETHEADERSIZE, "inconsistency"); - net_udp_send(Socket, pAddr, aBuffer, FinalSize); + net_udp_send(m_Socket, pAddr, aBuffer, FinalSize); // log raw socket data - if(ms_DataLogSent) + if(m_DataLogSent) { int Type = 0; - io_write(ms_DataLogSent, &Type, sizeof(Type)); - io_write(ms_DataLogSent, &FinalSize, sizeof(FinalSize)); - io_write(ms_DataLogSent, aBuffer, FinalSize); - io_flush(ms_DataLogSent); + io_write(m_DataLogSent, &Type, sizeof(Type)); + io_write(m_DataLogSent, &FinalSize, sizeof(FinalSize)); + io_write(m_DataLogSent, aBuffer, FinalSize); + io_flush(m_DataLogSent); } } } // TODO: rename this function -int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket) +int CNetBase::UnpackPacket(NETADDR *pAddr, unsigned char *pBuffer, CNetPacketConstruct *pPacket) { + int Size = net_udp_recv(m_Socket, pAddr, pBuffer, NET_MAX_PACKETSIZE); + // no more packets for now + if(Size <= 0) + return 1; + // log the data - if(ms_DataLogRecv) + if(m_DataLogRecv) { int Type = 0; - io_write(ms_DataLogRecv, &Type, sizeof(Type)); - io_write(ms_DataLogRecv, &Size, sizeof(Size)); - io_write(ms_DataLogRecv, pBuffer, Size); - io_flush(ms_DataLogRecv); + io_write(m_DataLogRecv, &Type, sizeof(Type)); + io_write(m_DataLogRecv, &Size, sizeof(Size)); + io_write(m_DataLogRecv, pBuffer, Size); + io_flush(m_DataLogRecv); } // check the size @@ -249,7 +301,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct pPacket->m_ResponseToken = NET_TOKEN_NONE; if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION) - pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); + pPacket->m_DataSize = m_Huffman.Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); else mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize); } @@ -277,13 +329,13 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct } // log the data - if(ms_DataLogRecv) + if(m_DataLogRecv) { int Type = 1; - io_write(ms_DataLogRecv, &Type, sizeof(Type)); - io_write(ms_DataLogRecv, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize)); - io_write(ms_DataLogRecv, pPacket->m_aChunkData, pPacket->m_DataSize); - io_flush(ms_DataLogRecv); + io_write(m_DataLogRecv, &Type, sizeof(Type)); + io_write(m_DataLogRecv, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize)); + io_write(m_DataLogRecv, pPacket->m_aChunkData, pPacket->m_DataSize); + io_flush(m_DataLogRecv); } // return success @@ -291,7 +343,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct } -void CNetBase::SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize) +void CNetBase::SendControlMsg(const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize) { CNetPacketConstruct Construct; Construct.m_Token = Token; @@ -303,11 +355,11 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Toke mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize); // send the control message - CNetBase::SendPacket(Socket, pAddr, &Construct); + SendPacket(pAddr, &Construct); } -void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended) +void CNetBase::SendControlMsgWithToken(const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended) { dbg_assert((Token&~NET_TOKEN_MASK) == 0, "token out of range"); dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range"); @@ -317,7 +369,7 @@ void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, T aBuf[1] = (MyToken>>16)&0xff; aBuf[2] = (MyToken>>8)&0xff; aBuf[3] = (MyToken)&0xff; - SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4); + SendControlMsg(pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4); } unsigned char *CNetChunkHeader::Pack(unsigned char *pData) @@ -346,69 +398,8 @@ unsigned char *CNetChunkHeader::Unpack(unsigned char *pData) return pData + 2; } - -int CNetBase::IsSeqInBackroom(int Seq, int Ack) +void CNetBase::UpdateLogHandles() { - int Bottom = (Ack-NET_MAX_SEQUENCE/2); - if(Bottom < 0) - { - if(Seq <= Ack) - return 1; - if(Seq >= (Bottom + NET_MAX_SEQUENCE)) - return 1; - } - else - { - if(Seq <= Ack && Seq >= Bottom) - return 1; - } - - return 0; -} - -IOHANDLE CNetBase::ms_DataLogSent = 0; -IOHANDLE CNetBase::ms_DataLogRecv = 0; -CHuffman CNetBase::ms_Huffman; -CConfig *CNetBase::m_pConfig = 0; // todo: fix me - -void CNetBase::OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv) -{ - if(DataLogSent) - { - ms_DataLogSent = DataLogSent; - dbg_msg("network", "logging sent packages"); - } - else - dbg_msg("network", "failed to start logging sent packages"); - - if(DataLogRecv) - { - ms_DataLogRecv = DataLogRecv; - dbg_msg("network", "logging recv packages"); - } - else - dbg_msg("network", "failed to start logging recv packages"); -} - -void CNetBase::CloseLog() -{ - if(ms_DataLogSent) - { - dbg_msg("network", "stopped logging sent packages"); - io_close(ms_DataLogSent); - ms_DataLogSent = 0; - } - - if(ms_DataLogRecv) - { - dbg_msg("network", "stopped logging recv packages"); - io_close(ms_DataLogRecv); - ms_DataLogRecv = 0; - } -} - -void CNetBase::Init(CConfig *pConfig) -{ - m_pConfig = pConfig; - ms_Huffman.Init(); + if(Engine()) + Engine()->QueryNetLogHandles(&m_DataLogSent, &m_DataLogRecv); } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 8811b6dd..cf045435 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -187,10 +187,49 @@ class CNetPacketConstruct }; +class CNetBase +{ + class CNetInitializer + { + public: + CNetInitializer() + { + // init the network + net_init(); + } + }; + static CNetInitializer m_NetInitializer; + + class CConfig *m_pConfig; + class IEngine *m_pEngine; + NETSOCKET m_Socket; + IOHANDLE m_DataLogSent; + IOHANDLE m_DataLogRecv; + CHuffman m_Huffman; + +public: + CNetBase(); + ~CNetBase(); + CConfig *Config() { return m_pConfig; } + class IEngine *Engine() { return m_pEngine; } + int NetType() { return m_Socket.type; } + + void Init(NETSOCKET Socket, class CConfig *pConfig, class IConsole *pConsole, class IEngine *pEngine); + void Shutdown(); + void UpdateLogHandles(); + void Wait(int Time); + + void SendControlMsg(const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize); + void SendControlMsgWithToken(const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended); + void SendPacketConnless(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize); + void SendPacket(const NETADDR *pAddr, CNetPacketConstruct *pPacket); + int UnpackPacket(NETADDR *pAddr, unsigned char *pBuffer, CNetPacketConstruct *pPacket); +}; + class CNetTokenManager { public: - void Init(NETSOCKET Socket, int SeedTime = NET_SEEDTIME); + void Init(CNetBase *pNetBase, int SeedTime = NET_SEEDTIME); void Update(); void GenerateSeed(); @@ -202,7 +241,7 @@ class CNetTokenManager static TOKEN GenerateToken(const NETADDR *pAddr, int64 Seed); private: - NETSOCKET m_Socket; + CNetBase *m_pNetBase; int64 m_Seed; int64 m_PrevSeed; @@ -227,7 +266,7 @@ class CNetTokenCache public: CNetTokenCache(); ~CNetTokenCache(); - void Init(NETSOCKET Socket, const CNetTokenManager *pTokenManager); + void Init(CNetBase *pNetBase, const CNetTokenManager *pTokenManager); void SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize, CSendCBData *pCallbackData = 0); void PurgeStoredPacket(int TrackID); void FetchToken(const NETADDR *pAddr); @@ -268,7 +307,7 @@ class CNetTokenCache CConnlessPacketInfo *m_pConnlessPacketList; // TODO: enhance this, dynamic linked lists // are bad for performance - NETSOCKET m_Socket; + CNetBase *m_pNetBase; const CNetTokenManager *m_pTokenManager; }; @@ -302,8 +341,8 @@ class CNetConnection TOKEN m_PeerToken; NETADDR m_PeerAddr; - NETSOCKET m_Socket; NETSTATS m_Stats; + CNetBase *m_pNetBase; // void Reset(); @@ -320,7 +359,7 @@ class CNetConnection static TOKEN GenerateToken(const NETADDR *pPeerAddr); public: - void Init(NETSOCKET Socket, bool BlockCloseMsg); + void Init(CNetBase *pNetBase, bool BlockCloseMsg); int Connect(NETADDR *pAddr); void Disconnect(const char *pReason); @@ -328,7 +367,7 @@ class CNetConnection TOKEN Token() const { return m_Token; } TOKEN PeerToken() const { return m_PeerToken; } - NETSOCKET Socket() const { return m_Socket; } + class CConfig *Config() { return m_pNetBase->Config(); } int Update(); int Flush(); @@ -350,6 +389,8 @@ class CNetConnection int64 ConnectTime() const { return m_LastUpdateTime; } int AckSequence() const { return m_Ack; } + // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not + static int IsSeqInBackroom(int Seq, int Ack); }; class CConsoleNetConnection @@ -401,7 +442,7 @@ class CNetRecvUnpacker }; // server side -class CNetServer +class CNetServer : public CNetBase { struct CSlot { @@ -409,7 +450,7 @@ class CNetServer CNetConnection m_Connection; }; - NETSOCKET m_Socket; + int m_NetType; class CNetBan *m_pNetBan; CSlot m_aSlots[NET_MAX_CLIENTS]; int m_NumClients; @@ -427,13 +468,15 @@ class CNetServer public: // - bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); + bool Open(NETADDR BindAddr, class CConfig *pConfig, class IConsole *pConsole, class IEngine *pEngine, class CNetBan *pNetBan, + int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); void Close(); // the token parameter is only used for connless packets int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0); int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE); int Update(); + //void Wait(int Time) { m_pNetBase->Wait(Time); } void AddToken(const NETADDR *pAddr, TOKEN Token) { m_TokenCache.AddToken(pAddr, Token, 0); }; // @@ -441,9 +484,7 @@ class CNetServer // status requests 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; } // void SetMaxClients(int MaxClients); @@ -489,7 +530,7 @@ class CNetConsole // client side -class CNetClient +class CNetClient : public CNetBase { CNetConnection m_Connection; CNetRecvUnpacker m_RecvUnpacker; @@ -497,12 +538,12 @@ class CNetClient CNetTokenCache m_TokenCache; CNetTokenManager m_TokenManager; - NETSOCKET m_Socket; int m_Flags; + public: // openness - bool Open(NETADDR BindAddr, int Flags); - int Close(); + bool Open(NETADDR BindAddr, class CConfig *pConfig, class IConsole *pConsole, class IEngine *pEngine, int Flags); + void Close(); // connection state int Disconnect(const char *Reason); @@ -520,36 +561,9 @@ class CNetClient int ResetErrorString(); // error and state - int NetType() const { return m_Socket.type; } int State() const; bool GotProblems() const; const char *ErrorString() const; }; - - -// TODO: both, fix these. This feels like a junk class for stuff that doesn't fit anywere -class CNetBase -{ - static class CConfig *m_pConfig; - static IOHANDLE ms_DataLogSent; - static IOHANDLE ms_DataLogRecv; - static CHuffman ms_Huffman; -public: - static CConfig *Config() { return m_pConfig; } - static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv); - static void CloseLog(); - static void Init(class CConfig *pConfig); - - static void SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize); - static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended); - static void SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize); - static void SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketConstruct *pPacket); - static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket); - - // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not - static int IsSeqInBackroom(int Seq, int Ack); -}; - - #endif diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index f24b6415..0384fef8 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -1,9 +1,11 @@ /* (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" -bool CNetClient::Open(NETADDR BindAddr, int Flags) + +bool CNetClient::Open(NETADDR BindAddr, CConfig *pConfig, IConsole *pConsole, IEngine *pEngine, int Flags) { // open socket NETSOCKET Socket; @@ -15,27 +17,27 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags) mem_zero(this, sizeof(*this)); // init - m_Socket = Socket; - m_Connection.Init(m_Socket, false); + Init(Socket, pConfig, pConsole, pEngine); + m_Connection.Init(this, false); - m_TokenManager.Init(Socket); - m_TokenCache.Init(Socket, &m_TokenManager); + m_TokenManager.Init(this); + m_TokenCache.Init(this, &m_TokenManager); m_Flags = Flags; return true; } -int CNetClient::Close() +void CNetClient::Close() { - // TODO: implement me - return 0; + if(m_Connection.State() != NET_CONNSTATE_OFFLINE) + m_Connection.Disconnect("Client shutdown"); + Shutdown(); } int CNetClient::Disconnect(const char *pReason) { - //dbg_msg("netclient", "disconnected. reason=\"%s\"", pReason); m_Connection.Disconnect(pReason); return 0; } @@ -72,13 +74,12 @@ int CNetClient::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) // TODO: empty the recvinfo NETADDR Addr; - int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); - + int Result = UnpackPacket(&Addr, m_RecvUnpacker.m_aBuffer, &m_RecvUnpacker.m_Data); // no more packets for now - if(Bytes <= 0) + if(Result > 0) break; - if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) + if(!Result) { if(m_Connection.State() != NET_CONNSTATE_OFFLINE && m_Connection.State() != NET_CONNSTATE_ERROR && net_addr_comp(m_Connection.PeerAddress(), &Addr) == 0) { @@ -136,7 +137,7 @@ int CNetClient::Send(CNetChunk *pChunk, TOKEN Token, CSendCBData *pCallbackData) if(Token != NET_TOKEN_NONE) { - CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, Token, m_TokenManager.GenerateToken(&pChunk->m_Address), pChunk->m_pData, pChunk->m_DataSize); + SendPacketConnless(&pChunk->m_Address, Token, m_TokenManager.GenerateToken(&pChunk->m_Address), pChunk->m_pData, pChunk->m_DataSize); } else { diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index 8519b937..f7f8dfec 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -54,12 +54,12 @@ void CNetConnection::SetError(const char *pString) str_copy(m_ErrorString, pString, sizeof(m_ErrorString)); } -void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg) +void CNetConnection::Init(CNetBase *pNetBase, bool BlockCloseMsg) { Reset(); ResetStats(); - m_Socket = Socket; + m_pNetBase = pNetBase; m_BlockCloseMsg = BlockCloseMsg; mem_zero(m_ErrorString, sizeof(m_ErrorString)); } @@ -72,7 +72,7 @@ void CNetConnection::AckChunks(int Ack) if(!pResend) break; - if(CNetBase::IsSeqInBackroom(pResend->m_Sequence, Ack)) + if(IsSeqInBackroom(pResend->m_Sequence, Ack)) m_Buffer.PopFirst(); else break; @@ -93,7 +93,7 @@ int CNetConnection::Flush() // send of the packets m_Construct.m_Ack = m_Ack; m_Construct.m_Token = m_PeerToken; - CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct); + m_pNetBase->SendPacket(&m_PeerAddr, &m_Construct); // update send times m_LastSendTime = time_get(); @@ -163,18 +163,18 @@ void CNetConnection::SendControl(int ControlMsg, const void *pExtra, int ExtraSi { // send the control message m_LastSendTime = time_get(); - CNetBase::SendControlMsg(m_Socket, &m_PeerAddr, m_PeerToken, m_Ack, ControlMsg, pExtra, ExtraSize); + m_pNetBase->SendControlMsg(&m_PeerAddr, m_PeerToken, m_Ack, ControlMsg, pExtra, ExtraSize); } void CNetConnection::SendPacketConnless(const char *pData, int DataSize) { - CNetBase::SendPacketConnless(m_Socket, &m_PeerAddr, m_PeerToken, m_Token, pData, DataSize); + m_pNetBase->SendPacketConnless(&m_PeerAddr, m_PeerToken, m_Token, pData, DataSize); } void CNetConnection::SendControlWithToken(int ControlMsg) { m_LastSendTime = time_get(); - CNetBase::SendControlMsgWithToken(m_Socket, &m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token, true); + m_pNetBase->SendControlMsgWithToken(&m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token, true); } void CNetConnection::ResendChunk(CNetChunkResend *pResend) @@ -286,7 +286,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SetError(Str); } - if(CNetBase::Config()->m_Debug) + if(Config()->m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; @@ -304,7 +304,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) SendControlWithToken(NET_CTRLMSG_CONNECT); dbg_msg("connection", "got token, replying, token=%x mytoken=%x", m_PeerToken, m_Token); } - else if(CNetBase::Config()->m_Debug) + else if(Config()->m_Debug) dbg_msg("connection", "got token, token=%x", m_PeerToken); } else @@ -325,7 +325,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); - if(CNetBase::Config()->m_Debug) + if(Config()->m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } @@ -337,7 +337,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; - if(CNetBase::Config()->m_Debug) + if(Config()->m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } @@ -350,7 +350,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; - if(CNetBase::Config()->m_Debug) + if(Config()->m_Debug) dbg_msg("connection", "connecting online"); } } @@ -410,7 +410,7 @@ int CNetConnection::Update() if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed { int NumFlushedChunks = Flush(); - if(NumFlushedChunks && CNetBase::Config()->m_Debug) + if(NumFlushedChunks && Config()->m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } @@ -435,3 +435,22 @@ int CNetConnection::Update() return 0; } + +int CNetConnection::IsSeqInBackroom(int Seq, int Ack) +{ + int Bottom = (Ack - NET_MAX_SEQUENCE / 2); + if(Bottom < 0) + { + if(Seq <= Ack) + return 1; + if(Seq >= (Bottom + NET_MAX_SEQUENCE)) + return 1; + } + else + { + if(Seq <= Ack && Seq >= Bottom) + return 1; + } + + return 0; +} diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index c0c3544c..b4184fae 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -9,27 +9,30 @@ #include "network.h" -bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) +bool CNetServer::Open(NETADDR BindAddr, CConfig *pConfig, IConsole *pConsole, IEngine *pEngine, CNetBan *pNetBan, + int MaxClients, int MaxClientsPerIP, NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) { // zero out the whole structure mem_zero(this, sizeof(*this)); // open socket - m_Socket = net_udp_create(BindAddr, 0); - if(!m_Socket.type) + NETSOCKET Socket = net_udp_create(BindAddr, 0); + if(!Socket.type) return false; - - m_TokenManager.Init(m_Socket); - m_TokenCache.Init(m_Socket, &m_TokenManager); - + + // init m_pNetBan = pNetBan; + Init(Socket, pConfig, pConsole, pEngine); + + m_TokenManager.Init(this); + m_TokenCache.Init(this, &m_TokenManager); m_NumClients = 0; SetMaxClients(MaxClients); SetMaxClientsPerIP(MaxClientsPerIP); for(int i = 0; i < NET_MAX_CLIENTS; i++) - m_aSlots[i].m_Connection.Init(m_Socket, true); + m_aSlots[i].m_Connection.Init(this, true); m_pfnNewClient = pfnNewClient; m_pfnDelClient = pfnDelClient; @@ -43,7 +46,7 @@ void CNetServer::Close() for(int i = 0; i < NET_MAX_CLIENTS; i++) Drop(i, "Server shutdown"); - net_udp_close(m_Socket); + Shutdown(); } void CNetServer::Drop(int ClientID, const char *pReason) @@ -92,20 +95,18 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { while(1) { - NETADDR Addr; - // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; // TODO: empty the recvinfo - int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); - + NETADDR Addr; + int Result = UnpackPacket(&Addr, m_RecvUnpacker.m_aBuffer, &m_RecvUnpacker.m_Data); // no more packets for now - if(Bytes <= 0) + if(Result > 0) break; - if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) + if(!Result) { // check for bans char aBuf[128]; @@ -116,7 +117,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) int Time = time_timestamp(); if(LastInfoQuery + 5 < Time) { - CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); + SendControlMsg(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); } continue; } @@ -168,7 +169,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) if(m_NumClients >= m_MaxClients) { const char FullMsg[] = "This server is full"; - CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); + SendControlMsg(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); continue; } @@ -189,7 +190,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP); - CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); + SendControlMsg(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); return 0; } } @@ -255,7 +256,7 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) if(Token != NET_TOKEN_NONE) { - CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, Token, m_TokenManager.GenerateToken(&pChunk->m_Address), pChunk->m_pData, pChunk->m_DataSize); + SendPacketConnless(&pChunk->m_Address, Token, m_TokenManager.GenerateToken(&pChunk->m_Address), pChunk->m_pData, pChunk->m_DataSize); } else { diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index e2fe8891..13e4b5b0 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -19,9 +19,9 @@ static unsigned int Hash(char *pData, int Size) int CNetTokenCache::CConnlessPacketInfo::m_UniqueID = 0; -void CNetTokenManager::Init(NETSOCKET Socket, int SeedTime) +void CNetTokenManager::Init(CNetBase *pNetBase, int SeedTime) { - m_Socket = Socket; + m_pNetBase = pNetBase; m_SeedTime = SeedTime; GenerateSeed(); } @@ -62,9 +62,7 @@ int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConst // client requesting token if(pPacket->m_DataSize >= NET_TOKENREQUEST_DATASIZE) { - CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr, - pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN, - GenerateToken(pAddr), false); + m_pNetBase->SendControlMsgWithToken((NETADDR *)pAddr, pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN, GenerateToken(pAddr), false); } return 0; // no need to process NET_CTRLMSG_TOKEN further } @@ -154,13 +152,13 @@ CNetTokenCache::~CNetTokenCache() m_pConnlessPacketList = 0; } -void CNetTokenCache::Init(NETSOCKET Socket, const CNetTokenManager *pTokenManager) +void CNetTokenCache::Init(CNetBase *pNetBase, const CNetTokenManager *pTokenManager) { // call the destructor to clear the linked list this->~CNetTokenCache(); m_TokenCache.Init(); - m_Socket = Socket; + m_pNetBase = pNetBase; m_pTokenManager = pTokenManager; } @@ -169,8 +167,7 @@ void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, TOKEN Token = GetToken(pAddr); if(Token != NET_TOKEN_NONE) { - CNetBase::SendPacketConnless(m_Socket, pAddr, Token, - m_pTokenManager->GenerateToken(pAddr), pData, DataSize); + m_pNetBase->SendPacketConnless(pAddr, Token, m_pTokenManager->GenerateToken(pAddr), pData, DataSize); } else { @@ -247,8 +244,7 @@ TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr) void CNetTokenCache::FetchToken(const NETADDR *pAddr) { - CNetBase::SendControlMsgWithToken(m_Socket, pAddr, NET_TOKEN_NONE, 0, - NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr), true); + m_pNetBase->SendControlMsgWithToken(pAddr, NET_TOKEN_NONE, 0, NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr), true); } void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag) @@ -271,9 +267,7 @@ void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag) // notify the user that the packet gets delivered if(pInfo->m_pfnCallback) pInfo->m_pfnCallback(pInfo->m_TrackID, pInfo->m_pCallbackUser); - CNetBase::SendPacketConnless(m_Socket, &(pInfo->m_Addr), Token, - m_pTokenManager->GenerateToken(pAddr), - pInfo->m_aData, pInfo->m_DataSize); + m_pNetBase->SendPacketConnless(&(pInfo->m_Addr), Token, m_pTokenManager->GenerateToken(pAddr), pInfo->m_aData, pInfo->m_DataSize); CConnlessPacketInfo *pNext = pInfo->m_pNext; if(pPrevInfo) pPrevInfo->m_pNext = pNext; diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 78f179a0..727ab1ed 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -287,7 +287,6 @@ int main(int argc, const char **argv) // ignore_convention NETADDR BindAddr; dbg_logger_stdout(); - net_init(); mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); @@ -298,8 +297,6 @@ int main(int argc, const char **argv) // ignore_convention CConfig *pConfig = pConfigManager->Values(); m_pConsole = CreateConsole(FlagMask); - CNetBase::Init(pConfig); - bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(m_pConsole); RegisterFail |= !pKernel->RegisterInterface(pConfigManager); @@ -331,13 +328,13 @@ int main(int argc, const char **argv) // ignore_convention dbg_msg("mastersrv", "could not initialize secure RNG"); return -1; } - if(!m_NetOp.Open(BindAddr, 0)) + if(!m_NetOp.Open(BindAddr, pConfig, m_pConsole, 0, 0)) { dbg_msg("mastersrv", "couldn't start network (op)"); return -1; } BindAddr.port = MASTERSERVER_PORT+1; - if(!m_NetChecker.Open(BindAddr, 0)) + if(!m_NetChecker.Open(BindAddr, pConfig, m_pConsole, 0, 0)) { dbg_msg("mastersrv", "couldn't start network (checker)"); return -1; diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index 952d5625..69825106 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -84,7 +84,6 @@ int main(int argc, const char **argv) // ignore_convention NETADDR BindAddr; dbg_logger_stdout(); - net_init(); int FlagMask = 0; IKernel *pKernel = IKernel::Create(); @@ -92,8 +91,6 @@ int main(int argc, const char **argv) // ignore_convention IConfigManager *pConfigManager = CreateConfigManager(); IConsole *pConsole = CreateConsole(FlagMask); - CNetBase::Init(pConfigManager->Values()); - bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(pConsole); RegisterFail |= !pKernel->RegisterInterface(pConfigManager); @@ -111,7 +108,7 @@ int main(int argc, const char **argv) // ignore_convention dbg_msg("versionsrv", "could not initialize secure RNG"); return -1; } - if(!g_NetOp.Open(BindAddr, 0)) + if(!g_NetOp.Open(BindAddr, pConfigManager->Values(), pConsole, 0, 0)) { dbg_msg("mastersrv", "couldn't start network"); return -1; From 6a783a66c3c936764771da95b2458380e117a5be Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 8 Feb 2020 19:27:34 +0100 Subject: [PATCH 172/479] fixed compiling the fake_server --- src/tools/fake_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp index 2fba98a2..81bb1ceb 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, 0, 0, 0)) + if(!pNet->Open(BindAddr, 0, 0, 0, 0, 0, 0, 0, 0, 0)) return 0; while(1) From 2ef9395023ea344dd10061f5e719474c8707f63e Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 8 Feb 2020 19:48:43 +0100 Subject: [PATCH 173/479] added a function to invalidate sockets --- src/base/system.c | 5 +++++ src/base/system.h | 8 ++++++++ src/engine/shared/network.cpp | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index f3ae0abf..d4522064 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1454,6 +1454,11 @@ int net_would_block() #endif } +void net_invalidate_socket(NETSOCKET *socket) +{ + *socket = invalid_socket; +} + int net_init() { #if defined(CONF_FAMILY_WINDOWS) diff --git a/src/base/system.h b/src/base/system.h index 50d2eb46..6678a2f7 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -590,6 +590,14 @@ typedef struct unsigned short port; } NETADDR; +/* + Function: net_invalidate_socket + Invalidates a socket. + + Remarks: + You should close the socket before invalidating it. +*/ +void net_invalidate_socket(NETSOCKET *socket); /* Function: net_init Initiates network functionallity. diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index dd0e46ec..88079f40 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -100,7 +100,7 @@ CNetBase::CNetInitializer CNetBase::m_NetInitializer; CNetBase::CNetBase() { - m_Socket = { NETTYPE_INVALID, -1, -1 }; + net_invalidate_socket(&m_Socket); m_pConfig = 0; m_pEngine = 0; m_DataLogSent = 0; @@ -126,7 +126,7 @@ void CNetBase::Init(NETSOCKET Socket, CConfig *pConfig, IConsole *pConsole, IEng void CNetBase::Shutdown() { net_udp_close(m_Socket); - m_Socket = { NETTYPE_INVALID, -1, -1 }; + net_invalidate_socket(&m_Socket); } void CNetBase::Wait(int Time) From 07b971fa3854f9f9dbf452445dbcfb627402efbb Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 8 Feb 2020 19:52:57 +0100 Subject: [PATCH 174/479] removed old code --- src/engine/shared/network.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index cf045435..3294ea5b 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -450,7 +450,6 @@ class CNetServer : public CNetBase CNetConnection m_Connection; }; - int m_NetType; class CNetBan *m_pNetBan; CSlot m_aSlots[NET_MAX_CLIENTS]; int m_NumClients; @@ -476,7 +475,6 @@ class CNetServer : public CNetBase int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0); int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE); int Update(); - //void Wait(int Time) { m_pNetBase->Wait(Time); } void AddToken(const NETADDR *pAddr, TOKEN Token) { m_TokenCache.AddToken(pAddr, Token, 0); }; // From da6d2d7e1aa3af0b0dbb191fcad66e7712a9b9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 8 Feb 2020 20:00:44 +0100 Subject: [PATCH 175/479] use byted_be_to_uint, add uint_to_bytes_be to system.h --- src/base/system.c | 8 ++++++++ src/base/system.h | 10 ++++++++++ src/engine/shared/demo.cpp | 35 +++++++++++------------------------ 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index f3ae0abf..28a8e21c 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2617,6 +2617,14 @@ unsigned bytes_be_to_uint(const unsigned char *bytes) return (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<<8) | bytes[3]; } +void uint_to_bytes_be(unsigned char *bytes, unsigned value) +{ + bytes[0] = (value>>24)&0xff; + bytes[1] = (value>>16)&0xff; + bytes[2] = (value>>8)&0xff; + bytes[3] = value&0xff; +} + #if defined(__cplusplus) } #endif diff --git a/src/base/system.h b/src/base/system.h index 50d2eb46..7d3fd007 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1666,6 +1666,16 @@ int pid(); */ unsigned bytes_be_to_uint(const unsigned char *bytes); +/* + Function: uint_to_bytes_be + Packs an unsigned into 4 big endian bytes + + Remarks: + - Assumes the passed array is 4 bytes + - Assumes unsigned is 4 bytes +*/ +void uint_to_bytes_be(unsigned char *bytes, unsigned value); + #ifdef __cplusplus } #endif diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 9df3b87e..93a44c48 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -18,19 +18,6 @@ static const unsigned char gs_ActVersion = 4; static const int gs_LengthOffset = 152; static const int gs_NumMarkersOffset = 176; -static inline void EncodeUnsigned(unsigned char *pOut, unsigned Value) -{ - pOut[0] = (Value>>24)&0xff; - pOut[1] = (Value>>16)&0xff; - pOut[2] = (Value>>8)&0xff; - pOut[3] = Value&0xff; -} - -static inline unsigned DecodeUnsigned(const unsigned char *pIn) -{ - return ((pIn[0]<<24)&0xFF000000) | ((pIn[1]<<16)&0xFF0000) | ((pIn[2]<<8)&0xFF00) | (pIn[3]&0xFF); -} - CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta) { m_File = 0; @@ -101,8 +88,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con str_copy(Header.m_aNetversion, pNetVersion, sizeof(Header.m_aNetversion)); str_copy(Header.m_aMapName, pMap, sizeof(Header.m_aMapName)); unsigned MapSize = io_length(MapFile); - EncodeUnsigned(Header.m_aMapSize, MapSize); - EncodeUnsigned(Header.m_aMapCrc, Crc); + uint_to_bytes_be(Header.m_aMapSize, MapSize); + uint_to_bytes_be(Header.m_aMapCrc, Crc); 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)); @@ -168,7 +155,7 @@ void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe) { unsigned char aChunk[5]; aChunk[0] = CHUNKTYPEFLAG_TICKMARKER; - EncodeUnsigned(aChunk+1, Tick); + uint_to_bytes_be(aChunk+1, Tick); if(Keyframe) aChunk[0] |= CHUNKTICKFLAG_KEYFRAME; @@ -285,18 +272,18 @@ int CDemoRecorder::Stop() // add the demo length to the header io_seek(m_File, gs_LengthOffset, IOSEEK_START); unsigned char aLength[4]; - EncodeUnsigned(aLength, Length()); + uint_to_bytes_be(aLength, Length()); io_write(m_File, aLength, sizeof(aLength)); // add the timeline markers to the header io_seek(m_File, gs_NumMarkersOffset, IOSEEK_START); unsigned char aNumMarkers[4]; - EncodeUnsigned(aNumMarkers, m_NumTimelineMarkers); + uint_to_bytes_be(aNumMarkers, m_NumTimelineMarkers); io_write(m_File, aNumMarkers, sizeof(aNumMarkers)); for(int i = 0; i < m_NumTimelineMarkers; i++) { unsigned char aMarker[4]; - EncodeUnsigned(aMarker, m_aTimelineMarkers[i]); + uint_to_bytes_be(aMarker, m_aTimelineMarkers[i]); io_write(m_File, aMarker, sizeof(aMarker)); } @@ -365,7 +352,7 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) unsigned char aTickData[4]; if(io_read(m_File, aTickData, sizeof(aTickData)) != sizeof(aTickData)) return -1; - *pTick = DecodeUnsigned(aTickData); + *pTick = bytes_be_to_uint(aTickData); } else { @@ -659,11 +646,11 @@ const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole m_DemoType = DEMOTYPE_INVALID; // read map - unsigned MapSize = DecodeUnsigned(m_Info.m_Header.m_aMapSize); + unsigned MapSize = bytes_be_to_uint(m_Info.m_Header.m_aMapSize); // check if we already have the map // TODO: improve map checking (maps folder, check crc) - unsigned Crc = DecodeUnsigned(m_Info.m_Header.m_aMapCrc); + unsigned Crc = bytes_be_to_uint(m_Info.m_Header.m_aMapCrc); char aMapFilename[128]; str_format(aMapFilename, sizeof(aMapFilename), "downloadedmaps/%s_%08x.map", m_Info.m_Header.m_aMapName, Crc); IOHANDLE MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_READ, IStorage::TYPE_ALL); @@ -689,10 +676,10 @@ const char *CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole } // get timeline markers - m_Info.m_Info.m_NumTimelineMarkers = min(DecodeUnsigned(m_Info.m_Header.m_aNumTimelineMarkers), unsigned(MAX_TIMELINE_MARKERS)); + m_Info.m_Info.m_NumTimelineMarkers = min(bytes_be_to_uint(m_Info.m_Header.m_aNumTimelineMarkers), unsigned(MAX_TIMELINE_MARKERS)); for(int i = 0; i < m_Info.m_Info.m_NumTimelineMarkers; i++) { - m_Info.m_Info.m_aTimelineMarkers[i] = DecodeUnsigned(m_Info.m_Header.m_aTimelineMarkers[i]); + m_Info.m_Info.m_aTimelineMarkers[i] = bytes_be_to_uint(m_Info.m_Header.m_aTimelineMarkers[i]); } // scan the file for interesting points From 5236a0436858848d6d63444d730292881663d931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 9 Feb 2020 11:24:17 +0100 Subject: [PATCH 176/479] rename 'dump_binds' to 'binds', fix variable naming --- src/game/client/components/binds.cpp | 16 ++++++++-------- src/game/client/components/binds.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index cea50b34..6030df8f 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -271,7 +271,7 @@ void CBinds::OnConsoleInit() Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); - Console()->Register("dump_binds", "", CFGFLAG_CLIENT, ConDumpBinds, this, "Dump binds"); + Console()->Register("binds", "", CFGFLAG_CLIENT, ConBinds, this, "Show list of key bindings"); // default bindings SetDefaults(); @@ -282,9 +282,9 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData) CBinds *pBinds = (CBinds *)pUserData; const char *pKeyName = pResult->GetString(0); int Modifier; - int id = pBinds->DecodeBindString(pKeyName, &Modifier); + int KeyID = pBinds->DecodeBindString(pKeyName, &Modifier); - if(!id) + if(!KeyID) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName); @@ -292,7 +292,7 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData) return; } - pBinds->Bind(id, Modifier, pResult->GetString(1)); + pBinds->Bind(KeyID, Modifier, pResult->GetString(1)); } @@ -301,9 +301,9 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData) CBinds *pBinds = (CBinds *)pUserData; const char *pKeyName = pResult->GetString(0); int Modifier; - int id = pBinds->DecodeBindString(pKeyName, &Modifier); + int KeyID = pBinds->DecodeBindString(pKeyName, &Modifier); - if(!id) + if(!KeyID) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName); @@ -311,7 +311,7 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData) return; } - pBinds->Bind(id, Modifier, ""); + pBinds->Bind(KeyID, Modifier, ""); } @@ -322,7 +322,7 @@ void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData) } -void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData) +void CBinds::ConBinds(IConsole::IResult *pResult, void *pUserData) { CBinds *pBinds = (CBinds *)pUserData; char aBuf[1024]; diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index fc30ee5c..1b302b9f 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -12,7 +12,7 @@ class CBinds : public CComponent static void ConBind(IConsole::IResult *pResult, void *pUserData); static void ConUnbind(IConsole::IResult *pResult, void *pUserData); static void ConUnbindAll(IConsole::IResult *pResult, void *pUserData); - static void ConDumpBinds(IConsole::IResult *pResult, void *pUserData); + static void ConBinds(IConsole::IResult *pResult, void *pUserData); class IConsole *GetConsole() const { return Console(); } static void ConfigSaveCallback(class IConfigManager *pConfigManager, void *pUserData); From 850907a695517e4c11cf8a76aa252c5fa41c28de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 9 Feb 2020 11:33:26 +0100 Subject: [PATCH 177/479] rename 'tune_dump' to 'tunes', update descriptions, fix naming --- src/game/server/gamecontext.cpp | 12 ++++++------ src/game/server/gamecontext.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 324a930d..d95c35fe 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1178,15 +1178,15 @@ void CGameContext::ConTuneReset(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", "Tuning reset"); } -void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData) +void CGameContext::ConTunes(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; char aBuf[256]; for(int i = 0; i < pSelf->Tuning()->Num(); i++) { - float v; - pSelf->Tuning()->Get(i, &v); - str_format(aBuf, sizeof(aBuf), "%s %.2f", pSelf->Tuning()->m_apNames[i], v); + float Value; + pSelf->Tuning()->Get(i, &Value); + str_format(aBuf, sizeof(aBuf), "%s %.2f", pSelf->Tuning()->m_apNames[i], Value); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", aBuf); } } @@ -1509,8 +1509,8 @@ void CGameContext::OnConsoleInit() m_pConsole = Kernel()->RequestInterface(); Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); - Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning"); - Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning"); + Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset all tuning variables to defaults"); + Console()->Register("tunes", "", CFGFLAG_SERVER, ConTunes, this, "List all tuning variables and their values"); Console()->Register("pause", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConPause, this, "Pause/unpause game"); Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map"); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 74e05945..f8fbb3da 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -46,7 +46,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 ConTunes(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); From f86e871e9a8cb12a6ac62aedccdbdb91993cd6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 9 Feb 2020 12:16:03 +0100 Subject: [PATCH 178/479] add success/error message to dump_*_console commands, update description --- src/game/client/components/console.cpp | 33 +++++++++++++++++--------- src/game/client/components/console.h | 1 + 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index ad9e845f..2ddb9cdb 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -43,9 +43,15 @@ CGameConsole::CInstance::CInstance(int Type) m_Type = Type; if(Type == CGameConsole::CONSOLETYPE_LOCAL) + { + m_pName = "local_console"; m_CompletionFlagmask = CFGFLAG_CLIENT; + } else + { + m_pName = "remote_console"; m_CompletionFlagmask = CFGFLAG_SERVER; + } m_aCompletionMapBuffer[0] = 0; m_CompletionMapChosen = -1; @@ -659,21 +665,26 @@ void CGameConsole::Toggle(int Type) void CGameConsole::Dump(int Type) { CInstance *pConsole = Type == CONSOLETYPE_REMOTE ? &m_RemoteConsole : &m_LocalConsole; + char aBuf[256]; char aFilename[128]; - char aDate[20]; - - str_timestamp(aDate, sizeof(aDate)); - str_format(aFilename, sizeof(aFilename), "dumps/%s_dump_%s.txt", Type==CONSOLETYPE_REMOTE?"remote_console":"local_console", aDate); - IOHANDLE io = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); - if(io) + str_timestamp(aBuf, sizeof(aBuf)); + str_format(aFilename, sizeof(aFilename), "dumps/%s_dump_%s.txt", pConsole->m_pName, aBuf); + IOHANDLE File = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); + if(File) { 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_newline(io); + io_write(File, pEntry->m_aText, str_length(pEntry->m_aText)); + io_write_newline(File); } - io_close(io); + io_close(File); + str_format(aBuf, sizeof(aBuf), "%s contents were written to '%s'", pConsole->m_pName, aFilename); + } + else + { + str_format(aBuf, sizeof(aBuf), "Failed to open '%s'", aFilename); } + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf); } void CGameConsole::ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData) @@ -749,8 +760,8 @@ void CGameConsole::OnConsoleInit() Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console"); Console()->Register("clear_local_console", "", CFGFLAG_CLIENT, ConClearLocalConsole, this, "Clear local console"); Console()->Register("clear_remote_console", "", CFGFLAG_CLIENT, ConClearRemoteConsole, this, "Clear remote console"); - Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Dump local console"); - Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Dump remote console"); + Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Write local console contents to a text file"); + Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Write remote console contents to a text file"); Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this); } diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h index 17b59c3f..b5efaa59 100644 --- a/src/game/client/components/console.h +++ b/src/game/client/components/console.h @@ -22,6 +22,7 @@ class CGameConsole : public CComponent char *m_pHistoryEntry; CLineInput m_Input; + const char *m_pName; int m_Type; int m_BacklogActPage; From 5a695ac7d5691f243ed41313ea9f48257a7998bb Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 9 Feb 2020 16:54:02 +0100 Subject: [PATCH 179/479] Always end match properly --- src/game/server/gamecontroller.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 942d4b56..b24214ea 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -922,15 +922,8 @@ void IGameController::ChangeMap(const char *pToMap) str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish)); m_MatchCount = m_GameInfo.m_MatchNum-1; - if(m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER) - SetGameState(IGS_GAME_RUNNING); + SetGameState(IGS_GAME_RUNNING); EndMatch(); - - if(m_GameState != IGS_END_MATCH) - { - // game could not been ended, force cycle - CycleMap(); - } } void IGameController::CycleMap() From 2cff81c1021ebaf15525b08052ddcc02f83e187a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 9 Feb 2020 19:57:02 +0100 Subject: [PATCH 180/479] remove obsolete count_source.sh and process_blame.py scripts --- scripts/count_source.sh | 1 - scripts/process_blame.py | 12 ------------ 2 files changed, 13 deletions(-) delete mode 100644 scripts/count_source.sh delete mode 100644 scripts/process_blame.py diff --git a/scripts/count_source.sh b/scripts/count_source.sh deleted file mode 100644 index 0f4a6a64..00000000 --- a/scripts/count_source.sh +++ /dev/null @@ -1 +0,0 @@ -svn blame `svn -R ls | grep ^src | grep -v external | grep -v /$ | grep -v \.txt` | python scripts/process_blame.py diff --git a/scripts/process_blame.py b/scripts/process_blame.py deleted file mode 100644 index ae2c55b6..00000000 --- a/scripts/process_blame.py +++ /dev/null @@ -1,12 +0,0 @@ -import sys -user_map = {"kma":"matricks", "teetow":"matricks", "jlha":"matricks", "jdv":"void", "jaf":"serp"} -users = {} -for line in sys.stdin: - fields = line.split() - name = user_map.get(fields[1], fields[1]) - users[name] = users.get(name, 0) + 1 - -total = reduce(lambda x,y: x+y, users.values()) -for u in users: - print "%6s %6d %s" % ("%03.2f"%(users[u]*100.0/total), users[u], u) -print "%03.2f %6d %s" % (100, total, "Total") From 7e58eeb081f699c4ce0b53aff04951b069ad4cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 9 Feb 2020 20:01:57 +0100 Subject: [PATCH 181/479] remove obsolete scripts/compiler.py --- scripts/compiler.py | 658 -------------------------------------------- 1 file changed, 658 deletions(-) delete mode 100755 scripts/compiler.py diff --git a/scripts/compiler.py b/scripts/compiler.py deleted file mode 100755 index 726785e0..00000000 --- a/scripts/compiler.py +++ /dev/null @@ -1,658 +0,0 @@ -#!/usr/bin/python - -import sys -import struct -import os - -option_ptrsize = struct.calcsize("P") -option_intsize = struct.calcsize("l") -option_floatsize = struct.calcsize("f") -option_inttype = "long" -option_floattype = "float" - -class node: - def __init__(self): - self.values = [] - self.children = [] - self.parent = 0 - - def name(self): - if len(self.values): - return self.values[0] - return "" - - def debug_print(self, level): - print (" "*level) + " ".join(self.values), - if len(self.children): - print "{" - for c in self.children: - c.debug_print(level+1) - print (" "*level)+"}" - else: - print "" - - def debug_root(self): - for c in self.children: - c.debug_print(0) - - # TODO: should return list of items in the tree, - def gather(self, str): - def recurse(parts, path, node): - if not len(parts): - r = {} - path = path + "." + node.values[0] - r = [node] - #print "found", path - return r - - l = [] - for c in node.children: - if parts[0] == "*" or c.values[0] == parts[0]: - if len(node.values): - if len(path): - l += recurse(parts[1:], path+"."+node.values[0], c) - else: - l += recurse(parts[1:], node.values[0], c) - else: - l += recurse(parts[1:], path, c) - return l - - parts = str.split(".") - return recurse(parts, "", self) - - def find_node(self, str): - parts = str.split(".") - node = self - for part in parts: - if len(part) == 0: - continue - if part == "parent": - node = node.parent - else: - found = 0 - for c in node.children: - if part == c.values[0]: - node = c - found = 1 - break - - if node == self: - return - return node - - def get_single(self, str): - parts = str.split("@") - index = -1 - if len(parts) == 2: - index = int(parts[1]) - - node = self - if len(parts[0]): - node = self.find_node(parts[0]) - - if not node: - print "failed to get", str - return Null - - if index == -1: - return node.get_path()[1:] - return node.values[index] - - def get_path(self): - if self.parent == 0: - return "" - return self.parent.get_path() + "." + self.values[0] - - def get_single_name(self, str): - return self.get_path()[1:] + "." + str - -class parser: - lines = [] - - def parse_node(self, this_node): - while len(self.lines): - line = self.lines.pop(0) # grab line - - fields = line.strip().split() # TODO: improve this to handle strings with spaces - if not len(fields): - continue - - if fields[-1] == '{': - new_node = node() - new_node.parent = this_node - new_node.values = fields[:-1] - this_node.children += [new_node] - self.parse_node(new_node) - elif fields[-1] == '}': - break - else: - new_node = node() - new_node.parent = this_node - new_node.values = fields - this_node.children += [new_node] - - def parse_file(self, filename): - self.lines = file(filename).readlines() - n = node() - self.parse_node(n) - return n - -def parse_file(filename): - return parser().parse_file(filename) - -class pointer: - def __init__(self, index, target): - self.index = index - self.target = target - -class data_constructor: - def __init__(self): - self.data = "" - self.trans = 0 - self.pointers = [] - self.targets = {} - self.enums = {} - - def get_type(self, s): - return self.trans.types[s] - - def allocate(self, size): - index = len(self.data) - self.data += "\0"*size - return index - - def add_pointer(self, index, target): - self.pointers += [pointer(index, target)] - - def add_enum(self, name, value): - self.enums[name] = value - - def get_enum_value(self, name): - if not name in self.enums: - print "ERROR: couldn't find enum '%s'" % (name) - return self.enums[name] - - def add_target(self, target, index): - # TODO: warn about duplicates - #print "add_target(target='%s' index=%d)" % (target, index) - self.targets[target] = index - - def write(self, index, size, data): - try: - self.data = self.data[:index] + data + self.data[index+size:] - except: - print "write error:" - print "\tself.data =", self.data - print "\tdata =", data - - def patch_pointers(self): - for p in self.pointers: - if p.target in self.targets: - i = self.targets[p.target] - #print "ptr @ %d -> %s -> %d" % (p.index, p.target, i) - data = struct.pack("P", i) - self.write(p.index, len(data), data) - else: - print "ERROR: couldn't find target '%s' for pointer at %d" % (p.target, p.index) - -class type: - def __init__(self): - self.name = "" - - def size(self): - pass - -class structure: - def __init__(self): - self.name = "" - self.members = [] - - def size(self): - s = 0 - for m in self.members: - s += m.size() - return s - - def emit_header_code(self, out): - print >>out, "struct", self.name - print >>out, "{" - for m in self.members: - for l in m.get_code(): - print >>out, "\t" + l - print >>out, "};" - print >>out, "" - - def emit_source_code(self, out): - print >>out, "static void patch_ptr_%s(%s *self, char *base)" % (self.name, self.name) - print >>out, "{" - for m in self.members: - for l in m.get_patch_code("self", "base"): - print >>out, "\t" + l - print >>out, "}" - print >>out, "" - - def emit_data(self, cons, index, src_data): - #print self.name+":" - member_index = index - for m in self.members: - #print "\t" + m.name - m.emit_data(cons, member_index, src_data) - member_index += m.size() - -class variable: - def __init__(self): - self.expr = "" - self.type = "" - self.subtype = "" - - def get_code(self): - return [] - - def get_patch_code(self, ptrname, basename): - return [] - - def emit_data(self, cons, index, src_data): - pass - -class variable_int(variable): - def get_code(self): - return ["%s %s;" % (option_inttype, self.name)] - def size(self): - return option_intsize - def emit_data(self, cons, index, src_data): - try: - value = int(self.expr) - except: - value = int(src_data.get_single(self.expr)) - #print "int", self.name, "=", value, "@", index - data = struct.pack("l", value) - cons.write(index, len(data), data) - -class variable_float(variable): - def get_code(self): - return ["%s %s;" % (option_floattype, self.name)] - def size(self): - return option_floatsize - def emit_data(self, cons, index, src_data): - try: - value = float(self.expr) - except: - value = float(src_data.get_single(self.expr)) - #print "int", self.name, "=", value, "@", index - data = struct.pack("f", value) - cons.write(index, len(data), data) - -class variable_string(variable): - def get_code(self): - return ["char *%s;" % (self.name)] - def get_patch_code(self, ptrname, basename): - return ["patch_ptr((char **)&(%s->%s), %s);" % (ptrname, self.name, basename)] - def size(self): - return option_ptrsize - def emit_data(self, cons, index, src_data): - string = src_data.get_single(self.expr) - string = string.strip()[1:-1] # skip " and " - - string_index = cons.allocate(len(string)+1) - cons.write(string_index, len(string), string) - - data = struct.pack("P", string_index) # TODO: solve this - cons.write(index, len(data), data) - -class variable_ptr(variable): - def get_code(self): - return ["%s *%s;" % (self.subtype, self.name)] - def get_patch_code(self, ptrname, basename): - return ["patch_ptr((char**)&(%s->%s), %s);" % (ptrname, self.name, basename)] - def size(self): - return option_ptrsize - def emit_data(self, cons, index, src_data): - target = src_data.get_single(self.expr) - cons.add_pointer(index, target) - -class variable_enum(variable): - def get_code(self): - return ["long *%s;" % (self.name)] - def size(self): - return option_intsize - def emit_data(self, cons, index, src_data): - target = src_data.get_single(self.expr) - data = struct.pack("l", cons.get_enum_value(target)) - cons.write(index, len(data), data) - -class variable_instance(variable): - def get_code(self): - return ["%s %s;" % (self.subtype, self.name)] - def get_patch_code(self, ptrname, basename): - return ["patch_ptr_%s(&(%s->%s), %s);" % (self.subtype, ptrname, self.name, basename)] - def size(self): - return self.translator.types[self.subtype].size() - def emit_data(self, cons, index, src_data): - target = src_data.find_node(self.expr) - translator.types[self.subtype].emit_data(cons, index, target) - #target = - #cons.add_pointer(index, target) - -class variable_array(variable): - def get_code(self): - return ["long num_%s;" % self.name, - "%s *%s;" % (self.subtype, self.name)] - def get_patch_code(self, ptrname, baseptr): - code = [] - code += ["patch_ptr((char**)&(%s->%s), %s);" % (ptrname, self.name, baseptr)] - code += ["for(int i = 0; i < %s->num_%s; i++)" % (ptrname, self.name)] - code += ["\tpatch_ptr_%s(%s->%s+i, %s);" % (self.subtype, ptrname, self.name, baseptr)] - return code - def emit_data(self, cons, index, src_data): - array_data = src_data.gather(self.expr) - array_type = cons.get_type(self.subtype) - size = array_type.size()*len(array_data) - - #print "packing array", self.name - #print "\ttype =", array_type.name - #print "\tsize =", array_type.size() - array_index = cons.allocate(size) - data = struct.pack("lP", len(array_data), array_index) # TODO: solve this - cons.write(index, len(data), data) - - member_index = array_index - for node in array_data: - cons.add_target(node.get_path()[1:], member_index) - array_type.emit_data(cons, member_index, node) - member_index += array_type.size() - #print "array", member_index - - def size(self): - return option_ptrsize+option_intsize - -class const_arrayint: - def __init__(self): - self.name = "" - self.values = [] - - def emit_header_code(self, out): - print >>out, "enum" - print >>out, "{" - for i in xrange(0, len(self.values)): - print >>out, "\t%s_%s = %d," % (self.name.upper(), self.values[i].upper(), i) - - print >>out, "\tNUM_%sS = %d" % (self.name.upper(), len(self.values)) - print >>out, "};" - print >>out, "" - -class translator: - def __init__(self): - self.types = {} - self.structs = [] - self.constants = [] - self.data = 0 - self.srcdata = 0 - - self.types["int"] = variable_int() - self.types["float"] = variable_float() - self.types["string"] = variable_string() - self.types["ptr"] = variable_ptr() - self.types["array"] = variable_array() - - def parse_variable(self, node): - if len(node.values) != 4: - print node.values - raise "error parsing variable" - - type = node.values[0] - subtype = "" - if type == "int": - v = variable_int() - elif type == "enum": - v = variable_enum() - elif type == "float": - v = variable_float() - elif type == "string": - v = variable_string() - else: - # complex type - parts = type.split(":") - if len(parts) != 2: - raise "can't emit code for variable %s of type %s" % (self.name, self.type) - elif parts[0] == "ptr": - subtype = parts[1] - v = variable_ptr() - elif parts[0] == "instance": - subtype = parts[1] - v = variable_instance() - elif parts[0] == "array": - subtype = parts[1] - v = variable_array() - else: - raise "can't emit code for variable %s of type %s" % (self.name, self.type) - - v.translator = self - v.type = node.values[0] - v.subtype = subtype - v.name = node.values[1] - assignment = node.values[2] - v.expr = node.values[3] - if assignment != "=": - raise "error parsing variable. expected =" - return v - - def parse_struct(self, node): - if len(node.values) != 2: - raise "error parsing struct" - s = structure() - s.name = node.values[1] - - for statement in node.children: - s.members += [self.parse_variable(statement)] - return s - - def parse_constant(self, node): - if len(node.values) != 5: - print node.values - raise "error parsing constant" - - type = node.values[1] - name = node.values[2] - assignment = node.values[3] - expression = node.values[4] - - if assignment != "=": - print node.values - raise "error parsing constant" - - ints = const_arrayint() - ints.name = name - - items = self.srcdata.gather(expression) - for c in items: - ints.values += [c.name()] - self.constants += [ints] - - def parse(self, script, srcdata): - self.srcdata = srcdata - for statement in script.children: - if statement.values[0] == "struct": - s = self.parse_struct(statement) - self.structs += [s] - self.types[s.name] = s - elif statement.values[0] == "const": - self.parse_constant(statement) - else: - raise "unknown statement:" + statement - - def emit_header_code(self, out): - for c in self.constants: - c.emit_header_code(out) - - for s in self.structs: - s.emit_header_code(out) - print >>out, "" - print >>out, "struct data_container *load_data_from_file(const char *filename);" - print >>out, "struct data_container *load_data_from_memory(unsigned char *filename);" - print >>out, "" - - - def emit_source_code(self, out, header_filename): - print >>out, ''' - -#include "%s" -#include -#include - -static void patch_ptr(char **ptr, char *base) -{ - *ptr = base+(size_t)(*ptr); -} -''' % header_filename - - for s in self.structs: - s.emit_source_code(out) - print >>out, ''' - -data_container *load_data_from_memory(unsigned char *mem) -{ - if(mem[0] != sizeof(void*)) - return 0; - if(mem[1] != sizeof(long)) - return 0; - if(mem[2] != sizeof(float)) - return 0; - - /* patch all pointers */ - data_container *con = (data_container*)(mem + 4); - patch_ptr_data_container(con, (char *)con); - return con; -} - -data_container *load_data_from_file(const char *filename) -{ - unsigned char *data = 0; - int size; - - /* open file */ - FILE *f = fopen(filename, "rb"); - - /* get size */ - fseek(f, 0, SEEK_END); - size = ftell(f); - fseek(f, 0, SEEK_SET); - - /* allocate, read data and close file */ - data = (unsigned char *)malloc(size); - fread(data, 1, size, f); - fclose(f); - - return load_data_from_memory(data); -} - -''' - - def emit_data(self): - for s in self.structs: - if s.name == "data_container": - #print "found data_container" - cons = data_constructor() - cons.trans = self - i = cons.allocate(s.size()) - s.emit_data(cons, i, self.srcdata) - cons.patch_pointers() - header = struct.pack("bbbb", option_ptrsize, option_intsize, option_floatsize, 0) - return header + cons.data - -def create_translator(script, srcdata): - t = translator() - t.parse(script, srcdata) - return t - -def validate(script, validator): - def validate_values(values, check): - if not len(check) or check[0] == "*": - print "too many values" - return - p = check[0].split(":") - type = p[0] - name = p[1] - - # TODO: check type and stuff - - # recurse - if len(values) > 1: - if not len(check): - print "unexpected value" - validate_values(values[1:], check[1:]) - else: - if len(check) > 1 and check[1] != "*": - print "to few values" - - if len(script.values): - validate_values(script.values, validator.values) - - for child in script.children: - tag = child.values[0] - n = validator.find_node("tag:"+tag) - if not n: - found = 0 - for vc in validator.children: - if "ident:" in vc.values[0]: - validate(child, vc) - print vc.values[0] - found = 1 - break - - if not found: - print "error:", tag, "not found" - else: - print "tag:"+tag - validate(child, n) - -input_filename = sys.argv[1] -script_filename = sys.argv[2] - -output_filename = 0 -coutput_filename = 0 -header_filename = 0 -source_filename = 0 -sheader_filename = 0 - -if sys.argv[3] == '-h': - header_filename = sys.argv[4] -elif sys.argv[3] == '-s': - source_filename = sys.argv[4] - sheader_filename = sys.argv[5] -elif sys.argv[3] == '-d': - output_filename = sys.argv[4] -elif sys.argv[3] == '-c': - coutput_filename = sys.argv[4] - -srcdata = parse_file(input_filename) -script = parse_file(script_filename) - -translator = create_translator(script, srcdata) - -if header_filename: - translator.emit_header_code(file(header_filename, "w")) -if source_filename: - translator.emit_source_code(file(source_filename, "w"), os.path.basename(sheader_filename)) - -if output_filename: - rawdata = translator.emit_data() - file(output_filename, "wb").write(rawdata) -if coutput_filename: - i = 0 - rawdata = translator.emit_data() - f = file(coutput_filename, "w") - - print >>f,"unsigned char internal_data[] = {" - print >>f,str(ord(rawdata[0])), - for d in rawdata[1:]: - s = ","+str(ord(d)) - print >>f,s, - i += len(s)+1 - - if i >= 70: - print >>f,"" - i = 0 - print >>f,"" - print >>f,"};" - print >>f,"" - f.close() From ceced3f72e0e2537f32a9afda0a2f95b29fdd944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 10 Feb 2020 12:04:33 +0100 Subject: [PATCH 182/479] add *.vcxproj and *.vcxproj.filters to .gitignore (VS 2015 generated project files) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 018e9f28..c98c3d12 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ versionsrv* .settings .vs .vscode +*.vcxproj +*.vcxproj.filters compile_commands.json cscope.files cscope.out From d360629bd5b6163bbd7c67d734c3a7194ba86838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 10 Feb 2020 17:52:10 +0100 Subject: [PATCH 183/479] remove unnecessary MapScreen (RenderBackground already does) --- src/game/client/components/menus.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index a38099c2..8da810de 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1249,11 +1249,9 @@ void CMenus::RenderLoading(int WorkedAmount) s_LastLoadRender = time_get(); - CUIRect Screen = *UI()->Screen(); - Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); - RenderBackground(); + CUIRect Screen = *UI()->Screen(); float w = 700; float h = 200; float x = Screen.w/2-w/2; From afda8d5923c60fa381de9c5f912579d74b5cad17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 10 Feb 2020 18:02:09 +0100 Subject: [PATCH 184/479] fix background checkers not animated on loading screen because local time not running --- src/game/client/components/menus.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8da810de..11cfb6a9 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2502,7 +2502,8 @@ void CMenus::RenderBackground() Graphics()->TextureClear(); Graphics()->QuadsBegin(); float Size = 15.0f; - float OffsetTime = fmod(Client()->LocalTime()*0.15f, 2.0f); + static int64 s_MenuBackgroundStart = time_get(); + float OffsetTime = fmod((time_get()-s_MenuBackgroundStart)*0.15f/time_freq(), 2.0f); for(int y = -2; y < (int)(sw/Size); y++) for(int x = -2; x < (int)(sh/Size); x++) { From dc9a7174073e32330e3c114717b09f60f855bb7c Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 12 Feb 2020 17:06:58 +0100 Subject: [PATCH 185/479] fixed text colour reset. closes # 2466 --- src/game/client/components/chat.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 4a6f5463..77a2d161 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1458,6 +1458,7 @@ void CChat::HandleCommands(float x, float y, float w) TextRender()->TextEx(&Cursor, Localize("Press Enter to confirm or Esc to cancel"), -1); else TextRender()->TextEx(&Cursor, Localize("Press Tab to select or Esc to cancel"), -1); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } } } From 10128dadb8e029d8fb1cf340ebfc168c56add92f Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 12 Feb 2020 17:32:59 +0100 Subject: [PATCH 186/479] moved a function --- src/base/system.c | 10 ++++++++++ src/base/system.h | 15 +++++++++++++++ src/engine/server/server.cpp | 2 +- src/engine/shared/netban.cpp | 14 +------------- src/engine/shared/netban.h | 3 --- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 75485921..080ae13f 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2275,6 +2275,16 @@ void str_hex(char *dst, int dst_size, const void *data, int data_size) } } +int str_is_number(const char *str) +{ + while(*str) + { + if(!(*str >= '0' && *str <= '9')) + return -1; + str++; + } + return 0; +} #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" diff --git a/src/base/system.h b/src/base/system.h index 83c3b7da..65ce0245 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1248,6 +1248,21 @@ const char *str_find(const char *haystack, const char *needle); */ void str_hex(char *dst, int dst_size, const void *data, int data_size); +/* + Function: str_is_number + Check if the string contains only digits. + + Parameters: + str - String to check. + + Returns: + Returns 0 if it's a number, -1 otherwise. + + Remarks: + - The strings are treated as zero-terminated strings. +*/ +int str_is_number(const char *pstr); + /* Function: str_timestamp Copies a time stamp in the format year-month-day_hour-minute-second to the string. diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 1e6fb8d0..da886374 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -239,7 +239,7 @@ void CServerBan::ConBanExt(IConsole::IResult *pResult, void *pUser) 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)) + if(!str_is_number(pStr)) { int ClientID = str_toint(pStr); if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->Server()->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY) diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index a82440d9..6b27616d 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -7,18 +7,6 @@ #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) @@ -535,7 +523,7 @@ void CNetBan::ConUnban(IConsole::IResult *pResult, void *pUser) str_copy(aBuf, pResult->GetString(0), sizeof(aBuf)); const char *pSeparator = str_find(aBuf, "-"); - if(StrAllnum(aBuf)) + if(!str_is_number(aBuf)) { pThis->UnbanByIndex(str_toint(aBuf)); } diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h index 31e9b0da..2d35fe01 100644 --- a/src/engine/shared/netban.h +++ b/src/engine/shared/netban.h @@ -60,9 +60,6 @@ class CNetBan return pBuffer; } - // todo: move? - static bool StrAllnum(const char *pStr); - class CNetHash { public: From fb3f76d087b643bf6d132133e9f34e5d3c7a7706 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 12 Feb 2020 17:48:28 +0100 Subject: [PATCH 187/479] removed a static variable --- src/engine/shared/network.cpp | 12 ++++++------ src/engine/shared/network.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 88079f40..59fcac53 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -119,6 +119,7 @@ void CNetBase::Init(NETSOCKET Socket, CConfig *pConfig, IConsole *pConsole, IEng m_pConfig = pConfig; m_pEngine = pEngine; m_Huffman.Init(); + mem_zero(m_aRequestTokenBuf, sizeof(m_aRequestTokenBuf)); if(pEngine) pConsole->Chain("dbg_lognetwork", ConchainDbgLognetwork, this); } @@ -364,12 +365,11 @@ void CNetBase::SendControlMsgWithToken(const NETADDR *pAddr, TOKEN Token, int Ac dbg_assert((Token&~NET_TOKEN_MASK) == 0, "token out of range"); dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range"); - static unsigned char aBuf[NET_TOKENREQUEST_DATASIZE] = { 0 }; - aBuf[0] = (MyToken>>24)&0xff; - aBuf[1] = (MyToken>>16)&0xff; - aBuf[2] = (MyToken>>8)&0xff; - aBuf[3] = (MyToken)&0xff; - SendControlMsg(pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4); + m_aRequestTokenBuf[0] = (MyToken>>24)&0xff; + m_aRequestTokenBuf[1] = (MyToken>>16)&0xff; + m_aRequestTokenBuf[2] = (MyToken>>8)&0xff; + m_aRequestTokenBuf[3] = (MyToken)&0xff; + SendControlMsg(pAddr, Token, 0, ControlMsg, m_aRequestTokenBuf, Extended ? sizeof(m_aRequestTokenBuf) : 4); } unsigned char *CNetChunkHeader::Pack(unsigned char *pData) diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 3294ea5b..ebf8a13b 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -206,6 +206,7 @@ class CNetBase IOHANDLE m_DataLogSent; IOHANDLE m_DataLogRecv; CHuffman m_Huffman; + unsigned char m_aRequestTokenBuf[NET_TOKENREQUEST_DATASIZE]; public: CNetBase(); From c08acbe115fc9e88d1ab8ea39a47651264a08ba9 Mon Sep 17 00:00:00 2001 From: yangfl Date: Tue, 10 Jul 2018 17:29:02 +0800 Subject: [PATCH 188/479] Fix typo (cherry picked from commit https://github.com/ddnet/ddnet/commit/81a39c229b47adfb19062e672d28680082b1459a) --- scripts/gen_keys.py | 2 +- src/base/hash_libtomcrypt.c | 2 +- src/base/system.h | 30 +++++++++++++-------------- src/base/tl/array.h | 2 +- src/engine/client.h | 2 +- src/engine/client/backend_sdl.h | 2 +- src/engine/client/sound.cpp | 2 +- src/engine/docs/prediction.txt | 2 +- src/engine/docs/snapshots.txt | 2 +- src/engine/external/important.txt | 2 +- src/engine/kernel.h | 2 +- src/engine/server/server.cpp | 6 +++--- src/engine/server/server.h | 2 +- src/engine/shared/netban.cpp | 2 +- src/engine/shared/network_conn.cpp | 2 +- src/engine/shared/protocol.h | 4 ++-- src/engine/shared/ringbuffer.cpp | 2 +- src/game/client/components/chat.cpp | 2 +- src/game/client/components/items.cpp | 2 +- src/game/client/components/sounds.cpp | 2 +- src/game/client/gameclient.cpp | 2 +- src/game/editor/editor.cpp | 2 +- 22 files changed, 39 insertions(+), 39 deletions(-) diff --git a/scripts/gen_keys.py b/scripts/gen_keys.py index 3325f27c..f1c2cfd8 100644 --- a/scripts/gen_keys.py +++ b/scripts/gen_keys.py @@ -1,6 +1,6 @@ import sys, os -# genereate keys.h file +# generate keys.h file f = file("src/engine/keys.h", "w") keynames = [] diff --git a/src/base/hash_libtomcrypt.c b/src/base/hash_libtomcrypt.c index 7482bcd1..50bf770d 100755 --- a/src/base/hash_libtomcrypt.c +++ b/src/base/hash_libtomcrypt.c @@ -169,7 +169,7 @@ static void sha_done(sha256_state* md, void* out) md->curlen = 0; } - // Pad upto 56 bytes of zeroes + // Pad up to 56 bytes of zeroes while(md->curlen < 56) md->buf[md->curlen++] = 0; diff --git a/src/base/system.h b/src/base/system.h index 65ce0245..8743de4b 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -225,7 +225,7 @@ IOHANDLE io_open(const char *filename, int flags); Parameters: io - Handle to the file to read data from. - buffer - Pointer to the buffer that will recive the data. + buffer - Pointer to the buffer that will receive the data. size - Number of bytes to read from the file. Returns: @@ -528,7 +528,7 @@ int64 time_freq(); /* Function: time_timestamp - Retrives the current time as a UNIX timestamp + Retrieves the current time as a UNIX timestamp Returns: The time as a UNIX timestamp @@ -600,7 +600,7 @@ typedef struct void net_invalidate_socket(NETSOCKET *socket); /* Function: net_init - Initiates network functionallity. + Initiates network functionality. Returns: Returns 0 on success, @@ -699,13 +699,13 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size /* Function: net_udp_recv - Recives a packet over an UDP socket. + Receives a packet over an UDP socket. Parameters: sock - Socket to use. - addr - Pointer to an NETADDR that will recive the address. - data - Pointer to a buffer that will recive the data. - maxsize - Maximum size to recive. + addr - Pointer to an NETADDR that will receive the address. + data - Pointer to a buffer that will receive the data. + maxsize - Maximum size to receive. Returns: On success it returns the number of bytes recived. Returns -1 @@ -886,18 +886,18 @@ int str_length(const char *str); /* Function: str_format - Performs printf formating into a buffer. + Performs printf formatting into a buffer. Parameters: - buffer - Pointer to the buffer to recive the formated string. + buffer - Pointer to the buffer to receive the formatted string. buffer_size - Size of the buffer. - format - printf formating string. - ... - Parameters for the formating. + format - printf formatting string. + ... - Parameters for the formatting. Remarks: - - See the C manual for syntax for the printf formating string. - - The strings are treated as zero-terminated strings. - - Garantees that dst string will contain zero-termination. + - See the C manual for syntax for the printf formatting string. + - The strings are treated as zero-termineted strings. + - Guarantees that dst string will contain zero-termination. */ void str_format(char *buffer, int buffer_size, const char *format, ...) GNUC_ATTRIBUTE((format(printf, 3, 4))); @@ -1244,7 +1244,7 @@ const char *str_find(const char *haystack, const char *needle); data - Size of the data Remarks: - - The desination buffer will be zero-terminated + - The destination buffer will be zero-terminated */ void str_hex(char *dst, int dst_size, const void *data, int data_size); diff --git a/src/base/tl/array.h b/src/base/tl/array.h index 230e5210..2040be22 100644 --- a/src/base/tl/array.h +++ b/src/base/tl/array.h @@ -268,7 +268,7 @@ class array : private ALLOCATOR /* Function: optimize - Removes unnessasary data, returns how many bytes was earned. + Removes unnecessary data, returns how many bytes was earned. Remarks: - Invalidates ranges diff --git a/src/engine/client.h b/src/engine/client.h index cd9f684e..7ca62011 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -46,7 +46,7 @@ class IClient : public IInterface STATE_LOADING - The client has connected to a server and is loading resources. STATE_ONLINE - The client is connected to a server and running the game. STATE_DEMOPLAYBACK - The client is playing a demo - STATE_QUITING - The client is quiting. + STATE_QUITING - The client is quitting. */ enum diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h index 1f3647b8..6e64123c 100644 --- a/src/engine/client/backend_sdl.h +++ b/src/engine/client/backend_sdl.h @@ -42,7 +42,7 @@ class CGraphicsBackend_Threaded : public IGraphicsBackend { public: - // constructed on the main thread, the rest of the functions is runned on the render thread + // constructed on the main thread, the rest of the functions is run on the render thread class ICommandProcessor { public: diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 39b1bb68..f5c126c7 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -312,7 +312,7 @@ void CSound::RateConvert(int SampleID) for(int i = 0; i < NumFrames; i++) { - // resample TODO: this should be done better, like linear atleast + // resample TODO: this should be done better, like linear at least float a = i/(float)NumFrames; int f = (int)(a*pSample->m_NumFrames); if(f >= pSample->m_NumFrames) diff --git a/src/engine/docs/prediction.txt b/src/engine/docs/prediction.txt index e740b1e8..637c5596 100644 --- a/src/engine/docs/prediction.txt +++ b/src/engine/docs/prediction.txt @@ -2,7 +2,7 @@ Title: Prediction The engine calls when reprediction is required. This happens usally when new data has arrived from the server. should to prediction from the current snapshot and current snapshot tick ( + 1) upto and including the tick returned by . -Predicted input sent to the server can be retrived by calling with the corresponding tick that you want the input for. Here is a simple example of how it might look. +Predicted input sent to the server can be retrieved by calling with the corresponding tick that you want the input for. Here is a simple example of how it might look. > void modc_predict() > { diff --git a/src/engine/docs/snapshots.txt b/src/engine/docs/snapshots.txt index 46ee3105..35dd5852 100644 --- a/src/engine/docs/snapshots.txt +++ b/src/engine/docs/snapshots.txt @@ -4,7 +4,7 @@ Section: Overview Topic: Definitions -- *Snapshot*. A is a serialized game state from which a client can render the game from. They are sent from the server at a regular interval and is created specificly for each client in order to reduce bandwidth. +- *Snapshot*. A is a serialized game state from which a client can render the game from. They are sent from the server at a regular interval and is created specifically for each client in order to reduce bandwidth. - *Delta Snapshot*. A set of data that can be applied to a snapshot in order to create a new snapshot with the updated game state. Topic: Structure diff --git a/src/engine/external/important.txt b/src/engine/external/important.txt index 305ccadc..41b9c6a1 100644 --- a/src/engine/external/important.txt +++ b/src/engine/external/important.txt @@ -1,5 +1,5 @@ The source code under this directory are external libraries with their own licences. The source you find here is stripped -of unnessesary information. Please visit their websites for +of unnecessary information. Please visit their websites for more information and official releases. diff --git a/src/engine/kernel.h b/src/engine/kernel.h index b5961bc3..de3696db 100644 --- a/src/engine/kernel.h +++ b/src/engine/kernel.h @@ -44,7 +44,7 @@ class IKernel static IKernel *Create(); virtual ~IKernel() {} - // templated access to handle pointer convertions and interface names + // templated access to handle pointer conversions and interface names template bool RegisterInterface(TINTERFACE *pInterface) { diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index da886374..86911427 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -124,7 +124,7 @@ void CSnapIDPool::FreeID(int ID) { if(ID < 0) return; - dbg_assert(m_aIDs[ID].m_State == 1, "id is not alloced"); + dbg_assert(m_aIDs[ID].m_State == 1, "id is not allocated"); m_InUsage--; m_aIDs[ID].m_State = 2; @@ -551,7 +551,7 @@ void CServer::DoSnapshot() // create snapshots for all clients for(int i = 0; i < MAX_CLIENTS; i++) { - // client must be ingame to recive snapshots + // client must be ingame to receive snapshots if(m_aClients[i].m_State != CClient::STATE_INGAME) continue; @@ -591,7 +591,7 @@ void CServer::DoSnapshot() // save it the snapshot m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0); - // find snapshot that we can preform delta against + // find snapshot that we can perform delta against EmptySnap.Clear(); { diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 6bdb468d..7e8d3415 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -17,7 +17,7 @@ class CSnapIDPool { public: short m_Next; - short m_State; // 0 = free, 1 = alloced, 2 = timed + short m_State; // 0 = free, 1 = allocated, 2 = timed int m_Timeout; }; diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index 6b27616d..7a5d5f5a 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -460,7 +460,7 @@ bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize, in CNetHash aHash[17]; int Length = CNetHash::MakeHashArray(pAddr, aHash); - // check ban adresses + // check ban addresses CBanAddr *pBan = m_BanAddrPool.Find(pAddr, &aHash[Length]); if(pBan) { diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index f7f8dfec..8e3bfd1d 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -398,7 +398,7 @@ int CNetConnection::Update() } else { - // resend packet if we havn't got it acked in 1 second + // resend packet if we haven't got it acked in 1 second if(Now-pResend->m_LastSendTime > time_freq()) ResendChunk(pResend); } diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index 145474bd..bfdec29e 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -6,7 +6,7 @@ #include /* - Connection diagram - How the initilization works. + Connection diagram - How the initialization works. Client -> INFO -> Server Contains version info, name, and some other info. @@ -20,7 +20,7 @@ modc_connected is called on the client and mods_connected is called on the server. The client should call client_entergame when the - mod has done it's initilization. + mod has done it's initialization. Client -> ENTERGAME -> Server Tells the server to start sending snapshots. diff --git a/src/engine/shared/ringbuffer.cpp b/src/engine/shared/ringbuffer.cpp index b9f55d73..a164a83e 100644 --- a/src/engine/shared/ringbuffer.cpp +++ b/src/engine/shared/ringbuffer.cpp @@ -145,7 +145,7 @@ int CRingBufferBase::PopFirst() m_pConsume = NextBlock(m_pConsume); } - // in the case that we have catched up with the produce pointer + // in the case that we have caught up with the produce pointer // we might stand on a free block so merge em MergeBack(m_pConsume); return 1; diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 77a2d161..bc250bc5 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -607,7 +607,7 @@ void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) while(*p) { pLine = p; - // find line seperator and strip multiline + // find line separator and strip multiline while(*p) { if(*p++ == '\n') diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 1bf67eb2..e6560f5e 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -41,7 +41,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) 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 + return; // projectile haven't been shot yet vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 0acb9c56..bdbcc89f 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -113,7 +113,7 @@ void CSounds::OnRender() return; } - // set listner pos + // set listener pos vec2 Pos = *m_pClient->m_pCamera->GetCenter(); Sound()->SetListenerPos(Pos.x, Pos.y); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 5e203c27..24f36460 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -88,7 +88,7 @@ void FormatTimeDiff(char *pBuf, int Size, int Time, int Precision, bool ForceSig AppendDecimals(pBuf, Size, Time, Precision); } -// instanciate all systems +// instantiate all systems static CInfoMessages gs_InfoMessages; static CCamera gs_Camera; static CChat gs_Chat; diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 9becd3e2..0054ce63 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -920,7 +920,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) // tile info button TB_Top.VSplitLeft(40.0f, &Button, &TB_Top); static int s_TileInfoButton = 0; - if(DoButton_Editor(&s_TileInfoButton, "Info", m_ShowTileInfo, &Button, 0, "[ctrl+i] Show tile informations") || + if(DoButton_Editor(&s_TileInfoButton, "Info", m_ShowTileInfo, &Button, 0, "[ctrl+i] Show tile information") || (Input()->KeyPress(KEY_I) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) { m_ShowTileInfo = !m_ShowTileInfo; From 473358ac5abf1928976a45249002c0abb94676ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 13 Feb 2020 17:54:07 +0100 Subject: [PATCH 189/479] only call time_get once in RenderLoading, move Clear --- src/game/client/components/menus.cpp | 26 ++++++++++++++------------ src/game/client/components/menus.h | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 11cfb6a9..5ab821be 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1234,22 +1234,28 @@ void CMenus::RenderLoading(int WorkedAmount) { static int64 s_LastLoadRender = 0; m_LoadCurrent += WorkedAmount; + const int64 Now = time_get(); + const float Freq = time_freq(); if(Config()->m_Debug) { char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "progress: %03d/%03d (+%02d) %dms", m_LoadCurrent, m_LoadTotal, WorkedAmount, s_LastLoadRender == 0 ? 0 : int((time_get()-s_LastLoadRender)*1000.0f/time_freq())); + str_format(aBuf, sizeof(aBuf), "progress: %03d/%03d (+%02d) %dms", m_LoadCurrent, m_LoadTotal, WorkedAmount, s_LastLoadRender == 0 ? 0 : int((Now-s_LastLoadRender)*1000.0f/Freq)); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "loading", aBuf); } // make sure that we don't render for each little thing we load // because that will slow down loading if we have vsync - if(s_LastLoadRender > 0 && time_get()-s_LastLoadRender < time_freq()/60) + if(s_LastLoadRender > 0 && Now-s_LastLoadRender < Freq/60) + return; + if(!Graphics()->IsIdle()) return; - s_LastLoadRender = time_get(); + s_LastLoadRender = Now; + static int64 s_LoadingStart = Now; - RenderBackground(); + Graphics()->Clear(0.45f, 0.45f, 0.45f); + RenderBackground((Now-s_LoadingStart)/Freq); CUIRect Screen = *UI()->Screen(); float w = 700; @@ -1521,7 +1527,7 @@ int CMenus::Render() // render background only if needed if(Client()->State() != IClient::STATE_ONLINE && !m_pClient->m_pMapLayersBackGround->MenuMapLoaded()) - RenderBackground(); + RenderBackground(Client()->LocalTime()); CUIRect TabBar, MainView; @@ -2466,7 +2472,7 @@ void CMenus::OnRender() CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); - char aBuf[512]; + char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->GetActiveItem(), UI()->LastActiveItem()); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, 10, 10, 10, TEXTFLAG_RENDER); @@ -2489,11 +2495,8 @@ bool CMenus::CheckHotKey(int Key) const Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } -void CMenus::RenderBackground() +void CMenus::RenderBackground(float Time) { - // render background color - Graphics()->Clear(0.45f, 0.45f, 0.45f); - float sw = 300*Graphics()->ScreenAspect(); float sh = 300; Graphics()->MapScreen(0, 0, sw, sh); @@ -2502,8 +2505,7 @@ void CMenus::RenderBackground() Graphics()->TextureClear(); Graphics()->QuadsBegin(); float Size = 15.0f; - static int64 s_MenuBackgroundStart = time_get(); - float OffsetTime = fmod((time_get()-s_MenuBackgroundStart)*0.15f/time_freq(), 2.0f); + float OffsetTime = fmod(Time*0.15f, 2.0f); for(int y = -2; y < (int)(sw/Size); y++) for(int x = -2; x < (int)(sh/Size); x++) { diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index c4aad0a1..52bf6877 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -772,7 +772,7 @@ class CMenus : public CComponent bool CheckHotKey(int Key) const; - void RenderBackground(); + void RenderBackground(float Time); void RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom); public: void InitLoading(int TotalWorkAmount); From a020a9fea00e1c63b5e0b5e5de1467ecaea9e5c6 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 13 Feb 2020 18:17:22 +0100 Subject: [PATCH 190/479] made a variable non static --- src/engine/shared/network_token.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index 13e4b5b0..ca71bd71 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -259,7 +259,7 @@ void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag) bool Found = false; while(pInfo) { - static NETADDR NullAddr = { 0 }; + NETADDR NullAddr = { 0 }; NullAddr.type = 7; // cover broadcasts NullAddr.port = pAddr->port; if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || ((TokenFLag&NET_TOKENFLAG_ALLOWBROADCAST) && net_addr_comp(&pInfo->m_Addr, &NullAddr) == 0)) From e8aa6010444a75dce26a432d8b58ffbf922b1089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 17 Feb 2020 17:59:28 +0100 Subject: [PATCH 191/479] remove declaration of unused font_debug_render --- src/game/client/components/menus.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 5ab821be..0c61dbc7 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2391,8 +2391,6 @@ void CMenus::OnStateChange(int NewState, int OldState) } } -extern "C" void font_debug_render(); - void CMenus::OnRender() { UI()->StartCheck(); From bd4ff14fdd7a1bb20c4e46badbe611f644b32e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 17 Feb 2020 18:15:32 +0100 Subject: [PATCH 192/479] add early exit to some render methods only used when online --- src/game/client/components/broadcast.cpp | 3 +++ src/game/client/components/chat.cpp | 2 +- src/game/client/components/emoticon.cpp | 7 +++++++ src/game/client/components/infomessages.cpp | 2 +- src/game/client/components/nameplates.cpp | 2 +- src/game/client/components/particles.cpp | 10 +++++----- src/game/client/components/players.cpp | 3 +++ 7 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index d9dc1c78..11b6f3d3 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -422,6 +422,9 @@ void CBroadcast::OnMessage(int MsgType, void* pRawMsg) void CBroadcast::OnRender() { + if(Client()->State() < IClient::STATE_ONLINE) + return; + // server broadcast RenderServerBroadcast(); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 77a2d161..714840f6 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -737,7 +737,7 @@ const char* CChat::GetCommandName(int Mode) const void CChat::OnRender() { - if(Client()->State() <= Client()->STATE_LOADING) + if(Client()->State() < IClient::STATE_ONLINE) return; // send pending chat messages diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index 6ad0a8c6..91f4eda7 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -93,6 +93,13 @@ void CEmoticon::DrawCircle(float x, float y, float r, int Segments) void CEmoticon::OnRender() { + if(Client()->State() < IClient::STATE_ONLINE) + { + m_Active = false; + m_WasActive = false; + return; + } + if(!m_Active) { if(m_WasActive && m_SelectedEmote != -1) diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index 6ee3ac0b..84fa81f5 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -141,7 +141,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) void CInfoMessages::OnRender() { - if(!Config()->m_ClShowhud) + if(!Config()->m_ClShowhud || Client()->State() < IClient::STATE_ONLINE) return; float Width = 400*3.0f*Graphics()->ScreenAspect(); diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 7220c4f8..120af70c 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -71,7 +71,7 @@ void CNamePlates::RenderNameplate( void CNamePlates::OnRender() { - if (!Config()->m_ClNameplates) + if (!Config()->m_ClNameplates || Client()->State() < IClient::STATE_ONLINE) return; for(int i = 0; i < MAX_CLIENTS; i++) diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index 56132054..c9af6343 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -137,22 +137,22 @@ void CParticles::OnRender() if(Client()->State() < IClient::STATE_ONLINE) return; - static int64 LastTime = 0; - int64 t = time_get(); + static int64 s_LastTime = 0; + int64 Now = time_get(); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(!pInfo->m_Paused) - Update((float)((t-LastTime)/(double)time_freq())*pInfo->m_Speed); + Update((float)((Now-s_LastTime)/(double)time_freq())*pInfo->m_Speed); } else { if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) - Update((float)((t-LastTime)/(double)time_freq())); + Update((float)((Now-s_LastTime)/(double)time_freq())); } - LastTime = t; + s_LastTime = Now; } void CParticles::RenderGroup(int Group) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index a28f28bc..94bf9512 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -483,6 +483,9 @@ void CPlayers::RenderPlayer( void CPlayers::OnRender() { + if(Client()->State() < IClient::STATE_ONLINE) + return; + // update RenderInfo for ninja bool IsTeamplay = (m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) != 0; for(int i = 0; i < MAX_CLIENTS; ++i) From f354d1c7e0235f3872687c285b63a50d86006f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 17 Feb 2020 18:35:27 +0100 Subject: [PATCH 193/479] fix high LAN latency (maybe also missing servers) on first refresh --- src/game/client/components/menus.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0c61dbc7..07fee3a7 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1513,16 +1513,23 @@ int CMenus::Render() CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); - static bool s_First = true; - if(s_First) + static int s_InitTick = 5; + if(s_InitTick > 0) { - // refresh server browser before we are in browser menu to save time - m_pClient->m_pCamera->ChangePosition(CCamera::POS_START); - ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); - ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); - - UpdateMusicState(); - s_First = false; + s_InitTick--; + if(s_InitTick == 4) + { + m_pClient->m_pCamera->ChangePosition(CCamera::POS_START); + UpdateMusicState(); + } + else if(s_InitTick == 0) + { + // Wait a few frames before refreshing server browser, + // else the increased rendering time at startup prevents + // the network from being pumped effectively. + ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); + ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); + } } // render background only if needed From 2272325e7325cc398d5a2a2a85d7acf0ed40db8e Mon Sep 17 00:00:00 2001 From: Learath Date: Mon, 24 Feb 2020 01:34:13 +0300 Subject: [PATCH 194/479] Fix #2476 --- src/engine/shared/network.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 59fcac53..157a66a8 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -34,6 +34,13 @@ void CNetRecvUnpacker::Start(const NETADDR *pAddr, CNetConnection *pConnection, // TODO: rename this function int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) { + // Don't bother with connections that already went offline + if(m_pConnection && m_pConnection->State() != NET_CONNSTATE_ONLINE) + { + Clear(); + return 0; + } + CNetChunkHeader Header; unsigned char *pEnd = m_Data.m_aChunkData + m_Data.m_DataSize; @@ -300,7 +307,7 @@ int CNetBase::UnpackPacket(NETADDR *pAddr, unsigned char *pBuffer, CNetPacketCon pPacket->m_Token = (pBuffer[3] << 24) | (pBuffer[4] << 16) | (pBuffer[5] << 8) | pBuffer[6]; // TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT pPacket->m_ResponseToken = NET_TOKEN_NONE; - + if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION) pPacket->m_DataSize = m_Huffman.Decompress(&pBuffer[NET_PACKETHEADERSIZE], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData)); else From d03c1f2a4b67129cb6393ba4943781ae4c73aba2 Mon Sep 17 00:00:00 2001 From: nheir Date: Mon, 20 Jan 2020 22:10:42 +0100 Subject: [PATCH 195/479] mitigate weak hook --- src/game/gamecore.cpp | 13 ++++++++----- src/game/gamecore.h | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index ee05c538..23f42974 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -65,6 +65,7 @@ void CCharacterCore::Reset() { m_Pos = vec2(0,0); m_Vel = vec2(0,0); + m_InteractVel = vec2(0,0); m_HookPos = vec2(0,0); m_HookDir = vec2(0,0); m_HookTick = 0; @@ -326,15 +327,12 @@ void CCharacterCore::Tick(bool UseInput) if(Distance > PhysSize*1.50f) // TODO: fix tweakable variable { float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (Distance/m_pWorld->m_Tuning.m_HookLength); - float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; // add force to the hooked player - pCharCore->m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.x, Accel*Dir.x*1.5f); - pCharCore->m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.y, Accel*Dir.y*1.5f); + pCharCore->m_InteractVel += Dir*Accel*1.5f; // add a little bit force to the guy who has the grip - m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -Accel*Dir.x*0.25f); - m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -Accel*Dir.y*0.25f); + m_InteractVel -= Dir*Accel*0.25f; } } } @@ -353,6 +351,11 @@ void CCharacterCore::Move() float PhysSize = 28.0f; float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); + float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; + m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, m_InteractVel.x); + m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, m_InteractVel.y); + m_InteractVel = vec2(0,0); + m_Vel.x = m_Vel.x*RampValue; vec2 NewPos = m_Pos; diff --git a/src/game/gamecore.h b/src/game/gamecore.h index b40237d9..03693335 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -150,6 +150,8 @@ class CCharacterCore vec2 m_Pos; vec2 m_Vel; + vec2 m_InteractVel; + vec2 m_HookPos; vec2 m_HookDir; int m_HookTick; From 241f62c3e405ae13546f14b7cdb3933fe2740b69 Mon Sep 17 00:00:00 2001 From: nheir Date: Mon, 24 Feb 2020 13:18:28 +0100 Subject: [PATCH 196/479] ignore dragging force when firing ninja --- src/game/gamecore.cpp | 10 ++++++++-- src/game/gamecore.h | 1 + src/game/server/entities/character.cpp | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index 23f42974..02b18743 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -65,6 +65,7 @@ void CCharacterCore::Reset() { m_Pos = vec2(0,0); m_Vel = vec2(0,0); + m_IgnoreInteractVel = false; m_InteractVel = vec2(0,0); m_HookPos = vec2(0,0); m_HookDir = vec2(0,0); @@ -351,9 +352,14 @@ void CCharacterCore::Move() float PhysSize = 28.0f; float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); + // Apply hook interaction velocity float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; - m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, m_InteractVel.x); - m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, m_InteractVel.y); + if (!m_IgnoreInteractVel) + { + m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, m_InteractVel.x); + m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, m_InteractVel.y); + } + m_IgnoreInteractVel = false; m_InteractVel = vec2(0,0); m_Vel.x = m_Vel.x*RampValue; diff --git a/src/game/gamecore.h b/src/game/gamecore.h index 03693335..5286aada 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -150,6 +150,7 @@ class CCharacterCore vec2 m_Pos; vec2 m_Vel; + bool m_IgnoreInteractVel; vec2 m_InteractVel; vec2 m_HookPos; diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 4d170dac..8fa1d785 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -154,6 +154,9 @@ void CCharacter::HandleNinja() // reset velocity so the client doesn't predict stuff m_Core.m_Vel = vec2(0.f, 0.f); + // ignore other player hook + m_Core.m_IgnoreInteractVel = true; + // check if we Hit anything along the way { CCharacter *aEnts[MAX_CLIENTS]; From 25e9ce40585b3659aad0d22eb779e8973723b9cf Mon Sep 17 00:00:00 2001 From: nheir Date: Mon, 24 Feb 2020 15:44:41 +0100 Subject: [PATCH 197/479] move drag velocity to CCharacter::TickDiffered --- src/game/gamecore.cpp | 31 ++++++++++++++------------ src/game/gamecore.h | 6 +++-- src/game/server/entities/character.cpp | 7 +++--- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index 02b18743..189502fa 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -65,8 +65,7 @@ void CCharacterCore::Reset() { m_Pos = vec2(0,0); m_Vel = vec2(0,0); - m_IgnoreInteractVel = false; - m_InteractVel = vec2(0,0); + m_HookDragVel = vec2(0,0); m_HookPos = vec2(0,0); m_HookDir = vec2(0,0); m_HookTick = 0; @@ -330,10 +329,10 @@ void CCharacterCore::Tick(bool UseInput) float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (Distance/m_pWorld->m_Tuning.m_HookLength); // add force to the hooked player - pCharCore->m_InteractVel += Dir*Accel*1.5f; + pCharCore->m_HookDragVel += Dir*Accel*1.5f; // add a little bit force to the guy who has the grip - m_InteractVel -= Dir*Accel*0.25f; + m_HookDragVel -= Dir*Accel*0.25f; } } } @@ -344,6 +343,20 @@ void CCharacterCore::Tick(bool UseInput) m_Vel = normalize(m_Vel) * 6000; } +void CCharacterCore::AddDragVelocity() +{ + // Apply hook interaction velocity + float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; + + m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, m_HookDragVel.x); + m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, m_HookDragVel.y); +} + +void CCharacterCore::ResetDragVelocity() +{ + m_HookDragVel = vec2(0,0); +} + void CCharacterCore::Move() { if(!m_pWorld) @@ -352,16 +365,6 @@ void CCharacterCore::Move() float PhysSize = 28.0f; float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); - // Apply hook interaction velocity - float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; - if (!m_IgnoreInteractVel) - { - m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, m_InteractVel.x); - m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, m_InteractVel.y); - } - m_IgnoreInteractVel = false; - m_InteractVel = vec2(0,0); - m_Vel.x = m_Vel.x*RampValue; vec2 NewPos = m_Pos; diff --git a/src/game/gamecore.h b/src/game/gamecore.h index 5286aada..dfbb8dbe 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -150,8 +150,7 @@ class CCharacterCore vec2 m_Pos; vec2 m_Vel; - bool m_IgnoreInteractVel; - vec2 m_InteractVel; + vec2 m_HookDragVel; vec2 m_HookPos; vec2 m_HookDir; @@ -175,6 +174,9 @@ class CCharacterCore void Tick(bool UseInput); void Move(); + void AddDragVelocity(); + void ResetDragVelocity(); + void Read(const CNetObj_CharacterCore *pObjCore); void Write(CNetObj_CharacterCore *pObjCore); void Quantize(); diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 8fa1d785..9141c81e 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -154,9 +154,6 @@ void CCharacter::HandleNinja() // reset velocity so the client doesn't predict stuff m_Core.m_Vel = vec2(0.f, 0.f); - // ignore other player hook - m_Core.m_IgnoreInteractVel = true; - // check if we Hit anything along the way { CCharacter *aEnts[MAX_CLIENTS]; @@ -559,6 +556,10 @@ void CCharacter::TickDefered() m_ReckoningCore.Quantize(); } + if(m_ActiveWeapon != WEAPON_NINJA || m_Ninja.m_CurrentMoveTime < 0) + m_Core.AddDragVelocity(); + m_Core.ResetDragVelocity(); + //lastsentcore vec2 StartPos = m_Core.m_Pos; vec2 StartVel = m_Core.m_Vel; From a04a33e29d26ee0701c1ed31843d1274f412b7b5 Mon Sep 17 00:00:00 2001 From: Learath Date: Mon, 24 Feb 2020 17:48:13 +0300 Subject: [PATCH 198/479] Add command usage --- src/engine/client/client.cpp | 10 ++--- src/engine/client/contacts.cpp | 10 ++--- src/engine/client/serverbrowser_fav.cpp | 8 ++-- src/engine/console.h | 2 +- src/engine/server/server.cpp | 11 +++--- src/engine/shared/config.cpp | 4 +- src/engine/shared/console.cpp | 47 +++++++++++++++++++----- src/engine/shared/console.h | 9 +++++ src/engine/shared/netban.cpp | 14 +++---- src/game/client/components/binds.cpp | 4 +- src/game/client/components/chat.cpp | 10 ++--- src/game/client/components/emoticon.cpp | 2 +- src/game/client/components/spectator.cpp | 2 +- src/game/client/components/voting.cpp | 4 +- src/game/client/gameclient.cpp | 2 +- src/game/server/gamecontext.cpp | 22 +++++------ 16 files changed, 97 insertions(+), 64 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 123891fc..574a8159 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2479,14 +2479,14 @@ void CClient::RegisterCommands() m_pConsole->Register("quit", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds"); m_pConsole->Register("exit", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds"); m_pConsole->Register("minimize", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Minimize, this, "Minimize Teeworlds"); - m_pConsole->Register("connect", "s", CFGFLAG_CLIENT, Con_Connect, this, "Connect to the specified host/ip"); + m_pConsole->Register("connect", "s[host|ip]", CFGFLAG_CLIENT, Con_Connect, this, "Connect to the specified host/ip"); m_pConsole->Register("disconnect", "", CFGFLAG_CLIENT, Con_Disconnect, this, "Disconnect from the server"); m_pConsole->Register("ping", "", CFGFLAG_CLIENT, Con_Ping, this, "Ping the current server"); 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|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("rcon", "r[command]", CFGFLAG_CLIENT, Con_Rcon, this, "Send specified command to rcon"); + m_pConsole->Register("rcon_auth", "s[password]", CFGFLAG_CLIENT, Con_RconAuth, this, "Authenticate to rcon"); + m_pConsole->Register("play", "r[file]", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Play, this, "Play the file specified"); + m_pConsole->Register("record", "?s[file]", 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"); diff --git a/src/engine/client/contacts.cpp b/src/engine/client/contacts.cpp index f136402e..fa3fed0f 100644 --- a/src/engine/client/contacts.cpp +++ b/src/engine/client/contacts.cpp @@ -130,7 +130,7 @@ void IContactList::ConfigSave(IConfigManager *pConfigManager, const char* pCmdSt *pDst++ = 0; pConfigManager->WriteLine(aBuf); - } + } } void CFriends::ConAddFriend(IConsole::IResult *pResult, void *pUserData) @@ -166,8 +166,8 @@ void CFriends::Init() 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"); + pConsole->Register("add_friend", "s[name] s[clan]", CFGFLAG_CLIENT, ConAddFriend, this, "Add a friend"); + pConsole->Register("remove_friend", "s[name] s[clan]", CFGFLAG_CLIENT, ConRemoveFriend, this, "Remove a friend"); } } @@ -180,8 +180,8 @@ void CBlacklist::Init() IConsole *pConsole = Kernel()->RequestInterface(); if(pConsole) { - pConsole->Register("add_ignore", "ss", CFGFLAG_CLIENT, ConAddIgnore, this, "Ignore a player"); - pConsole->Register("remove_ignore", "ss", CFGFLAG_CLIENT, ConRemoveIgnore, this, "Stop ignoring a player"); + pConsole->Register("add_ignore", "s[name] s[clan]", CFGFLAG_CLIENT, ConAddIgnore, this, "Ignore a player"); + pConsole->Register("remove_ignore", "s[name] s[clan]", CFGFLAG_CLIENT, ConRemoveIgnore, this, "Stop ignoring a player"); } } diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index aeddd2a8..a2e58db2 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -35,8 +35,8 @@ void CServerBrowserFavorites::Init(CNetClient *pNetClient, IConsole *pConsole, I if(pConfigManager) pConfigManager->RegisterCallback(ConfigSaveCallback, this); - m_pConsole->Register("add_favorite", "s?s", CFGFLAG_CLIENT, ConAddFavorite, this, "Add a server (optionally with password) as a favorite. Also updates password of existing favorite."); - m_pConsole->Register("remove_favorite", "s", CFGFLAG_CLIENT, ConRemoveFavorite, this, "Remove a server from favorites"); + m_pConsole->Register("add_favorite", "s[hostname] ?s[password]", CFGFLAG_CLIENT, ConAddFavorite, this, "Add a server (optionally with password) as a favorite. Also updates password of existing favorite."); + m_pConsole->Register("remove_favorite", "s[hostname]", CFGFLAG_CLIENT, ConRemoveFavorite, this, "Remove a server from favorites"); } bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck, const char *pPassword) @@ -128,7 +128,7 @@ CServerBrowserFavorites::CFavoriteServer *CServerBrowserFavorites::FindFavoriteB return &m_aFavoriteServers[i]; } } - + return 0; } @@ -159,7 +159,7 @@ bool CServerBrowserFavorites::RemoveFavoriteEx(const char *pHostname, const NETA // skip result on favorite hostname lookup m_FavLookup.m_FavoriteIndex = -1; } - + // remove favorite RemoveFavoriteEntry(Index); if(m_FavLookup.m_FavoriteIndex > Index) diff --git a/src/engine/console.h b/src/engine/console.h index c5915313..de5de45f 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -22,7 +22,7 @@ class IConsole : public IInterface TEMPCMD_NAME_LENGTH=32, TEMPCMD_HELP_LENGTH=96, - TEMPCMD_PARAMS_LENGTH=16, + TEMPCMD_PARAMS_LENGTH=96, TEMPMAP_NAME_LENGTH = 32, diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 86911427..0dd0f878 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -151,7 +151,7 @@ void CServerBan::InitServerBan(IConsole *pConsole, IStorage *pStorage, CServer* m_pServer = pServer; // overwrites base command, todo: improve this - Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with IP/IP range/client id for x minutes for any reason"); + Console()->Register("ban", "s[id|ip|range] ?i[minutes] r[reason]", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with IP/IP range/client id for x minutes for any reason"); } template @@ -1201,7 +1201,7 @@ void CServer::PumpNetwork() CPacker Packer; CNetChunk Response; - + GenerateServerInfo(&Packer, SrvBrwsToken); Response.m_ClientID = -1; @@ -1513,7 +1513,7 @@ int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, pThis->m_pStorage->ListDirectory(IStorage::TYPE_ALL, FindPath, MapListEntryCallback, &Userdata); return 0; } - + const char *pSuffix = str_endswith(aFilename, ".map"); if(!pSuffix) // not ending with .map { @@ -1745,12 +1745,12 @@ void CServer::RegisterCommands() m_pStorage = Kernel()->RequestInterface(); // register console commands - Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason"); + Console()->Register("kick", "i[id] ?r[reason]", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason"); Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players"); Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down"); Console()->Register("logout", "", CFGFLAG_SERVER|CFGFLAG_BASICACCESS, ConLogout, this, "Logout of rcon"); - Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "Record to a file"); + Console()->Register("record", "?s[file]", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "Record to a file"); Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "Stop recording"); Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, "Reload the map"); @@ -1902,4 +1902,3 @@ int main(int argc, const char **argv) // ignore_convention return Ret; } - diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index aedaa04b..15cd537b 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -49,7 +49,7 @@ void CConfigManager::Init(int FlagMask) Reset(); if(m_pConsole) - m_pConsole->Register("save_config", "?s", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_SaveConfig, this, "Save config to file"); + m_pConsole->Register("save_config", "?s[file]", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_SaveConfig, this, "Save config to file"); } void CConfigManager::Reset() @@ -78,7 +78,7 @@ void CConfigManager::Save(const char *pFilename) { if(!m_pStorage) return; - + if(!pFilename) pFilename = SETTINGS_FILENAME ".cfg"; m_ConfigFile = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index b035f1f9..60a15a27 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -88,7 +88,7 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length) int CConsole::ParseArgs(CResult *pResult, const char *pFormat) { - char Command; + char Command = *pFormat; char *pStr; int Optional = 0; int Error = 0; @@ -97,10 +97,6 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) while(1) { - // fetch command - Command = *pFormat; - pFormat++; - if(!Command) break; @@ -113,7 +109,9 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) if(!(*pStr)) // error, non optional command needs value { if(!Optional) + { Error = 1; + } break; } @@ -175,11 +173,40 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) } } } + + // fetch next command + Command = NextParam(pFormat); } return Error; } +char CConsole::NextParam(const char *&pFormat) +{ + if(*pFormat) + { + pFormat++; + + if(*pFormat == '[') + { + // skip bracket contents + for(; *pFormat != ']'; pFormat++) + { + if (!*pFormat) + return *pFormat; + } + + // skip ']' + pFormat++; + + // skip space if there is one + if (*pFormat == ' ') + pFormat++; + } + } + return *pFormat; +} + int CConsole::ParseCommandArgs(const char *pArgs, const char *pFormat, FCommandCallback pfnCallback, void *pContext) { CResult Result; @@ -704,13 +731,13 @@ CConsole::CConsole(int FlagMask) m_pStorage = 0; // register some basic commands - Register("echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text"); - Register("exec", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file"); + Register("echo", "r[text]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text"); + Register("exec", "r[file]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file"); - Register("toggle", "sii", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConToggle, this, "Toggle config value"); - Register("+toggle", "sii", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress"); + Register("toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConToggle, this, "Toggle config value"); + Register("+toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress"); - Register("mod_command", "s?i", CFGFLAG_SERVER, ConModCommandAccess, this, "Specify command accessibility for moderators"); + Register("mod_command", "s[command] ?i[access-level]", CFGFLAG_SERVER, ConModCommandAccess, this, "Specify command accessibility for moderators"); Register("mod_status", "", CFGFLAG_SERVER, ConModCommandStatus, this, "List all commands which are accessible for moderators"); } diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index c50623af..25671c25 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -123,6 +123,15 @@ class CConsole : public IConsole int ParseStart(CResult *pResult, const char *pString, int Length); int ParseArgs(CResult *pResult, const char *pFormat); + /* + This function will set pFormat to the next parameter (i,s,r,v,?) it contains and + return the parameter. + Descriptions in brackets like [file] will be skipped. + Returns '\0' if there is no next parameter. + Expects pFormat to point at a parameter. + */ + char NextParam(const char *&pFormat); + class CExecutionQueue { CHeap m_Queue; diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp index 7a5d5f5a..a9b85fd2 100644 --- a/src/engine/shared/netban.cpp +++ b/src/engine/shared/netban.cpp @@ -237,7 +237,7 @@ void CNetBan::MakeBanInfo(CBan *pBan, char *pBuf, unsigned BuffSize, int Type pBuf[0] = 0; return; } - + // build type based part char aBuf[256]; if(Type == MSGTYPE_PLAYER) @@ -352,11 +352,11 @@ void CNetBan::Init(IConsole *pConsole, IStorage *pStorage) 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 (or IP range) for x minutes for any reason"); - Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnban, this, "Unban IP/IP range/banlist entry"); + Console()->Register("ban", "s[ip|range] ?i[minutes] r[reason]", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBan, this, "Ban IP (or IP range) for x minutes for any reason"); + Console()->Register("unban", "s[ip|range]", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnban, this, "Unban IP/IP range/banlist entry"); 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"); + Console()->Register("bans_save", "s[file]", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBansSave, this, "Save banlist in a file"); } void CNetBan::Update() @@ -402,7 +402,7 @@ 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; } @@ -480,7 +480,7 @@ bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize, in } } } - + return false; } @@ -582,7 +582,7 @@ void CNetBan::ConBansSave(IConsole::IResult *pResult, void *pUser) CNetBan *pThis = static_cast(pUser); char aBuf[256]; const char *pFilename = pResult->GetString(0); - + IOHANDLE File = pThis->Storage()->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(!File) { diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 6030df8f..14658a32 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -268,8 +268,8 @@ void CBinds::OnConsoleInit() if(pConfigManager) pConfigManager->RegisterCallback(ConfigSaveCallback, this); - Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); - Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); + Console()->Register("bind", "s[key] r[command]", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); + Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); Console()->Register("binds", "", CFGFLAG_CLIENT, ConBinds, this, "Show list of key bindings"); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index bc250bc5..c91cabfa 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -204,11 +204,11 @@ void CChat::OnInit() void CChat::OnConsoleInit() { - Console()->Register("say", "r", CFGFLAG_CLIENT, ConSay, this, "Say in chat"); - Console()->Register("say_team", "r", CFGFLAG_CLIENT, ConSayTeam, this, "Say in team chat"); - Console()->Register("say_self", "r", CFGFLAG_CLIENT, ConSaySelf, this, "Say message just for yourself"); - Console()->Register("whisper", "ir", CFGFLAG_CLIENT, ConWhisper, this, "Whisper to a client in chat"); - Console()->Register("chat", "s?i", CFGFLAG_CLIENT, ConChat, this, "Enable chat with all/team/whisper mode"); + Console()->Register("say", "r[text]", CFGFLAG_CLIENT, ConSay, this, "Say in chat"); + Console()->Register("say_team", "r[text]", CFGFLAG_CLIENT, ConSayTeam, this, "Say in team chat"); + Console()->Register("say_self", "r[text]", CFGFLAG_CLIENT, ConSaySelf, this, "Say message just for yourself"); + Console()->Register("whisper", "i[target] r[text]", CFGFLAG_CLIENT, ConWhisper, this, "Whisper to a client in chat"); + Console()->Register("chat", "s[text] ?i[whisper-target]", CFGFLAG_CLIENT, ConChat, this, "Enable chat with all/team/whisper mode"); Console()->Register("+show_chat", "", CFGFLAG_CLIENT, ConShowChat, this, "Show chat"); } diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index 6ad0a8c6..8957d8ed 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -29,7 +29,7 @@ void CEmoticon::ConEmote(IConsole::IResult *pResult, void *pUserData) void CEmoticon::OnConsoleInit() { Console()->Register("+emote", "", CFGFLAG_CLIENT, ConKeyEmoticon, this, "Open emote selector"); - Console()->Register("emote", "i", CFGFLAG_CLIENT, ConEmote, this, "Use emote"); + Console()->Register("emote", "i[emote-id]", CFGFLAG_CLIENT, ConEmote, this, "Use emote"); } void CEmoticon::OnReset() diff --git a/src/game/client/components/spectator.cpp b/src/game/client/components/spectator.cpp index 8f558d78..b90a0fc3 100644 --- a/src/game/client/components/spectator.cpp +++ b/src/game/client/components/spectator.cpp @@ -123,7 +123,7 @@ CSpectator::CSpectator() void CSpectator::OnConsoleInit() { Console()->Register("+spectate", "", CFGFLAG_CLIENT, ConKeySpectator, this, "Open spectator mode selector"); - Console()->Register("spectate", "ii", CFGFLAG_CLIENT, ConSpectate, this, "Switch spectator mode"); + Console()->Register("spectate", "i[mode] i[target]", CFGFLAG_CLIENT, ConSpectate, this, "Switch spectator mode"); Console()->Register("spectate_next", "", CFGFLAG_CLIENT, ConSpectateNext, this, "Spectate the next player"); Console()->Register("spectate_previous", "", CFGFLAG_CLIENT, ConSpectatePrevious, this, "Spectate the previous player"); } diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index e2b75b34..c2f60edd 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -162,7 +162,7 @@ void CVoting::OnStateChange(int NewState, int OldState) void CVoting::OnConsoleInit() { - Console()->Register("vote", "r", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no"); + Console()->Register("vote", "r['yes'|'no']", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no"); } void CVoting::OnMessage(int MsgType, void *pRawMsg) @@ -350,5 +350,3 @@ void CVoting::RenderBars(CUIRect Bars, bool Text) } } } - - diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1603853d..66c3026c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -294,7 +294,7 @@ void CGameClient::OnConsoleInit() m_Input.Add(m_pBinds); // add the some console commands - Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); + Console()->Register("team", "i[team]", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself"); Console()->Register("ready_change", "", CFGFLAG_CLIENT, ConReadyChange, this, "Change ready state"); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index d95c35fe..3b9e3d4c 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1508,26 +1508,26 @@ void CGameContext::OnConsoleInit() m_pConfig = Kernel()->RequestInterface()->Values(); m_pConsole = Kernel()->RequestInterface(); - Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); + Console()->Register("tune", "s[tuning] i[value]", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset all tuning variables to defaults"); Console()->Register("tunes", "", CFGFLAG_SERVER, ConTunes, this, "List all tuning variables and their values"); - Console()->Register("pause", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, 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("say", "r", CFGFLAG_SERVER, ConSay, this, "Say in chat"); - Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message"); - Console()->Register("set_team", "ii?i", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team"); - Console()->Register("set_team_all", "i", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team"); + Console()->Register("pause", "?i[seconds]", CFGFLAG_SERVER|CFGFLAG_STORE, ConPause, this, "Pause/unpause game"); + Console()->Register("change_map", "?r[map]", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map"); + Console()->Register("restart", "?i[seconds]", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)"); + Console()->Register("say", "r[text]", CFGFLAG_SERVER, ConSay, this, "Say in chat"); + Console()->Register("broadcast", "r[text]", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message"); + Console()->Register("set_team", "i[id] i[team] ?i[delay]", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team"); + Console()->Register("set_team_all", "i[team]", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team"); Console()->Register("swap_teams", "", CFGFLAG_SERVER, ConSwapTeams, this, "Swap the current teams"); Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, ConShuffleTeams, this, "Shuffle the current teams"); Console()->Register("lock_teams", "", CFGFLAG_SERVER, ConLockTeams, this, "Lock/unlock teams"); Console()->Register("force_teambalance", "", CFGFLAG_SERVER, ConForceTeamBalance, this, "Force team balance"); - Console()->Register("add_vote", "sr", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option"); - Console()->Register("remove_vote", "s", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option"); + Console()->Register("add_vote", "s[option] r[command]", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option"); + Console()->Register("remove_vote", "s[option]", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option"); Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "Clears the voting options"); - Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, "Force a vote to yes/no"); + Console()->Register("vote", "r['yes'|'no']", CFGFLAG_SERVER, ConVote, this, "Force a vote to yes/no"); } void CGameContext::NewCommandHook(const CCommandManager::CCommand *pCommand, void *pContext) From 6cefadb6311477dd053440fef7ad2b40bd1902c9 Mon Sep 17 00:00:00 2001 From: nheir Date: Mon, 24 Feb 2020 15:56:14 +0100 Subject: [PATCH 199/479] comment drag velocity --- src/game/server/entities/character.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 9141c81e..cc18f971 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -556,6 +556,8 @@ void CCharacter::TickDefered() m_ReckoningCore.Quantize(); } + // apply drag velocity when the player is not firing ninja + // and set it back to 0 for the next tick if(m_ActiveWeapon != WEAPON_NINJA || m_Ninja.m_CurrentMoveTime < 0) m_Core.AddDragVelocity(); m_Core.ResetDragVelocity(); From 1894f14a80048b5e5d33ec3aaea6249c8eb4d81c Mon Sep 17 00:00:00 2001 From: nheir Date: Tue, 25 Feb 2020 18:56:04 +0100 Subject: [PATCH 200/479] fix: use drag velocity on client side --- src/game/client/gameclient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1603853d..9652816e 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1529,6 +1529,8 @@ void CGameClient::OnPredict() if(!World.m_apCharacters[c]) continue; + World.m_apCharacters[c]->AddDragVelocity(); + World.m_apCharacters[c]->ResetDragVelocity(); World.m_apCharacters[c]->Move(); World.m_apCharacters[c]->Quantize(); } From c366b3f7050ba8380c519b5eece3c3794af79879 Mon Sep 17 00:00:00 2001 From: Learath Date: Fri, 28 Feb 2020 16:39:59 +0300 Subject: [PATCH 201/479] Handle new type argument strings in commands --- src/base/system.c | 4 +++ src/base/system.h | 13 ++++++++ src/engine/shared/console.cpp | 2 -- src/game/client/components/chat.cpp | 52 ++++++++++++++++++++--------- src/game/commands.h | 2 +- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 080ae13f..2f356b77 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2312,6 +2312,10 @@ void str_timestamp(char *buffer, int buffer_size) #pragma GCC diagnostic pop #endif +int str_span(const char *str, const char *set) +{ + return strcspn(str, set); +} int mem_comp(const void *a, const void *b, int size) { diff --git a/src/base/system.h b/src/base/system.h index 8743de4b..c15802d2 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1280,6 +1280,19 @@ GNUC_ATTRIBUTE((format(strftime, 3, 0))); void str_timestamp_ex(time_t time, char *buffer, int buffer_size, const char *format) GNUC_ATTRIBUTE((format(strftime, 4, 0))); +/* + Function: str_span + Returns the length of the minimum initial segment that doesn't contain characters in set + + Parameters: + str - String to search in + set - Set of characters to stop on + + Remarks: + - Also stops on '\0' +*/ +int str_span(const char *str, const char *set); + #define FORMAT_TIME "%H:%M:%S" #define FORMAT_SPACE "%Y-%m-%d %H:%M:%S" #define FORMAT_NOSPACE "%Y-%m-%d_%H-%M-%S" diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 60a15a27..07caaf84 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -163,8 +163,6 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) pStr = str_skip_to_whitespace(pStr); else if(Command == 's') // validate string pStr = str_skip_to_whitespace(pStr); - else if(Command == 'p') - pStr = str_skip_to_whitespace(pStr); if(pStr[0] != 0) // check for end of string { diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index c91cabfa..d64d7f66 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1420,30 +1420,52 @@ void CChat::HandleCommands(float x, float y, float w) TextRender()->TextEx(&Cursor, " ", -1); TextRender()->TextColor(0.0f, 0.5f, 0.5f, 1.0f); - for(const char *c = pCommand->m_aArgsFormat; *c; c++) + for(const char *c = pCommand->m_aArgsFormat; *c;) { - // Integer argument - if(*c == 'i') - { - TextRender()->TextEx(&Cursor, " ", -1); - } - // Player name argument - else if(*c == 'p') + const char Brackets[2][3] = { "<>", "[]" }; + char aBuf[32]; + + bool Optional = false; + if(c[0] == '?') { - TextRender()->TextEx(&Cursor, " ", -1); + Optional = true; + c++; } - // String argument - else if(*c == 's') + + if(c[1] == '[') { - TextRender()->TextEx(&Cursor, " ", -1); + str_format(aBuf, sizeof(aBuf), "%c%.*s%c ", + Brackets[Optional][0], str_span(&c[2], "]"), &c[2], Brackets[Optional][1]); + c += str_span(c, "]") + 1; } - // Subcommand argument - else if(*c == 'c') + else { - TextRender()->TextEx(&Cursor, " ", -1); + switch(c[0]) { + case 'i': + str_format(aBuf, sizeof(aBuf), "%cnumber%c", + Brackets[Optional][0], Brackets[Optional][1]); + break; + case 'f': + str_format(aBuf, sizeof(aBuf), "%cfloat%c", + Brackets[Optional][0], Brackets[Optional][1]); + break; + case 'r': + case 's': + str_format(aBuf, sizeof(aBuf), "%cstring%c", + Brackets[Optional][0], Brackets[Optional][1]); + break; + default: + goto illformed; + } + c++; } + c = str_skip_whitespaces_const(c); + TextRender()->TextEx(&Cursor, aBuf, -1); } + illformed: TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); + + // TODO: Truncate HelpText TextRender()->TextEx(&Cursor, pCommand->m_aHelpText, -1); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } diff --git a/src/game/commands.h b/src/game/commands.h index 766c3cf8..283f0a5b 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -13,7 +13,7 @@ class CCommandManager public: char m_aName[16]; char m_aHelpText[64]; - char m_aArgsFormat[16]; + char m_aArgsFormat[64]; IConsole::FCommandCallback m_pfnCallback; void *m_pContext; From 60fbcf94e5354c478addc310e5f105e37b6f6780 Mon Sep 17 00:00:00 2001 From: Learath Date: Sun, 1 Mar 2020 18:58:38 +0300 Subject: [PATCH 202/479] Truncate the helptext to fit --- src/game/client/components/chat.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index d64d7f66..15120104 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1415,6 +1415,10 @@ void CChat::HandleCommands(float x, float y, float w) // print command CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Rect.x + 5.0f, y, 5.0f, TEXTFLAG_RENDER); + // Janky way to truncate + Cursor.m_LineWidth = LineWidth; + Cursor.m_MaxLines = 1; + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); TextRender()->TextEx(&Cursor, pCommand->m_aName, -1); TextRender()->TextEx(&Cursor, " ", -1); @@ -1464,8 +1468,6 @@ void CChat::HandleCommands(float x, float y, float w) } illformed: TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); - - // TODO: Truncate HelpText TextRender()->TextEx(&Cursor, pCommand->m_aHelpText, -1); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } From a50f2750c4a8fa5fd59e0a7d6821be34fb7e9856 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 11 Mar 2020 18:08:08 +0100 Subject: [PATCH 203/479] fixed a possible problem with freetype detection on windows --- other/freetype/freetype.lua | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/other/freetype/freetype.lua b/other/freetype/freetype.lua index f2517fd6..ada34c51 100644 --- a/other/freetype/freetype.lua +++ b/other/freetype/freetype.lua @@ -9,20 +9,18 @@ FreeType = { option.use_winlib = 0 option.lib_path = nil - if ExecuteSilent("pkg-config freetype2") == 0 then - option.value = true - option.use_pkgconfig = true - elseif ExecuteSilent("freetype-config") > 0 and ExecuteSilent("freetype-config --cflags") == 0 then - option.value = true - option.use_ftconfig = true - end - if platform == "win32" then option.value = true option.use_winlib = 32 elseif platform == "win64" then option.value = true option.use_winlib = 64 + elseif ExecuteSilent("pkg-config freetype2") == 0 then + option.value = true + option.use_pkgconfig = true + elseif ExecuteSilent("freetype-config") > 0 and ExecuteSilent("freetype-config --cflags") == 0 then + option.value = true + option.use_ftconfig = true end end From 2165d9987fc376d7ee97dd5d01caa18ded890e11 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 11 Mar 2020 23:02:35 +0300 Subject: [PATCH 204/479] Get rid of the evil goto --- src/game/client/components/chat.cpp | 51 +++++++++++++++++------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 15120104..52de06a5 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1426,8 +1426,8 @@ void CChat::HandleCommands(float x, float y, float w) TextRender()->TextColor(0.0f, 0.5f, 0.5f, 1.0f); for(const char *c = pCommand->m_aArgsFormat; *c;) { - const char Brackets[2][3] = { "<>", "[]" }; - char aBuf[32]; + char aBuf[32] = ""; + char aDesc[32]; bool Optional = false; if(c[0] == '?') @@ -1436,37 +1436,46 @@ void CChat::HandleCommands(float x, float y, float w) c++; } + const char *pDesc = 0; if(c[1] == '[') { - str_format(aBuf, sizeof(aBuf), "%c%.*s%c ", - Brackets[Optional][0], str_span(&c[2], "]"), &c[2], Brackets[Optional][1]); + str_format(aDesc, sizeof(aDesc), "%.*s", str_span(&c[2], "]"), &c[2]); + pDesc = aDesc; c += str_span(c, "]") + 1; } else { - switch(c[0]) { - case 'i': - str_format(aBuf, sizeof(aBuf), "%cnumber%c", - Brackets[Optional][0], Brackets[Optional][1]); - break; - case 'f': - str_format(aBuf, sizeof(aBuf), "%cfloat%c", - Brackets[Optional][0], Brackets[Optional][1]); - break; - case 'r': - case 's': - str_format(aBuf, sizeof(aBuf), "%cstring%c", - Brackets[Optional][0], Brackets[Optional][1]); - break; - default: - goto illformed; + if(c[0] == 'i') + { + pDesc = "number"; } + else if(c[0] == 'f') + { + pDesc = "float"; + } + else if(c[0] == 'r' || c[0] == 's') + { + pDesc = "string"; + } + else + { + break; // ill-formed + } + + if(Optional) + { + str_format(aBuf, sizeof(aBuf), "[%s] ", pDesc); + } + else + { + str_format(aBuf, sizeof(aBuf), "<%s> ", pDesc); + } + c++; } c = str_skip_whitespaces_const(c); TextRender()->TextEx(&Cursor, aBuf, -1); } - illformed: TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); TextRender()->TextEx(&Cursor, pCommand->m_aHelpText, -1); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); From 2fc4a0dab2dceb9e4cfe5618e473e21e81f4246f Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 12 Mar 2020 19:44:24 +0300 Subject: [PATCH 205/479] Usage for commands, make whisper consistent --- src/game/client/components/chat.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 52de06a5..5a182931 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -76,14 +76,14 @@ void CChat::OnReset() // init chat commands (must be in alphabetical order) m_CommandManager.ClearCommands(); - m_CommandManager.AddCommand("all", "Switch to all chat", "?r", &Com_All, this); - m_CommandManager.AddCommand("friend", "Add player as friend", "p", &Com_Befriend, this); - m_CommandManager.AddCommand("m", "Mute a player", "p", &Com_Mute, this); - m_CommandManager.AddCommand("mute", "Mute a player", "p", &Com_Mute, this); - m_CommandManager.AddCommand("r", "Reply to a whisper", "?r", &Com_Reply, this); - m_CommandManager.AddCommand("team", "Switch to team chat", "?r", &Com_Team, this); - m_CommandManager.AddCommand("w", "Whisper another player", "p", &Com_Whisper, this); - m_CommandManager.AddCommand("whisper", "Whisper another player", "p", &Com_Whisper, this); + m_CommandManager.AddCommand("all", "Switch to all chat", "?r[message]", &Com_All, this); + m_CommandManager.AddCommand("friend", "Add player as friend", "s[name]", &Com_Befriend, this); + m_CommandManager.AddCommand("m", "Mute a player", "s[name]", &Com_Mute, this); + m_CommandManager.AddCommand("mute", "Mute a player", "s[name]", &Com_Mute, this); + m_CommandManager.AddCommand("r", "Reply to a whisper", "?r[message]", &Com_Reply, this); + m_CommandManager.AddCommand("team", "Switch to team chat", "?r[message]", &Com_Team, this); + m_CommandManager.AddCommand("w", "Whisper another player", "s[name] ?r[message]", &Com_Whisper, this); + m_CommandManager.AddCommand("whisper", "Whisper another player", "s[name] ?r[message]", &Com_Whisper, this); } void CChat::OnMapLoad() @@ -1586,7 +1586,13 @@ void CChat::Com_Whisper(IConsole::IResult *pResult, void *pContext) if(TargetID != -1) { pChatData->m_WhisperTarget = TargetID; - pChatData->EnableMode(CHAT_WHISPER); + pChatData->m_ChatCmdBuffer[0] = 0; + if(pResult->NumArguments() > 1) + { + // save the parameter in a buffer before EnableMode clears it + str_copy(pChatData->m_ChatCmdBuffer, pResult->GetString(1), sizeof(pChatData->m_ChatCmdBuffer)); + } + pChatData->EnableMode(CHAT_WHISPER, pChatData->m_ChatCmdBuffer); } } From dae893db9f535c1275b1682b5a34247698be5837 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 15 Mar 2020 18:39:45 +0100 Subject: [PATCH 206/479] Remove whispers from server logs This stops admins from accidentally looking at whispers. Fixes #2482. --- src/game/server/gamecontext.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index d95c35fe..5ddca7f2 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -197,15 +197,18 @@ void CGameContext::SendChat(int ChatterClientID, int Mode, int To, const char *p else str_format(aBuf, sizeof(aBuf), "*** %s", pText); - char aBufMode[32]; + const char *pModeStr; if(Mode == CHAT_WHISPER) - str_copy(aBufMode, "whisper", sizeof(aBufMode)); + pModeStr = 0; else if(Mode == CHAT_TEAM) - str_copy(aBufMode, "teamchat", sizeof(aBufMode)); + pModeStr = "teamchat"; else - str_copy(aBufMode, "chat", sizeof(aBufMode)); + pModeStr = "chat"; - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, aBufMode, aBuf); + if(pModeStr) + { + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, pModeStr, aBuf); + } CNetMsg_Sv_Chat Msg; From 939cb812317507ff27011307a191d993814d5f7f Mon Sep 17 00:00:00 2001 From: Learath Date: Sun, 15 Mar 2020 20:45:22 +0300 Subject: [PATCH 207/479] Fix small refactoring error --- src/game/client/components/chat.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 78251bc6..2808c9bb 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1462,17 +1462,17 @@ void CChat::HandleCommands(float x, float y, float w) break; // ill-formed } - if(Optional) - { - str_format(aBuf, sizeof(aBuf), "[%s] ", pDesc); - } - else - { - str_format(aBuf, sizeof(aBuf), "<%s> ", pDesc); - } - c++; } + + if(Optional) + { + str_format(aBuf, sizeof(aBuf), "[%s] ", pDesc); + } + else + { + str_format(aBuf, sizeof(aBuf), "<%s> ", pDesc); + } c = str_skip_whitespaces_const(c); TextRender()->TextEx(&Cursor, aBuf, -1); } From b4c88f9d75950158f94e190043731955e3c4a5b7 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sun, 15 Mar 2020 19:51:50 +0000 Subject: [PATCH 208/479] Edit whisper helper to add a privacy notice --- src/game/client/components/chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 78251bc6..cbecc309 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -979,7 +979,7 @@ void CChat::OnRender() TextRender()->SetCursor(&InfoCursor, 2.0f, y+12.0f, CategoryFontSize*0.75, TEXTFLAG_RENDER); char aInfoText[128]; - str_format(aInfoText, sizeof(aInfoText), Localize("Press Tab to cycle chat recipients")); + str_format(aInfoText, sizeof(aInfoText), Localize("Press Tab to cycle chat recipients. Whispers aren't encrypted and might be logged by the server.")); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); TextRender()->TextEx(&InfoCursor, aInfoText, -1); } From 090af8aa8f6b9a4d033649904b271aebf4b2be92 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 15 Mar 2020 21:20:07 +0100 Subject: [PATCH 209/479] added a labeled scrollbar and test it in settings --- src/game/client/components/menus.cpp | 24 +++++++++++++++++++ src/game/client/components/menus.h | 1 + src/game/client/components/menus_settings.cpp | 8 +++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 07fee3a7..df9a14ba 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -644,6 +644,30 @@ void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, co *pOption = Value; } +void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char* aLabels[], int Num, IScrollbarScale *pScale) +{ + int Value = clamp(*pOption, 0, Num - 1); + int Max = Num - 1; + + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "%s: %s", pStr, aLabels[Value]); + + float FontSize = pRect->h*ms_FontmodHeight*0.8f; + + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + CUIRect Label, ScrollBar; + pRect->VSplitRight(60.0f, &Label, &ScrollBar); + + Label.y += 2.0f; + UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); + + ScrollBar.VMargin(4.0f, &ScrollBar); + Value = pScale->ToAbsolute(DoScrollbarH(pID, &ScrollBar, pScale->ToRelative(Value, 0, Max)), 0, Max); + + *pOption = clamp(Value, 0, Max); +} + float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback) { CUIRect View = *pRect; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 52bf6877..5d23d558 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -121,6 +121,7 @@ class CMenus : public CComponent bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false); void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite=false); + void DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char* aLabels[], int Num, IScrollbarScale *pScale = &LinearScrollbarScale); float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive); void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index e2286f07..99d38cad 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -971,7 +971,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); Button.VSplitLeft(ButtonHeight, 0, &Button); RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - CUIRect Text; + /*CUIRect Text; Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button); Button.VSplitLeft(200.0f, &Text, &Button); @@ -989,7 +989,11 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) str_format(aBuf, sizeof(aBuf), Localize("no one", "Show chat messages from:")); static CButtonContainer s_ButtonFilterchat; if(DoButton_Menu(&s_ButtonFilterchat, aBuf, 0, &Button)) - Config()->m_ClFilterchat = (Config()->m_ClFilterchat + 1) % 3; + Config()->m_ClFilterchat = (Config()->m_ClFilterchat + 1) % 3;*/ + const int NumLabels = 3; + const char *aLabels[NumLabels] = { Localize("everyone", "Show chat messages from"), Localize("friends only", "Show chat messages from"), Localize("no one", "Show chat messages from")}; + Button.VSplitLeft(5.0f, 0, &Button); + DoScrollbarOptionLabeled(&Config()->m_ClFilterchat, &Config()->m_ClFilterchat, &Button, Localize("Show chat messages from"), aLabels, NumLabels); } GameRight.HSplitTop(Spacing, 0, &GameRight); From b0fc570b9e0ba04f9f7d47d0a0b11a1c0891c7b2 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 15 Mar 2020 22:02:24 +0100 Subject: [PATCH 210/479] fixed background alpha labeled scrollbar option and small handle sizes --- src/game/client/components/menus.cpp | 5 +++-- src/game/client/components/menus_settings.cpp | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index df9a14ba..1b5c22c4 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -657,7 +657,8 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Label, ScrollBar; - pRect->VSplitRight(60.0f, &Label, &ScrollBar); + pRect->VSplitLeft(5.0f, 0, &Label); + Label.VSplitRight(60.0f, &Label, &ScrollBar); Label.y += 2.0f; UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); @@ -855,7 +856,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) { // layout CUIRect Handle; - pRect->VSplitLeft(min(pRect->w/8.0f, 33.0f), &Handle, 0); + pRect->VSplitLeft(max(min(pRect->w/8.0f, 33.0f), pRect->h), &Handle, 0); Handle.x += (pRect->w-Handle.w)*Current; Handle.HMargin(5.0f, &Handle); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 99d38cad..cbaf93b9 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -970,8 +970,8 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); Button.VSplitLeft(ButtonHeight, 0, &Button); - RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - /*CUIRect Text; + /*RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Text; Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button); Button.VSplitLeft(200.0f, &Text, &Button); @@ -992,7 +992,6 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Config()->m_ClFilterchat = (Config()->m_ClFilterchat + 1) % 3;*/ const int NumLabels = 3; const char *aLabels[NumLabels] = { Localize("everyone", "Show chat messages from"), Localize("friends only", "Show chat messages from"), Localize("no one", "Show chat messages from")}; - Button.VSplitLeft(5.0f, 0, &Button); DoScrollbarOptionLabeled(&Config()->m_ClFilterchat, &Config()->m_ClFilterchat, &Button, Localize("Show chat messages from"), aLabels, NumLabels); } From 4ab3fa2548d175477fb9045d36a461c73dd34d4f Mon Sep 17 00:00:00 2001 From: nheir Date: Mon, 16 Mar 2020 19:21:52 +0100 Subject: [PATCH 211/479] add knowledge about bot into engine - drop packet to bots - remove dummy when connecting on its slot fix #2491 --- src/engine/server.h | 1 + src/engine/server/server.cpp | 12 ++++++++++++ src/game/server/gamecontext.cpp | 13 +++++++------ src/game/server/gamecontext.h | 1 + 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/engine/server.h b/src/engine/server.h index de5f5f08..bd24e639 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -91,6 +91,7 @@ class IGameServer : public IInterface virtual void OnClientDirectInput(int ClientID, void *pInput) = 0; virtual void OnClientPredictedInput(int ClientID, void *pInput) = 0; + virtual bool IsClientBot(int ClientID) const = 0; virtual bool IsClientReady(int ClientID) const = 0; virtual bool IsClientPlayer(int ClientID) const = 0; virtual bool IsClientSpectator(int ClientID) const = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 86911427..21010010 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -496,6 +496,10 @@ int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) if(!pMsg) return -1; + // drop packet to dummy client + if(0 <= ClientID && ClientID < MAX_CLIENTS && GameServer()->IsClientBot(ClientID)) + return 0; + mem_zero(&Packet, sizeof(CNetChunk)); Packet.m_ClientID = ClientID; Packet.m_pData = pMsg->Data(); @@ -665,6 +669,13 @@ void CServer::DoSnapshot() int CServer::NewClientCallback(int ClientID, void *pUser) { CServer *pThis = (CServer *)pUser; + + // Remove non human player on same slot + if(pThis->GameServer()->IsClientBot(ClientID)) + { + pThis->GameServer()->OnClientDrop(ClientID, "removing dummy"); + } + pThis->m_aClients[ClientID].m_State = CClient::STATE_AUTH; pThis->m_aClients[ClientID].m_aName[0] = 0; pThis->m_aClients[ClientID].m_aClan[0] = 0; @@ -676,6 +687,7 @@ int CServer::NewClientCallback(int ClientID, void *pUser) pThis->m_aClients[ClientID].m_NoRconNote = false; pThis->m_aClients[ClientID].m_Quitting = false; pThis->m_aClients[ClientID].Reset(); + return 0; } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index d95c35fe..32b29b49 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -700,11 +700,7 @@ void CGameContext::OnClientEnter(int ClientID) void CGameContext::OnClientConnected(int ClientID, bool Dummy, bool AsSpec) { - if(m_apPlayers[ClientID]) - { - dbg_assert(m_apPlayers[ClientID]->IsDummy(), "invalid clientID"); - OnClientDrop(ClientID, "removing dummy"); - } + dbg_assert(!m_apPlayers[ClientID], "non-free player slot"); m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy, AsSpec); @@ -742,7 +738,7 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason) m_pController->OnPlayerDisconnect(m_apPlayers[ClientID]); // update clients on drop - if(Server()->ClientIngame(ClientID)) + if(Server()->ClientIngame(ClientID) || IsClientBot(ClientID)) { if(Server()->DemoRecorder_IsRecording()) { @@ -1660,6 +1656,11 @@ void CGameContext::OnPostSnap() m_Events.Clear(); } +bool CGameContext::IsClientBot(int ClientID) const +{ + return m_apPlayers[ClientID] && m_apPlayers[ClientID]->IsDummy(); +} + bool CGameContext::IsClientReady(int ClientID) const { return m_apPlayers[ClientID] && m_apPlayers[ClientID]->m_IsReadyToEnter; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index f8fbb3da..3013dc10 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -188,6 +188,7 @@ class CGameContext : public IGameServer virtual void OnClientDirectInput(int ClientID, void *pInput); virtual void OnClientPredictedInput(int ClientID, void *pInput); + virtual bool IsClientBot(int ClientID) const; virtual bool IsClientReady(int ClientID) const; virtual bool IsClientPlayer(int ClientID) const; virtual bool IsClientSpectator(int ClientID) const; From e17c50842f096a41d9bb68a9395e3391832c7e29 Mon Sep 17 00:00:00 2001 From: Learath Date: Mon, 23 Mar 2020 15:20:40 +0300 Subject: [PATCH 212/479] Add commands to chat history --- src/game/client/components/chat.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 8d519809..1b9f12c5 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -257,16 +257,15 @@ bool CChat::OnInput(IInput::CEvent Event) } else if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)) { + bool AddEntry = false; if(IsTypingCommand() && ExecuteCommand(true)) { - // everything is handled within + AddEntry = true; } else { if(m_Input.GetString()[0]) { - bool AddEntry = false; - if(m_PendingChatCounter == 0 && m_LastChatSend+time_freq() < time_get()) { Say(m_Mode, m_Input.GetString()); @@ -277,18 +276,18 @@ bool CChat::OnInput(IInput::CEvent Event) ++m_PendingChatCounter; AddEntry = true; } - - if(AddEntry) - { - CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength()); - pEntry->m_Mode = m_Mode; - mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1); - } } m_pHistoryEntry = 0x0; m_Mode = CHAT_NONE; m_pClient->OnRelease(); } + + if(AddEntry) + { + CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength()); + pEntry->m_Mode = m_Mode; + mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1); + } } if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_TAB) { From 5090c39d94bad0b6dda8caaef271133c46c00ee0 Mon Sep 17 00:00:00 2001 From: Ryozuki Date: Tue, 24 Mar 2020 16:16:54 +0100 Subject: [PATCH 213/479] Log team id on chat, and reorder it. --- src/game/server/gamecontext.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 793a2139..7584fa06 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -193,7 +193,15 @@ void CGameContext::SendChat(int ChatterClientID, int Mode, int To, const char *p { char aBuf[256]; if(ChatterClientID >= 0 && ChatterClientID < MAX_CLIENTS) - str_format(aBuf, sizeof(aBuf), "%d:%d:%s: %s", ChatterClientID, Mode, Server()->ClientName(ChatterClientID), pText); + { + if(Mode == CHAT_TEAM) + { + int TeamID = m_apPlayers[ChatterClientID]->GetTeam(); + str_format(aBuf, sizeof(aBuf), "%d:%d:%d:%s: %s", Mode, TeamID, ChatterClientID, Server()->ClientName(ChatterClientID), pText); + } + else + str_format(aBuf, sizeof(aBuf), "%d:%d:%s: %s", Mode, ChatterClientID, Server()->ClientName(ChatterClientID), pText); + } else str_format(aBuf, sizeof(aBuf), "*** %s", pText); From ac27d4a05c9c6201e2e90b26fab849d2df27c0b1 Mon Sep 17 00:00:00 2001 From: Ryozuki Date: Tue, 24 Mar 2020 15:54:21 +0100 Subject: [PATCH 214/479] CMake fix freetype warning --- CMakeLists.txt | 6 +++++- cmake/{FindOwnFreetype.cmake => FindFreetype.cmake} | 0 2 files changed, 5 insertions(+), 1 deletion(-) rename cmake/{FindOwnFreetype.cmake => FindFreetype.cmake} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 210abf2d..23ba81be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,10 @@ else() message(FATAL_ERROR "Couldn't parse version from src/game/version.h") endif() +if(POLICY CMP0017) + cmake_policy(SET CMP0017 NEW) +endif() + if(POLICY CMP0072) cmake_policy(SET CMP0072 OLD) endif() @@ -309,7 +313,7 @@ if(NOT CMAKE_CROSSCOMPILING) endif() find_package(ZLIB) find_package(Crypto) -find_package(OwnFreetype) +find_package(Freetype) find_package(Git) find_package(GTest) find_package(Pnglite) diff --git a/cmake/FindOwnFreetype.cmake b/cmake/FindFreetype.cmake similarity index 100% rename from cmake/FindOwnFreetype.cmake rename to cmake/FindFreetype.cmake From 5e9cf8dadcf6d3385780109879483998a13d9874 Mon Sep 17 00:00:00 2001 From: Ryozuki Date: Tue, 24 Mar 2020 17:03:33 +0100 Subject: [PATCH 215/479] Add option to disable whisper feature --- src/game/client/components/chat.cpp | 20 ++++++++++++++++++- src/game/client/components/menus_settings.cpp | 7 +++++++ src/game/variables.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 8d519809..579cbbca 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -489,9 +489,13 @@ void CChat::EnableMode(int Mode, const char* pText) if(Client()->State() == IClient::STATE_DEMOPLAYBACK) return; - m_Mode = Mode; ClearInput(); + if(Mode == CHAT_WHISPER && Config()->m_ClDisableWhisper) + return; + + m_Mode = Mode; + if(pText) // optional text to initalize with { m_Input.Set(pText); @@ -535,6 +539,8 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) if(MsgType == NETMSGTYPE_SV_CHAT) { CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg; + if(pMsg->m_Mode == CHAT_WHISPER && Config()->m_ClDisableWhisper) + return; AddLine(pMsg->m_pMessage, pMsg->m_ClientID, pMsg->m_Mode, pMsg->m_TargetID); } else if(MsgType == NETMSGTYPE_SV_COMMANDINFO) @@ -1561,6 +1567,12 @@ void CChat::Com_Reply(IConsole::IResult *pResult, void *pContext) CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; CChat *pChatData = (CChat *)pCommandContext->m_pContext; + if(pChatData->Config()->m_ClDisableWhisper) + { + pChatData->ClearInput(); + return; + } + if(pChatData->m_LastWhisperFrom == -1) pChatData->ClearInput(); // just reset the chat else @@ -1582,6 +1594,12 @@ void CChat::Com_Whisper(IConsole::IResult *pResult, void *pContext) CCommandManager::SCommandContext *pCommandContext = (CCommandManager::SCommandContext *)pContext; CChat *pChatData = (CChat *)pCommandContext->m_pContext; + if(pChatData->Config()->m_ClDisableWhisper) + { + pChatData->ClearInput(); + return; + } + int TargetID = pChatData->m_pClient->GetClientID(pResult->GetString(0)); if(TargetID != -1) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index cbaf93b9..96bbde87 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1001,6 +1001,13 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) if(DoButton_CheckBox(&s_EnableColoredBroadcasts, Localize("Enable colored server broadcasts"), Config()->m_ClColoredBroadcast, &Button)) Config()->m_ClColoredBroadcast ^= 1; + + GameRight.HSplitTop(Spacing, 0, &GameRight); + GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); + static int s_DisableWhisperFeature = 0; + if(DoButton_CheckBox(&s_DisableWhisperFeature, Localize("Disable whisper feature"), + Config()->m_ClDisableWhisper, &Button)) + Config()->m_ClDisableWhisper ^= 1; // render client menu Client.HSplitTop(ButtonHeight, &Label, &Client); diff --git a/src/game/variables.h b/src/game/variables.h index 1065f36e..22080698 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -15,6 +15,7 @@ MACRO_CONFIG_INT(ClAutoswitchWeapons, cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CL MACRO_CONFIG_INT(ClShowhud, cl_showhud, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame HUD") MACRO_CONFIG_INT(ClFilterchat, cl_filterchat, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show chat messages from: 0=all, 1=friends only, 2=no one") +MACRO_CONFIG_INT(ClDisableWhisper, cl_disable_whisper, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable completely the whisper feature.") MACRO_CONFIG_INT(ClShowsocial, cl_showsocial, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show social data like names, clans, chat etc.") MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter") From 50859a087d7333bf921f14b51759b12d1742833d Mon Sep 17 00:00:00 2001 From: Ryozuki Date: Wed, 25 Mar 2020 14:36:46 +0100 Subject: [PATCH 216/479] ename some structs to match naming convetions --- src/engine/client/backend_sdl.cpp | 74 ++++++++++---------- src/engine/client/backend_sdl.h | 46 ++++++------- src/engine/client/graphics_threaded.cpp | 34 ++++----- src/engine/client/graphics_threaded.h | 92 ++++++++++++------------- 4 files changed, 123 insertions(+), 123 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 81c975af..5f92d58a 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -86,17 +86,17 @@ void CGraphicsBackend_Threaded::WaitForIdle() // ------------ CCommandProcessorFragment_General -void CCommandProcessorFragment_General::Cmd_Signal(const CCommandBuffer::SCommand_Signal *pCommand) +void CCommandProcessorFragment_General::Cmd_Signal(const CCommandBuffer::CSignalCommand *pCommand) { pCommand->m_pSemaphore->signal(); } -bool CCommandProcessorFragment_General::RunCommand(const CCommandBuffer::SCommand * pBaseCommand) +bool CCommandProcessorFragment_General::RunCommand(const CCommandBuffer::CCommand * pBaseCommand) { switch(pBaseCommand->m_Cmd) { case CCommandBuffer::CMD_NOP: break; - case CCommandBuffer::CMD_SIGNAL: Cmd_Signal(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_SIGNAL: Cmd_Signal(static_cast(pBaseCommand)); break; default: return false; } @@ -148,7 +148,7 @@ void *CCommandProcessorFragment_OpenGL::Rescale(int Width, int Height, int NewWi return pTmpData; } -void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &State) +void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::CState &State) { // clip if(State.m_ClipEnable) @@ -244,7 +244,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St glOrtho(State.m_ScreenTL.x, State.m_ScreenBR.x, State.m_ScreenBR.y, State.m_ScreenTL.y, -1.0f, 1.0f); } -void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Init(const CInitCommand *pCommand) { m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage; *m_pTextureMemoryUsage = 0; @@ -257,7 +257,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand) *pCommand->m_pTextureArraySize = m_TextureArraySize; } -void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::CTextureUpdateCommand *pCommand) { if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX2D) { @@ -268,7 +268,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer:: mem_free(pCommand->m_pData); } -void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer::CTextureDestroyCommand *pCommand) { if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX2D) glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex2D); @@ -279,7 +279,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer: m_aTextures[pCommand->m_Slot].m_MemSize = 0; } -void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::CTextureCreateCommand *pCommand) { int Width = pCommand->m_Width; int Height = pCommand->m_Height; @@ -436,19 +436,19 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer:: mem_free(pTexData); } -void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::CClearCommand *pCommand) { glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::CRenderCommand *pCommand) { SetState(pCommand->m_State); - glVertexPointer(2, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices); - glTexCoordPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*2); - glColorPointer(4, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*5); + glVertexPointer(2, GL_FLOAT, sizeof(CCommandBuffer::CVertex), (char*)pCommand->m_pVertices); + glTexCoordPointer(3, GL_FLOAT, sizeof(CCommandBuffer::CVertex), (char*)pCommand->m_pVertices + sizeof(float)*2); + glColorPointer(4, GL_FLOAT, sizeof(CCommandBuffer::CVertex), (char*)pCommand->m_pVertices + sizeof(float)*5); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -466,7 +466,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand }; } -void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand) +void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::CScreenshotCommand *pCommand) { // fetch image data GLint aViewport[4] = {0,0,0,0}; @@ -509,17 +509,17 @@ CCommandProcessorFragment_OpenGL::CCommandProcessorFragment_OpenGL() m_pTextureMemoryUsage = 0; } -bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::SCommand * pBaseCommand) +bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::CCommand * pBaseCommand) { switch(pBaseCommand->m_Cmd) { - case CMD_INIT: Cmd_Init(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_TEXTURE_CREATE: Cmd_Texture_Create(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_TEXTURE_DESTROY: Cmd_Texture_Destroy(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_TEXTURE_UPDATE: Cmd_Texture_Update(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_CLEAR: Cmd_Clear(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_RENDER: Cmd_Render(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_SCREENSHOT: Cmd_Screenshot(static_cast(pBaseCommand)); break; + case CMD_INIT: Cmd_Init(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_TEXTURE_CREATE: Cmd_Texture_Create(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_TEXTURE_DESTROY: Cmd_Texture_Destroy(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_TEXTURE_UPDATE: Cmd_Texture_Update(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_CLEAR: Cmd_Clear(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_RENDER: Cmd_Render(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_SCREENSHOT: Cmd_Screenshot(static_cast(pBaseCommand)); break; default: return false; } @@ -529,7 +529,7 @@ bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::SCommand // ------------ CCommandProcessorFragment_SDL -void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand) +void CCommandProcessorFragment_SDL::Cmd_Init(const CInitCommand *pCommand) { m_GLContext = pCommand->m_GLContext; m_pWindow = pCommand->m_pWindow; @@ -547,12 +547,12 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand) glDepthMask(0); } -void CCommandProcessorFragment_SDL::Cmd_Shutdown(const SCommand_Shutdown *pCommand) +void CCommandProcessorFragment_SDL::Cmd_Shutdown(const CShutdownCommand *pCommand) { SDL_GL_MakeCurrent(NULL, NULL); } -void CCommandProcessorFragment_SDL::Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand) +void CCommandProcessorFragment_SDL::Cmd_Swap(const CCommandBuffer::CSwapCommand *pCommand) { SDL_GL_SwapWindow(m_pWindow); @@ -560,12 +560,12 @@ void CCommandProcessorFragment_SDL::Cmd_Swap(const CCommandBuffer::SCommand_Swap glFinish(); } -void CCommandProcessorFragment_SDL::Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand) +void CCommandProcessorFragment_SDL::Cmd_VSync(const CCommandBuffer::CVSyncCommand *pCommand) { *pCommand->m_pRetOk = SDL_GL_SetSwapInterval(pCommand->m_VSync) == 0; } -void CCommandProcessorFragment_SDL::Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand) +void CCommandProcessorFragment_SDL::Cmd_VideoModes(const CCommandBuffer::CVideoModesCommand *pCommand) { SDL_DisplayMode mode; int maxModes = SDL_GetNumDisplayModes(pCommand->m_Screen), @@ -605,15 +605,15 @@ CCommandProcessorFragment_SDL::CCommandProcessorFragment_SDL() { } -bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::SCommand *pBaseCommand) +bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::CCommand *pBaseCommand) { switch(pBaseCommand->m_Cmd) { - case CCommandBuffer::CMD_SWAP: Cmd_Swap(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_VSYNC: Cmd_VSync(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast(pBaseCommand)); break; - case CMD_INIT: Cmd_Init(static_cast(pBaseCommand)); break; - case CMD_SHUTDOWN: Cmd_Shutdown(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_SWAP: Cmd_Swap(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_VSYNC: Cmd_VSync(static_cast(pBaseCommand)); break; + case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast(pBaseCommand)); break; + case CMD_INIT: Cmd_Init(static_cast(pBaseCommand)); break; + case CMD_SHUTDOWN: Cmd_Shutdown(static_cast(pBaseCommand)); break; default: return false; } @@ -627,7 +627,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer) unsigned CmdIndex = 0; while(1) { - const CCommandBuffer::SCommand *pBaseCommand = pBuffer->GetCommand(&CmdIndex); + const CCommandBuffer::CCommand *pBaseCommand = pBuffer->GetCommand(&CmdIndex); if(pBaseCommand == 0x0) break; @@ -777,11 +777,11 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin // issue init commands for OpenGL and SDL CCommandBuffer CmdBuffer(1024, 512); - CCommandProcessorFragment_SDL::SCommand_Init CmdSDL; + CCommandProcessorFragment_SDL::CInitCommand CmdSDL; CmdSDL.m_pWindow = m_pWindow; CmdSDL.m_GLContext = m_GLContext; CmdBuffer.AddCommand(CmdSDL); - CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL; + CCommandProcessorFragment_OpenGL::CInitCommand CmdOpenGL; CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage; CmdOpenGL.m_pTextureArraySize = &m_TextureArraySize; CmdBuffer.AddCommand(CmdOpenGL); @@ -796,7 +796,7 @@ int CGraphicsBackend_SDL_OpenGL::Shutdown() { // issue a shutdown command CCommandBuffer CmdBuffer(1024, 512); - CCommandProcessorFragment_SDL::SCommand_Shutdown Cmd; + CCommandProcessorFragment_SDL::CShutdownCommand Cmd; CmdBuffer.AddCommand(Cmd); RunBuffer(&CmdBuffer); WaitForIdle(); diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h index 72f66ed9..16fa049d 100644 --- a/src/engine/client/backend_sdl.h +++ b/src/engine/client/backend_sdl.h @@ -75,9 +75,9 @@ class CGraphicsBackend_Threaded : public IGraphicsBackend class CCommandProcessorFragment_General { void Cmd_Nop(); - void Cmd_Signal(const CCommandBuffer::SCommand_Signal *pCommand); + void Cmd_Signal(const CCommandBuffer::CSignalCommand *pCommand); public: - bool RunCommand(const CCommandBuffer::SCommand * pBaseCommand); + bool RunCommand(const CCommandBuffer::CCommand * pBaseCommand); }; // takes care of opengl related rendering @@ -113,9 +113,9 @@ class CCommandProcessorFragment_OpenGL CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_OPENGL, }; - struct SCommand_Init : public CCommandBuffer::SCommand + struct CInitCommand : public CCommandBuffer::CCommand { - SCommand_Init() : SCommand(CMD_INIT) {} + CInitCommand() : CCommand(CMD_INIT) {} volatile int *m_pTextureMemoryUsage; int *m_pTextureArraySize; }; @@ -125,20 +125,20 @@ class CCommandProcessorFragment_OpenGL 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 void *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData); - void SetState(const CCommandBuffer::SState &State); + void SetState(const CCommandBuffer::CState &State); - void Cmd_Init(const SCommand_Init *pCommand); - void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand); - void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand); - void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand); - void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand); - void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand); - void Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand); + void Cmd_Init(const CInitCommand *pCommand); + void Cmd_Texture_Update(const CCommandBuffer::CTextureUpdateCommand *pCommand); + void Cmd_Texture_Destroy(const CCommandBuffer::CTextureDestroyCommand *pCommand); + void Cmd_Texture_Create(const CCommandBuffer::CTextureCreateCommand *pCommand); + void Cmd_Clear(const CCommandBuffer::CClearCommand *pCommand); + void Cmd_Render(const CCommandBuffer::CRenderCommand *pCommand); + void Cmd_Screenshot(const CCommandBuffer::CScreenshotCommand *pCommand); public: CCommandProcessorFragment_OpenGL(); - bool RunCommand(const CCommandBuffer::SCommand * pBaseCommand); + bool RunCommand(const CCommandBuffer::CCommand * pBaseCommand); }; // takes care of sdl related commands @@ -154,28 +154,28 @@ class CCommandProcessorFragment_SDL CMD_SHUTDOWN, }; - struct SCommand_Init : public CCommandBuffer::SCommand + struct CInitCommand : public CCommandBuffer::CCommand { - SCommand_Init() : SCommand(CMD_INIT) {} + CInitCommand() : CCommand(CMD_INIT) {} SDL_Window *m_pWindow; SDL_GLContext m_GLContext; }; - struct SCommand_Shutdown : public CCommandBuffer::SCommand + struct CShutdownCommand : public CCommandBuffer::CCommand { - SCommand_Shutdown() : SCommand(CMD_SHUTDOWN) {} + CShutdownCommand() : CCommand(CMD_SHUTDOWN) {} }; private: - void Cmd_Init(const SCommand_Init *pCommand); - void Cmd_Shutdown(const SCommand_Shutdown *pCommand); - void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand); - void Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand); - void Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand); + void Cmd_Init(const CInitCommand *pCommand); + void Cmd_Shutdown(const CShutdownCommand *pCommand); + void Cmd_Swap(const CCommandBuffer::CSwapCommand *pCommand); + void Cmd_VSync(const CCommandBuffer::CVSyncCommand *pCommand); + void Cmd_VideoModes(const CCommandBuffer::CVideoModesCommand *pCommand); public: CCommandProcessorFragment_SDL(); - bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand); + bool RunCommand(const CCommandBuffer::CCommand *pBaseCommand); }; // command processor impelementation, uses the fragments to combine into one processor diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index fa4f2b00..0b7c7a84 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -42,7 +42,7 @@ void CGraphics_Threaded::FlushVertices() int NumVerts = m_NumVertices; m_NumVertices = 0; - CCommandBuffer::SCommand_Render Cmd; + CCommandBuffer::CRenderCommand Cmd; Cmd.m_State = m_State; if(m_Drawing == DRAWING_QUADS) @@ -58,13 +58,13 @@ void CGraphics_Threaded::FlushVertices() else return; - Cmd.m_pVertices = (CCommandBuffer::SVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::SVertex)*NumVerts); + Cmd.m_pVertices = (CCommandBuffer::CVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::CVertex)*NumVerts); if(Cmd.m_pVertices == 0x0) { // kick command buffer and try again KickCommandBuffer(); - Cmd.m_pVertices = (CCommandBuffer::SVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::SVertex)*NumVerts); + Cmd.m_pVertices = (CCommandBuffer::CVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::CVertex)*NumVerts); if(Cmd.m_pVertices == 0x0) { dbg_msg("graphics", "failed to allocate data for vertices"); @@ -78,7 +78,7 @@ void CGraphics_Threaded::FlushVertices() // kick command buffer and try again KickCommandBuffer(); - Cmd.m_pVertices = (CCommandBuffer::SVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::SVertex)*NumVerts); + Cmd.m_pVertices = (CCommandBuffer::CVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::CVertex)*NumVerts); if(Cmd.m_pVertices == 0x0) { dbg_msg("graphics", "failed to allocate data for vertices"); @@ -92,7 +92,7 @@ void CGraphics_Threaded::FlushVertices() } } - mem_copy(Cmd.m_pVertices, m_aVertices, sizeof(CCommandBuffer::SVertex)*NumVerts); + mem_copy(Cmd.m_pVertices, m_aVertices, sizeof(CCommandBuffer::CVertex)*NumVerts); } void CGraphics_Threaded::AddVertices(int Count) @@ -102,7 +102,7 @@ void CGraphics_Threaded::AddVertices(int Count) FlushVertices(); } -void CGraphics_Threaded::Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints) +void CGraphics_Threaded::Rotate4(const CCommandBuffer::CPoint &rCenter, CCommandBuffer::CVertex *pPoints) { float c = cosf(m_Rotation); float s = sinf(m_Rotation); @@ -273,7 +273,7 @@ int CGraphics_Threaded::UnloadTexture(CTextureHandle *Index) if(!Index->IsValid()) return 0; - CCommandBuffer::SCommand_Texture_Destroy Cmd; + CCommandBuffer::CTextureDestroyCommand Cmd; Cmd.m_Slot = Index->Id(); m_pCommandBuffer->AddCommand(Cmd); @@ -308,7 +308,7 @@ int CGraphics_Threaded::LoadTextureRawSub(CTextureHandle TextureID, int x, int y if(!TextureID.IsValid()) return 0; - CCommandBuffer::SCommand_Texture_Update Cmd; + CCommandBuffer::CTextureUpdateCommand Cmd; Cmd.m_Slot = TextureID.Id(); Cmd.m_X = x; Cmd.m_Y = y; @@ -340,7 +340,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig m_FirstFreeTexture = m_aTextureIndices[Tex]; m_aTextureIndices[Tex] = -1; - CCommandBuffer::SCommand_Texture_Create Cmd; + CCommandBuffer::CTextureCreateCommand Cmd; Cmd.m_Slot = Tex; Cmd.m_Width = Width; Cmd.m_Height = Height; @@ -469,7 +469,7 @@ void CGraphics_Threaded::ScreenshotDirect(const char *pFilename) CImageInfo Image; mem_zero(&Image, sizeof(Image)); - CCommandBuffer::SCommand_Screenshot Cmd; + CCommandBuffer::CScreenshotCommand Cmd; Cmd.m_pImage = &Image; Cmd.m_X = 0; Cmd.m_Y = 0; Cmd.m_W = -1; Cmd.m_H = -1; @@ -510,7 +510,7 @@ void CGraphics_Threaded::TextureSet(CTextureHandle TextureID) void CGraphics_Threaded::Clear(float r, float g, float b) { - CCommandBuffer::SCommand_Clear Cmd; + CCommandBuffer::CClearCommand Cmd; Cmd.m_Color.r = r; Cmd.m_Color.g = g; Cmd.m_Color.b = b; @@ -642,7 +642,7 @@ void CGraphics_Threaded::QuadsDraw(CQuadItem *pArray, int Num) void CGraphics_Threaded::QuadsDrawTL(const CQuadItem *pArray, int Num) { - CCommandBuffer::SPoint Center; + CCommandBuffer::CPoint Center; dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawTL without begin"); @@ -926,7 +926,7 @@ void CGraphics_Threaded::ReadBackbuffer(unsigned char **ppPixels, int x, int y, CImageInfo Image; mem_zero(&Image, sizeof(Image)); - CCommandBuffer::SCommand_Screenshot Cmd; + CCommandBuffer::CScreenshotCommand Cmd; Cmd.m_pImage = &Image; Cmd.m_X = x; Cmd.m_Y = y; Cmd.m_W = w; Cmd.m_H = h; @@ -959,7 +959,7 @@ void CGraphics_Threaded::Swap() } // add swap command - CCommandBuffer::SCommand_Swap Cmd; + CCommandBuffer::CSwapCommand Cmd; Cmd.m_Finish = m_pConfig->m_GfxFinish; m_pCommandBuffer->AddCommand(Cmd); @@ -971,7 +971,7 @@ bool CGraphics_Threaded::SetVSync(bool State) { // add vsnc command bool RetOk = 0; - CCommandBuffer::SCommand_VSync Cmd; + CCommandBuffer::CVSyncCommand Cmd; Cmd.m_VSync = State ? 1 : 0; Cmd.m_pRetOk = &RetOk; m_pCommandBuffer->AddCommand(Cmd); @@ -985,7 +985,7 @@ bool CGraphics_Threaded::SetVSync(bool State) // syncronization void CGraphics_Threaded::InsertSignal(semaphore *pSemaphore) { - CCommandBuffer::SCommand_Signal Cmd; + CCommandBuffer::CSignalCommand Cmd; Cmd.m_pSemaphore = pSemaphore; m_pCommandBuffer->AddCommand(Cmd); } @@ -1016,7 +1016,7 @@ int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Scre mem_zero(&Image, sizeof(Image)); int NumModes = 0; - CCommandBuffer::SCommand_VideoModes Cmd; + CCommandBuffer::CVideoModesCommand Cmd; Cmd.m_pModes = pModes; Cmd.m_MaxModes = MaxModes; Cmd.m_pNumModes = &NumModes; diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index 4c1df7c0..ce92dede 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -118,26 +118,26 @@ class CCommandBuffer BLEND_ADDITIVE, }; - struct SPoint { float x, y; }; - struct STexCoord { float u, v, i; }; - struct SColor { float r, g, b, a; }; + struct CPoint { float x, y; }; + struct CTexCoord { float u, v, i; }; + struct CColor { float r, g, b, a; }; - struct SVertex + struct CVertex { - SPoint m_Pos; - STexCoord m_Tex; - SColor m_Color; + CPoint m_Pos; + CTexCoord m_Tex; + CColor m_Color; }; - struct SCommand + struct CCommand { public: - SCommand(unsigned Cmd) : m_Cmd(Cmd), m_Size(0) {} + CCommand(unsigned Cmd) : m_Cmd(Cmd), m_Size(0) {} unsigned m_Cmd; unsigned m_Size; }; - struct SState + struct CState { int m_BlendMode; int m_WrapModeU; @@ -145,8 +145,8 @@ class CCommandBuffer int m_Texture; int m_TextureArrayIndex; int m_Dimension; - SPoint m_ScreenTL; - SPoint m_ScreenBR; + CPoint m_ScreenTL; + CPoint m_ScreenBR; // clip bool m_ClipEnable; @@ -156,43 +156,43 @@ class CCommandBuffer int m_ClipH; }; - struct SCommand_Clear : public SCommand + struct CClearCommand : public CCommand { - SCommand_Clear() : SCommand(CMD_CLEAR) {} - SColor m_Color; + CClearCommand() : CCommand(CMD_CLEAR) {} + CColor m_Color; }; - struct SCommand_Signal : public SCommand + struct CSignalCommand : public CCommand { - SCommand_Signal() : SCommand(CMD_SIGNAL) {} + CSignalCommand() : CCommand(CMD_SIGNAL) {} semaphore *m_pSemaphore; }; - struct SCommand_RunBuffer : public SCommand + struct CRunBufferCommand : public CCommand { - SCommand_RunBuffer() : SCommand(CMD_RUNBUFFER) {} + CRunBufferCommand() : CCommand(CMD_RUNBUFFER) {} CCommandBuffer *m_pOtherBuffer; }; - struct SCommand_Render : public SCommand + struct CRenderCommand : public CCommand { - SCommand_Render() : SCommand(CMD_RENDER) {} - SState m_State; + CRenderCommand() : CCommand(CMD_RENDER) {} + CState m_State; unsigned m_PrimType; unsigned m_PrimCount; - SVertex *m_pVertices; // you should use the command buffer data to allocate vertices for this command + CVertex *m_pVertices; // you should use the command buffer data to allocate vertices for this command }; - struct SCommand_Screenshot : public SCommand + struct CScreenshotCommand : public CCommand { - SCommand_Screenshot() : SCommand(CMD_SCREENSHOT) {} + CScreenshotCommand() : CCommand(CMD_SCREENSHOT) {} int m_X, m_Y, m_W, m_H; // specify rectangle size, -1 if fullscreen (width/height) CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well }; - struct SCommand_VideoModes : public SCommand + struct CVideoModesCommand : public CCommand { - SCommand_VideoModes() : SCommand(CMD_VIDEOMODES) {} + CVideoModesCommand() : CCommand(CMD_VIDEOMODES) {} CVideoMode *m_pModes; // processor will fill this in int m_MaxModes; // maximum of modes the processor can write to the m_pModes @@ -200,24 +200,24 @@ class CCommandBuffer int m_Screen; }; - struct SCommand_Swap : public SCommand + struct CSwapCommand : public CCommand { - SCommand_Swap() : SCommand(CMD_SWAP) {} + CSwapCommand() : CCommand(CMD_SWAP) {} int m_Finish; }; - struct SCommand_VSync : public SCommand + struct CVSyncCommand : public CCommand { - SCommand_VSync() : SCommand(CMD_VSYNC) {} + CVSyncCommand() : CCommand(CMD_VSYNC) {} int m_VSync; bool *m_pRetOk; }; - struct SCommand_Texture_Create : public SCommand + struct CTextureCreateCommand : public CCommand { - SCommand_Texture_Create() : SCommand(CMD_TEXTURE_CREATE) {} + CTextureCreateCommand() : CCommand(CMD_TEXTURE_CREATE) {} // texture information int m_Slot; @@ -231,9 +231,9 @@ class CCommandBuffer void *m_pData; // will be freed by the command processor }; - struct SCommand_Texture_Update : public SCommand + struct CTextureUpdateCommand : public CCommand { - SCommand_Texture_Update() : SCommand(CMD_TEXTURE_UPDATE) {} + CTextureUpdateCommand() : CCommand(CMD_TEXTURE_UPDATE) {} // texture information int m_Slot; @@ -247,9 +247,9 @@ class CCommandBuffer }; - struct SCommand_Texture_Destroy : public SCommand + struct CTextureDestroyCommand : public CCommand { - SCommand_Texture_Destroy() : SCommand(CMD_TEXTURE_DESTROY) {} + CTextureDestroyCommand() : CCommand(CMD_TEXTURE_DESTROY) {} // texture information int m_Slot; @@ -270,10 +270,10 @@ class CCommandBuffer bool AddCommand(const T &Command) { // make sure that we don't do something stupid like ->AddCommand(&Cmd); - (void)static_cast(&Command); + (void)static_cast(&Command); // allocate and copy the command into the buffer - SCommand *pCmd = (SCommand *)m_CmdBuffer.Alloc(sizeof(Command)); + CCommand *pCmd = (CCommand *)m_CmdBuffer.Alloc(sizeof(Command)); if(!pCmd) return false; mem_copy(pCmd, &Command, sizeof(Command)); @@ -281,12 +281,12 @@ class CCommandBuffer return true; } - SCommand *GetCommand(unsigned *pIndex) + CCommand *GetCommand(unsigned *pIndex) { if(*pIndex >= m_CmdBuffer.DataUsed()) return NULL; - SCommand *pCommand = (SCommand *)&m_CmdBuffer.DataPtr()[*pIndex]; + CCommand *pCommand = (CCommand *)&m_CmdBuffer.DataPtr()[*pIndex]; *pIndex += pCommand->m_Size; return pCommand; } @@ -351,7 +351,7 @@ class CGraphics_Threaded : public IEngineGraphics DRAWING_LINES=2 }; - CCommandBuffer::SState m_State; + CCommandBuffer::CState m_State; IGraphicsBackend *m_pBackend; CCommandBuffer *m_apCommandBuffers[NUM_CMDBUFFERS]; @@ -363,11 +363,11 @@ class CGraphics_Threaded : public IEngineGraphics class CConfig *m_pConfig; class IConsole *m_pConsole; - CCommandBuffer::SVertex m_aVertices[MAX_VERTICES]; + CCommandBuffer::CVertex m_aVertices[MAX_VERTICES]; int m_NumVertices; - CCommandBuffer::SColor m_aColor[4]; - CCommandBuffer::STexCoord m_aTexture[4]; + CCommandBuffer::CColor m_aColor[4]; + CCommandBuffer::CTexCoord m_aTexture[4]; bool m_RenderEnable; @@ -385,7 +385,7 @@ class CGraphics_Threaded : public IEngineGraphics void FlushVertices(); void AddVertices(int Count); - void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints); + void Rotate4(const CCommandBuffer::CPoint &rCenter, CCommandBuffer::CVertex *pPoints); void KickCommandBuffer(); From 8c54425d42b34ac4fa5433800e5d5406434ac03d Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 26 Mar 2020 17:28:10 +0300 Subject: [PATCH 217/479] Fix #2498 --- src/game/client/components/menus.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 1b5c22c4..cfb933bf 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -653,13 +653,13 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR str_format(aBuf, sizeof(aBuf), "%s: %s", pStr, aLabels[Value]); float FontSize = pRect->h*ms_FontmodHeight*0.8f; - + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Label, ScrollBar; pRect->VSplitLeft(5.0f, 0, &Label); Label.VSplitRight(60.0f, &Label, &ScrollBar); - + Label.y += 2.0f; UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); @@ -884,10 +884,10 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) OffsetX = UI()->MouseX()-Handle.x; } } - else if(UI()->MouseButton(0) && !InsideHandle && InsideRail) + else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail) { - bool Left = UI()->MouseX() < Handle.x + Handle.w/2; - OffsetX = UI()->MouseX() - Handle.x + 8 * (Left ? 1 : -1); + OffsetX = Handle.w * 0.5f; + UI()->SetActiveItem(pID); Grabbed = true; } @@ -2520,7 +2520,7 @@ void CMenus::OnRender() bool CMenus::CheckHotKey(int Key) const { - return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && + return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } From 803211c0afda9f815e0020e3bc108f6ad826dc36 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 26 Mar 2020 21:21:50 +0300 Subject: [PATCH 218/479] Allow adding comments as votes --- src/game/server/gamecontext.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 793a2139..a6f25cd3 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1323,15 +1323,15 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) } // check for valid option - if(!pSelf->Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH) + if((pCommand[0] != '#' && !pSelf->Console()->LineIsValid(pCommand)) || str_length(pCommand) >= VOTE_CMD_LENGTH) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "skipped invalid command '%s'", pCommand); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); return; } - while(*pDescription == ' ') - pDescription++; + + pDescription = str_skip_whitespaces_const(pDescription); if(str_length(pDescription) >= VOTE_DESC_LENGTH || *pDescription == 0) { char aBuf[256]; @@ -1341,8 +1341,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) } // check for duplicate entry - CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst; - while(pOption) + for(CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst; pOption; pOption = pOption->m_pNext) { if(str_comp_nocase(pDescription, pOption->m_aDescription) == 0) { @@ -1351,14 +1350,13 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); return; } - pOption = pOption->m_pNext; } // add the option ++pSelf->m_NumVoteOptions; int Len = str_length(pCommand); - pOption = (CVoteOptionServer *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len); + CVoteOptionServer *pOption = (CVoteOptionServer *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len); pOption->m_pNext = 0; pOption->m_pPrev = pSelf->m_pVoteOptionLast; if(pOption->m_pPrev) From 51ce1e674760c709b44a82c9e58391d5263d13c6 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 26 Mar 2020 22:15:55 +0300 Subject: [PATCH 219/479] Handle depth in descriptions. Fix #2242 --- src/game/client/components/menus.h | 2 ++ src/game/client/components/menus_ingame.cpp | 32 ++++++++++++-------- src/game/client/components/menus_listbox.cpp | 8 +++++ src/game/client/components/voting.cpp | 12 ++++++++ src/game/voting.h | 3 ++ 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 5d23d558..2f635c3f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -241,6 +241,7 @@ class CMenus : public CComponent { bool m_Visible; bool m_Selected; + bool m_Disabled; CUIRect m_Rect; }; @@ -278,6 +279,7 @@ class CMenus : public CComponent void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, const CUIRect *pRect = 0, bool Background = true, bool *pActive = 0); CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = 0); + CListboxItem DoSubheader(); int DoEnd(); bool FilterMatches(const char *pNeedle) const; bool WasItemActivated() const { return m_ListBoxItemActivated; }; diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index dc9080f4..e9b72a1a 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -59,7 +59,7 @@ void CMenus::RenderGame(CUIRect MainView) float Spacing = 3.0f; float ButtonWidth = (MainView.w/6.0f)-(Spacing*5.0)/6.0f; - + // cut view MainView.HSplitTop(20.0f, 0, &MainView); float NoteHeight = !Info.m_aNotification[0] ? 0.0f : 45.0f; @@ -372,7 +372,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) UI()->DoLabel(&Label, Localize("Server info"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); RenderTools()->DrawUIRect(&ServerInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f); ServerInfo.Margin(5.0f, &ServerInfo); - + ServerInfo.HSplitTop(2*ButtonHeight, &Label, &ServerInfo); Label.y += 2.0f; UI()->DoLabel(&Label, CurrentServerInfo.m_aName, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT, Label.w); @@ -381,7 +381,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) Label.y += 2.0f; str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Address"), CurrentServerInfo.m_aHostname); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - + ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo); Label.y += 2.0f; str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency); @@ -396,7 +396,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) Label.y += 2.0f; str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Password"), CurrentServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD ? Localize("Yes", "With") : Localize("No", "Without/None")); UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - + const bool IsFavorite = CurrentServerInfo.m_Favorite; ServerInfo.HSplitBottom(ButtonHeight, &ServerInfo, &Label); static int s_AddFavButton = 0; @@ -508,15 +508,21 @@ bool CMenus::RenderServerControlServer(CUIRect MainView) for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { - if(m_aFilterString[0] && !str_find_nocase(pOption->m_aDescription, m_aFilterString)) + if(m_aFilterString[0] && !pOption->m_IsSubheader && !str_find_nocase(pOption->m_aDescription, m_aFilterString)) continue; // no match found - CListboxItem Item = s_ListBox.DoNextItem(pOption); + if(!pOption->m_aDescription[0]) + continue; // depth resets + + CListboxItem Item = pOption->m_IsSubheader ? s_ListBox.DoSubheader() : s_ListBox.DoNextItem(pOption); if(Item.m_Visible) - { + { Item.m_Rect.VMargin(5.0f, &Item.m_Rect); Item.m_Rect.y += 2.0f; + for(int i = pOption->m_IsSubheader ? 1 : 0; i < pOption->m_Depth; i++) + Item.m_Rect.VSplitLeft(10.0f, 0, &Item.m_Rect); + UI()->DoLabel(&Item.m_Rect, pOption->m_aDescription, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } } @@ -606,9 +612,12 @@ void CMenus::HandleCallvote(int Page, bool Force) int RealIndex = 0, FilteredIndex = 0; for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext, RealIndex++) { - if(m_aFilterString[0] && !str_find_nocase(pOption->m_aDescription, m_aFilterString)) + if(m_aFilterString[0] && !pOption->m_IsSubheader && !str_find_nocase(pOption->m_aDescription, m_aFilterString)) continue; // no match found + if(!pOption->m_aDescription[0]) + continue; // depth reset + if(FilteredIndex == m_CallvoteSelectedOption) break; @@ -723,12 +732,12 @@ void CMenus::RenderServerControl(CUIRect MainView) // render background MainView.HSplitBottom(90.0f+2*20.0f, &MainView, &Extended); RenderTools()->DrawUIRect(&Extended, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - + bool doCallVote = false; // render page if(s_ControlPage == 0) // double click triggers vote if not spectating - doCallVote = RenderServerControlServer(MainView) && m_pClient->m_aClients[m_pClient->m_LocalClientID].m_Team != TEAM_SPECTATORS; + doCallVote = RenderServerControlServer(MainView) && m_pClient->m_aClients[m_pClient->m_LocalClientID].m_Team != TEAM_SPECTATORS; else if(s_ControlPage == 1) RenderServerControlKick(MainView, false); else if(s_ControlPage == 2) @@ -785,7 +794,7 @@ void CMenus::RenderServerControl(CUIRect MainView) m_aCallvoteReason[0] = 0; } } - + if(pNotification == 0) { // call vote @@ -861,4 +870,3 @@ void CMenus::RenderServerControl(CUIRect MainView) } } } - diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 218c8a69..8455c7b4 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -198,6 +198,14 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected return Item; } +CMenus::CListboxItem CMenus::CListBox::DoSubheader() +{ + CListboxItem Item = DoNextRow(); + CUIRect r = Item.m_Rect; + m_pRenderTools->DrawUIRect(&r, vec4(1, 1, 1, 0.2f), 0, 0.0f); + return Item; +} + int CMenus::CListBox::DoEnd() { m_ScrollRegion.End(); diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index c2f60edd..075aa94c 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -120,7 +120,19 @@ void CVoting::AddOption(const char *pDescription) if(!m_pFirst) m_pFirst = pOption; + int Depth = 0; + for(;*pDescription == '#'; pDescription++, Depth++); + pOption->m_Depth = Depth ? Depth : pOption->m_pPrev ? pOption->m_pPrev->m_Depth : 0; + + if(Depth) + pOption->m_IsSubheader = true; + + if(!*pDescription) + pOption->m_Depth = 0; + str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription)); + + dbg_msg("Debug", "Added option '%s' with depth='%d'", pDescription, pOption->m_Depth); ++m_NumVoteOptions; } diff --git a/src/game/voting.h b/src/game/voting.h index f342143d..8b006fef 100644 --- a/src/game/voting.h +++ b/src/game/voting.h @@ -21,6 +21,9 @@ struct CVoteOptionClient CVoteOptionClient *m_pNext; CVoteOptionClient *m_pPrev; char m_aDescription[VOTE_DESC_LENGTH]; + + int m_Depth; + bool m_IsSubheader; }; struct CVoteOptionServer From 233ca9e68ca070ba05d2c1c064b1149ee707c726 Mon Sep 17 00:00:00 2001 From: Learath Date: Fri, 27 Mar 2020 00:28:03 +0300 Subject: [PATCH 220/479] Fix #1860 --- CMakeLists.txt | 8 +- bam.lua | 24 +- src/engine/client/backend_sdl.cpp | 6 +- src/engine/client/client.cpp | 6 - src/osxlaunch/client.h | 14 -- src/osxlaunch/client.m | 373 ------------------------------ 6 files changed, 17 insertions(+), 414 deletions(-) delete mode 100644 src/osxlaunch/client.h delete mode 100644 src/osxlaunch/client.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 23ba81be..b1044a77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,21 +397,15 @@ if(NOT(GTEST_FOUND)) endif() if(TARGET_OS STREQUAL "windows") - set(PLATFORM_CLIENT) set(PLATFORM_CLIENT_LIBS opengl32 winmm) set(PLATFORM_LIBS ws2_32) # Windows sockets elseif(TARGET_OS STREQUAL "mac") find_library(CARBON Carbon) find_library(COCOA Cocoa) find_library(OPENGL OpenGL) - set(PLATFORM_CLIENT - src/osxlaunch/client.h - src/osxlaunch/client.m - ) set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL}) set(PLATFORM_LIBS ${CARBON}) else() - set(PLATFORM_CLIENT) find_package(OpenGL) find_package(X11) set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) @@ -1519,7 +1513,7 @@ if(CLIENT) src/generated/client_data.cpp src/generated/client_data.h ) - set(CLIENT_SRC ${PLATFORM_CLIENT} ${ENGINE_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT}) + set(CLIENT_SRC ${ENGINE_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT}) set(DEPS_CLIENT ${DEPS} ${PNGLITE_DEP} ${WAVPACK_DEP}) diff --git a/bam.lua b/bam.lua index d879883c..1c244363 100644 --- a/bam.lua +++ b/bam.lua @@ -166,7 +166,7 @@ function GenerateMacOSXSettings(settings, conf, arch, compiler) settings.link.frameworks:Add("AGL") -- FIXME: the SDL config is applied in BuildClient too but is needed here before so the launcher will compile config.sdl:Apply(settings) - settings.link.extrafiles:Merge(Compile(settings, "src/osxlaunch/client.m")) + -- settings.link.extrafiles:Merge(Compile(settings, "src/osxlaunch/client.m")) BuildClient(settings) -- Content @@ -349,20 +349,20 @@ end function BuildClient(settings, family, platform) config.sdl:Apply(settings) config.freetype:Apply(settings) - + local client = Compile(settings, Collect("src/engine/client/*.cpp")) - + local game_client = Compile(settings, CollectRecursive("src/game/client/*.cpp"), SharedClientFiles()) local game_editor = Compile(settings, Collect("src/game/editor/*.cpp")) - + Link(settings, "teeworlds", libs["zlib"], libs["md5"], libs["wavpack"], libs["png"], libs["json"], client, game_client, game_editor) end function BuildServer(settings, family, platform) local server = Compile(settings, Collect("src/engine/server/*.cpp")) - + local game_server = Compile(settings, CollectRecursive("src/game/server/*.cpp"), SharedServerFiles()) - + return Link(settings, "teeworlds_srv", libs["zlib"], libs["md5"], server, game_server) end @@ -423,7 +423,7 @@ function GenerateSettings(conf, arch, builddir, compiler) config.compiler:Apply(settings) compiler = config.compiler.driver end - + if conf == "debug" then settings.debug = 1 settings.optimize = 0 @@ -433,25 +433,25 @@ function GenerateSettings(conf, arch, builddir, compiler) settings.optimize = 1 settings.cc.defines:Add("CONF_RELEASE") end - + -- Generate object files in {builddir}/objs/ settings.cc.Output = function (settings_, input) - -- strip + -- strip input = input:gsub("^src/", "") input = input:gsub("^" .. generated_src_dir .. "/", "") return PathJoin(PathJoin(builddir, "objs"), PathBase(input)) end - + -- Build output files in {builddir} settings.link.Output = function (settings_, input) return PathJoin(builddir, PathBase(input) .. settings_.config_ext) end - + settings.cc.includes:Add("src") settings.cc.includes:Add("src/engine/external/pnglite") settings.cc.includes:Add("src/engine/external/wavpack") settings.cc.includes:Add(generated_src_dir) - + if family == "windows" then GenerateWindowsSettings(settings, conf, arch, compiler) elseif family == "unix" then diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 81c975af..6e633943 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -699,9 +699,11 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin SdlFlags |= SDL_WINDOW_BORDERLESS; if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN) #if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen) + { SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; // always use "fake" fullscreen - *pWindowWidth = *pDesktopWidth; - *pWindowHeight = *pDesktopHeight; + *pWindowWidth = *pDesktopWidth; + *pWindowHeight = *pDesktopHeight; + } #else SdlFlags |= SDL_WINDOW_FULLSCREEN; #endif diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 574a8159..71f02310 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2529,14 +2529,8 @@ void CClient::DoVersionSpecificActions() Prediction Latency Upstream latency */ -#if defined(CONF_PLATFORM_MACOSX) -extern "C" int SDL_main(int argc, char **argv_) // ignore_convention -{ - const char **argv = const_cast(argv_); -#else int main(int argc, const char **argv) // ignore_convention { -#endif #if defined(CONF_FAMILY_WINDOWS) bool QuickEditMode = false; for(int i = 1; i < argc; i++) // ignore_convention diff --git a/src/osxlaunch/client.h b/src/osxlaunch/client.h deleted file mode 100644 index 0afe1fe6..00000000 --- a/src/osxlaunch/client.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef OSXLAUNCH_CLIENT_H -#define OSXLAUNCH_CLIENT_H -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - -@interface SDLMain : NSObject -@end -#endif diff --git a/src/osxlaunch/client.m b/src/osxlaunch/client.m deleted file mode 100644 index e8933c1a..00000000 --- a/src/osxlaunch/client.m +++ /dev/null @@ -1,373 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import -#import "client.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface TWSDLApplication : NSApplication -@end - -@implementation TWSDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - [[NSFileManager defaultManager] changeCurrentDirectoryPath:resourcePath]; -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [TWSDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [TWSDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [[NSApplication sharedApplication] setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - -#ifdef main -#undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [TWSDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - - return 0; -} - From 4d1862117c0591db2b1dd967c3e2c3898f5878a3 Mon Sep 17 00:00:00 2001 From: Learath Date: Fri, 27 Mar 2020 14:28:15 +0300 Subject: [PATCH 221/479] Allow empty commands too --- src/engine/shared/console.cpp | 6 +++++- src/game/client/components/voting.cpp | 4 +++- src/game/server/gamecontext.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 07caaf84..43eb7521 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -257,9 +257,13 @@ void CConsole::Print(int Level, const char *pFrom, const char *pStr, bool Highli bool CConsole::LineIsValid(const char *pStr) { - if(!pStr || *pStr == 0) + if(!pStr) return false; + // Comments and empty lines are valid commands + if(*pStr == '#' || *pStr == '\0') + return true; + do { CResult Result; diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index 075aa94c..af8582d5 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -132,7 +132,9 @@ void CVoting::AddOption(const char *pDescription) str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription)); - dbg_msg("Debug", "Added option '%s' with depth='%d'", pDescription, pOption->m_Depth); + if(Config()->m_Debug) + dbg_msg("voting", "added option '%s' with depth='%d'", pDescription, pOption->m_Depth); + ++m_NumVoteOptions; } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index a6f25cd3..3fdfb1a3 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1323,7 +1323,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) } // check for valid option - if((pCommand[0] != '#' && !pSelf->Console()->LineIsValid(pCommand)) || str_length(pCommand) >= VOTE_CMD_LENGTH) + if(!pSelf->Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "skipped invalid command '%s'", pCommand); From 14b96a4609f803588d8ad7c02d81e24a7567a019 Mon Sep 17 00:00:00 2001 From: Learath Date: Sat, 28 Mar 2020 01:26:42 +0300 Subject: [PATCH 222/479] Streamline the platform client --- CMakeLists.txt | 7 ++++++- bam.lua | 24 ++++++++++++------------ src/engine/client/backend_sdl.cpp | 6 ++---- src/engine/client/client.cpp | 4 ++++ src/osxlaunch/client.m | 23 +++++++++++++++++++++++ 5 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 src/osxlaunch/client.m diff --git a/CMakeLists.txt b/CMakeLists.txt index b1044a77..c1f941de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,15 +397,20 @@ if(NOT(GTEST_FOUND)) endif() if(TARGET_OS STREQUAL "windows") + set(PLATFORM_CLIENT) set(PLATFORM_CLIENT_LIBS opengl32 winmm) set(PLATFORM_LIBS ws2_32) # Windows sockets elseif(TARGET_OS STREQUAL "mac") find_library(CARBON Carbon) find_library(COCOA Cocoa) find_library(OPENGL OpenGL) + set(PLATFORM_CLIENT + src/osxlaunch/client.m + ) set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL}) set(PLATFORM_LIBS ${CARBON}) else() + set(PLATFORM_CLIENT) find_package(OpenGL) find_package(X11) set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) @@ -1513,7 +1518,7 @@ if(CLIENT) src/generated/client_data.cpp src/generated/client_data.h ) - set(CLIENT_SRC ${ENGINE_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT}) + set(CLIENT_SRC ${PLATFORM_CLIENT} ${ENGINE_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT}) set(DEPS_CLIENT ${DEPS} ${PNGLITE_DEP} ${WAVPACK_DEP}) diff --git a/bam.lua b/bam.lua index 1c244363..d879883c 100644 --- a/bam.lua +++ b/bam.lua @@ -166,7 +166,7 @@ function GenerateMacOSXSettings(settings, conf, arch, compiler) settings.link.frameworks:Add("AGL") -- FIXME: the SDL config is applied in BuildClient too but is needed here before so the launcher will compile config.sdl:Apply(settings) - -- settings.link.extrafiles:Merge(Compile(settings, "src/osxlaunch/client.m")) + settings.link.extrafiles:Merge(Compile(settings, "src/osxlaunch/client.m")) BuildClient(settings) -- Content @@ -349,20 +349,20 @@ end function BuildClient(settings, family, platform) config.sdl:Apply(settings) config.freetype:Apply(settings) - + local client = Compile(settings, Collect("src/engine/client/*.cpp")) - + local game_client = Compile(settings, CollectRecursive("src/game/client/*.cpp"), SharedClientFiles()) local game_editor = Compile(settings, Collect("src/game/editor/*.cpp")) - + Link(settings, "teeworlds", libs["zlib"], libs["md5"], libs["wavpack"], libs["png"], libs["json"], client, game_client, game_editor) end function BuildServer(settings, family, platform) local server = Compile(settings, Collect("src/engine/server/*.cpp")) - + local game_server = Compile(settings, CollectRecursive("src/game/server/*.cpp"), SharedServerFiles()) - + return Link(settings, "teeworlds_srv", libs["zlib"], libs["md5"], server, game_server) end @@ -423,7 +423,7 @@ function GenerateSettings(conf, arch, builddir, compiler) config.compiler:Apply(settings) compiler = config.compiler.driver end - + if conf == "debug" then settings.debug = 1 settings.optimize = 0 @@ -433,25 +433,25 @@ function GenerateSettings(conf, arch, builddir, compiler) settings.optimize = 1 settings.cc.defines:Add("CONF_RELEASE") end - + -- Generate object files in {builddir}/objs/ settings.cc.Output = function (settings_, input) - -- strip + -- strip input = input:gsub("^src/", "") input = input:gsub("^" .. generated_src_dir .. "/", "") return PathJoin(PathJoin(builddir, "objs"), PathBase(input)) end - + -- Build output files in {builddir} settings.link.Output = function (settings_, input) return PathJoin(builddir, PathBase(input) .. settings_.config_ext) end - + settings.cc.includes:Add("src") settings.cc.includes:Add("src/engine/external/pnglite") settings.cc.includes:Add("src/engine/external/wavpack") settings.cc.includes:Add(generated_src_dir) - + if family == "windows" then GenerateWindowsSettings(settings, conf, arch, compiler) elseif family == "unix" then diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 6e633943..81c975af 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -699,11 +699,9 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin SdlFlags |= SDL_WINDOW_BORDERLESS; if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN) #if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen) - { SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; // always use "fake" fullscreen - *pWindowWidth = *pDesktopWidth; - *pWindowHeight = *pDesktopHeight; - } + *pWindowWidth = *pDesktopWidth; + *pWindowHeight = *pDesktopHeight; #else SdlFlags |= SDL_WINDOW_FULLSCREEN; #endif diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 71f02310..fa16f648 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2529,7 +2529,11 @@ void CClient::DoVersionSpecificActions() Prediction Latency Upstream latency */ +#if defined(CONF_PLATFORM_MACOSX) +extern "C" int TWMain(int argc, const char **argv) // ignore_convention +#else int main(int argc, const char **argv) // ignore_convention +#endif { #if defined(CONF_FAMILY_WINDOWS) bool QuickEditMode = false; diff --git a/src/osxlaunch/client.m b/src/osxlaunch/client.m new file mode 100644 index 00000000..cfd62570 --- /dev/null +++ b/src/osxlaunch/client.m @@ -0,0 +1,23 @@ +#import +#include + +extern int TWMain(int argc, const char **argv); + +int main(int argc, const char **argv) +{ + BOOL FinderLaunch = argc >= 2 && !str_comp_num(argv[1], "-psn", 4); + + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + if(!resourcePath) + return -1; + + [[NSFileManager defaultManager] changeCurrentDirectoryPath:resourcePath]; + + if(FinderLaunch) + { + const char *paArgv[2] = { argv[0], NULL }; + return TWMain(1, paArgv); + } + else + return TWMain(argc, argv); +} From b77132aab333be0aafdec00986573f402ec5a4db Mon Sep 17 00:00:00 2001 From: sirius Date: Tue, 31 Mar 2020 13:10:09 +0800 Subject: [PATCH 223/479] add skip for space char u3000 --- src/base/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index 2f356b77..0c8f7983 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2356,7 +2356,7 @@ int str_utf8_is_whitespace(int code) { // check if unicode is not empty if(code > 0x20 && code != 0xA0 && code != 0x034F && (code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) && - (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0xFE00 || code > 0xFE0F) && + (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0x2FFF || code > 0x3001) && (code < 0xFE00 || code > 0xFE0F) && code != 0xFEFF && (code < 0xFFF9 || code > 0xFFFC)) { return 0; From 7d03e50ad88adff6d9a68226b4dec516becfe837 Mon Sep 17 00:00:00 2001 From: sirius Date: Tue, 31 Mar 2020 13:20:28 +0800 Subject: [PATCH 224/479] range change to U+2FFC~U+3000 --- src/base/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index 0c8f7983..cc98c9f8 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2356,7 +2356,7 @@ int str_utf8_is_whitespace(int code) { // check if unicode is not empty if(code > 0x20 && code != 0xA0 && code != 0x034F && (code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) && - (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0x2FFF || code > 0x3001) && (code < 0xFE00 || code > 0xFE0F) && + (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0x2FFC || code > 0x3000) && (code < 0xFE00 || code > 0xFE0F) && code != 0xFEFF && (code < 0xFFF9 || code > 0xFFFC)) { return 0; From dbf6c45afb1bcc37eb4dd9262f1a700c9fd0fe71 Mon Sep 17 00:00:00 2001 From: sirius Date: Tue, 31 Mar 2020 22:33:36 +0800 Subject: [PATCH 225/479] range change to only U+3000 --- src/base/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index cc98c9f8..9a1a042a 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2356,7 +2356,7 @@ int str_utf8_is_whitespace(int code) { // check if unicode is not empty if(code > 0x20 && code != 0xA0 && code != 0x034F && (code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) && - (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0x2FFC || code > 0x3000) && (code < 0xFE00 || code > 0xFE0F) && + (code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && code != 0x3000 && (code < 0xFE00 || code > 0xFE0F) && code != 0xFEFF && (code < 0xFFF9 || code > 0xFFFC)) { return 0; From 3c219e8184be10faa7b601dc907463155dfbfc48 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 1 Apr 2020 16:43:06 +0300 Subject: [PATCH 226/479] Fix small bug --- src/game/client/components/chat.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 8d519809..197711a2 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -257,7 +257,7 @@ bool CChat::OnInput(IInput::CEvent Event) } else if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)) { - if(IsTypingCommand() && ExecuteCommand(true)) + if(IsTypingCommand() && m_SelectedCommand >= 0 && ExecuteCommand(true)) { // everything is handled within } @@ -292,7 +292,7 @@ bool CChat::OnInput(IInput::CEvent Event) } if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_TAB) { - if(IsTypingCommand() && ExecuteCommand(false)) + if(IsTypingCommand() && m_SelectedCommand >= 0 && ExecuteCommand(false)) { // everything is handled within } @@ -1353,7 +1353,11 @@ void CChat::HandleCommands(float x, float y, float w) NextActiveCommand(&m_CommandStart); } - if(DisplayCount > 0) // at least one command to display + if(!DisplayCount) + { + m_SelectedCommand = -1; + } + else { CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth, (DisplayCount+1)*LineHeight}; RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_ALL, 3.0f); From d294fb11dfb27b0dda22922091cc4aaed1352b30 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 1 Apr 2020 19:07:27 +0300 Subject: [PATCH 227/479] Clean up RegisterCommands --- src/engine/server/server.cpp | 16 ++++++++++------ src/engine/server/server.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 0dd0f878..66c90dc0 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1284,6 +1284,15 @@ void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterS m_Register.Init(pNetServer, pMasterServer, pConfig, pConsole); } +void CServer::InitInterfaces(CConfig *pConfig, IConsole *pConsole, IGameServer *pGameServer, IEngineMap *pMap, IStorage *pStorage) +{ + m_pConfig = pConfig; + m_pConsole = pConsole; + m_pGameServer = pGameServer; + m_pMap = pMap; + m_pStorage = pStorage; +} + int CServer::Run() { // @@ -1738,12 +1747,6 @@ void CServer::ConchainRconPasswordSet(IConsole::IResult *pResult, void *pUserDat void CServer::RegisterCommands() { - m_pConfig = Kernel()->RequestInterface()->Values(); - m_pConsole = Kernel()->RequestInterface(); - m_pGameServer = Kernel()->RequestInterface(); - m_pMap = Kernel()->RequestInterface(); - m_pStorage = Kernel()->RequestInterface(); - // register console commands Console()->Register("kick", "i[id] ?r[reason]", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason"); Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players"); @@ -1865,6 +1868,7 @@ int main(int argc, const char **argv) // ignore_convention pEngineMasterServer->Init(); pEngineMasterServer->Load(); + pServer->InitInterfaces(pConfigManager->Values(), pConsole, pGameServer, pEngineMap, pStorage); if(!UseDefaultConfig) { // register all console commands diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 7e8d3415..4516f0e6 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -257,6 +257,7 @@ class CServer : public IServer int LoadMap(const char *pMapName); void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, CConfig *pConfig, IConsole *pConsole); + void InitInterfaces(CConfig *pConfig, IConsole *pConsole, IGameServer *pGameServer, IEngineMap *pMap, IStorage *pStorage); int Run(); static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser); From d95b2069a4e27eb4f54cb4e4908ec5fee91fef3e Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 1 Apr 2020 19:14:27 +0300 Subject: [PATCH 228/479] Don't return if the client doesn't fit I hope you won't reject this just out of spite to goto, this is a legitimate shortcoming of the language. --- src/engine/shared/network_server.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index b4184fae..70b008c7 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -19,7 +19,7 @@ bool CNetServer::Open(NETADDR BindAddr, CConfig *pConfig, IConsole *pConsole, IE NETSOCKET Socket = net_udp_create(BindAddr, 0); if(!Socket.type) return false; - + // init m_pNetBan = pNetBan; Init(Socket, pConfig, pConsole, pEngine); @@ -95,6 +95,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { while(1) { + loopbegin: // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; @@ -191,7 +192,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP); SendControlMsg(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); - return 0; + goto loopbegin; } } } @@ -207,7 +208,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) m_pfnNewClient(i, m_UserPtr); break; } - } + } } else if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_TOKEN) m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, NET_TOKENFLAG_RESPONSEONLY); From cd96bda72a9228849ac14199e3daaff906341223 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 2 Apr 2020 13:25:37 +0300 Subject: [PATCH 229/479] Don't hardcode 28.0f in CCharacter either --- src/game/gamecore.cpp | 23 +++++++++++------------ src/game/gamecore.h | 1 + src/game/server/entities/character.cpp | 7 ++++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index ee05c538..485af420 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -55,6 +55,8 @@ float VelocityRamp(float Value, float Start, float Range, float Curvature) return 1.0f/powf(Curvature, (Value-Start)/Range); } +const float CCharacterCore::PHYS_SIZE = 28.0f; + void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision) { m_pWorld = pWorld; @@ -77,14 +79,13 @@ void CCharacterCore::Reset() void CCharacterCore::Tick(bool UseInput) { - float PhysSize = 28.0f; m_TriggeredEvents = 0; // get ground state bool Grounded = false; - if(m_pCollision->CheckPoint(m_Pos.x+PhysSize/2, m_Pos.y+PhysSize/2+5)) + if(m_pCollision->CheckPoint(m_Pos.x+PHYS_SIZE/2, m_Pos.y+PHYS_SIZE/2+5)) Grounded = true; - if(m_pCollision->CheckPoint(m_Pos.x-PhysSize/2, m_Pos.y+PhysSize/2+5)) + if(m_pCollision->CheckPoint(m_Pos.x-PHYS_SIZE/2, m_Pos.y+PHYS_SIZE/2+5)) Grounded = true; vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY)); @@ -129,7 +130,7 @@ void CCharacterCore::Tick(bool UseInput) if(m_HookState == HOOK_IDLE) { m_HookState = HOOK_FLYING; - m_HookPos = m_Pos+TargetDirection*PhysSize*1.5f; + m_HookPos = m_Pos+TargetDirection*PHYS_SIZE*1.5f; m_HookDir = TargetDirection; m_HookedPlayer = -1; m_HookTick = 0; @@ -206,7 +207,7 @@ void CCharacterCore::Tick(bool UseInput) continue; vec2 ClosestPoint = closest_point_on_line(m_HookPos, NewPos, pCharCore->m_Pos); - if(distance(pCharCore->m_Pos, ClosestPoint) < PhysSize+2.0f) + if(distance(pCharCore->m_Pos, ClosestPoint) < PHYS_SIZE+2.0f) { if (m_HookedPlayer == -1 || distance(m_HookPos, pCharCore->m_Pos) < Distance) { @@ -306,9 +307,9 @@ void CCharacterCore::Tick(bool UseInput) // handle player <-> player collision float Distance = distance(m_Pos, pCharCore->m_Pos); vec2 Dir = normalize(m_Pos - pCharCore->m_Pos); - if(m_pWorld->m_Tuning.m_PlayerCollision && Distance < PhysSize*1.25f && Distance > 0.0f) + if(m_pWorld->m_Tuning.m_PlayerCollision && Distance < PHYS_SIZE*1.25f && Distance > 0.0f) { - float a = (PhysSize*1.45f - Distance); + float a = (PHYS_SIZE*1.45f - Distance); float Velocity = 0.5f; // make sure that we don't add excess force by checking the @@ -323,7 +324,7 @@ void CCharacterCore::Tick(bool UseInput) // handle hook influence if(m_HookedPlayer == i && m_pWorld->m_Tuning.m_PlayerHooking) { - if(Distance > PhysSize*1.50f) // TODO: fix tweakable variable + if(Distance > PHYS_SIZE*1.50f) // TODO: fix tweakable variable { float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (Distance/m_pWorld->m_Tuning.m_HookLength); float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; @@ -350,13 +351,12 @@ void CCharacterCore::Move() if(!m_pWorld) return; - float PhysSize = 28.0f; float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); m_Vel.x = m_Vel.x*RampValue; vec2 NewPos = m_Pos; - m_pCollision->MoveBox(&NewPos, &m_Vel, vec2(PhysSize, PhysSize), 0, &m_Death); + m_pCollision->MoveBox(&NewPos, &m_Vel, vec2(PHYS_SIZE, PHYS_SIZE), 0, &m_Death); m_Vel.x = m_Vel.x*(1.0f/RampValue); @@ -376,7 +376,7 @@ void CCharacterCore::Move() if(!pCharCore || pCharCore == this) continue; float D = distance(Pos, pCharCore->m_Pos); - if(D < PhysSize && D >= 0.0f) + if(D < PHYS_SIZE && D >= 0.0f) { if(a > 0.0f) m_Pos = LastPos; @@ -435,4 +435,3 @@ void CCharacterCore::Quantize() Write(&Core); Read(&Core); } - diff --git a/src/game/gamecore.h b/src/game/gamecore.h index b40237d9..cede7f73 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -147,6 +147,7 @@ class CCharacterCore CWorldCore *m_pWorld; CCollision *m_pCollision; public: + static const float PHYS_SIZE; vec2 m_Pos; vec2 m_Vel; diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 4d170dac..7f938a19 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -547,6 +547,7 @@ void CCharacter::Tick() void CCharacter::TickDefered() { + static const vec2 ColBox(CCharacterCore::PHYS_SIZE, CCharacterCore::PHYS_SIZE); // advance the dummy { CWorldCore TempWorld; @@ -559,13 +560,13 @@ void CCharacter::TickDefered() //lastsentcore vec2 StartPos = m_Core.m_Pos; vec2 StartVel = m_Core.m_Vel; - bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, ColBox); m_Core.Move(); - bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, ColBox); m_Core.Quantize(); - bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, ColBox); m_Pos = m_Core.m_Pos; if(!StuckBefore && (StuckAfterMove || StuckAfterQuant)) From 06db9bf53fd2df9ae3c251e9435cc7e9a8bc7df5 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 2 Apr 2020 13:28:23 +0300 Subject: [PATCH 230/479] Use the servers tuning in EvolveCharacter --- src/game/client/gameclient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 66c3026c..3cfc7cc2 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -534,6 +534,8 @@ void CGameClient::UpdatePositions() void CGameClient::EvolveCharacter(CNetObj_Character *pCharacter, int Tick) { CWorldCore TempWorld; + TempWorld.m_Tuning = m_Tuning; + CCharacterCore TempCore; mem_zero(&TempCore, sizeof(TempCore)); TempCore.Init(&TempWorld, Collision()); From cdc708150fcc604c1537bd949ae4670ddad6f8b1 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 2 Apr 2020 13:31:52 +0300 Subject: [PATCH 231/479] Use SetEmote in CCharacter --- src/game/server/entities/character.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 7f938a19..fcf1236c 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -784,8 +784,7 @@ bool CCharacter::TakeDamage(vec2 Force, vec2 Source, int Dmg, int From, int Weap CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter(); if (pChr) { - pChr->m_EmoteType = EMOTE_HAPPY; - pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed(); + pChr->SetEmote(EMOTE_HAPPY, Server()->Tick() + Server()->TickSpeed()); } } @@ -797,8 +796,7 @@ bool CCharacter::TakeDamage(vec2 Force, vec2 Source, int Dmg, int From, int Weap else GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT); - m_EmoteType = EMOTE_PAIN; - m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000; + SetEmote(EMOTE_PAIN, Server()->Tick() + 500 * Server()->TickSpeed() / 1000); return true; } @@ -829,8 +827,7 @@ void CCharacter::Snap(int SnappingClient) // set emote if (m_EmoteStop < Server()->Tick()) { - m_EmoteType = EMOTE_NORMAL; - m_EmoteStop = -1; + SetEmote(EMOTE_NORMAL, -1); } pCharacter->m_Emote = m_EmoteType; From 0a7d0fee7ca11ea3cfa1effd28a6aa06b5f50821 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 2 Apr 2020 14:14:28 +0300 Subject: [PATCH 232/479] Move MAX_PATH_LENGTH to a more central place --- src/base/system.h | 4 +- src/engine/client/client.h | 6 +- src/engine/client/graphics_threaded.cpp | 4 +- src/engine/client/text.cpp | 2 +- src/engine/server/server.cpp | 6 +- src/engine/shared/demo.cpp | 2 +- src/engine/shared/filecollection.cpp | 2 +- src/engine/shared/filecollection.h | 2 +- src/engine/shared/mapchecker.cpp | 2 +- src/engine/shared/storage.cpp | 65 +++++++++---------- src/game/client/components/mapimages.cpp | 2 +- src/game/client/components/maplayers.cpp | 2 +- src/game/client/components/menus.cpp | 16 ++--- src/game/client/components/menus.h | 4 +- src/game/client/components/menus_browser.cpp | 30 ++++----- src/game/client/components/menus_demo.cpp | 10 +-- src/game/client/components/menus_settings.cpp | 10 +-- src/game/client/components/skins.cpp | 6 +- src/game/client/gameclient.cpp | 4 +- src/game/editor/editor.cpp | 10 +-- src/game/editor/editor.h | 22 +++---- src/game/editor/io.cpp | 6 +- src/game/editor/popups.cpp | 8 +-- 23 files changed, 112 insertions(+), 113 deletions(-) diff --git a/src/base/system.h b/src/base/system.h index c15802d2..f08a9e37 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -200,7 +200,9 @@ enum { IOSEEK_START = 0, IOSEEK_CUR = 1, - IOSEEK_END = 2 + IOSEEK_END = 2, + + IO_MAX_PATH_LENGTH = 512, }; typedef struct IOINTERNAL *IOHANDLE; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index afaf8a52..a49a04bd 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -116,7 +116,7 @@ class CClient : public IClient, public CDemoPlayer::IListener // char m_aCurrentMap[256]; - char m_aCurrentMapPath[256]; + char m_aCurrentMapPath[IO_MAX_PATH_LENGTH]; SHA256_DIGEST m_CurrentMapSha256; unsigned m_CurrentMapCrc; @@ -124,8 +124,8 @@ class CClient : public IClient, public CDemoPlayer::IListener char m_aCmdConnect[256]; // map download - char m_aMapdownloadFilename[256]; - char m_aMapdownloadName[256]; + char m_aMapdownloadFilename[IO_MAX_PATH_LENGTH]; + char m_aMapdownloadName[IO_MAX_PATH_LENGTH]; IOHANDLE m_MapdownloadFile; int m_MapdownloadChunk; int m_MapdownloadChunkNum; diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index fa4f2b00..4169b07e 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -407,7 +407,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTexture(const char *pFilename, int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType) { - char aCompleteFilename[512]; + char aCompleteFilename[IO_MAX_PATH_LENGTH]; unsigned char *pBuffer; png_t Png; // ignore_convention @@ -617,7 +617,7 @@ void CGraphics_Threaded::QuadsSetSubsetFree( // tileset fallback system if(m_pBackend->GetTextureArraySize() > 1 && TextureIndex >= 0) TilesetFallbackSystem(TextureIndex); - + m_State.m_TextureArrayIndex = m_TextureArrayIndex; m_aTexture[0].u = x0; m_aTexture[0].v = y0; diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index a9018c7f..f37d18b0 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -62,7 +62,7 @@ struct CFontSizeData class CFont { public: - char m_aFilename[512]; + char m_aFilename[IO_MAX_PATH_LENGTH]; FT_Face m_FtFace; CFontSizeData m_aSizes[NUM_FONT_SIZES]; }; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 66c90dc0..d457e2e8 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1234,7 +1234,7 @@ const char *CServer::GetMapName() int CServer::LoadMap(const char *pMapName) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName); // check for valid standard map @@ -1506,7 +1506,7 @@ int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, if(pFilename[0] == '.') // hidden files return 0; - char aFilename[512]; + char aFilename[IO_MAX_PATH_LENGTH]; if(pUserdata->m_aName[0]) str_format(aFilename, sizeof(aFilename), "%s/%s", pUserdata->m_aName, pFilename); else @@ -1517,7 +1517,7 @@ int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, CSubdirCallbackUserdata Userdata; Userdata.m_pServer = pThis; str_copy(Userdata.m_aName, aFilename, sizeof(Userdata.m_aName)); - char FindPath[512]; + char FindPath[IO_MAX_PATH_LENGTH]; str_format(FindPath, sizeof(FindPath), "maps/%s/", aFilename); pThis->m_pStorage->ListDirectory(IStorage::TYPE_ALL, FindPath, MapListEntryCallback, &Userdata); return 0; diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 93a44c48..552d925b 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -57,7 +57,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con if(!MapFile) { // search for the map within subfolders - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aMapFilename, sizeof(aMapFilename), "%s.map", pMap); if(pStorage->FindFile(aMapFilename, "maps", IStorage::TYPE_ALL, aBuf, sizeof(aBuf))) MapFile = pStorage->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL, 0, 0, CDataFileReader::CheckSha256, &Sha256); diff --git a/src/engine/shared/filecollection.cpp b/src/engine/shared/filecollection.cpp index 622534f2..9a0ed2ca 100644 --- a/src/engine/shared/filecollection.cpp +++ b/src/engine/shared/filecollection.cpp @@ -111,7 +111,7 @@ void CFileCollection::AddEntry(int64 Timestamp) // remove old file if(m_NumTimestamps == m_MaxEntries) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; char aTimestring[TIMESTAMP_LENGTH]; BuildTimestring(m_aTimestamps[0], aTimestring); str_format(aBuf, sizeof(aBuf), "%s/%s_%s%s", m_aPath, m_aFileDesc, aTimestring, m_aFileExt); diff --git a/src/engine/shared/filecollection.h b/src/engine/shared/filecollection.h index ac633892..47206c24 100644 --- a/src/engine/shared/filecollection.h +++ b/src/engine/shared/filecollection.h @@ -18,7 +18,7 @@ class CFileCollection int m_FileDescLength; char m_aFileExt[32]; int m_FileExtLength; - char m_aPath[512]; + char m_aPath[IO_MAX_PATH_LENGTH]; IStorage *m_pStorage; bool IsFilenameValid(const char *pFilename); diff --git a/src/engine/shared/mapchecker.cpp b/src/engine/shared/mapchecker.cpp index 59262e9e..e027d89a 100644 --- a/src/engine/shared/mapchecker.cpp +++ b/src/engine/shared/mapchecker.cpp @@ -92,7 +92,7 @@ bool CMapChecker::ReadAndValidateMap(IStorage *pStorage, const char *pFilename, if(str_comp(pCurrent->m_aMapName, aMapName) == 0) { StandardMap = true; - char aBuffer[512]; // TODO: MAX_PATH_LENGTH (512) should be defined in a more central header and not in storage.cpp and editor.h + char aBuffer[IO_MAX_PATH_LENGTH]; if(pStorage->FindFile(aMapNameExt, "maps", StorageType, aBuffer, sizeof(aBuffer), &pCurrent->m_MapSha256, pCurrent->m_MapCrc, pCurrent->m_MapSize)) return true; } diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 84cebef5..f646f3e7 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -14,17 +14,16 @@ class CStorage : public IStorage public: enum { - MAX_PATHS = 16, - MAX_PATH_LENGTH = 512 + MAX_PATHS = 16 }; - char m_aaStoragePaths[MAX_PATHS][MAX_PATH_LENGTH]; + char m_aaStoragePaths[MAX_PATHS][IO_MAX_PATH_LENGTH]; int m_NumPaths; - char m_aDataDir[MAX_PATH_LENGTH]; - char m_aUserDir[MAX_PATH_LENGTH]; - char m_aCurrentDir[MAX_PATH_LENGTH]; - char m_aAppDir[MAX_PATH_LENGTH]; - + char m_aDataDir[IO_MAX_PATH_LENGTH]; + char m_aUserDir[IO_MAX_PATH_LENGTH]; + char m_aCurrentDir[IO_MAX_PATH_LENGTH]; + char m_aAppDir[IO_MAX_PATH_LENGTH]; + CStorage() { mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths)); @@ -39,7 +38,7 @@ class CStorage : public IStorage { // get userdir fs_storage_path(pApplicationName, m_aUserDir, sizeof(m_aUserDir)); - + // get appdir FindAppDir(ppArguments[0]); @@ -64,7 +63,7 @@ class CStorage : public IStorage { if(m_NumPaths && (!m_aaStoragePaths[TYPE_SAVE][0] || !fs_makedir_recursive(m_aaStoragePaths[TYPE_SAVE]))) { - char aPath[MAX_PATH_LENGTH]; + char aPath[IO_MAX_PATH_LENGTH]; if(StorageType == STORAGETYPE_CLIENT) { fs_makedir(GetPath(TYPE_SAVE, "screenshots", aPath, sizeof(aPath))); @@ -95,7 +94,7 @@ class CStorage : public IStorage if(!File) { // check usable path in argv[0] - char aBuffer[MAX_PATH_LENGTH]; + char aBuffer[IO_MAX_PATH_LENGTH]; str_copy(aBuffer, m_aAppDir, sizeof(aBuffer)); str_append(aBuffer, "/storage.cfg", sizeof(aBuffer)); File = io_open(aBuffer, IOFLAG_READ); @@ -154,7 +153,7 @@ class CStorage : public IStorage { if(!IsDuplicatePath(m_aUserDir)) { - str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserDir, MAX_PATH_LENGTH); + str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserDir, IO_MAX_PATH_LENGTH); dbg_msg("storage", "added path '$USERDIR' ('%s')", m_aUserDir); } else @@ -167,7 +166,7 @@ class CStorage : public IStorage { if(!IsDuplicatePath(m_aDataDir)) { - str_copy(m_aaStoragePaths[m_NumPaths++], m_aDataDir, MAX_PATH_LENGTH); + str_copy(m_aaStoragePaths[m_NumPaths++], m_aDataDir, IO_MAX_PATH_LENGTH); dbg_msg("storage", "added path '$DATADIR' ('%s')", m_aDataDir); } else @@ -180,7 +179,7 @@ class CStorage : public IStorage { if(!IsDuplicatePath(m_aCurrentDir)) { - str_copy(m_aaStoragePaths[m_NumPaths++], m_aCurrentDir, MAX_PATH_LENGTH); + str_copy(m_aaStoragePaths[m_NumPaths++], m_aCurrentDir, IO_MAX_PATH_LENGTH); dbg_msg("storage", "added path '$CURRENTDIR' ('%s')", m_aCurrentDir); } else @@ -193,7 +192,7 @@ class CStorage : public IStorage { if(!IsDuplicatePath(m_aAppDir)) { - str_copy(m_aaStoragePaths[m_NumPaths++], m_aAppDir, MAX_PATH_LENGTH); + str_copy(m_aaStoragePaths[m_NumPaths++], m_aAppDir, IO_MAX_PATH_LENGTH); dbg_msg("storage", "added path '$APPDIR' ('%s')", m_aAppDir); } else @@ -206,7 +205,7 @@ class CStorage : public IStorage { if(!IsDuplicatePath(pPath)) { - str_copy(m_aaStoragePaths[m_NumPaths++], pPath, MAX_PATH_LENGTH); + str_copy(m_aaStoragePaths[m_NumPaths++], pPath, IO_MAX_PATH_LENGTH); dbg_msg("storage", "added path '%s'", pPath); } else @@ -214,7 +213,7 @@ class CStorage : public IStorage } } } - + void FindAppDir(const char *pArgv0) { // check for usable path in argv[0] @@ -222,8 +221,8 @@ class CStorage : public IStorage for(unsigned i = 0; pArgv0[i]; ++i) if(pArgv0[i] == '/' || pArgv0[i] == '\\') Pos = i; - - if(Pos < MAX_PATH_LENGTH) + + if(Pos < IO_MAX_PATH_LENGTH) { str_copy(m_aAppDir, pArgv0, Pos+1); if(!fs_is_dir(m_aAppDir)) @@ -249,7 +248,7 @@ class CStorage : public IStorage // 3) check for usable path in argv[0] { - char aBaseDir[MAX_PATH_LENGTH]; + char aBaseDir[IO_MAX_PATH_LENGTH]; str_copy(aBaseDir, m_aAppDir, sizeof(aBaseDir)); str_format(m_aDataDir, sizeof(m_aDataDir), "%s/data", aBaseDir); str_append(aBaseDir, "/data/mapres", sizeof(aBaseDir)); @@ -294,7 +293,7 @@ class CStorage : public IStorage virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) { - char aBuffer[MAX_PATH_LENGTH]; + char aBuffer[IO_MAX_PATH_LENGTH]; if(Type == TYPE_ALL) { // list all available directories @@ -318,7 +317,7 @@ class CStorage : public IStorage // of one of the storage paths. virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0, FCheckCallback pfnCheckCB = 0, const void *pCheckCBData = 0) { - char aBuffer[MAX_PATH_LENGTH]; + char aBuffer[IO_MAX_PATH_LENGTH]; if(!pBuffer) { pBuffer = aBuffer; @@ -348,7 +347,7 @@ class CStorage : public IStorage { IOHANDLE Handle = 0; int LB = 0, UB = m_NumPaths; // check all available directories - + if(Type >= 0 && Type < m_NumPaths) // check wanted directory { LB = Type; @@ -426,8 +425,8 @@ class CStorage : public IStorage return 0; // search within the folder - char aBuf[MAX_PATH_LENGTH]; - char aPath[MAX_PATH_LENGTH]; + char aBuf[IO_MAX_PATH_LENGTH]; + char aPath[IO_MAX_PATH_LENGTH]; str_format(aPath, sizeof(aPath), "%s/%s", Data.m_pPath, pName); Data.m_pPath = aPath; fs_listdir(Data.m_pStorage->GetPath(Type, aPath, aBuf, sizeof(aBuf)), FindFileCallback, Type, &Data); @@ -451,7 +450,7 @@ class CStorage : public IStorage return 0; } } - + return 1; } @@ -465,8 +464,8 @@ class CStorage : public IStorage pCBData->m_pBuffer[0] = 0; - char aBuf[MAX_PATH_LENGTH]; - + char aBuf[IO_MAX_PATH_LENGTH]; + if(Type == TYPE_ALL) { // search within all available directories @@ -521,7 +520,7 @@ class CStorage : public IStorage if(Type < 0 || Type >= m_NumPaths) return false; - char aBuffer[MAX_PATH_LENGTH]; + char aBuffer[IO_MAX_PATH_LENGTH]; return !fs_remove(GetPath(Type, pFilename, aBuffer, sizeof(aBuffer))); } @@ -529,8 +528,8 @@ class CStorage : public IStorage { if(Type < 0 || Type >= m_NumPaths) return false; - char aOldBuffer[MAX_PATH_LENGTH]; - char aNewBuffer[MAX_PATH_LENGTH]; + char aOldBuffer[IO_MAX_PATH_LENGTH]; + char aNewBuffer[IO_MAX_PATH_LENGTH]; return !fs_rename(GetPath(Type, pOldFilename, aOldBuffer, sizeof(aOldBuffer)), GetPath(Type, pNewFilename, aNewBuffer, sizeof (aNewBuffer))); } @@ -539,7 +538,7 @@ class CStorage : public IStorage if(Type < 0 || Type >= m_NumPaths) return false; - char aBuffer[MAX_PATH_LENGTH]; + char aBuffer[IO_MAX_PATH_LENGTH]; return !fs_makedir(GetPath(Type, pFoldername, aBuffer, sizeof(aBuffer))); } @@ -554,7 +553,7 @@ class CStorage : public IStorage GetPath(Type, pDir, pBuffer, BufferSize); } - + virtual bool GetHashAndSize(const char *pFilename, int StorageType, SHA256_DIGEST *pSha256, unsigned *pCrc, unsigned *pSize) { IOHANDLE File = OpenFile(pFilename, IOFLAG_READ, StorageType); diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index f024ae02..c30cf49e 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -50,7 +50,7 @@ void CMapImages::LoadMapImages(IMap *pMap, class CLayers *pLayers, int MapType) CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start+i, 0, 0); if(pImg->m_External || (pImg->m_Version > 1 && pImg->m_Format != CImageInfo::FORMAT_RGB && pImg->m_Format != CImageInfo::FORMAT_RGBA)) { - char Buf[256]; + char Buf[IO_MAX_PATH_LENGTH]; char *pName = (char *)pMap->GetData(pImg->m_ImageName); str_format(Buf, sizeof(Buf), "mapres/%s.png", pName); m_Info[MapType].m_aTextures[i] = Graphics()->LoadTexture(Buf, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, TextureFlags); diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index dfa083a0..7f8c0cef 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -437,7 +437,7 @@ void CMapLayers::OnRender() CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTMap->m_Data); CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); - char aFilename[256]; + char aFilename[IO_MAX_PATH_LENGTH]; str_format(aFilename, sizeof(aFilename), "dumps/tilelayer_dump_%s-%d-%d-%dx%d.txt", CurrentServerInfo.m_aMap, g, l, pTMap->m_Width, pTMap->m_Height); IOHANDLE File = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(File) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 1b5c22c4..c7939c90 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -653,13 +653,13 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR str_format(aBuf, sizeof(aBuf), "%s: %s", pStr, aLabels[Value]); float FontSize = pRect->h*ms_FontmodHeight*0.8f; - + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Label, ScrollBar; pRect->VSplitLeft(5.0f, 0, &Label); Label.VSplitRight(60.0f, &Label, &ScrollBar); - + Label.y += 2.0f; UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); @@ -1355,7 +1355,7 @@ int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser if(IsDir || !str_endswith(pName, ".png")) return 0; - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "ui/menuimages/%s", pName); CImageInfo Info; if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType)) @@ -2056,7 +2056,7 @@ int CMenus::Render() // delete demo if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); if(Storage()->RemoveFile(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType)) { @@ -2098,10 +2098,10 @@ int CMenus::Render() // rename demo if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir) { - char aBufOld[512]; + char aBufOld[IO_MAX_PATH_LENGTH]; str_format(aBufOld, sizeof(aBufOld), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); int Length = str_length(m_aCurrentDemoFile); - char aBufNew[512]; + char aBufNew[IO_MAX_PATH_LENGTH]; if(Length <= 4 || m_aCurrentDemoFile[Length-5] != '.' || str_comp_nocase(m_aCurrentDemoFile+Length-4, "demo")) str_format(aBufNew, sizeof(aBufNew), "%s/%s.demo", m_aCurrentDemoFolder, m_aCurrentDemoFile); else @@ -2231,7 +2231,7 @@ int CMenus::Render() // delete demo if(m_pSelectedSkin) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "skins/%s.json", m_pSelectedSkin->m_aName); if(Storage()->RemoveFile(aBuf, IStorage::TYPE_SAVE)) { @@ -2520,7 +2520,7 @@ void CMenus::OnRender() bool CMenus::CheckHotKey(int Key) const { - return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && + return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 5d23d558..58527837 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -469,8 +469,8 @@ class CMenus : public CComponent }; sorted_array m_lDemos; - char m_aCurrentDemoFolder[256]; - char m_aCurrentDemoFile[64]; + char m_aCurrentDemoFolder[IO_MAX_PATH_LENGTH]; + char m_aCurrentDemoFile[IO_MAX_PATH_LENGTH]; int m_DemolistSelectedIndex; bool m_DemolistSelectedIsDir; int m_DemolistStorageType; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 8392b826..3707287f 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -508,7 +508,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Button.w; } - + TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) @@ -625,19 +625,19 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { StartColor = vec4(0.0f, 1.0f, 0.0f, TextAlpha); EndColor = vec4(1.0f, 1.0f, 0.0f, TextAlpha); - + MixVal = (Ping-50.0f)/75.0f; } else { StartColor = vec4(1.0f, 1.0f, 0.0f, TextAlpha); EndColor = vec4(1.0f, 0.0f, 0.0f, TextAlpha); - + MixVal = (Ping-125.0f)/75.0f; } Color = mix(StartColor, EndColor, MixVal); } - + str_format(aTemp, sizeof(aTemp), "%d", pEntry->m_Latency); TextRender()->TextColor(Color.r, Color.g, Color.b, Color.a); Button.y += 2.0f; @@ -720,7 +720,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) View.VSplitLeft(20.0f, &Button, &View); Button.Margin(2.0f, &Button); DoIconColor(IMAGE_MENUICONS, pFilter->Extended() ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED, &Button, Color); - + // split buttons from label View.VSplitLeft(Spacing, 0, &View); View.VSplitRight((ButtonHeight+Spacing)*4.0f, &View, &EditButtons); @@ -733,7 +733,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) char aBuf[64]; str_format(aBuf, sizeof(aBuf), Localize("%d servers, %d players"), pFilter->NumSortedServers(), pFilter->NumPlayers()); UI()->DoLabel(&View, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); - + EditButtons.VSplitRight(ButtonHeight, &EditButtons, &Button); Button.Margin(2.0f, &Button); if(pFilter->Custom() == CBrowserFilter::FILTER_CUSTOM) @@ -1545,12 +1545,12 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) const CServerInfo *pEntry = ServerBrowser()->Get(ServerIndex); if(pEntry->m_FriendState == CContactInfo::CONTACT_NO) continue; - + for(int j = 0; j < pEntry->m_NumClients; ++j) { if(pEntry->m_aClients[j].m_FriendState == CContactInfo::CONTACT_NO) continue; - + CFriendItem FriendItem; FriendItem.m_pServerInfo = pEntry; str_copy(FriendItem.m_aName, pEntry->m_aClients[j].m_aName, sizeof(FriendItem.m_aName)); @@ -1657,7 +1657,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) } } View.HSplitTop(2.0f, 0, &View); - + // header RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); Header.VSplitLeft(Header.h, &Icon, &Label); @@ -2035,7 +2035,7 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) CUIRect Row; // Localize("Map:"); Localize("Game type:"); Localize("Version:"); Localize("Difficulty:"); Localize("Casual", "Server difficulty"); Localize("Normal", "Server difficulty"); Localize("Competitive", "Server difficulty"); static CLocConstString s_aLabels[] = { - "Map:", + "Map:", "Game type:", "Version:", "Difficulty:" }; @@ -2104,7 +2104,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int int ActColumn = 0; RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); View.Margin(2.0f, &View); - + if(pInfo) { int Count = 0; @@ -2137,7 +2137,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int LineHeight = 0.25f*View.h; } } - + CUIRect Row = View; for(int i = 0; i < pInfo->m_NumClients; i++) @@ -2152,7 +2152,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int View.VSplitLeft(RowWidth, &Row, &View); ActColumn++; } - + Row.HSplitTop(LineHeight, &Name, &Row); s_ScrollRegion.AddRect(Name); RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); @@ -2338,7 +2338,7 @@ int CMenus::GameIconScan(const char *pName, int IsDir, int DirType, void *pUser) str_truncate(aGameIconName, sizeof(aGameIconName), pName, pSuffix - pName); // add new game icon - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "ui/gametypes/%s", pName); CImageInfo Info; if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType) || Info.m_Width != CGameIcon::GAMEICON_SIZE || (Info.m_Height != CGameIcon::GAMEICON_SIZE && Info.m_Height != CGameIcon::GAMEICON_OLDHEIGHT)) @@ -2377,7 +2377,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView) MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitBottom(80.0f, &MainView, &BottomBox); MainView.VSplitRight(20.0f, &ServerList, &SidebarButton); - + if(m_SidebarActive) ServerList.VSplitRight(150.0f, &ServerList, &Sidebar); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 142db77a..663aaf4e 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -364,7 +364,7 @@ void CMenus::RenderDemoList(CUIRect MainView) { if(!Item->m_InfosLoaded) { - char aBuffer[512]; + char aBuffer[IO_MAX_PATH_LENGTH]; str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename); Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, &Item->m_Info); Item->m_InfosLoaded = true; @@ -507,7 +507,7 @@ void CMenus::RenderDemoList(CUIRect MainView) fs_parent_dir(m_aCurrentDemoFolder); else // sub folder { - char aTemp[256]; + char aTemp[IO_MAX_PATH_LENGTH]; str_copy(aTemp, m_aCurrentDemoFolder, sizeof(aTemp)); str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", aTemp, m_lDemos[m_DemolistSelectedIndex].m_aFilename); m_DemolistStorageType = m_lDemos[m_DemolistSelectedIndex].m_StorageType; @@ -517,7 +517,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } else // file { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); const char *pError = Client()->DemoPlayer_Play(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType); if(pError) @@ -538,10 +538,10 @@ float CMenus::RenderDemoDetails(CUIRect View) if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) { CUIRect Button; - + const float ButtonHeight = 20.0f; const float Spacing = 2.0f; - + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); DoInfoBox(&Button, Localize("Created"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index cbaf93b9..dc870b3e 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -510,7 +510,7 @@ void CMenus::RenderSkinPartPalette(CUIRect MainView) for(int p = 0; p < NUM_SKINPARTS; p++) { MainView.VSplitLeft(Width/NUM_SKINPARTS, &Button, &MainView); - + // no palette if color is unused for this skin parts static int s_aColorPalettes[NUM_SKINPARTS]; if(*CSkins::ms_apUCCVariables[p]) @@ -520,7 +520,7 @@ void CMenus::RenderSkinPartPalette(CUIRect MainView) Button.VSplitRight(HMargin, &Button, 0); vec4 PartColor = m_pClient->m_pSkins->GetColorV4(*CSkins::ms_apColorVariables[p], p==SKINPART_MARKING); - + bool Hovered = UI()->HotItem() == &s_aColorPalettes[p]; bool Clicked = UI()->DoButtonLogic(&s_aColorPalettes[p], &Button); bool Selected = m_TeePartSelected == p; @@ -623,7 +623,7 @@ int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser { if(str_comp(r.front().m_Name, aThemeName) == 0 || (!r.front().m_Name[0] && str_comp(aThemeName, "none") == 0)) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "ui/themes/%s", pName); CImageInfo Info; if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType)) @@ -1553,11 +1553,11 @@ float CMenus::RenderSettingsControlsStats(CUIRect View) View.HSplitTop(20.0f, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+5, Localize("Frags per minute"), Config()->m_ClStatboardInfos & TC_STATS_FPM, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_FPM; - + View.HSplitTop(20.0f, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+6, Localize("Current spree"), Config()->m_ClStatboardInfos & TC_STATS_SPREE, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_SPREE; - + View.HSplitTop(20.0f, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+7, Localize("Best spree"), Config()->m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_BESTSPREE; diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 66b2b123..1086606b 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -31,7 +31,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) if(IsDir || !str_endswith(pName, ".png")) return 0; - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "skins/%s/%s", CSkins::ms_apSkinPartNames[pSelf->m_ScanningPart], pName); CImageInfo Info; if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType)) @@ -111,7 +111,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) CSkins *pSelf = (CSkins *)pUser; // read file data into buffer - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "skins/%s", pName); IOHANDLE File = pSelf->Storage()->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL); if(!File) @@ -530,7 +530,7 @@ bool CSkins::ValidateSkinParts(char* aPartNames[NUM_SKINPARTS], int* aUseCustomC void CSkins::SaveSkinfile(const char *pSaveSkinName) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "skins/%s.json", pSaveSkinName); IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(!File) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 3cfc7cc2..c9c92b0a 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -356,9 +356,9 @@ void CGameClient::OnInit() Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); // load default font - char aFontName[256]; + char aFontName[IO_MAX_PATH_LENGTH]; str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->m_ClFontfile); - char aFilename[512]; + char aFilename[IO_MAX_PATH_LENGTH]; IOHANDLE File = Storage()->OpenFile(aFontName, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); if(File) { diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 0054ce63..7ade6bad 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -211,7 +211,7 @@ void CEditorImage::LoadAutoMapper() return; // read file data into buffer - char aBuf[256]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "editor/automap/%s.json", m_aName); IOHANDLE File = m_pEditor->Storage()->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL); if(!File) @@ -3297,9 +3297,9 @@ void CEditor::RenderFileDialog() } else { - char aTemp[MAX_PATH_LENGTH]; + char aTemp[IO_MAX_PATH_LENGTH]; str_copy(aTemp, m_pFileDialogPath, sizeof(aTemp)); - str_format(m_pFileDialogPath, MAX_PATH_LENGTH, "%s/%s", aTemp, m_FileList[m_FilesSelectedIndex].m_aFilename); + str_format(m_pFileDialogPath, IO_MAX_PATH_LENGTH, "%s/%s", aTemp, m_FileList[m_FilesSelectedIndex].m_aFilename); } } FilelistPopulate(!str_comp(m_pFileDialogPath, "maps") || !str_comp(m_pFileDialogPath, "mapres") ? m_FileDialogStorageType : @@ -3531,7 +3531,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) ToolBar.VSplitLeft(60.0f, &Shifter, &ToolBar); Shifter.VSplitRight(15.0f, &Shifter, &Inc); Shifter.VSplitLeft(15.0f, &Dec, &Shifter); - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf),"%d/%d", m_SelectedEnvelope+1, m_Map.m_lEnvelopes.size()); RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f); UI()->DoLabel(&Shifter, aBuf, 10.0f, CUI::ALIGN_CENTER); @@ -4111,7 +4111,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar) MenuBar.VSplitRight(20.f, &MenuBar, &ExitButton); MenuBar.VSplitLeft(40.0f, 0, &MenuBar); MenuBar.VSplitLeft(MenuBar.w*0.75f, &MenuBar, &Info); - + char aBuf[128]; str_format(aBuf, sizeof(aBuf), "File: %s", m_aFileName); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 3a6228bc..81657e5c 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -534,7 +534,7 @@ class CEditor : public IEditor m_GridActive = false; m_GridFactor = 1; - + m_MouseEdMode = MOUSE_EDIT; m_aFileName[0] = 0; @@ -588,7 +588,7 @@ class CEditor : public IEditor m_ShowEnvelopePreview = SHOWENV_NONE; m_SelectedQuadEnvelope = -1; m_SelectedEnvelopePoint = -1; - + m_SelectedColor = vec4(0,0,0,0); m_InitialPickerColor = vec3(1,0,0); m_SelectedPickerColor = vec3(1,0,0); @@ -626,17 +626,17 @@ class CEditor : public IEditor bool m_GridActive; int m_GridFactor; - + enum { MOUSE_EDIT=0, MOUSE_PIPETTE, }; - + int m_MouseEdMode; - char m_aFileName[512]; - char m_aFileSaveName[512]; + char m_aFileName[IO_MAX_PATH_LENGTH]; + char m_aFileSaveName[IO_MAX_PATH_LENGTH]; bool m_ValidSaveFilename; enum @@ -656,8 +656,6 @@ class CEditor : public IEditor { FILETYPE_MAP, FILETYPE_IMG, - - MAX_PATH_LENGTH = 512 }; int m_FileDialogStorageType; @@ -665,9 +663,9 @@ class CEditor : public IEditor const char *m_pFileDialogButtonText; void (*m_pfnFileDialogFunc)(const char *pFileName, int StorageType, void *pUser); void *m_pFileDialogUser; - char m_aFileDialogFileName[MAX_PATH_LENGTH]; - char m_aFileDialogCurrentFolder[MAX_PATH_LENGTH]; - char m_aFileDialogCurrentLink[MAX_PATH_LENGTH]; + char m_aFileDialogFileName[IO_MAX_PATH_LENGTH]; + char m_aFileDialogCurrentFolder[IO_MAX_PATH_LENGTH]; + char m_aFileDialogCurrentLink[IO_MAX_PATH_LENGTH]; char *m_pFileDialogPath; bool m_aFileDialogActivate; int m_FileDialogFileType; @@ -740,7 +738,7 @@ class CEditor : public IEditor int m_SelectedEnvelopePoint; int m_SelectedQuadEnvelope; int m_SelectedImage; - + vec4 m_SelectedColor; vec3 m_InitialPickerColor; vec3 m_SelectedPickerColor; diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index 9fef63ec..0200a66b 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -183,7 +183,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) // check for bezier curve envelopes, otherwise use older, smaller envelope points int Version = CMapItemEnvelope_v2::CURRENT_VERSION; - int Size = sizeof(CEnvPoint_v1); + int Size = sizeof(CEnvPoint_v1); for(int e = 0; e < m_lEnvelopes.size(); e++) { for(int p = 0; p < m_lEnvelopes[e]->m_lPoints.size(); p++) @@ -305,7 +305,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag if(pItem->m_External || (pItem->m_Version > 1 && pItem->m_Format != CImageInfo::FORMAT_RGB && pItem->m_Format != CImageInfo::FORMAT_RGBA)) { - char aBuf[256]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName); // load external @@ -423,7 +423,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pTiles->ExtractTiles((CTile *)pData); else mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); - + if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) { diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 6d1e7f76..584c51fb 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -649,7 +649,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) // create the folder if(*pEditor->m_FileDialogNewFolderName) { - char aBuf[512]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "%s/%s", pEditor->m_pFileDialogPath, pEditor->m_FileDialogNewFolderName); if(pEditor->Storage()->CreateFolder(aBuf, IStorage::TYPE_SAVE)) { @@ -1116,7 +1116,7 @@ int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View) if(pEditor->UI()->DoPickerLogic(&s_SVPicker, &SVPicker, &X, &Y)) { hsv.y = X/SVPicker.w; - hsv.z = 1.0f - Y/SVPicker.h; + hsv.z = 1.0f - Y/SVPicker.h; } // hue slider @@ -1157,9 +1157,9 @@ int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View) static int s_HuePicker = 0; if(pEditor->UI()->DoPickerLogic(&s_HuePicker, &HuePicker, &X, &Y)) { - hsv.x = 1.0f - Y/HuePicker.h; + hsv.x = 1.0f - Y/HuePicker.h; } - + // palette static int s_Palette = 0; pEditor->RenderTools()->DrawUIRect(&Palette, pEditor->m_SelectedColor, 0, 0.0f); From 0ab4525dc4d795f9e204716e2fe7ea3a9ef5361b Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 2 Apr 2020 15:48:11 +0300 Subject: [PATCH 233/479] Don't use dangerous constructs --- src/engine/shared/network_server.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 70b008c7..cca1a498 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -95,7 +95,6 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { while(1) { - loopbegin: // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; @@ -178,6 +177,8 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 1; ThisAddr.port = 0; + + bool Continue = false; for(int i = 0; i < NET_MAX_CLIENTS; i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) @@ -192,11 +193,15 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP); SendControlMsg(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); - goto loopbegin; + Continue = true; + break; } } } + if(Continue) + continue; + for(int i = 0; i < NET_MAX_CLIENTS; i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) From c1d0c9464c0873fa3d34d5fac84082f83ecdf65e Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Fri, 3 Apr 2020 15:57:15 +0200 Subject: [PATCH 234/479] Add defaults for ints later introduced in the protocol This allows introducing new fields in the network protocol without breaking backward compatibility (new client -- old server scenario). --- datasrc/datatypes.py | 17 +++++++++++------ src/engine/shared/packer.cpp | 13 +++++++++++++ src/engine/shared/packer.h | 1 + 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/datasrc/datatypes.py b/datasrc/datatypes.py index 5682ab41..4fd88420 100644 --- a/datasrc/datatypes.py +++ b/datasrc/datatypes.py @@ -285,8 +285,9 @@ def emit_declaration(self): class NetVariable: - def __init__(self, name): + def __init__(self, name, default=None): self.name = name + self.default = None if default is None else str(default) def emit_declaration(self): return [] def emit_validate(self): @@ -318,13 +319,16 @@ class NetIntAny(NetVariable): def emit_declaration(self): return ["int %s;"%self.name] def emit_unpack(self): - return ["pMsg->%s = pUnpacker->GetInt();" % self.name] + if self.default is None: + return ["pMsg->%s = pUnpacker->GetInt();" % self.name] + else: + return ["pMsg->%s = pUnpacker->GetIntOrDefault(%s);" % (self.name, self.default)] def emit_pack(self): return ["pPacker->AddInt(%s);" % self.name] class NetIntRange(NetIntAny): - def __init__(self, name, min, max): - NetIntAny.__init__(self,name) + def __init__(self, name, min, max, default=None): + NetIntAny.__init__(self,name,default=default) self.min = str(min) self.max = str(max) def emit_validate(self): @@ -351,8 +355,9 @@ def emit_unpack_check(self): return ["if(!CheckFlag(\"%s\", pMsg->%s, %s)) break;"%(self.name, self.name, self.mask)] class NetBool(NetIntRange): - def __init__(self, name): - NetIntRange.__init__(self,name,0,1) + def __init__(self, name, default=None): + default = None if default is None else int(default) + NetIntRange.__init__(self,name,0,1,default=default) class NetTick(NetIntRange): def __init__(self, name): diff --git a/src/engine/shared/packer.cpp b/src/engine/shared/packer.cpp index 788e564d..c33d666e 100644 --- a/src/engine/shared/packer.cpp +++ b/src/engine/shared/packer.cpp @@ -114,6 +114,19 @@ int CUnpacker::GetInt() return i; } +int CUnpacker::GetIntOrDefault(int Default) +{ + if(m_Error) + { + return 0; + } + if(m_pCurrent == m_pEnd) + { + return Default; + } + return GetInt(); +} + const char *CUnpacker::GetString(int SanitizeType) { if(m_Error || m_pCurrent >= m_pEnd) diff --git a/src/engine/shared/packer.h b/src/engine/shared/packer.h index bd04e36e..967c2e6d 100644 --- a/src/engine/shared/packer.h +++ b/src/engine/shared/packer.h @@ -43,6 +43,7 @@ class CUnpacker void Reset(const void *pData, int Size); int GetInt(); + int GetIntOrDefault(int Default); const char *GetString(int SanitizeType = SANITIZE); const unsigned char *GetRaw(int Size); bool Error() const { return m_Error; } From 73f7182e50ddd9a9b6fac2d7ee93089e3d056673 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Fri, 3 Apr 2020 16:17:22 +0200 Subject: [PATCH 235/479] Make the race record message change backward compatible --- datasrc/network.py | 5 ++--- src/game/client/components/infomessages.cpp | 19 ++++++++++--------- src/game/client/components/infomessages.h | 3 ++- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/datasrc/network.py b/datasrc/network.py index f59d3dc1..315f976f 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -5,7 +5,6 @@ Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"]) Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"]) # todo 0.8: add RUN_OP, RUN_KICK, RUN_SPEC; rem UNKNOWN ChatModes = Enum("CHAT", ["NONE", "ALL", "TEAM", "WHISPER"]) -RaceRecordTypes = Enum("RECORDTYPE", ["NONE", "PLAYER", "MAP"]) PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING", "BOT"]) GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL", "RACE"]) @@ -69,7 +68,6 @@ Emoticons, Votes, ChatModes, - RaceRecordTypes, GameMsgIDs, ] @@ -454,7 +452,8 @@ NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'), NetIntRange("m_Time", -1, 'max_int'), NetIntAny("m_Diff"), - NetEnum("m_RecordType", RaceRecordTypes) + NetBool("m_RecordPersonal"), + NetBool("m_RecordServer", default=False), ]), NetMessage("Sv_Checkpoint", [ diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index 84fa81f5..24413c59 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -97,11 +97,11 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) str_format(aBuf, sizeof(aBuf), "%2d: %s: finished in %s", pMsg->m_ClientID, m_pClient->m_aClients[pMsg->m_ClientID].m_aName, aTime); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "race", aBuf); - if(pMsg->m_RecordType != RECORDTYPE_NONE) + if(pMsg->m_RecordPersonal || pMsg->m_RecordServer) { - if(pMsg->m_RecordType == RECORDTYPE_MAP) + if(pMsg->m_RecordServer) str_format(aBuf, sizeof(aBuf), Localize("'%s' has set a new map record: %s"), aLabel, aTime); - else // RECORDTYPE_PLAYER + else // m_RecordPersonal str_format(aBuf, sizeof(aBuf), Localize("'%s' has set a new personal record: %s"), aLabel, aTime); if(pMsg->m_Diff < 0) @@ -117,7 +117,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) if(m_pClient->m_Snap.m_pGameDataRace && m_pClient->m_Snap.m_pGameDataRace->m_RaceFlags&RACEFLAG_FINISHMSG_AS_CHAT) { - if(pMsg->m_RecordType == RECORDTYPE_NONE) // don't print the time twice + if(!pMsg->m_RecordPersonal && !pMsg->m_RecordServer) // don't print the time twice { str_format(aBuf, sizeof(aBuf), Localize("'%s' finished in: %s"), aLabel, aTime); m_pClient->m_pChat->AddLine(aBuf); @@ -132,7 +132,8 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Finish.m_Time = pMsg->m_Time; Finish.m_Diff = pMsg->m_Diff; - Finish.m_RecordType = pMsg->m_RecordType; + Finish.m_RecordPersonal = pMsg->m_RecordPersonal; + Finish.m_RecordServer = pMsg->m_RecordServer; AddInfoMsg(INFOMSG_FINISH, Finish); } @@ -289,10 +290,10 @@ void CInfoMessages::RenderFinishMsg(const CInfoMsg *pInfoMsg, float x, float y) float TimeW = TextRender()->TextWidth(0, FontSize, aTime, -1, -1.0f); x -= TimeW; - if(pInfoMsg->m_RecordType == RECORDTYPE_PLAYER) - TextRender()->TextColor(0.2f, 0.6f, 1.0f, 1.0f); - else if(pInfoMsg->m_RecordType == RECORDTYPE_MAP) + if(pInfoMsg->m_RecordServer) TextRender()->TextColor(1.0f, 0.5f, 0.0f, 1.0f); + else if(pInfoMsg->m_RecordPersonal) + TextRender()->TextColor(0.2f, 0.6f, 1.0f, 1.0f); TextRender()->Text(0, x, y, FontSize, aTime, -1); x -= 52.0f + 10.0f; @@ -318,6 +319,6 @@ void CInfoMessages::RenderFinishMsg(const CInfoMsg *pInfoMsg, float x, float y) x -= 28.0f; // render player tee - int Emote = pInfoMsg->m_RecordType != RECORDTYPE_NONE ? EMOTE_HAPPY : EMOTE_NORMAL; + int Emote = (pInfoMsg->m_RecordPersonal || pInfoMsg->m_RecordServer) ? EMOTE_HAPPY : EMOTE_NORMAL; RenderTools()->RenderTee(CAnimState::GetIdle(), &pInfoMsg->m_Player1RenderInfo, Emote, vec2(-1,0), vec2(x, y+28)); } diff --git a/src/game/client/components/infomessages.h b/src/game/client/components/infomessages.h index 69a4dc86..319a87fc 100644 --- a/src/game/client/components/infomessages.h +++ b/src/game/client/components/infomessages.h @@ -30,7 +30,8 @@ class CInfoMessages : public CComponent // finish msg int m_Time; int m_Diff; - int m_RecordType; + int m_RecordPersonal; + int m_RecordServer; }; enum From 8428d2cf40fcc64da169a8c6c41debe8fb95c561 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 3 Apr 2020 17:35:09 +0200 Subject: [PATCH 236/479] added a check --- src/engine/shared/network.h | 3 ++- src/engine/shared/network_server.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index ebf8a13b..983e5cb4 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -426,9 +426,9 @@ class CConsoleNetConnection class CNetRecvUnpacker { -public: bool m_Valid; +public: NETADDR m_Addr; CNetConnection *m_pConnection; int m_CurrentChunk; @@ -437,6 +437,7 @@ class CNetRecvUnpacker unsigned char m_aBuffer[NET_MAX_PACKETSIZE]; CNetRecvUnpacker() { Clear(); } + bool IsActive() { return m_Valid; } void Clear(); void Start(const NETADDR *pAddr, CNetConnection *pConnection, int ClientID); int FetchChunk(CNetChunk *pChunk); diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index cca1a498..8ef5e291 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -96,7 +96,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) while(1) { // check for a chunk - if(m_RecvUnpacker.FetchChunk(pChunk)) + if(m_RecvUnpacker.IsActive() && m_RecvUnpacker.FetchChunk(pChunk)) return 1; // TODO: empty the recvinfo From 5e995d23a2be251498380282c13f982acf2f43d0 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 3 Apr 2020 17:39:53 +0200 Subject: [PATCH 237/479] fixed an overlap in the settings menu --- src/game/client/components/menus_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 2af40778..c4f59192 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -855,7 +855,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) BottomView.HSplitTop(20.f, 0, &BottomView); // render game menu backgrounds - int NumOptions = max(Config()->m_ClNameplates ? 6 : 3, Config()->m_ClShowsocial ? 5 : 4); + int NumOptions = max(Config()->m_ClNameplates ? 6 : 3, Config()->m_ClShowsocial ? 6 : 5); float ButtonHeight = 20.0f; float Spacing = 2.0f; float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; From da9369c896b19f81f0d4ce262ff25cd3caab2531 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 3 Apr 2020 18:12:22 +0200 Subject: [PATCH 238/479] reverted "using server tunings in EvolveCharacter" for now --- src/game/client/gameclient.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index c9c92b0a..8c35eb1f 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -534,8 +534,6 @@ void CGameClient::UpdatePositions() void CGameClient::EvolveCharacter(CNetObj_Character *pCharacter, int Tick) { CWorldCore TempWorld; - TempWorld.m_Tuning = m_Tuning; - CCharacterCore TempCore; mem_zero(&TempCore, sizeof(TempCore)); TempCore.Init(&TempWorld, Collision()); From d3fc0807d5f59d88661c8e58854805b064db3c4d Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 4 Apr 2020 09:16:22 +0200 Subject: [PATCH 239/479] Remove useless `NET_CTRLMSG_ACCEPT` from the network Rename `NET_CTRLMSG_CONNECTACCEPT` to take its place. The connection buildup looks like this (as before): ``` -> CONNECT <- ACCEPT -> first data packet or KEEPALIVE due to timeout ``` The old `NET_CTRLMSG_ACCEPT` was never used in the server. --- src/engine/shared/network.h | 3 +-- src/engine/shared/network_conn.cpp | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 983e5cb4..1c0b713c 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -124,8 +124,7 @@ enum NET_CTRLMSG_KEEPALIVE=0, NET_CTRLMSG_CONNECT=1, - NET_CTRLMSG_CONNECTACCEPT=2, - NET_CTRLMSG_ACCEPT=3, + NET_CTRLMSG_ACCEPT=2, NET_CTRLMSG_CLOSE=4, NET_CTRLMSG_TOKEN=5, diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index 8e3bfd1d..6ebb5d7a 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -324,21 +324,20 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastSendTime = Now; m_LastRecvTime = Now; m_LastUpdateTime = Now; - SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); + SendControl(NET_CTRLMSG_ACCEPT, 0, 0); if(Config()->m_Debug) - dbg_msg("connection", "got connection, sending connect+accept"); + dbg_msg("connection", "got connection, sending accept"); } } else if(State() == NET_CONNSTATE_CONNECT) { // connection made - if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT) + if(CtrlMsg == NET_CTRLMSG_ACCEPT) { m_LastRecvTime = Now; - SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; if(Config()->m_Debug) - dbg_msg("connection", "got connect+accept, sending accept. connection online"); + dbg_msg("connection", "got accept. connection online"); } } } @@ -430,7 +429,7 @@ int CNetConnection::Update() else if(State() == NET_CONNSTATE_PENDING) { if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms - SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); + SendControl(NET_CTRLMSG_ACCEPT, 0, 0); } return 0; From 7854fd7ef5e33eb04dc568b3d72ba3657093f01c Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 4 Apr 2020 10:04:52 +0200 Subject: [PATCH 240/479] Clean up `CDatafile{Reader,Writer}` interface a bit --- src/engine/shared/datafile.cpp | 13 +++++++------ src/engine/shared/datafile.h | 7 ++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 44bb25ff..33e05131 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -1,10 +1,11 @@ /* (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 "datafile.h" + #include #include #include #include -#include "datafile.h" #include static const int DEBUG=0; @@ -498,7 +499,7 @@ bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) return true; } -int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) +int CDataFileWriter::AddItem(int Type, int ID, int Size, const void *pData) { if(!m_File) return 0; @@ -534,7 +535,7 @@ int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) return m_NumItems-1; } -int CDataFileWriter::AddData(int Size, void *pData) +int CDataFileWriter::AddData(int Size, const void *pData) { if(!m_File) return 0; @@ -561,7 +562,7 @@ int CDataFileWriter::AddData(int Size, void *pData) return m_NumDatas-1; } -int CDataFileWriter::AddDataSwapped(int Size, void *pData) +int CDataFileWriter::AddDataSwapped(int Size, const void *pData) { dbg_assert(Size%sizeof(int) == 0, "incorrect boundary"); @@ -580,7 +581,7 @@ int CDataFileWriter::AddDataSwapped(int Size, void *pData) int CDataFileWriter::Finish() { - if(!m_File) return 1; + if(!m_File) return 0; int ItemSize = 0; int TypesSize, HeaderSize, OffsetSize, FileSize, SwapSize; @@ -755,5 +756,5 @@ int CDataFileWriter::Finish() if(DEBUG) dbg_msg("datafile", "done"); - return 0; + return 1; } diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h index f70a5819..024b086c 100644 --- a/src/engine/shared/datafile.h +++ b/src/engine/shared/datafile.h @@ -3,6 +3,7 @@ #ifndef ENGINE_SHARED_DATAFILE_H #define ENGINE_SHARED_DATAFILE_H +#include #include // raw datafile access @@ -84,9 +85,9 @@ class CDataFileWriter CDataFileWriter(); ~CDataFileWriter(); bool Open(class IStorage *pStorage, const char *Filename); - int AddData(int Size, void *pData); - int AddDataSwapped(int Size, void *pData); - int AddItem(int Type, int ID, int Size, void *pData); + int AddData(int Size, const void *pData); + int AddDataSwapped(int Size, const void *pData); + int AddItem(int Type, int ID, int Size, const void *pData); int Finish(); }; From 3606c0b6322f3d38cec436e2c13590f0312b4d7c Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 4 Apr 2020 10:06:05 +0200 Subject: [PATCH 241/479] Report actual data sizes in `CDataFileReader::GetDataSize` Previously it reported the internal file data size (compressed). This made the `map_resave` tool do the wrong job. --- CMakeLists.txt | 1 + src/engine/shared/datafile.cpp | 45 ++++++++++++++++++++++++++----- src/engine/shared/datafile.h | 3 ++- src/engine/shared/map.cpp | 2 +- src/test/datafile.cpp | 48 ++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 src/test/datafile.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c1f941de..65dfdd3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1722,6 +1722,7 @@ add_custom_target(everything DEPENDS ${TARGETS_OWN}) if(GTEST_FOUND OR DOWNLOAD_GTEST) set_src(TESTS GLOB src/test + datafile.cpp fs.cpp git_revision.cpp hash.cpp diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 33e05131..43c924f2 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -66,6 +66,7 @@ struct CDatafile CDatafileHeader m_Header; int m_DataStartOffset; char **m_ppDataPtrs; + int *m_pDataSizes; char *m_pData; }; @@ -139,6 +140,7 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int int64 AllocSize = Size; AllocSize += sizeof(CDatafile); // add space for info structure AllocSize += Header.m_NumRawData*sizeof(void*); // add space for data pointers + AllocSize += Header.m_NumRawData*sizeof(int); // add space for data sizes if(Size > (int64(1)<<31) || Header.m_NumItemTypes < 0 || Header.m_NumItems < 0 || Header.m_NumRawData < 0 || Header.m_ItemSize < 0) { io_close(File); @@ -149,14 +151,16 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int CDatafile *pTmpDataFile = (CDatafile*)mem_alloc(AllocSize, 1); pTmpDataFile->m_Header = Header; pTmpDataFile->m_DataStartOffset = sizeof(CDatafileHeader) + Size; - pTmpDataFile->m_ppDataPtrs = (char**)(pTmpDataFile+1); - pTmpDataFile->m_pData = (char *)(pTmpDataFile+1)+Header.m_NumRawData*sizeof(char *); + pTmpDataFile->m_ppDataPtrs = (char **)(pTmpDataFile+1); + pTmpDataFile->m_pDataSizes = (int *)(pTmpDataFile->m_ppDataPtrs + Header.m_NumRawData); + pTmpDataFile->m_pData = (char *)(pTmpDataFile->m_pDataSizes + Header.m_NumRawData); pTmpDataFile->m_File = File; pTmpDataFile->m_Sha256 = sha256_finish(&Sha256Ctx); pTmpDataFile->m_Crc = Crc; - // clear the data pointers + // clear the data pointers and sizes mem_zero(pTmpDataFile->m_ppDataPtrs, Header.m_NumRawData*sizeof(void*)); + mem_zero(pTmpDataFile->m_pDataSizes, Header.m_NumRawData*sizeof(int)); // read types, offsets, sizes and item data unsigned ReadSize = io_read(File, pTmpDataFile->m_pData, Size); @@ -242,8 +246,7 @@ int CDataFileReader::NumData() const return m_pDataFile->m_Header.m_NumRawData; } -// always returns the size in the file -int CDataFileReader::GetDataSize(int Index) const +int CDataFileReader::GetFileDataSize(int Index) const { if(!m_pDataFile) { return 0; } @@ -252,6 +255,27 @@ int CDataFileReader::GetDataSize(int Index) const return m_pDataFile->m_Info.m_pDataOffsets[Index+1]-m_pDataFile->m_Info.m_pDataOffsets[Index]; } +int CDataFileReader::GetDataSize(int Index) const +{ + if(Index < 0 || Index >= m_pDataFile->m_Header.m_NumRawData) + { + return 0; + } + + if(!m_pDataFile->m_ppDataPtrs[Index]) + { + if(m_pDataFile->m_Header.m_Version >= 4) + { + return m_pDataFile->m_Info.m_pDataSizes[Index]; + } + else + { + return GetFileDataSize(Index); + } + } + return m_pDataFile->m_pDataSizes[Index]; +} + void *CDataFileReader::GetDataImpl(int Index, int Swap) { if(!m_pDataFile) { return 0; } @@ -263,7 +287,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap) if(!m_pDataFile->m_ppDataPtrs[Index]) { // fetch the data size - int DataSize = GetDataSize(Index); + int DataSize = GetFileDataSize(Index); #if defined(CONF_ARCH_ENDIAN_BIG) int SwapSize = DataSize; #endif @@ -277,6 +301,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap) dbg_msg("datafile", "loading data index=%d size=%d uncompressed=%lu", Index, DataSize, UncompressedSize); m_pDataFile->m_ppDataPtrs[Index] = (char *)mem_alloc(UncompressedSize, 1); + m_pDataFile->m_pDataSizes[Index] = UncompressedSize; // read the compressed data io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset+m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START); @@ -297,6 +322,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap) // load the data dbg_msg("datafile", "loading data index=%d size=%d", Index, DataSize); m_pDataFile->m_ppDataPtrs[Index] = (char *)mem_alloc(DataSize, 1); + m_pDataFile->m_pDataSizes[Index] = DataSize; io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset+m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START); io_read(m_pDataFile->m_File, m_pDataFile->m_ppDataPtrs[Index], DataSize); } @@ -320,7 +346,7 @@ void *CDataFileReader::GetDataSwapped(int Index) return GetDataImpl(Index, 1); } -void CDataFileReader::ReplaceData(int Index, char *pData) +void CDataFileReader::ReplaceData(int Index, char *pData, int Size) { if(Index < 0 || Index >= m_pDataFile->m_Header.m_NumRawData) return; @@ -330,6 +356,7 @@ void CDataFileReader::ReplaceData(int Index, char *pData) UnloadData(Index); m_pDataFile->m_ppDataPtrs[Index] = pData; + m_pDataFile->m_pDataSizes[Index] = Size; } void CDataFileReader::UnloadData(int Index) @@ -339,6 +366,7 @@ void CDataFileReader::UnloadData(int Index) mem_free(m_pDataFile->m_ppDataPtrs[Index]); m_pDataFile->m_ppDataPtrs[Index] = 0x0; + m_pDataFile->m_pDataSizes[Index] = 0; } int CDataFileReader::GetItemSize(int Index) const @@ -418,7 +446,10 @@ bool CDataFileReader::Close() // free the data that is loaded int i; for(i = 0; i < m_pDataFile->m_Header.m_NumRawData; i++) + { mem_free(m_pDataFile->m_ppDataPtrs[i]); + m_pDataFile->m_pDataSizes[i] = 0; + } io_close(m_pDataFile->m_File); mem_free(m_pDataFile); diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h index 024b086c..6e14e258 100644 --- a/src/engine/shared/datafile.h +++ b/src/engine/shared/datafile.h @@ -11,6 +11,7 @@ class CDataFileReader { struct CDatafile *m_pDataFile; void *GetDataImpl(int Index, int Swap); + int GetFileDataSize(int Index) const; public: CDataFileReader() : m_pDataFile(0) {} ~CDataFileReader() { Close(); } @@ -23,7 +24,7 @@ class CDataFileReader void *GetData(int Index); void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved int GetDataSize(int Index) const; - void ReplaceData(int Index, char *pData); + void ReplaceData(int Index, char *pData, int Size); void UnloadData(int Index); void *GetItem(int Index, int *pType, int *pID); int GetItemSize(int Index) const; diff --git a/src/engine/shared/map.cpp b/src/engine/shared/map.cpp index 64b1a224..44c28e3e 100644 --- a/src/engine/shared/map.cpp +++ b/src/engine/shared/map.cpp @@ -81,7 +81,7 @@ class CMap : public IEngineMap pSavedTiles++; } - m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast(pTiles)); + m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast(pTiles), TilemapSize); } } } diff --git a/src/test/datafile.cpp b/src/test/datafile.cpp new file mode 100644 index 00000000..c2827be8 --- /dev/null +++ b/src/test/datafile.cpp @@ -0,0 +1,48 @@ +#include "test.h" + +#include + +#include +#include + +TEST(Datafile, RoundtripDataAndSize) +{ + CTestInfo Info; + char aFilename[64]; + Info.Filename(aFilename, sizeof(aFilename), ".datafile"); + IStorage *pStorage = CreateTestStorage(); + CDataFileWriter Writer; + ASSERT_TRUE(Writer.Open(pStorage, aFilename)); + + static const char TEST_DATA[] = "Hello World!"; + int Index = Writer.AddData(sizeof(TEST_DATA), TEST_DATA); + int Index4 = Writer.AddData(4, TEST_DATA); + EXPECT_TRUE(Writer.Finish()); + + CDataFileReader Reader; + EXPECT_FALSE(Reader.IsOpen()); + ASSERT_TRUE(Reader.Open(pStorage, aFilename, IStorage::TYPE_ALL)); + EXPECT_TRUE(Reader.IsOpen()); + + ASSERT_EQ(Reader.GetDataSize(Index), sizeof(TEST_DATA)); + EXPECT_TRUE(mem_comp(Reader.GetData(Index), TEST_DATA, sizeof(TEST_DATA)) == 0); + ASSERT_EQ(Reader.GetDataSize(Index4), 4); + EXPECT_TRUE(mem_comp(Reader.GetData(Index), TEST_DATA, 4) == 0); + + static const char REPL_DATA[] = "Replacement"; + char *pReplace4 = (char *)mem_alloc(4, 1); + mem_copy(pReplace4, REPL_DATA, 4); + char *pReplace = (char *)mem_alloc(sizeof(REPL_DATA), 1); + mem_copy(pReplace, REPL_DATA, sizeof(REPL_DATA)); + Reader.ReplaceData(Index, pReplace4, 4); + Reader.ReplaceData(Index4, pReplace, sizeof(REPL_DATA)); + + ASSERT_EQ(Reader.GetDataSize(Index), 4); + EXPECT_TRUE(mem_comp(Reader.GetData(Index), REPL_DATA, 4) == 0); + ASSERT_EQ(Reader.GetDataSize(Index4), sizeof(REPL_DATA)); + EXPECT_TRUE(mem_comp(Reader.GetData(Index4), REPL_DATA, sizeof(REPL_DATA)) == 0); + + EXPECT_TRUE(Reader.Close()); + + EXPECT_TRUE(pStorage->RemoveFile(aFilename, IStorage::TYPE_SAVE)); +} From 03802de0e553c73a5ebfb492c71090271751d3a9 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 4 Apr 2020 10:19:24 +0200 Subject: [PATCH 242/479] Report actual item sizes in `CDataFileReader::GetItemSize` Previously it reported the file item size, i.e. including item header. --- src/engine/shared/datafile.cpp | 12 +++++++++++- src/engine/shared/datafile.h | 1 + src/test/datafile.cpp | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 43c924f2..55041b06 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -369,7 +369,7 @@ void CDataFileReader::UnloadData(int Index) m_pDataFile->m_pDataSizes[Index] = 0; } -int CDataFileReader::GetItemSize(int Index) const +int CDataFileReader::GetFileItemSize(int Index) const { if(!m_pDataFile) { return 0; } if(Index == m_pDataFile->m_Header.m_NumItems-1) @@ -377,6 +377,16 @@ int CDataFileReader::GetItemSize(int Index) const return m_pDataFile->m_Info.m_pItemOffsets[Index+1]-m_pDataFile->m_Info.m_pItemOffsets[Index]; } +int CDataFileReader::GetItemSize(int Index) const +{ + int FileSize = GetFileItemSize(Index); + if(FileSize == 0) + { + return 0; + } + return FileSize - sizeof(CDatafileItem); +} + void *CDataFileReader::GetItem(int Index, int *pType, int *pID) { if(!m_pDataFile || Index < 0 || Index >= m_pDataFile->m_Header.m_NumItems) diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h index 6e14e258..98529e5f 100644 --- a/src/engine/shared/datafile.h +++ b/src/engine/shared/datafile.h @@ -12,6 +12,7 @@ class CDataFileReader struct CDatafile *m_pDataFile; void *GetDataImpl(int Index, int Swap); int GetFileDataSize(int Index) const; + int GetFileItemSize(int Index) const; public: CDataFileReader() : m_pDataFile(0) {} ~CDataFileReader() { Close(); } diff --git a/src/test/datafile.cpp b/src/test/datafile.cpp index c2827be8..dbc3f4d5 100644 --- a/src/test/datafile.cpp +++ b/src/test/datafile.cpp @@ -5,7 +5,7 @@ #include #include -TEST(Datafile, RoundtripDataAndSize) +TEST(Datafile, RoundtripItemDataAndSize) { CTestInfo Info; char aFilename[64]; @@ -17,6 +17,8 @@ TEST(Datafile, RoundtripDataAndSize) static const char TEST_DATA[] = "Hello World!"; int Index = Writer.AddData(sizeof(TEST_DATA), TEST_DATA); int Index4 = Writer.AddData(4, TEST_DATA); + int aItem[2] = {Index, Index4}; + Writer.AddItem(12, 34, sizeof(aItem), aItem); EXPECT_TRUE(Writer.Finish()); CDataFileReader Reader; @@ -42,6 +44,21 @@ TEST(Datafile, RoundtripDataAndSize) ASSERT_EQ(Reader.GetDataSize(Index4), sizeof(REPL_DATA)); EXPECT_TRUE(mem_comp(Reader.GetData(Index4), REPL_DATA, sizeof(REPL_DATA)) == 0); + bool FoundItem = false; + for(int i = 0; i < Reader.NumItems(); i++) + { + int Type; + int ID; + void *pItem = Reader.GetItem(i, &Type, &ID); + ASSERT_EQ(Reader.GetItemSize(i), sizeof(aItem)); + EXPECT_TRUE(mem_comp(pItem, aItem, sizeof(aItem)) == 0); + EXPECT_EQ(Type, 12); + EXPECT_EQ(ID, 34); + + FoundItem = true; + } + EXPECT_TRUE(FoundItem); + EXPECT_TRUE(Reader.Close()); EXPECT_TRUE(pStorage->RemoveFile(aFilename, IStorage::TYPE_SAVE)); From 0aee8ab994da607fe32dfa6a6f6f3e83d8dac016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 10 Apr 2020 13:42:26 +0200 Subject: [PATCH 243/479] fix incorrect address being used for connecting- and password-popups --- src/engine/client.h | 1 + src/engine/client/client.h | 1 + src/game/client/components/menus.cpp | 13 ++++++++++--- src/game/client/components/menus.h | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index 853ae23e..369efdbe 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -147,6 +147,7 @@ class IClient : public IInterface } // + virtual const char *ServerAddress() const = 0; virtual const char *ErrorString() const = 0; virtual const char *LatestVersion() const = 0; virtual bool ConnectionProblems() const = 0; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index a49a04bd..812c8bfe 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -238,6 +238,7 @@ class CClient : public IClient, public CDemoPlayer::IListener virtual void Connect(const char *pAddress); void DisconnectWithReason(const char *pReason); virtual void Disconnect(); + const char *ServerAddress() const { return m_aServerAddressStr; } virtual void GetServerInfo(CServerInfo *pServerInfo); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 57788408..568a700c 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1870,7 +1870,7 @@ int CMenus::Render() Box.HSplitTop(2.0f, 0, &Box); Box.HSplitTop(20.0f, &Save, &Box); CServerInfo ServerInfo = {0}; - str_copy(ServerInfo.m_aHostname, GetServerBrowserAddress(), sizeof(ServerInfo.m_aHostname)); + str_copy(ServerInfo.m_aHostname, m_aPasswordPopupServerAddress, sizeof(ServerInfo.m_aHostname)); ServerBrowser()->UpdateFavoriteState(&ServerInfo); const bool Favorite = ServerInfo.m_Favorite; const int OnValue = Favorite ? 1 : 2; @@ -1883,12 +1883,16 @@ int CMenus::Render() static CButtonContainer s_ButtonAbort; if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed) + { m_Popup = POPUP_NONE; + m_aPasswordPopupServerAddress[0] = '\0'; + } static CButtonContainer s_ButtonTryAgain; if(DoButton_Menu(&s_ButtonTryAgain, Localize("Try again"), 0, &TryAgain) || m_EnterPressed) { - Client()->Connect(GetServerBrowserAddress()); + Client()->Connect(ServerInfo.m_aHostname); + m_aPasswordPopupServerAddress[0] = '\0'; } } else if(m_Popup == POPUP_CONNECTING) @@ -1954,7 +1958,7 @@ int CMenus::Render() else { Box.HSplitTop(27.0f, 0, &Box); - UI()->DoLabel(&Box, GetServerBrowserAddress(), ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Box, Client()->ServerAddress(), ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); } } else if(m_Popup == POPUP_LANGUAGE) @@ -2394,12 +2398,15 @@ void CMenus::OnStateChange(int NewState, int OldState) { if(OldState >= IClient::STATE_ONLINE && NewState < IClient::STATE_QUITING) UpdateMusicState(); + m_Popup = POPUP_NONE; + if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) { if(str_find(Client()->ErrorString(), "password")) { m_Popup = POPUP_PASSWORD; + str_copy(m_aPasswordPopupServerAddress, Client()->ServerAddress(), sizeof(m_aPasswordPopupServerAddress)); UI()->SetHotItem(&Config()->m_Password); UI()->SetActiveItem(&Config()->m_Password); } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 58527837..15781b62 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -437,6 +437,9 @@ class CMenus : public CComponent int m_DownloadLastCheckSize; float m_DownloadSpeed; + // for password popup + char m_aPasswordPopupServerAddress[256]; + // for call vote int m_CallvoteSelectedOption; int m_CallvoteSelectedPlayer; From c68402fa7e279d42886d5951d1ea8ac2facc1ea5 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Apr 2020 18:58:44 +0200 Subject: [PATCH 244/479] changed a check --- src/engine/server/server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index e3ac6cb2..f01f7cc6 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -496,8 +496,8 @@ int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) if(!pMsg) return -1; - // drop packet to dummy client - if(0 <= ClientID && ClientID < MAX_CLIENTS && GameServer()->IsClientBot(ClientID)) + // drop invalid packet + if(ClientID != -1 && (ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State == CClient::STATE_EMPTY || m_aClients[ClientID].m_Quitting)) return 0; mem_zero(&Packet, sizeof(CNetChunk)); From f93ed2bae3cc93274bee4d4e6882f653696999df Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Apr 2020 19:13:20 +0200 Subject: [PATCH 245/479] changed default menu theme back to heavens --- src/game/variables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/variables.h b/src/game/variables.h index 22080698..85305699 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -88,7 +88,7 @@ MACRO_CONFIG_INT(UiWideview, ui_wideview, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping") -MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 64, "winter", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Background map in the menu") +MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 64, "heavens", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Background map in the menu") MACRO_CONFIG_INT(ClShowMenuMap, cl_show_menu_map, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Display background map in the menu") MACRO_CONFIG_INT(ClMenuAlpha, cl_menu_alpha, 25, 0, 75, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Transparency of the menu background") MACRO_CONFIG_INT(ClRotationRadius, cl_rotation_radius, 30, 1, 500, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Menu camera rotation radius") From 52aa38795e1e6772c75b90779590edc3c28c2dd6 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Apr 2020 21:04:38 +0200 Subject: [PATCH 246/479] updated map_version tool --- src/tools/map_version.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tools/map_version.cpp b/src/tools/map_version.cpp index 8d8c59e3..092f3e57 100644 --- a/src/tools/map_version.cpp +++ b/src/tools/map_version.cpp @@ -18,12 +18,13 @@ int MaplistCallback(const char *pName, int IsDir, int DirType, void *pUser) if(l < 4 || IsDir || str_comp(pName+l-4, ".map") != 0) return 0; - char aBuf[128]; + char aBuf[512]; str_format(aBuf, sizeof(aBuf), "maps/%s", pName); if(!s_pEngineMap->Load(aBuf)) return 0; unsigned MapCrc = s_pEngineMap->Crc(); + SHA256_DIGEST MapSha256 = s_pEngineMap->Sha256(); s_pEngineMap->Unload(); IOHANDLE MapFile = s_pStorage->OpenFile(aBuf, IOFLAG_READ, DirType); @@ -33,10 +34,14 @@ int MaplistCallback(const char *pName, int IsDir, int DirType, void *pUser) char aMapName[8]; str_copy(aMapName, pName, min((int)sizeof(aMapName),l-3)); - str_format(aBuf, sizeof(aBuf), "\t{\"%s\", {0x%02x, 0x%02x, 0x%02x, 0x%02x}, {0x%02x, 0x%02x, 0x%02x, 0x%02x}},\n", aMapName, + str_format(aBuf, sizeof(aBuf), "\t{\"%s\", {0x%02x, 0x%02x, 0x%02x, 0x%02x}, {0x%02x, 0x%02x, 0x%02x, 0x%02x}, {0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}, \n", aMapName, (MapCrc>>24)&0xff, (MapCrc>>16)&0xff, (MapCrc>>8)&0xff, MapCrc&0xff, - (MapSize>>24)&0xff, (MapSize>>16)&0xff, (MapSize>>8)&0xff, MapSize&0xff); - io_write(s_File, aBuf, str_length(aBuf)); + (MapSize>>24)&0xff, (MapSize>>16)&0xff, (MapSize>>8)&0xff, MapSize&0xff, + MapSha256.data[0], MapSha256.data[1], MapSha256.data[2], MapSha256.data[3], MapSha256.data[4], MapSha256.data[5], MapSha256.data[6], MapSha256.data[7], + MapSha256.data[8], MapSha256.data[9], MapSha256.data[10], MapSha256.data[11], MapSha256.data[12], MapSha256.data[13], MapSha256.data[14], MapSha256.data[15], + MapSha256.data[16], MapSha256.data[17], MapSha256.data[18], MapSha256.data[19], MapSha256.data[20], MapSha256.data[21], MapSha256.data[22], MapSha256.data[23], + MapSha256.data[24], MapSha256.data[25], MapSha256.data[26], MapSha256.data[27], MapSha256.data[28], MapSha256.data[29], MapSha256.data[30], MapSha256.data[31]); +io_write(s_File, aBuf, str_length(aBuf)); return 0; } From da45f073b1c702750b51007c0fa58264e32ec568 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 10 Apr 2020 21:05:17 +0200 Subject: [PATCH 247/479] updated map versions for the map checker --- src/versionsrv/mapversions.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/versionsrv/mapversions.h b/src/versionsrv/mapversions.h index 0e434ba9..1c8805c4 100644 --- a/src/versionsrv/mapversions.h +++ b/src/versionsrv/mapversions.h @@ -9,6 +9,7 @@ static CMapVersion s_aMapVersionList[] = { {"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}, {0xd2, 0x14, 0x6f, 0xa3, 0x73, 0x11, 0x9c, 0x78, 0xdc, 0x46, 0x7e, 0x98, 0x78, 0x0a, 0x73, 0xf0, 0xbb, 0x55, 0x45, 0x43, 0xf2, 0xf6, 0x84, 0x70, 0x3c, 0xe8, 0x3a, 0x8d, 0x6d, 0x06, 0x43, 0xff}}, {"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}, {0xdc, 0x01, 0xc0, 0x70, 0x6f, 0xf6, 0x25, 0x88, 0x1a, 0xa5, 0x8c, 0x7d, 0xf3, 0xde, 0xbd, 0x2f, 0x9e, 0x69, 0x2c, 0x83, 0xec, 0xf9, 0xe7, 0x9c, 0x5b, 0x55, 0xbf, 0x8a, 0x2f, 0x83, 0x7c, 0x4b}}, {"ctf5", {0x3a, 0x16, 0x94, 0xa7}, {0x00, 0x00, 0x28, 0x0a}, {0x86, 0x92, 0xf4, 0xf9, 0x12, 0x39, 0xb2, 0x98, 0xb6, 0xec, 0xad, 0xb4, 0x70, 0x0d, 0x1a, 0x7a, 0x7f, 0x16, 0x67, 0x42, 0xe3, 0x86, 0x4d, 0x80, 0x26, 0xa4, 0x1c, 0x1d, 0x43, 0xe6, 0x4a, 0x42}}, + {"ctf5", {0x20, 0xb9, 0x79, 0x05}, {0x00, 0x00, 0x28, 0x34}, {0xa3, 0x5d, 0xdd, 0x0b, 0xe1, 0x27, 0x9a, 0x6f, 0x3a, 0xc4, 0xe2, 0xc5, 0xe2, 0x9c, 0xa8, 0xda, 0x6b, 0x03, 0xf5, 0x34, 0x7c, 0x5c, 0x44, 0x03, 0x24, 0x84, 0x55, 0x31, 0x81, 0xae, 0x80, 0xc0}}, {"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}, {0x1c, 0xe6, 0x18, 0x8e, 0x68, 0xaa, 0xf1, 0xf7, 0xe3, 0xaa, 0xdf, 0x27, 0x8a, 0xb4, 0x4d, 0x8d, 0x9a, 0x02, 0x3f, 0xec, 0xa7, 0x7c, 0xc7, 0x1a, 0xc8, 0xb5, 0x54, 0xc8, 0xfc, 0x8b, 0x3b, 0x63}}, {"ctf7", {0xec, 0x97, 0xbf, 0x07}, {0x00, 0x00, 0x19, 0x36}, {0x6e, 0x74, 0x9e, 0x6b, 0xf4, 0x01, 0xe5, 0xd3, 0xe2, 0xcb, 0x9d, 0x95, 0x43, 0xb5, 0x25, 0x34, 0x70, 0xfc, 0x00, 0xdd, 0x42, 0xe0, 0x96, 0xa4, 0x8f, 0x47, 0x19, 0xba, 0x1f, 0xcb, 0x8d, 0xe2}}, {"ctf8", {0x68, 0xe5, 0x43, 0xd2}, {0x00, 0x00, 0x3e, 0xdb}, {0x78, 0x04, 0x36, 0x19, 0x30, 0xb6, 0xee, 0x50, 0xf5, 0x9b, 0xfe, 0x49, 0xbf, 0x9d, 0xa3, 0xb9, 0x01, 0xed, 0x01, 0x47, 0xa5, 0xf2, 0xec, 0xae, 0x25, 0xb2, 0xa4, 0x17, 0xac, 0x95, 0x5f, 0x01}}, @@ -17,6 +18,7 @@ static CMapVersion s_aMapVersionList[] = { {"dm3", {0x77, 0x52, 0x3f, 0x3e}, { 0x00, 0x01, 0x28, 0xb5}, {0x4d, 0x18, 0x05, 0xbd, 0xa0, 0xf4, 0x82, 0xf1, 0x88, 0x2f, 0x41, 0x00, 0xd1, 0xf2, 0x1a, 0xe9, 0xf4, 0x38, 0xcc, 0x2c, 0x74, 0xa7, 0x1a, 0x24, 0x22, 0x7e, 0xa8, 0x1e, 0x87, 0x51, 0xe1, 0x93}}, {"dm6", {0x47, 0x4d, 0xa2, 0x35}, { 0x00, 0x00, 0x1e, 0x95}, {0x09, 0x64, 0xbc, 0x24, 0xe7, 0xe6, 0xce, 0x7d, 0x1b, 0xca, 0x5c, 0x06, 0x21, 0x64, 0xa9, 0xba, 0xa3, 0xd3, 0x7c, 0x83, 0x4e, 0x0a, 0x83, 0x94, 0xf0, 0x7b, 0x2e, 0xe3, 0x71, 0x94, 0xf0, 0x8b}}, {"dm7", {0xa0, 0x09, 0x29, 0x06}, { 0x00, 0x00, 0x2a, 0x9e}, {0x8b, 0xde, 0xd9, 0x26, 0xf1, 0x2c, 0xa6, 0xd2, 0x45, 0xa3, 0x95, 0xb4, 0x83, 0x7e, 0xfc, 0x09, 0xd2, 0x5b, 0x5b, 0x0c, 0x72, 0x9d, 0x91, 0x4c, 0xe3, 0x35, 0x0c, 0xee, 0x5b, 0x13, 0x3e, 0x91}}, + {"dm7", {0xce, 0x14, 0x84, 0xea}, { 0x00, 0x00, 0x25, 0xd5}, {0xbf, 0x98, 0x2d, 0x36, 0x43, 0x0d, 0xab, 0x51, 0x5a, 0xac, 0xb1, 0x6c, 0x08, 0x59, 0x0a, 0xeb, 0xcb, 0x99, 0x17, 0x6e, 0x25, 0x36, 0xff, 0x67, 0x48, 0xf9, 0x75, 0x3f, 0x1b, 0xab, 0xca, 0x6d}}, {"dm8", {0x18, 0x39, 0x6d, 0x44}, { 0x00, 0x01, 0x12, 0x9d}, {0x65, 0x0a, 0x71, 0xa2, 0x0c, 0x54, 0x73, 0x32, 0x9e, 0x2c, 0x5d, 0xca, 0xcf, 0x66, 0x00, 0xf5, 0x41, 0xa6, 0xc9, 0x5a, 0xec, 0xc7, 0x45, 0x77, 0x48, 0x8e, 0x21, 0xae, 0x37, 0xc7, 0x12, 0x91}}, {"dm9", {0x51, 0x64, 0x9e, 0x61}, { 0x00, 0x00, 0x21, 0x8b}, {0x7e, 0x05, 0xc1, 0x57, 0x81, 0x11, 0x86, 0xca, 0x6e, 0x41, 0xb3, 0x36, 0x60, 0x65, 0x9b, 0xc3, 0x1f, 0x2f, 0xfb, 0xed, 0xf1, 0xe6, 0x21, 0xf6, 0x17, 0xdb, 0xae, 0x9d, 0x14, 0x4f, 0x3a, 0x83}}, {"lms1", {0xb2, 0x71, 0x4a, 0xde}, {0x00, 0x00, 0x2d, 0x33}, {0x97, 0x8d, 0x27, 0xa5, 0x69, 0x6a, 0x09, 0x9f, 0xfd, 0xd3, 0x55, 0x96, 0x93, 0x0d, 0x49, 0xf6, 0x28, 0xf8, 0xe7, 0x0a, 0x3a, 0x76, 0xc4, 0x82, 0x9f, 0x33, 0x65, 0x04, 0x49, 0x1e, 0xdc, 0x1f}} From 83fcf51429f7b8516d1121c280dd7dce2f354768 Mon Sep 17 00:00:00 2001 From: Sonix- Date: Sat, 11 Apr 2020 13:45:02 +0200 Subject: [PATCH 248/479] Fix jungle_midground bug --- datasrc/mapres/jungle_midground.png | Bin 45147 -> 45130 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/datasrc/mapres/jungle_midground.png b/datasrc/mapres/jungle_midground.png index 22b6136917ec83246f5943820de2f3157567aef0..13ac75a2d7842d0e8283de7bf825edff101a8168 100644 GIT binary patch delta 23300 zcmYJbcOcc@|2TfGkwVmqlr6538M1|zk(EletL*H(J#Pb*eeDpXQufN`8s)mlE_+5U zT_by3?)^R0`}6(X|D5yK=W)(?oX6wwG&)7~b&4uZo~n4iRFUg0)U!y-;Co}S?J?~a zao-2Hn1j|K&8RjGnbQBF)fXEc;Ha)xpJsTV!FuA>0%251`ZMuY@`AMe9L0=i@_cW? z(eJAQsVn27r;e|5mzw+)x&cn^Ddm#9*(;6zHL-}rEnR1LOaJKsl*mSM zHaM~OvpVwrhAW?AAf!Y=oQlDn!z4sYzwtk#zoX2|CA1q>O#5eSmsjmCa#^fXW+Z(X z`H4LF3ZiK;%!3`z>U)w;@{SA@@U7laZgP}*nU^hx+~)7^matbGzUlEpf8I}=9E6y#k^ zLKt=?GrrwaLxA?`UW_39|M+JAruAT9St^bOp_|FGm+(?DG0lR4lqe5&*JJLMknxo@ z85D2H8SVsYGgD?(0JMY8Ep+WYp#p3cjH7A(p&m3Z7De!Q{Xofmr8=4u$CiYMBA2Q#m)6`DH(siClBYEdGEco zqbNE0MHl>91s4G5!c58*rrWU}(byouF22AyRc&_F6Qb{^N6`?X&S9`?n>pxL-<{5h z(E(uPg_t@w;*CDPmnRW&W6lHf>nfKQR(j!hUe&dy1g4O}u3*TQf%WsI>HeD^008IZ zeM*ch_pSc(uB}kq+iUGJh0$72LG*Ecm57a$;11WvT>ZG2@csudY^5LB?99Z<@x*@I z{pC0=jyWSTJ#JL$9H+pFZ{)OjS;6cnU+&o+XO?DbX&Br@2xMrFG8umpl;m=9N^`Ei zs_!=F#?=q)zOC^%a)oB?Dhgk7p^z4UxQH%DAKzWEf_@Pb^T)U!=WJ(V)6l3nH6|s0 zjmSW=S!!cz$^ZbL1TC7*VG>^T1ZU1>582O|_wLod?Ad)6F>C89VEo%e%ifg!5G<3@ z={Sk-IS?|Do{}6GvRU`tsbf*@zLXRdCu#*5J-*@H)cw8!UU{`w^uXF-2JuQKQFLK_ zr_X+RrE`AIJgsHdP8*-Hc(YwT1i1`MkHSRVGNI4|x_x#L$6u>E55)rbTZx{gHwl^I z;kcMMi@mwnO~B+%m=2`fnM@7Wj?}S8O@*@b zJ4wRsQ+6BpUw#r@!i&_`A|r=2$~>J zD$9cYf~f<4@UQc*x@-(U3>w#~jPc%oG3&%KE;R0iyd#*UrIHxsbEgq;^af8LqXN{EjNemN@L1*)0ZF$of&E`C$dr%A(yvEK*dkW8(*# z4aF0}qQmcR%6d@Vr;I8LcFTUQ4nEzdexq&KxOc`T1i#HDwmr)TWkKNvv)8`fK({&^ zhiSZ>RB*60InVGV+pp_eiE|q2+fL~OuEFW3<`b2evhzk3uvNX4Xe0W>Y56^JXmO-B zb%^(CK4)q7-lvI)HQbX;@qYc+l_fyEdOGW~&le+ONV2YHtrSt5|GoFyDzNV@?c-DE zlK1<1fE<373{g8My(|=@R4mle0e8JAr(QN%{_?so0=f$`-PVW`v#Pp)F%*+m@!rqW z=t#CeX^f~bP|>=`iC?IxTTC5F6r%=P8STZn-1OJ&WFot1wKdhNs~o7ccFfD1!(*Sn z!ffY>l6))pZZ*ly%(by+<&KRzbAytZ>l5Lq19UqypRZyzJ5^s&Fnb%X(|8*>WvJE9 z$V0cshLLa*mE-1NE$sBKu(3>vJ<1nY<(HZFE5rHTswz%@B6__Y+l=>L@jRb z<$Z(jJSjn{rvJ4ED3!i5*$<#RbhV2_s8#C!=Io!N;g`8vR%CM?e-=}YG}0`()K$Lu ztCynkt)XxY;EOO~f+2zp(d#;)k%?W*9cS!6d+}XR)lAmkt^M%ir`~GmHvvaoKHSoE zZoaKkytr1HN)BK{`W(uzq}xRAHP*Fr9y16DGHbcU?KjI8pBuea7XN(yU{)$q9g{n} zsM*YbId{Q=#V9U##w!5ZKNH4w07U%w~T)nZh!q_exx0oJUbs&u=Rj$Y!-G zo*`JYfi>HgX2>2tX-bxjy_QiHA>z(ZlxA<(1)sTdN6aT0D}?C>!~5P4gYi|ER!^up zw1Zf@i-?Wj_Nw6a=IhZ$W+k!8?|IOGlFhfiR4zK%7b|+D^gQ$4T4Z{)a)b{8ev3WX zX!0>j=1p0G-!;({6PV(U(1#||dhvD0La(yW%TZocCbtN`tT;Ckl;3B<9D z^ZG@tn)>TL?WjFl7=3|;kL#4Q@ITcAR|EZuLT5LKY{22Ug?S^BvtF@jM$yRaU8{8ZO5 ztbKnIRgk*(@kNoeQ>|;dAH9Rm8ZG4xV1`w;BP9ecOVz4a=vG%jsPCRWM+U26ZFFde zTgNo0LAto*5>mB4hK63l?Ev+@Md3azUPqQ$G@E(f2KqESyfq7I4u9 zv9BsAF{uWba@4q9v*3O(*)y2$`>j3DJ1#16*LX+j+Ku#Xe#@dy1)S0iYuw-%y~#F223drsb8i9MEUfmFE1F?o~xUpBv& z9$$`e9Jl=G0IWK~w4tT+E2Afc5{)X>?@R}mq&*LXPF&(U2JhL8fCG}#)sC&Bh0$Y` zuNBiBEEDpmi)8g2xlM0c>isdcPR%Ysyr=+5P=;*Dw>(yE2uUgjRlE)JMc+`fp5I=-1Rk0WsnMcz+~P?Y_e`%}Foi3Hk0Tmi!9B;p(Ds$@)6cgpZ#DTr;*y&b!c= za@9CrYhYaseefs%fk* zKj5?9XqadaF<&pz@<>zf{hfXM*OQ5NWx+Zf4M{;!Z*84*h(9#e)L#(45LFPy9;=Gb z^FyqN<&S?N?O&?A{t;g%`~9Tkiu8)6;`RD(9a`_-2a5*tw)(xEG3nF}Xpo)$0IXWS z5K$E;5kTR`WW&IwY?sRqN7FMt_DmnEUSq0rW<9hLo+TTh!nQrtV>-7^7T%G@ce0!0 z+Wr%B@7dN_z?Zw>JEe{}Uw#*gQ*#};W&PiXo9i=&fbNc-(&6)uHy4lrvI4{$w^NSa z3=n+8(?v1o8W2_hXttoFD?~N=_S$thZ!&00vyAzLhnr7?p38i+nl~&nyH~)s%Xf{q zenEp4aEe=w_K4Gf*|B;?v5t2YDxUq}rh;Jy)lie|65p<JB}C+C`tK?W^lUK@w#S=E|t&Si=oet zB^<%0wFM}(QL(Hso#N|IA_XTT zx?r**i4es*s^NauIDm_2%tQIGmTB3-c6GvcM=u-!5I}R}YsFR1-k6seYoXrN5w`WJ zt+-|{o~rW3xs@z7uE9~SLrj$6jM9%QDoUkEaZoOIXwZliK(jj1{SLL;ij!i*=weU$%XT)3 zt)f5c$|wtnD}%K63~TfjywWV9rAGo$TF^`sxgp;sZnT-5U!muKa3kQ{3^ACi@C0!b zx}{`mgW?c#{7@3CtsUCFi*(tE!! z+tDxb)T02r(4F*ad>z}eh14D(nnsQ?M~~}`IJ#b|?Gu@6{DJKVQ2HIoxNJ14wOl#B z^Xhh`u1|2RN%E_FJ^Yl)$lWq1ZI*(JH4v+Ft{8a=8us8k z)p|S@4vjP;m4voegRD=lXX&_TiMx!Gk;FKQmGud{w0VO>%hT82W6*AG&l|b13wLd14FR zBYCvh&E!||+gt|%70By}Azaj2ryq>_6(t>t7F({&&Mc{|Ye3QW3|km41bv+ktdzmV zaK7%i{Mq_E!?dnvRc@m}^Ollo(7OuC?^yc-!IU&B>!3ozxX@Tjfff~0DXisLj`qDr z?kIZfgs7pdiEMl@9`ZQ>rkW!#nH@y}Iih9}IH?iY9vrnqQZSq6!8x-&w!T4~WL0Km zjk3_p?xp7YXP(Cj2Hl)9ZR9bncgXk?T9-3BcU19{Hfwfw&ZtP`sS6FaL^`XSv1<#K`aZfKTPz8MOf2)7 zlK?n7FAtPxh`5wyIry!#e#1vtPT$7sXZ$Go$Z#d4h z`1DM2kT+sa2_mLDtX%BHf!e-=r_prRa#NMaW&>#y3`Wv?8vxqPtMr59tu}V__E{E6 zaZ%8&v3N*->)J85$N`N0?}8^xnpMt8-KfvvQU5&=m{3hg%HR(WnES;uZJoA!u`82q zPjkgIdBblcK)&mVyy#=wexuw*^}|%6gbP7n z-fLUr^AP!%6i2mh&t9@FA=LMNb>(&`#phC2@q((2RgJ`&N9b;E>&AQSaGUJdoY>3J zdR8Qh|Ez}ZUFs4MxB&Q)p3DSiDeVStpAOrkx^%N>dIa2+skwb>SiU==0XK*6Bqlv8 zBJ4#{hN4bgQhF)`KH#h$l0@wvtJ*<6Zo?I?Y)*%draAq(KiN+pZQ`mvvYT#+g>cD* z&W}sF++Li?Nb1=NI^R@w`L@bmC8y-OXSyzT%2SUQoN!kWsFnqWmnBSUyTqKcO488g zfnu{h!PjP#rL$!8>5Nlu`o4I*?v#$;e2&E0IFSeY}|1nH>$w4?d1QknFj_o;x z+=<2MVnP2P&UrxRHN>(hLixQgZ9VK;cnNW6R-o{%i>YvhR^_|4p>#_fBbvV#_4?kL zaX?o49F-?w6FoQ}Bgky$-=O#G1Nc+=_QuntSB3n>Rq=xTL60oXyq{fd5RUz&(?0J> z>Bp6p>o*0=&nQO-4pl*p=K{`8FZn0pY@IA!P}xQ=kPKkdXo&8UV!*o#L0w`~8~Q(A zg75FDcKrUhD;LH!qnN={=>dYzrv#7X_VldPP1Cb#>91dw^FLg_6kmU;xwaEk5xRzz zC}X&`QBZ<)c~G`#tS3m)*vYv+-ja4~^~syqU;EeSM^~@JcKEtNpN{p2+`!NRZoX^0 z)YbPq%WN*Q^yd57DB`>>1LgjBuXKO;qI=)|NE`$EoP?b9ys8uWrB;~}$A(-#*uA&G z9~}|IU9XNAGyrH~XW2nP`slDl>gun7tM}}Aaos5X)ZE5#hnh1anLzvR8LXA>CVusl zb(Jlo>PZU$zV0w6teGui2VGFpJhS>PhfcKEXGa1 z95?Lxge>Sg-NL!NY%LZg{bx*6JDC)ah3moczg$UaBUt@Z3H{EM@N;Xdv1`r3g4nvj zb3cfH(%^s9u?ddO+Qj09d!2>(PPYvNEE2>S1|2ic&_iG^-?I3GOTx5d0U?bQ@D0dz zIhDF_7HrFB;cg{9iT-WI!W30a@$mdQy8eQrW1#hWjr1cPB%G=&zMmm?1RS+{WV5Y^ zOY^0-EBlBx_b+XcoETXu>8f-OQ90Th{(&%n?zd?14}xk?isw2y7F)vJW9?M!9L;jl zyJsBCq0b%Je)L4M7LFS|lzGQK?E23_jt)Pw2Il_Ar*N*-7MbNG2Cnwo<7Gdra{bA7 z=I4`xvkr|upWQ>AE^|f>+WSY*f~AUrQ&zP`ZPksuWelfBs7AY$RAO>sADAXb2rgaS zy2A6dy|Jg}Yc-9}HcKF;q;!2!Z;iKzTFs^rN)|;;8`nM4rJnsNuv}XB^ z|E!mV`eh^vOx|O^`RRWE*?!su^U(dk*!52!QsH7#>9FLq7v4R#Lq^eh^j^2_(zq?r zC3tN3M)7}@-ejm-0Z!3AOW}7g+F9LJ?El?uL?x<@!VZeVh%#Ze4I|(Euc1A7BEP-i z9{W{??~a%^X$kM5_=elZBLI44=qUr($FH>oWITeOfc?8DEvaZPII(}Ri#hE3L9 zVTmagD4E8)_%-GDX=n+~z1q`*c5MPSe)eov7693wA6+;FzGr=XUn+>AyVYBGHm1{1 zx@6x?3(jvX@i0i&XWG;3p17=Q^9fvh>;7csaeN|2mrzMajN?yyT7@CgbtUl0835_2(} zbNMcfaIcY_IQ!brBF^qDK>uU~J^5d3R6Q!iZ2_kN2GJzp>2$l6<4 zb1Xdp#kr9k^WOHu@~K({Si5E4WqgKurMu5ECLu&~%Nj zpOuBhSCi!8^a`R@^Y8xR?!5J&{5AkLS6F)z9y2jPW$Cj*c#2k0{Fr!v+FF!NhRx$y zr&eyb5Hh5WIzJF~C|!j1%j?0;;$Q4wEw6h>E%2GBmzBMB)2d8#zLRW?^isGCmrY(+ zusECs&)P)scQDhgO0@wre$?G|hrBSttlk)%pWk6Ygw@Y`H_)Ak&5ByzS$>vHi-2av z@C@`oZ87@Mkr`!m_?dx`L-j?#T#1j>7?^Pc7H3&_`oHK$cjV#4j(h3EQa?wn8KGjQ zRP>gwr>tc)fIIy;6*%E{&59b&r3bI}+pBa-7B67q$gkg|r=mtKAzOz;VYia!M05(S zcqqc<6PfepgO}*y#veC9=bewh^fRK-k@BYw=?|eu8gO9)-gzTn-qrsHybg{dGGRnj z0G9>njX`yIKP=?OfOGHu-_Xv#A!DK4L$hVWum2yQI_odk?y!6gRP`FhfCZ@L1jjK; zNI6XvLgJw<8WR}@AfnX&a12ivo0gT&B4?tQ|2&Stc9(g8lFHf`DeF)!h!uwlFe%jFGWb2~!JT7j@(4|&9OQ2_pY23*N032zKHS{ZV> z_K%RIB3VR}XAbrs^e5P6$(R0z@Gczo^b>gf3^oAT!v>L@2LA{-3S{TcD(KMxFxy3i z*TiG~8E}4oJ5J~4U0Bni&i@$$O$C8lV^mE}8Stqj6m<-9#rX)IbcMX!C%rl2YRkaw z-r#NMbnS(z`ALaAGuTKE#6lMZ0@V7R7Q&*zlvI=``DrLRW#ud}_!xl)$cmKXwy`Sn zE*iu#+rtsiZiJXZ)5lU@#wGv7;Zx0o4bYtzb*zlj>?m{yf(~W{T?LXt^Eiy1v*6(f zSX|!sOWHRkbn;yrhPM#>8?pe^W3BmDun84*PJby`*%PplHp#1V*DKHb1@UDA>StCO z<11|P{{a{g;48Csm7rM(mu}&o?umAr5DnEe|Y>>~g)#ZWaF zoU2}SzH;~%SQG;Fwk->|dw(bSMl&fcy8bysn7@-Yb>O1ZW2z=|Ese@^e@BKF_vMaD z?x1QyhTr@HDF-Fd&$}|64;Kb57Mg%+sTQiHSXfJV@efCgAh6SZJzv!f-g~e+5MnlB zFgd~dAuI<$coecqlYFk`u9UfF+3Zog8eSdaiU~iHTvPXaf_Cw+SO?JczGS(iZyrib z)R#l;6tcLTGRe6Z!uaFn1HpE8eJZ;au3$?84Lwr5Q|^CtQ~7oiY*?1A56+wGKX)Vtg%7>z6s)_co_y-wSBvHe*bU*tW!^eA z%;tVr*TN+&I%YVXxZC%cXyzA;fVgwA1Mu~OkshxGNn&6j$Brhxpe12MmLFPFyuJ?7sie1oAvRntA~8r-ExDp@pJ4Z z$qdTgl?`LG+1OC5HD>!xRR2I7zv4ZUNjA(Aq(nq2nE)sD;U5&Y(uHNB+Ag+MF1el!tdEY_u#mApLrzAV{k(?&q36_hr=N(VlOu z8!_$o5mV-V;~YrRO_dk!BSG%)E<4;E3}E}-Jk9dUzB1=qwo}-LTOXwxazgaF*oY{g1Ra!%&*vG~dk2$UA z5x8K4%eQ{jIr6g`OvgXTQTXfrd?Z>lPT7|}Yg1A;+usPShO2`RIzwPi>)Vu**W>G z&+xX?Evdpb`{kbwhlW8f`jR;x?!PhX^x=6Qq!u=acOiJB@#Ii4Ytz4O#oyqC#>N`$H;P2%(7u1_Uqd+AmaZovgP>4&pUGX6(-ySFR8< zCEVcnpAwJ(Umfsa`DuOf?wVE;)6eHJ??;=t;TE2dPOCwVtjl4Ie!nMtv5{RELU8c1 zhV~XI2168KeBf{PZGGHy?IRnH{NIhCSu5bJ`AqL;#1G43LKO0pVpfP2WKy&?EVlsV zE(_uF5Ruo!r0cPA)ug#Z;SRD+)H>vPezzqvmMN;{KYPAIDYSgTIqEWZF3J{4Ek#@o z-ug|SW%eBAzj69^G;)%5KR6|7d8I>3eb8i!@F0Vd)iJjjKJlnE4Zf%0FoF9GHUGRQ zxv<51RNF3SfB%(j*5xN;zu)4XxQ9m{4l^zjgET|`lq`1RE<{c$7&n=kMEzd;q8t$Ii zwh2^h`OHy4{DYM0_&~nL-(&Q}9UxzNlc46-+^AayHJse0{wDp^Y{^e3eG3&5YN>S4 zIc8RIx{t1E;^j$bC0|>sG9g2l{Q|o{fX12|eoaQDDxM_&gjWLR9!xB!^gsOOr8D+L z<i=W>vnFLqyEv0(b(@oPn*Pv5knGYntNJZ$;!+3 zxgP(>(;@id$3Tb5x$v3M4r?(Dk8_77%L@Zw+((drCd-kOM8>#F$1Y;kF*+`=s@myO9RdYqu2Tvl7R)m!v6otV_R z2gh>@^5}U<@4X6ZIZde~vfH$aaapkp6u;>72C8e#jdZ2>@ha^Ky;-olGgHmJMDDc3 zwDH6&7)DdBh^@>xANtoU7G!h3TR7<(H&>InCT_cKl0v@lpfZLeO1_1+m+YKz_Jamc zzf@z~Yfl>~s0>~p)j=;61-3gNtm2fEGs|?q4b+qBS00v~!|BpuFu}M?h`;H>8O57- zkQ!opU;6Gsyb33h^7+N>lKSNyh!Q8ZD50PGRm#7X2HbeJS>PdB#Z-FS^0)_+EW&0CChacbW(YoNEn6cVu?_*= zK$W{{rvK>sO}VZj7)4Ds5*YOjQvbKD8D{O_l-2J)Chs=U{_?VX`CnBd($dt&KwAjIZ7-Rhz%yt#tO$}v_dnPB$^(3EQ)!+?U^-gA`b7<|I zu}8NUVB9+96w;;TVc;q3YbXR9Nb#LaF_I@Ubv6fHKG9qAq0lC7mX~Mwg@0DL++V2P zLTp9DjY&pY8P(>1;|1>fzouQdNKfS{-U(b60(77s+mhX*3PIE`a5KlWQZF;j3HT-M zltoBSUY0muW+yBmt}NoxIN|xDmNfnujf^16b^EKR3`K3*F$){E{Le;g{fG`aI4=KB`;>CVZk1 z^cYBmg&qgYF?pUm3;gV7cLl=(9!lOn)-?dntL;#!d9@k?@SAkEuV8V%*V6Nm$B`pY zRL4xl$G@~QDbdK4zGB2w^CLk*%n`g5zUmm9sQHKeCkE2q_8s5da0LE;V&0Ypk&QLh zJg=_*z$Lu&8i1pB@Yshem#mYmO5GH}jm$(EAp}G3pt;hhV=mDPqX-c_mPi%49qeD-Aza!L5dM zY^4oH2pveSd;b4MFg8*LM?f;kvW&*w=THn!IGVyE_l^V4DZZ}X@QB*4E=nIJc0n4n zKkCJV#}PjJVwT$ika;Q7GLPZ;b}a&g4V#tOV+5X7l{P;(2zBb1U&wT#1r=r*VYQ}>fC?80O(FywAX?J zXn%fMFcXdj)n7W$UCQKlY%@GmxYC!r?e6A83q}u|Gwdn$xJw5RL-j*=rfC3{bDsZd{^F8@2hRw_0FDU$Ny&zcjSS% zAN*)pQ#U`(DuDhPlkdS}F(_}%{DH2f?2vZ&19Z&GhDSEgOg)Pk1GNM@A#+HT#^GXj zb~k|d=u|Els*_Wo$$L^C7gzjd;LHI4qYN~Ln2vh~eZyYUA!$y1XXL~BrgeP;gJQF^OFdNh4E($jo~)`@Z!N-Cl6E0D#*UsOmZH=lH+2 zDVTM}(;LnW@};R$5a@RkQa|X(#KqNp*;o08_jI2SSmdz2whLL{FKSg`c71Xwpy~FW zIb~0#D;HXoEDSY&1cSwSBh;XHNMKHVJs2;Ixh5FY69KF~Mn25Y4$`zEr4Cs915-a~ zW%c;@{P4zEU_7s@wa!849i1gQ*}bfP?$t+I-QC-^lY|vd}K$Yx3?U(9^*A z2lS;EfZB0}y6M5(&AmYdNaa8Gkp!o4Ll_TyHUvF&z%sj#8BlWEWZBILV>K}(zbi{$ zP95IIj;x4*ROx(<(BgD(K*05NrLccy5vF3yIbhD7Qva@?57&n|d+T3KeT97&T|o~z zkt;o9I<=G8zXLo8M+xf*TDvYl3T}tyMiR7nWV`b3Zz`5h8Qp-P7kx%PO;?7!wYc6t z+H;YQ4@7t0#QSO9=#~L!;c)V5O6~^OrPO`Ccz}CQt5P6Qb9c=VZOhSdiVeQr(r=(md^kJAQ#9kBczgTp5p$?0J`l%d)TmhrlxQ#9O zB}Dit?2`vtYu9x8Ed^(Nva4q4@!coI^xggs-2663rGoQ+sXCuVkXa07+#Zqg zZ|Bml_sB8nWM?vg_;fMH+cR8~2A(ymTlCnAujXFB^&hxBm8$8~NjWN?lBN)mZyJ+= z2iz_`a9Zr^sjix6QcR z$GT7qSlya8@Mg7v8biGSCKejWQP{{n0P z=<*G;futN0DtSZrg8UylxWv%K4L7!;axc1ZQ^J}lu;!w|fGbf=z$4tIdUmqn2ZHZ* zmS(7);{>zUDL6bT$p} zTk#qJR2Dmbu)ybH7nPblgf|~42Y|UvljA}CxyyWxx2K#ug^9)MiOPvv`;JKn5ce%? z`^rcKKr4FBQW_;uvEO%T8+mfe$Wq;rHya7x=ky~P0eaGsFC}SFL_z&;u7(f4h0#Si z-K?cab%jPg!MH{GAE*n$!hIObfu{F?ttGK${gPvMRx$)`fE>T zkKk)CAxI}})4OR~9ThGJV5pPqtp}sO5^+cH^=_sFTt-ck^lZr$8*s*R>Bid6XRg!x zw>&d#^tI0Wjnwru(t^9CZY|tapUfUHfae9+Z`M}PE6S_8{e9G6s_OLDQ@R_)AulBY zZg_@s%~Fq41GH4^`|k*{abH0bEn1D}mZ3p~)7~3Q;E3Rc`lR16m2hzMdUI;YN_WXC zc1i_DGk+qlZI4z@rUkZs_qTqsU&V4cm~ze9eDKShz6djX&Pk*Oo(9EB)BriXlc>}* zsbxx+F%W|xA@6*BA5eOO7IYIOpg|3(^2K$fd%L3prz#_#dy)oC241Y^CegtcHv>VY zLJI*T`=RFhobSdE_s$3IJBz@H`iZ1(`K6Zj#&^M=3i6sP$eG&a7XU~O9$iL1#Z)A9_uuyoJ^!@3qh+OPHy zrs4vLG>0h;USyCV@LF-_cV)4`iv#_T$R_lv(1OpiXht9Ok9b>1PHnB$<4D=2b!c1h z(yIaNqV(Vo6T-n)GC38HTH{X^S^wDWucZdrd$f16veGp_<$WPN&>W(wy5(LsOM?%@v`PA*b9%;qQZ?;hu>FMj$v>qNq}qhD&$*%0 zSy3%jmZ{{`)RYwshN6Yd4KK>Fa27E%@-0L&T7nv0`_0X7jdTh$uBu(nHKYURsw1tp zMlu09s#osVn4p4M-vw$oJ>+!@oDm#0DC;5A5;e&NW0LZDHYS_V*CUVI-@oB`J<}&& z2{QEtz~AZOC5*DZ8QeN&u#W78I0#80OSgr=M)wtjRguljrp+wQX4&tKq8$2D&*&)! zW5UEA6Y|z457Xd$Z`7|z;B`h)Vdnj~fp9@{km`v4GzT`4~{GwFD8%FpurO%W!5 zwmSaoU6fZ4oXR$lG%O3C=bm!90In~e<%N{s>LviIa{L4C2~{u7B7_o#UvN3laIc=3V46`VTghZ4)FI;|6M{! zjU_fPt5|bS)nEn%jkK8J3N#VuLk5SDrd(HkAe?#a^TQO1Edl-bv9k)A36_z3&{>mo zD)9GVIk1b;UOTy@57g*0e~BPFJ;xBCcz^!{1T9>Ufa8|l-AVm57MEK4;kH{< zLLJQWZ|?2zs@sE%Q5Lvrf?;~&_wMbTD~e4knj;1v8^%;K&7_E9avcxF+)A{Grt(3n zN}p|$&4$Y?@RfruiGFH`WcfS2QDzhQ*atnS|7KnPpYT68j&gDkWVB%crYAAn3_}PW z5flDqqSB$vf708U#lxG)0O0-grHuPNpt+~)b-#7*-}%S5FueIBX14+k10;jArG!4l zKu46CD2bQ!rxgz?HekQX(4Zv62H|oWs9k-p&6AuVK775e8gNgA!7+b0N5|0ZvPPR{ zvk&l}FzY!&$%jq`M)-_P))-t2fZB`qnyyKUXB`t-shV`~uC^Wh#$~T&k$9Jc-Y6Ex z2RYflMFVU;JL7XO2S{Cb2kdB;y&RoJjmu+~Ck4}fudcIrdeYGxY9e);#z92Ea*g+J z=P>S?mnD7Sp28s`Zjw*F84866>7F4hrbJ3(1~@OMS|Y{DF*o&9<*trYp{+ay&V5`=50(Xdew=3Xud3 z0@EXWg)VHQfZppDcPt*m>PzaZ>qHJ@9l8WRQ8qL9KB&quQ>m{`XuDsZ)0zfbBX zG0A0Pv%cehi#!lX^~9l$3Q*PdUH>yd;)1-3lRj|z|!NvFO zVSx<*vljr>lS~WzH*##YQ;W4_d*zN^68`fKr;Mt}qQV{lc!K#%#2yhbx=jB^4W4;k z;fMe}V;39~dVKI~lbSF8EjU`279H&{2scco=0jmWpB8IZ%GXU1|E@Iy1LzbicbuUD zUv(0lF)cp$BhtuBp~Ffh{2>Q_6S2Yz0R$Tp&5^@ri(-m?aZfSOHflUijF zvx@kjLl~KPCyF;{!fJ0}yv6+ye3dB5g}+qzUbJ18#2wP0GHwQI)VLR?{lK;&KG=6`?*;1c&weUc>JDrdajRA8s%1xIN4m zl#wjq1$>Ts184(GDD4t}Ki-4`B@m~Ui~TsOhL<0C1s`>1Bos7@4gUYx6COAeY8u)O z!sk{E6*Ms*zTqXOwZOj#UbFCQAc71g`-r zfyA5s?m(YRnZ_s~q0ayICM13`!D55~>w%Pdwb3&QxzrX#ttYWVtHn>yDjmzsWPJqR z_9TUTfoks;NevDK7ZB61&3s>yLjpL`8k~iB4*h z_xy=$tbH#d{7xCR?);;beTdk75`N4z6`yXm!z94RfNS`##sn^V z`oOyK0zWUjC&m)<4#_Q8NDNljpi`X~_q94Cmau{%`&qGVsqPYf3G%}E$&YY_54$p1 zpsE2Y5s4Bt(++J@`QHRP|20XEiopIwFp4OEBou5%=b1x&w zL5DQ0R<~E!w$8n6py07)CTjuF-CHjf>MWfP6yOc{A$0n?64eoHmG>6WQKY+`Z^>&G zf2=E?lblSA6|GWK{=1|u6*eAukVS>goW$NED(rh3k?ngu2gqw0i}_F(>v-3A*c zE&Gm`!Hx$b171VpizAeH5|vuRI*ORe;NOqT9T=g^VhbJW8v_5tN(OhI8q5-aZ2+DA zE{5E`IoG?T{-RAwR%BEzC3%s5S9K=p;z1fo+t(QDaI*Q0bw#d+>pG;N(wP(`JV`M~ zr9u;6)6OM6O(s0V|95H*TOY);_0utH@;+*&e&CNh_Hey`TFH?_CShOn=!rC~bgpCl z2d*;slNdAI`q+>2#%H3%lvFfIB4@vP<1^uie5r=&R1ugWk>tA6vQdK7QT<~|`5a@r z5>6Q!EcJWMxNXQ!Q!9R*c#}Xd{YQSM?XK7My@iv@66FjI#R7H=EE$8x*mx3_qNMpw zFJ3~ez4SO@zbN6@mh?W37A<)N3+;ZBydbtdgZZTUtCvh%SoCQ4+D#cHnLshHE#A19 z`^3X%NHbDy@8Su%hVtxp?{L%igF^;(zbx$#hagtYGq08;0ugG_M@vE#*A70jrYOt{ zJm&mvQY?_q3Q=b5|9ZhQZ0V=xq)0ZaQHvv^#=&DUm?(l%#fT`rA0r*L9@uuINGMDM z?1)pfPx3l1kQ-6aK8mGnnJDZ1e}1_tSNSTNo0(x8lkk%>c6JtL19uttnodE}zi-2q zFXl&=Zbx4x+%w5a_#N!(yO3$RIdHg`Xn#)A(H^^qcie?t3JOOkErV&=EQ0phwI1&- zTt_tBIoTv{ePrnO06nohYgKkmTebL~8S9T18ad>)UM0=VpZV^0A8IjrX|~5vS%>8G z{DKcbWV^y?0@65JF*F)!OMLT$p?h^_Sh~LG?;cu}Df7*BVPY6hYqj=ZNLWl~iHqsQ zAi{CfYv$mCDNP(SIiV4u5UC<=lCl|%HDa73`1~_cas1}FB@g2{FD+aKPwe38CR=#p zV;6`XQ6mQKic(ci)^vt?4(3#?QaJjLSsr>ToXqj(Fi!6|5@EaX!;tgWPO7uLKWnzb zL=vM^{bjybTJ)C}V68jHvqY~W-Kv;*K<@asHhe3hH#m%|dbYxCyM&rNYT}QPV_b)v z3T%{$bZSJve(_O0%BZ=N03A_U@w2`CVJ`t+W}6{hLsG1)oambsQ@6WuGwaTc%Pml! z(NW(ijwB_4C~2$1ui`=6&6(dvU!Ey>rm{WxNeyRjjTZ=Bfd2+f8v!Auw0-(T|46gLiT3RO7 zClkxiqqnDw&e8viWXz-UW*klV>?e{I?L|XwWP7~Y#6n$v3Lt}TGF|!PK+hX*4!dgL z2x|Ppi{C#UNDFTF=v)b}KhN&m&y6T65YZyH8W|mBK>BIjW2`Q&h~J3!{vSq@_LID@ z+1$86+YrIgQp+tk@GV0JSQO< zl;`Vg`~K4l)L;4_z8P@*m2l0KKI};G$F&u?w;vxzQT75G-fFAIG!I~UgT-oO2bMnj ztyk;MkKe^+RTvjoL19QJF$(O+No zUT;HXm$%YYd(8pKvvk`1W)=%WP5cQuR01D6ltXdv#c4tYu-cg+S2R{2A^Zbs+P_g1 zno8|7Uh1U2*Rh$XlYeA&*^GaNXpv}Qs*;Ajhj}$68aVt{vVF^z9fUJnB@okr^A^xhBQ4>J=%hvjhv^gJM#DCrkUOQDapg~ zP9^%>QO_w0d^T%ru7H3sUCa%oC~t^C*P|xxpXtyaI4!z+H`JKsy~re@MA-#i{ru|{ zDh%Tf+DNQ4FM=ZAH`d>`g@IhHZ1T5vy9n)tA=W3zXlZYqkW{4lLyWN zz9oh}+DljBJQQ2VN42`6c(ti_@=iQfA@{-$Kp4;)Wf{F9+hnaQ zgNp2ZWGm{22(%0~%dfF_9yFGUDQ#tLX%O|aT zi2i$L{K~c0VuqDpF_@c!c9fmr?=>naNxO@s`oJKf{7{S9-jqAHab#2x_iLv#0iTOa zg6OLZU48b|uke?RB5mt|SWo>}t$uMG-RTr|oMndr+bNXOzUR+DYo_KkXgD`z4E%RZ zYR5-futOa)j4~jWMbP;PGsXeMcnXTVYA(qK+#t@$b^qQCR}eLyF}h^B@+$L4Ql3Rr z(fZH(xN08ALlLcsHto2dX&ch*b8@iJ);M>ga^?ItS<*RQi>3id5AZsX7q~&v4M;%> z|2QG;o`ft!>USjzO)~>pmn8PVPs}{P+;m4snJh6++)htD?;h%jM#VunSI=$I^rYpc z%L{UjVHYnjyO3Y~c0FYjE-P-n*y|gyE7f_ zLpDc*Vgut+2K}V!z7pQkxfjRpWp@Z9K&X)H8OM+AFd*iVe3xV48QmpmzFBK(pfdKc|_1LR(-R0{x#yAs9^Q`NvCJ-t~rmO0ySv z;3yba1A_*CU*7WBg9dlDj|M2kO5Iob$}jNN6l}87A4v52y9nx7$6VtDk2TlvtGX35 znC9ZA7s#7W!^_Q0ATbgc-ec11vWi(R>-v>zT>}T4TdM*kocKKZl*${W$xrY|+%U@g zk7BE-#5;NaY|F@u@RGAQp!?B>pAeRjta%rW!EsPL7ZL717=T7c^*DB4MsXdI;c`l= z>orpPSf4Ux;IvC4=fDxE{CUPDNjc8c?ZU&G<>9XMs`_<~N*nO)6$hc)&UcTLf}mv% zc}W|rHL#NRL+i5v>k%+F`9S2@5u-fzp#9puYXuaq6LIu2o)JV+Im$uY?9lLIOQK8f zW7`ItCRm0t)>gU7Y4Zw;RUeVwdRyTwfX|TF$0hSpA>d2ijnL%Tnk%Bds@k)yn!Cgv z)K>&CL0Pe0kU;K@L|oZt1yj%%al1d8ubwiDJ^qj4pjDW!BW;StRYBXo*fnLcY4La~ zJYQ7HYFX@*hDQ^l_WFqxfieordm>-WxLAt0u`Ddv zGO_~xt9FEV>Vo~idt`)(QOwf^J1u3E-O-3NvFUEG%inG%yBZ8`I`c4GvG^4rntcAh zTc|zv*H~SG^=O`&0O8K>O)hdrxH4~gTJ~A8QWo#2H?B_d_@#)ytoQWq*eLc0Ia$26 ztZB5%3|qUPrdHx(9WCyuGgiM6+#Jom<#{h#?oNBdjD=bR8?YI2v+3czV^TXVV@#B9 z0xhFaR`dMe5;5c>Z>3S{8H~yJ;;;X+w)ma$#&5;OpxTeURI34bC-lljlVV67e~nL; zvg)|zA|@1XhN*6j6U%+Ydv97gtD|_E7r?)htKl=_wlU13He4I{gny**rsw{2MF9IR zqYjZ%^5=dqD=`7cDnK;Ny-;ZTB3<*nQe`4|rGF+JbFaQD0*#DG%nDyUTJr&J9QGFZ z62FBa`cim$PWea%eK*nI>W|v4YV{0_{$-X7({>cN+m-2_=f^mwXc17c*082IsT0t& zp%}IxX`K|Oz#&E!vvZVJXD zV%{=Z&VN<5i4W04x1bj(LPrmNWCxiI@C5ej*EO&UymRTuT(o(sFYY zz+K(e1Pa4pYZ94l!Q7_`k_#q1vs+Vbt;a$k2=p;!>V*1f!6}5_y0s|N?M#M7-}mU5 z@@duR_(F-*WV)&rmLObF>98}hZ9PSARx3$a5wf07Oht#*FHZ#pGMZDqvkp!b;aj}! zAAAvI%4HoKn%JD#uJW!2WrCp8;3vj13Oa=tm}>r5_-L%W4EFki7kbRysp>K+cGWKB zJ;@XNpH;kBy5=|fbvHSig~dlzPCHh@ol_GPPcoNFhQYM+ES*L=?(bGqMUx)T?}6qB z`c#F9)zUr@9VcQSOLaWioV9iFcMh$7S_~f(5N_3$T)iyp@rVQDRgwKxUq*;gf?`;O zAsa&73f!kQ{zcy5qWb4R;1$@TstWQai#J1T2em2)yiI%{%hb0R}RJ}2HsX^EBoZc6H}bizg>?dE-)X9C2CzYOTC zRWwH3Ut4sqmIoj+kkTH1+rTvM3pDYjpAk`j;_ZiH;rc<01v{+C2ZRm~f$-Im|00zaanxaUT_ ztXy7~^83Y|9v+aHrD;|Moy~>;h5kP^(uiW04f9q(Z+jQeL1ymJP&zDGkh(A%(tJ+O z&}pmIN(XZ_yomAnGS;))-6xDj+o{>Ur$D>aA^CdVWrB!lyZ^wJ?ALmrdZIVSOU;^` z)E=>4*6i$akNMR{TJ+nMILh@%zW0^yQF9FjzfB1vtb2OhN5l#Xrl=n0alLY;E!Iam`kuFk zUspT+l6LkZyO1`q$t}Be=yhNH(H$xg^Pybw_mr)sT3pKm&u2e46q>JV>H9}h{=-6* zTIU|QMR(^6C!HI028Wg$P7(x@{XF}l>u>5LT!A0~GGBg(3z_7T;#b|WVI#I=Fnjo+ zy$Ba9I=-*%+`i;EUh+tv`x>{?>lOc@;Bc zyQ0E)YRvMyK#6t6@I5YRqUoN&Z$cSwq>e z`>|@vMkw8SlF@^s2yil%SpeYCRbE>lHHr>Z1*QM~F`O-Y`6{W;{pLc0_ldjpw_l@R z6w{BP!#|9iv$io+$waSzS|FECw3lz|Q=R4)2Br2e_NAj=#Uzf1#`as#o=XivJ-h1g zuPQ^JH&rOR^h3jDx|j)VQQw>+(?9qHsoM3s2a%sMg0GdA*OxE4(HTs>II)o7DKf_n zwLRn8Y6*;f%w&Fj*2cymKr2hYLZLEx4IEFo1R_RA62Lce5r=Wqu=WxOL^W{k5niT9 z2oCLEdX?yW5Nas=A!x$ApI%w*lka-h40>-si`=Y9AfR2II84D0(osIf`Sdc(u@&h% zXS*>~P;DTILs0=_7?r`-*$C!v-pW`@;{mwe#4UsrSRX&2j3||_{{llA9S9Bf>1NwA zavVt#W9L{#4qSVn#%B-CXe9({1-K_ophaXL5Kr&L+>2u!%3_vE?*r6-XPP~U-F_k2 z#F+a;Flz;4Lct-u(e? zDoUEb)9guWoI}$tGrop z=b!7u1b$JSB82Y?a1Nd}XOWd-Yvi@ZlLSr?HVRIN@9`5V#4rhVlOeG}mo~yeS)AWm|U`% z1R#3tfH}27xVfun%nCYZ4@>d%Hl<4fc>V+5qFjF-S7bR`+?%3U8VH~M5eDM*{$Z6~ z0?v85kEs%6s1bJbUM^FLs}bbtep^yco^iXcc!*bMlK{MXJx(+2yeVvoJiUE+D6gOC z%V%^uIn)6sl{aXY2Q7xC_O<}8hcn>19+|PQ%7V;l9yfO)MP(!HAkcJk*J1)#7tqAxKjvmUrqVkz77Q+Sc z$5ycIC2{32?g)*r)$srq(6Djk~Q(B6|n>sI_og-`Nu=GWYK>Q&2X`}eo2E~-= zO=8d^xw8n+){#z0g!+EW`<5RcdGEh*3&7Q5<;E_e^J3&IKp3gx>nU zhjEipOTcF8Yu&0FZuq2TWFu0uBnJ6-x?279kJv}#$qurk$dJHU^7W_WRb3X@6ctTc zNDZ?5_((7{m&LeZguw#4AhaBqduU3Pg+QhMzgw9!U3BlhpXEZ}s|TG12}{yt8scUM z&PtUVqE2C;a&PG69wH0)9DQOU9gg;k(8wWdT_G9U9(+zG+6jcDsdGC!{`(86f<3g| zJf>K)t{&IH$)4yvfxNodL5<6LY}P-FcdthmljRiISm(L~2rI*=50hIFJh?@T{NI~k zTA}ezy!Hc7YzQZV&y8u~FQ6P9Brg010Nuh4zL4vA+egSHzXO zxxFeuKy)2$>XL!JYp^-n8e*dGU!&b!s_gU-5kl!e@`{~% z4lXq$-cI!vgMhpC0gv!f^Xl_qIrs=ACBwCps4fHyDBFI$LGF6cT025P$+g%0<11ps z8JdM8t12tcg)l%90<8A3pHra*xi%hekSA1Q-e?#uMl}TeA@ua4d{K66YM6Zfr{k<_l}zP`r-%!mYMj}OIf@*MhS64$ z-TH4*4XxIqoHqStv++HdIF-7{B8FKR9;MI4sm08)trscGD> z^;geZS7mSZ1I59KiM}Ga%r?RhhT{VK2=)6d58y()Sz!sx)Q9iX=;639t)oF=UI-XE z=y?lMx0nxyvuCMc2Q3Z)AU14ZrgQz6WIAEm?{b`GC<)MfUP#_|cUU2I0dRn~6GBHP uOa4qh^Qj1dh18Q~g;`H?#&Gb>hK3frdl5eKV(10*88Ff}*Q?NVe)K=r4u-V= delta 23309 zcmYJacRZE<`#63dJ4C%?WtMYfE6N_Hlx#}&&WVI%Z}*W%*+)j%S(S{C%|V5e94lKW za>(9}anA2P^?84P{_uF5`@Z(`dS1_KJnyeFR1-5)i3(H|CqF3h-T~30JRHlpr(s(rl=sQ{pX4OcqH+UzbR8(`zCxxjr?mZ3e0> zND!mTncqC9K>?-oi~zDD4kK~ve|$}(qcdLK2i&NAaJxVuXxPcG_hx+KJ5F& zSxN^0_TB`tfAu2zm6|6Hi5kIojo-sv@4(UB?aYQ^LHV4OAKP5I8ozuj2Q>gxG;d9} zuZMZ$W~#Ax7td8(#BQ1?Or>5L;|i>`VkThjA<8S31fM!(Fz{!<0HEs{Y({0=ul24} z+)s0>PSh-WP*7voESQeJ&=V)ia6XaqKnLIBA_)L!6(5pW;*s7V%bSIChJ-7j-<&ix zhnHe#@RAWS)h$RP0bSF=kC1Ykw}F7fT|T2B6`bE`UgwA(F898aoXD~Z(z11ue_WWI z>{C=o0UIDrV<51R1k6Wje#ba{Igh8<3vF9^#<)i~kjf8Xex3fvO-C0Ja_%i~F-neq z26r8YQA>~x3$jg8 z#l=2Ti+2N-8O91dNTZ1yRFKw=uo=G?9v5t%!3`ZvowGxVHA=6R)%RM!uLJ=;!ABfm zBb&@zpthMMJpc%n)1q;ym%lpcXz~yg|1={e1`Td}m3rrCEr|#meC)fB5$@gh2O~e4 zl?Y=^Pq&RZ0RV|9RIN+gZcmN{11&c%;94*y-Jp94$bZ#}oqPR|vGYZIfO;F|x7{Tn zLLLW37qK-~nD{zUxZNxak`DC&0Q&}3P)k~!m8pp!l@qS-U5Dvg8tL>M`y*yZXmh4w+(7vG+RgHi+S=ZaR3Wv>oGKf|A|y2x`dkK6cZH?e;(Ieh0N2&#r19_aelj-^&ohuM?d`Zm1Pl z(XJR0;a#N91NSeGG2g$M_Kwz)_O9*28rW|7n`e`sbk_( z=x`ey^~S3gaKd0UFLI*aO^8^mKcWhty{YV;)`*;XsVbpD?~}?byQ}&T)~KKK{$blj z-t3x+Y0dJ1(g2<1DUth)p4vFod!3)>-ME1Y!u2rf6(d0zSMv}l^J_Ab%{O?o+Mz8V z8>07KFtGeLzm2rz^^|(4Z{FsgE{y8AyzOtw&hRN4Hi68w~kcuw>j|} zRJJLXduBXyJRi9sp{xzZ(?9oj4OEXW5}`kX&8j{m{I7 z{VcLTce!EpIg&s905KS#W75o(yuAFj^z zC5nu|XpmQMf}F6C7P-vR_WrrR82u;A`{11cxp3FK7DoBy45{pVlUr|g2WK7-Ots~^ zN8Ejl$t#>YDh?Y5OQYtjBNkX^1&B<*lhy8+&10FPAwbxdfJCHB%fLnle1kHw&n?)Ya4JwApw!Ht#_H6V2yl= zhd<50>%&=tOSVkqagQwIi+pcI?+!la$0sMl#Vu-VyEE)^yc4c*>JD4c@ACZI8kc`2 z1Vg)XmKSw!f8;`LEPR+QYY)tenRAt6mC*u|md||pxLzHdwsppmEAqZZ*6NPgBiz~4 z_k&&?fpfw-R!$*V6FO2dZ5@roc<>)3QuT%KcBSgCfj_Uxos?OQk1mfmaEc|KmYxl* zzR1`gwYe2^NAg`+>c&ogtz8K3r%S;;nj>a*p22k+Lb8xrIqf za(DWaMbsG^*E%YsbhW0QZI}nBX)KNF$mq#jc6qWC}a8m9X$a}6hV!n%$ft4U|GHkGQ=nzCCz z-!rfSUvOT7c%HRy!*O5o${& zz3Qt})o~T7b$^2wel=3?2VD|pZ22@5lg6fEYNr3TRQdDg!}~m)ih!$>El>YL8pa!T zIm4x2rIBo7Dix!AYGt7p5OvnEEZNg?-^)&~UN9@DIEq8;35R5^Caxxfn+%G37|uk2EfWE=VuZ)aqbgnDd@9y^a>?KH1L{*>e@W_=`z|0fWf*T5KrA=- z$)zfm=Q~&{yRgs9#AaFEt#}^NXCvsz?s+4w@lykPyb1Dn@5D5n`1rijOa;H$jAsKM ztVHt=RF}0Uk~nTkO&CevXv$fbdEbbrUM3Xz#F8$B`%Xad$Dw`6m*XZ4z$0ZHv@~*g zJO)7X))#!eVn~0?lQkgIuh?bB^RC`=_1*JvLrmOV+g)lsFKldDqjJa2gLB*u2e`YP zF5aYt&~1783}}G4*p`vtFN`BiuEy3yN!3dCHHf+XZzTi;BRBt)(`?o0Wolmv>F zk2vwN18#MYr^}rO1d9(EMjF`Tysdm+acKT{sqx4C4SZE3@Y(?U_3t6GpUs&`j#Z)8 zm%i(H>1qzUaK|$Oa@I|1uR|GtF41Pbx}>?cpaeTSF+=Wq`jg!Z9wE!AEmJ}uQHLFf~WOO=r5mf>BwV(6|NGNx`SutXClx}uHNJ# z_#M8lkIQfWGh2VvE7fx<{zL1NCJoxIO}rWgI=`Um1i2(6@BT);sG7A|%w^S4krlV_ z;gLStUF|z+uYZV1LF~P1sxSEH+r-zF-Zcc@m{Qj)i+a*u-2REWi~%a#4IZ(caD>Nt zUF;9N-G?c5a}RT{c#`65=WY@&yD5LCQfjCAyO83v%E-i8zLsPM00|kWMyxc^x;kID zxJiKTrvtY@*ShC=Q|HS2a^hhzZRZZlUre)+eFNXbUIRA}G3WAhI$Vwm5WF!S-hlLq z^US^#c3Z}D^X*(GZ@E8cd2YBiui>7(`oWD#ow$1{3bUPU!TdGet~ke3-jNbdl(|1| z&dkqX)fmZ0m6dJhfn6G)V0jv&W>RK+VC`f!8(TAFH87%(53UJwFZey8(`E4@2j0r= z*;f)U6#on!$bH9ikELm9pB0ms9>565gz<)~{WKU#lT=FkINw$Ahl`Z8u^YuDsU?3m z=A5)LDU@5;)8G>RO$LDe6=*&n^w`zPgQ*PR+{gH#<)p7p)NZkcxWqIy2k(}*tK0N% z#F~{4=~eqJhoOzeB2+`dTCIT9$-pt9dQaaoV~=C-yZ`q;S|4L|0pQDaGODgXzjf&q z%b8sa?GlmxukK~NeWU{Hw!frB4Yix%REgWf5F*FQZ}se_TMj)RCT_^!2z$ZGRxE*| zM5}vqoEUCQ+r4hT$1vc`7$@dxQG02RZ<#y2MP*pp@Avxs8kJdApGUSOkjfA4bnLzb z!Mg5`Pv(?$<0BT?YnGxq>V>|`$yMeHQy}84f-xYkT9Du$%xR>RzoL`}e!|XKRf9+~G)+YNkOeB_VKd<-LS@W8TKR6$8 zIJAoimQZRbe&KG+H|>~ONO)%~TbCdQrnsFWs^i$$88r^F4{Kvk$*3GPed#v#;n)`^Hv}6CtJzoi=&iYX@7R}oxmJNtm|kfcexPP)|4QH&sLX$Z z^}iYc8qVTJUYWoB)~!tI5sNP4^#EF|dRFnyKvVk_l;UixfPGA`#Qh8J7ay*rQTh0B znjU1!G-SK?l+S7|c(Lw|;;scGPp-W6xKnYA@68rn!5++7*x`N)kB-_dohg{kABnC= zNc~oB7EMfbt=;gPNNX%E zwK{V9O7ibssC(gNPVf%);?n%(h_l7ir_Ce7iFzP|-X={y&L68<)&WabwtgjkJC{;594~XyYo1o zHN_GypYJ&K@vWs+J{R?y-vkYk@KM6!%6i+E&}G|jhuOA1(fN4tuFpn}&7O2Kp`)M4B}-Fksk+nK6(Q{tuRqQuD=pVwr^|s&)G-cvAQ5`O~)895Q5o%U` zF%DbB^l8Vm>)6u-D%$r>NY_r$ejlEdG3620nAkoD>WgCD_1%5$Ik6Zd&s1l9FdRkT z)Q`3m#i)qT-K^M3kmnEEkj@~el(8XASnpr?p;`mXO>|$fo&b4bx3ZTS^&9fv+3{5X zxd!p|$Abe39!cx7tBiy75jI?9-Bim@dl1xdvWYI1vx2c3ADX0xUJfS@XSAdWv zpsMH5fOg?M4#vv%_2|F|vYD>bMng=P z!llXf-4hunx(Y|G*>=jy;bpfhw)D`xZ&3uUakafDbLnO#`%;WcbE_2dhEG;#*;`M3 zF#K4|vAYyIEWZ;lxqaedDAes)IddR?3%gmK&99c~UaP~FOEGJr@zQeNf$hwvraM=J znz{jz|Bl%ouqUMKJ#&*1^tWXVaJRAAG>RHo`W(#&2OF!nE64iyd*2u`{vY9Z25=|Y@B&0lkZkW@w2&7 zhGBQo>z!mWUyl^?hij3??y||HonB&!g6#q)mpJfx(E?{eB?tnyN8?!ot!u!oclv0^ zPbGi_fct=})fZz7=Sh#YZ5A3-3}1rHyo}GB`25N9qgNED4a`g{2xOTxM+Q8nUD`Hi z_0zZ_i_q2VlTwsx_if6i0<1k!SDb%L;#b>arE57Vl@1lcNdL8|?5t>Ze;FM9Hf1f?XHD`!5_qk7`_6Quc6_qpXb6PadJr%Ig%?Q_$vTLVUB zQEq9~Ng+HxmGFK%+tMGHIHxZ93%ELDh7+7DDkr7)Ria4j{UO-PYV>S-8~O9;XKD#7 zzNu@kECq`87$%g-O8;$Gm(e2yivv{f@eanY`inJqM|FRzI)kMzP;0l(ZYL<}eg<=l zgKF<<0Qdk^$1&~`_RXD#Dp9X_-R?}kdSvwZIKlY#RJPf$c@2LNKI_D`po2F7l$>q4 z1RyUm!Gpgm;;W4>ChODAwJ$Js2DsLKQkrPrAqrmSd7V8$W#E5ecIEhY*kZbbbQKfl zE7Ggux)sRvZCscaIHLzoCcQC>4rY67rcgZ&LeoR|2?Sd@lU-IZm{x>*E*=o7(W? z4LvhhsdC+kB-lPNZrZJ~4`AJ+B*$+d0#0Q)Qw?3kXjGg0O+|CM`@%tvY z^F8r*V;Oe-$i)QwvCSF$ZsjrClzf-2@uI|Kh1LzCO>B3*2Vvp#dQ%<&|2|f^#wzl6 z<8(LuqJDb~9@{dwsfaH`&TXsKtmwvnl+@d`JEm>Tp^x+CapR9)**G`BW_w=)loS|j zim+kcKgm}NmUyFQWmj)vTGHIu?d!9@_0=@LcN-hN$iMbq-pvykO5~u%UkngUH-1^X zJ9!1cHpYuwJ$jMvtEd`Ig>LvUyB)+G?9os6Yg4OL;1H8b{hRNXW4&DOXbqoLO^AQc zv0$^#=pA66jc`lQ@8C!bdl%Lvb9}EQ_!=$HY;_mB$2u7NxSZDf+f`V6PyC4--Kaq8 zvRm8}H9-#_tVvBg@9503*%ouqC6MAaU2qzjc{8y^6&`Y;06GNc-=Z6xA&5N`K8j4eI4|dNw)P- zYhkeP_YiE`($u1eQ??zlH;++{{} zr`oL5vFhgY?jz_lJ2hsL9mYM?QL97xv!}6rG3hrRw8AxJszahKEk=)Xg)Odp`yr<1 zeA(_qMfyvODJ-EU<+iO~=+ORcME4d7jH=xd$K;3tg3?)JP0Uk8kP1NmM_+gcFapIg zI)+2|kT+^0739o%TQ{+YMf=R!V2N+*e%YtzG`24%4NF;?)0WRY1yT;}N%}AmGo*M)E)KB36@MflqnH^{$ECFH- z@{b*>1pdD5Cr)>P3TwNx03cFWe#SK;590ULFLq{hGQ39%1`yYdK%~4h-mOqCT%AS9{m^Hh?72lMXQ&rvc#3 zBL}?|2s7~JfXHh{Z&|qu5N0D#A^P+jglP}HDiDI^R9k)t>!XwC9&L!L6d)l^d``iA zp(xa`OOL)En{xSjfZOifWD4OJpcH;nhd=e(Oa%>)yWWyiT?BQ~r~FO}WR!f+76o$6 zzo0cSSKx=*_>@VpK%6@yKKibL)ch_TdObVg=jbxd2^vehm=evsK+6a6qWp3F7;>_; zc)iAE?wkcq0Y`%yiBe{SCM=FCB=> zl@UZh4}Bs_=r=!W?W?)>B4@XPiYjAG`0katD0j5nU41#%zFr<|cV&>h!~ zs^i&5x*!0skMyAE>0YFOWo z^>@%Z3{+b&j(|Wel%Q4sk0gtsNzLsoH=Y0YX#M2hM<0wfDP}`Lor8CJUZm8T~8 zArv?OiU9J!S@?wR!xtfVQHm`>M7hC&k$eBc5v-_2apG_t+yXP&xK2!crW61~|8T|V zL#P0xVNW}fOG*I6PWNbkdr`DPp3}kP@8yp&m!U@_=p6?)YgM<93+mK-?JOs1IB#fcL z4QLK{GW2Bm)Q6F%e}tNRj?6GB?U4TfuA!pbaF_o>&^Z~diD|>+C_q!YM5c0Wxx9ab z1~idoxUEbUX#SN&i#d%!h(gb4fj;8eIminkO|3KjXABT>lR8@Th{8!o87?+BHB)tq z(#2nQZjT;`5Wgt+x4(EL^wOz6=-Y?&(Lr~$>Er3hhhHTR_F_n>P_QtM5jfQ0e{tEt z6=DF%(2FOZogaa*O54Z$dw|7*8e{paK@RJ6|`d#mnIeu6-kApsjX zS0(27co|O_*+E7TphZ_bU}ik{P{3^ktpoJes7$u`G1B&3=7}UNFl<$ zwrdRsDM{3k^;`T7O8w1%1vY|7~zHVccM_ae%Eaf-g=S!NfQ-?pgS3qP96CiY61o)QXgL3_=L}Cvf96S|4PMJuMgxnF@7II9$#H)qLFC2e05X_)O zmz8;$wdDp4eB$ss zFVg3+X3;BS)|DBk>lO}$lPSxg6by8M64^?d!*n6jAQ|*oUniPkr1hIxd^<@>3>TC??wYZpmDME;ir9v2=&oaOuOtztl6NX~Rwm0lVjQ@heZ zY+CdDF@mu^M-*;V8NMq`Su*sIUqfxG+smYT^?e%76Wunz!P1_xaG?4Z1@~t0*N!PW z?&m;7^G&blMG)UlVE_Dsh@t8dL^52-|KOZ&7)gnjWx|40{``=>r9`L^WO zV73so#l&rD^nShky0WF>%_F z*}rpS^s+x`B=y@~pXl;ht&qT@z+GnI*XG?-AAF&Jz-WX?ONKD!Cp*8QLX^;7_ph`A z0wx`c*A)c@zmN3k57|8rm5PZ+sY@-FE@9XfKRvDVh+HcwM!BV6vCsbxvT7pCaZ^^kzg>yU03 zvR-p&pf?T3n%w12Tl74be%n~@CcynCFL(2G;UPJ`0UE?BLgxX5;SICLqI*aE-^u>y z6bo6siL>-ot1YmSKsLzvViUl5%!Epq)8l)GEmOozC){REFE?fPA#Ih(`iLBwWx?z_ zjtzX1r{~1`N0|LeH^z(?gNs+)_Zk-@0;f6&Vbv(?nn-WDJm4>Mm$L2s_HzTFy2+fMr}mJ^yx^8XW``kuc+;kyj@=`c8=(Zk?v<#KO_ z!kQmOdXl)%nqKmVjmZWr-E2J;_!KgqLAU_C|D4jr$M|2 zsNB?^nUs$T4OpXW@iC(Tk$GYZ$5rQB z%Fj#1d}^9rm93>n6PL{)yB~Di+$egL0*x&``sVEH{rQrfI@>O`HR#?<=S&HsxeB!C zS0lp6abC`AtJ%os}-+Ap!yXI5_>S`9|=$&__$9d>btdFHpfa7wF8o zgz<-yQzh(Xy))_(WcN3`m^*9L4%JILR60M~EK`D3Vir{^o?l6L3t^~Bw^;t_^tY{F z49X!;+P?b)7~I#5yT-6w=@5Nf8Cj4p$BSd*?>J|k|JBDJ@!QFYWyiY;EzK&!Uf^Zt zYZNKDXwisJ(k2x247EY+WMIn`{_>2&Qx9ugbsDR}NgHzQqB7x{fWYDFmMCanQ#Bvk zZpI`KL+nW1^+(=3xU6%jp?5xa`g!9}tXs$D{xpU_Q~^{i!$q~vvJ;Ou5dr1N6zQI#X&Is2NHMZ02^8BiEA0Y zUYYZZw8D}j)o?r=x;&R3T@>sdH|zA`P(DrfY_LL+nLLU9V^dDmIY_WXG8NkIMbXXC ztFH)tUmIWaIENk-M~?-qR_$xRbG}?o@SZ%j08_{c?TfazfA3qDFRzhY{=`m7laF7a zyDQwE5ZFUc{sQSb0bzo5zjSKR!C_bU8*4t#OC^~tryVW! zYRG#+*}E1d@jc?=rOt7V^}f;W>kp#6wS@L=#Z>+1WSvjZ+w;R$Qmp332v9pNUtTOB z#;1i`C7($RzCO_QL}0xfBlM0pLtv%uJO02UP-8 z2!*QTz8krl9ahWOIVa1nR_wp}evx$Sd0Mjjcy-%Si-pBve?PN|ayBG3Q=wZ<&L|%Q zw%#r3R5@M~<4rh_i%{fOFQ@*mW+XoNdUrnc{$d?pj^@QutfwF4?5VV%se9hSpICQO zoHu4-KeL0aBXCP|cp3MS9m;=!E+?41`@vo0uP74*j^3WOpv5d2K7}eu02-5|ip^7} zgTEWd4NjQ1Z_fT5OG#!>jliRe$Cm^zF?|IQY2d@eqr?bbWts4;lol~hG%6aUj-P?R z&{#TOV_fHUH~MyOMnA7(cH1&VukT(}~6;3V>fcmnT=jGUEb^_U%% z|4b~-m=nRx9+b2s1WvV$K~*-uFw8LhGE5K+Kqtwe%5=34xCo9ac(5|u1@V*6d*u3g zu$6859Sf5!CBP2;-eq!wIrWbRt zrOvoPnKtl58n`SU3+3Kmiy@-tD_&p)!Fkr%zO_!J?Ik5!Wtb*TU*D8EJ`3>k-tk(! zpU8{}$!HDP`}G%_W^KRL$73YRFozCJzovDzk&v(hm%eb>E>z{MqO&`MFKA8xjd3&w zvOvh_tpRPXd+m{*bQN7GqLGwILEWpTKDm;C{jE13NLjy%MPufmwoK#P{=6t!Xmh0>G~DGmX?kSJiKZk5T=e)UKg zs(^q${v>7H?ANTY*4xGZ@5zWas7ej+go?X#j`2c3Z=md1Z&T=)9t1d)GpiJ#M@EfX z*hmyzC_TWzBkl5;n~wrEMV!`=iD{t*ViwVbp$hpFwnNI~C7q&vf55&zL-Bu4O0l5Sv``LB&MrTqj|XyE)0PNZWk6Gf|)m8 z2c5MQg0duZrVq(V%Qn9kLUGbHE%$73g_v@&A*OhY@ z&uGh*QI@#k;}*6!7_<@xMpvC@RSwmaix!~^G87GK{7Ak=B^KMGUN}i|F89U%Q8+#w;NSy79gO)T2fNYQKp5H?c7E@6|HT_$9vS9mO0jRw%Qv7WUa*N~a$tX`e}3wHTAK>eQ^vbPA@1J^usUX3Uu zO!3b=e0;B-3W{KYi&V%6%GyXgd|u!T#(6I&VQ67R!7wvHNRonEG+am?0f0l+Y@ilT z-0DXUW?L_nQDU)R85MepcKy72D6lUOT7}D1BH(u>u}lv<%8<}&t$c=xu+|B4m|y~a z^U+j@;G7Eo>>tRT(ACcY`Tlu&z&qmU*6;Ci;IY|3>Wh2-tPVnEzm4IpK8BqcrO|d| zC3K6Qe>MH~pH-lj|oM9DNQD`A=pc1=8(K@zN9p9m-mb4JLS3t$?s2jHH`E_ZNO;`*j$cP`a-9U zqI9_H4MW^1+#sf&KUJGv#I45!ImpE0D`F5NgCkr; zqrza6<+G-~&^c?HkDUwxz3>QlbGz>h}LUbzA3SK5GmPx$SoDcvq&!dmlN-ybI z^;X55Z{YVyKDxT;*>&&i*CBR@5mdW#hF<>TGxz5w2D(ezh;>kb0vL!nIyG2r#uUhB zeha#+Nr+B$zEM^NnQKe}us)OPSv*U-aKHChMUTuoehi!{(V)tP1bY!1TW6#kFAg2< zNIxb(Inr%8E^S%T<&DfS9nQVF7bYk-a;UOaE?D2D5V3P(#i#5&g`_0l6TL8!GoqI= zqK3nIhy|v~DFL57rpdOitc&0axHl4Qc zg=%K%`qvcWVSx%8y|}hc_>b=Sk8e@J?!G|ucXXxqiYZ2(EfdQTmf>{+3OQY2Fl0`D z4!?2!`UM>HNdbnqlYDe77?Qv{K3F$wJ4<#C3zOR)NKh-g>@&W z|A)`Qlp^ekFM9BiBiqQ3<`QB6ZzfX6GYXYHH(fmh6TF?H6=vWvmGCIJB9a~SW`|f- zlryaJy59#X2HIcDE60~yfJkT2qT8zTV1U~4ry(||BF0l8opILVRRF-+p>_6dld!6Y z%k3FgFR`WatrsepyGJf5Fd*?;8Do_&#qK z!wjIOZ3WX(mMNe1%KeQYF2q8bzdPDs_GHQp(8qo4NzGur* zw{_X2HzyU^OW0;DHNuCaqVmWf!_9&@OJl#g9FsSOfBcv6#eb;&{xudH@u4GsK@J|5ko@ZcNoch;C(AC8oA_=d6TMB z_h2}g`6(Y*c}<7U{tEo{q8!G}A=A_6)xG_*0uPRVuhsfuWp|?9ZgkKQJuU?9lb(LA zD~svLF@-dWvAeh<1=vo|16u7TME%j&&|yu#lG|a za);@Sn!0?FoERW@H(z!XmJMG#UvIss5$$`}IzWXk1FIN8@X1r(us3sS8FX&ScQQfr zPKhFD=??(kTM}2VDYFCMsSkTlb-S80DO|7Vl}%!lfEszvL>o(0!dWUTPqj51k3po) z-r21!;URF4gXXoA8gdljpKEx|v>gm(s!J+E`Iw#FT3#t5pfyTWYxL;p+;tosrsI-7 zI=}D7FRIpk40e#PFund^>aad1SQf$*Xgg@8bgI#hI0wN(#Gp$IbiYAPW3z6~O!S6M6t$OZVy2cou+; z?Uz3>DXC~QAWBV(zTjm9aEXp-SN0Jamb6H>CNC*eqAYgeuE)?hKuu0mmT!qNXz2q0 z0j?J>gP10y6&sLvYYX1XO-Kn{xh)24_gsb9m!Wi8cXD{zL$JPVJICX zon`6lE29C-k#^!EiT3mXa9VWN(4Qeb>lsdY_j{1%W4K_V@)$Wj>RzhdoHqe`iK z(dx42I^=RGgChW45%**W&gMc9db<);^4J$WZTNc2@Sm(hXBl{S2v>9=em|!%S&XAF zesPQQZA;1&5!W+1+RCEZNC1EfFqF|6c!TDfA?SSrdykC&F)od2OTrMVZ^D2}!MZXR z-^PP<%B|!Vmkoa^8B$8iquN^)wJ4Z7G-bS2q|2WKwaxVg>Hxl(NQ?s}>TLJu?aDk< z#oT{5UkuZ0kyMJK0po(^CYwy|w*chxBCUtX%c3sHpQu{(aI5#a2hA(P=TJCsr6Z7i zrb#Tv!-3>}yp5cmJ9+<%3x5uChd1gV4%b5R!}!xjB?4o*Z)_QT;N9dLued# zK}YJvkI@Em;!Yf zyAnWa1S{MX{>Y{h_w#?$OaX;wa*{x9d?VcbzXqwXUp%0;HzWl_vf?dJabm?1K(c#( zG|F7}#c>eMgd9Uz2Vn02%dJPrxmyFsm(MUgx9gkKPuqMMb;F3(^|Bv?Lc(Of?vsxSmq^3(i15>mA zA5#r#9F&kfA5x|tJfRm9+wRm~$=)f3bOW+L$C{KT{l?QkA{%9fIQc(%xz{v6`%s+7 z_%o=y4ze9+Y~`DIU9L`X*txT#qYAx@_+n^4-&G%p5s%w?!?Q%$i0F29fInB20T4;& zWNaa^-iDxa(`nI9UFcuut`hc(*;+|<3&+^57STVX3tJCgy9-#N0rYD*^!Bwk34lbd zYV70vX~_y+GFh1v2+~9!=TIR%TgV?Q#>sPJfphi70}^>_$9GpDx<(8aoiuPU)p1GQ zN`1eBcsFAB$VvuhO@Q$$JI*^(|lLI6_bnv(~ewcIAXoAQY*>~$rZ&~^>oFfD+!5>b8 zW+D5;Imhv#t~x`+%|+>HT6L$4I&4v7A+_J4&{apc@o4iXSriy09(QAvMZ<~UJn4R4 z<=0)?&QDo4s2vZ=IISpF0)ZxWDwdQcZDk(rEf3t)@r}~TH90xFJ z($~-$R9%L89oAOz>l$K0OUcTw$(DbxCi~N>(+DYHk`wroMYim;Zp{!@EFC6YAVW7V zSB4_M*q^~=b$<=I-49KXTvlzLOYoq>gcFJ(Jo;YwtRS^#pE8rBWe_hve#AM;ZZaMlum2(G=NRcV zC-8k8SSl8pHq`Tc8KHK*?pD^0(mS1vJ;ShnUa-$&l~Iqq53BicucGuzr;QLUphdH! z2csgSIH*wW>^AfKb{!RZ4XTxo&!w)e9gdh6CqI}ZUg_xl>zAiM$0coWe50bTR8h2L zL(3pcFEuvNt(=y>ObW96z8Do(@bsv+ZOV>fJ)Yo{HucuT<5&?2FVVGmA0^%W%*Xrx zWF|YVONV6DU%urPU%+Gb>e?AVg&h_v>x3?SSW=;O$m8MIvc1vp*NmSh`hp_;lq9O{ z;^VJ|a_(LTDXcF9%N-i6DleI3Qk)2CAz-H+HyYxktT_3s1L8Y-vlo5;u`EyeNbl}# zzEH-?A7k|rHJyp}iN$QotMDfhsE|XDiif*uO5ZHDJ#h_g_m7(I?uV5x^+K0pkRfsJ ziuN&2I-ZWtZ1p+-7&9H)7~=hvnWq4YnTR-FK54`NhwY%P(ck{2#mG@Q>W? zkIXggY(8qoC*b^|Zo;0=+u)F&Ca5>f0rU4z(?UgteyO_Y#O{H8=wM$cz3ij{^*oekLKjyqm&F%6gT*X(lWmxMLgZ3azK+-F{?B7F4+20wh$|u7zuWp>6@rIjoy#4;{b|Hb3!FboOF7*H-$e}#ba2PgcPWKR zPC3x38hixSFMKM2#ms@6IQz2O|4wzZ2#@K7{wDN|ZC@8K)$IYJ%=nE7GDjF=g~)x$MkHcmXZrcF2Ia}zDGB!(fc53#pX;eKFJs8_|^ z;mz=@|HD`x$bE2*C_3j0eQM!XSWr^%axVClSXa7#?ACpxMn^*D55yo5Y+xMRu#-hT z1~zcGd_m=nA1bSCLGnW%FllkMo`NLkde{FbT;eZlRFc{G)Df84kkYx>a?_iZ zyZFodS-r=z)OCD~gK&DC;nd41DxGFY%HuAezE>&=k#MNVwnT(sRrOefbyGmPr00OL4W?e4~7f537-(gRQM%l zZC%E{i8;`8`AwKld8zD=_`a8z9lfr$fo)SWCAo?&cyg=OADM*d4{w>S=IpH9cDC#5 zKNK*i97XEV4s4H(4Ki zq_XjbctQ2X=)Pr#Lc|>#A#Ud*);qK)oH(XMl=r58)gqGyeUKYmaZ+Jc_4-QkW1EP7 z2z?8GoHIvWNP@X19`gp6$z1$0yZDA-INY(HMQHMxv9;9ef2I@sqdBs5Sv8URAd?I` zh;jScIr!joY45e#^bIxI@Ly97|EDYRdt8}5!rLXR^|q4S7o_$qGoP{Djk+*dc(L|y z+OiNas=Vpcl=#d?28!DwubnJsgJ91efHC`8(49Kf?1%9VS!5x_$K@>-@qc;O{}@r$ zsmb3t0cagQ_Bp423Y8gOp>ADy?f+}x$^)VLzW5umWKFg#gM`RZWQ!6dJ1w@17+Xm~ zwyfh#iTFmQ5!oqw)?~{zqAbatEF%;e`!+OYhMC_}zyI&M_r7z_{k(TR=W|X+LOw0r znpIDneiKrW$^vtK7pJ@TwC*m*RO`S14`hl`uF&JSLHn8Y#1(muJKetD+8n$kVg{L- zX=n!BDbnWINrq`j+kq{p6b=RY4v|ujrk01~AkN8Q%dq=9wjf!|G-%UWGAB|Fy2`q1 z6En;6<#>!68c2?w6L#F?8QJ z+*@HBubwo;IdJ^Z?Ym0j_I@AoE+{$xx;2um*>|xL$9;^L3B}-SZWIU9P^D&LaftyL z1U(W?n}m-Pu1g6@ z@AQ~4boLvy+}PcC?`C)4wMXze1+(wX6t#a-KC4zFW8E*5Qeu_AHpbdpRcxC~Ob<6O z0pA)iq6(>?A@R`Rv=c(d?Z&rUpVq-z6HM77%3w_BdeXbhQ(q}3yKNvQJavvIp(Mio z32~%RgMK{&)NrJTU}#T*!kWq=;DJZd zct3VKcB6@oNw5ax-;m3tLWbJ+p66M!0~?{fY5#tl=2_hXsXhC=X zcxVS>q<6k*0(vYnld^N$BBpEGAC_=WKGX^k-bFiO$HfSB8j1)2oz31`h22!O#$aDb zmmnT~Rq)8LH+ytXC$V~t!oUW+TSKnK6Thb-0xFxV87z=KIGozd(rMlYS(LYvBvc=` z98`S=21K0J)M_9rs@h_X!mAhE($|NUD>j zV=^Si4TfS5d|kg5yg=}OL7ShSkObeq@MSLLoV~?O95m$ER{P+L>}@(!W(S~0pSfc` zdZDEj;Bs)4;I9imR3Ki$I;}mPq?d-i5)clcq<_E0@*jLBK;0aasdm35qr!LbB{SPj z{*+@Mm!@yI>u3#3!+H37MeYtV08Ng%LcOAP>Uu-+jBr|6_22?+;?oQmlQu;OOLwz1 z<~{Ja8INhi@fnxJid9BWGt%=I8+xoT@g_n={SCPZiLPCGfe0uZ;R1eMEeg|rfEPNV z0hib~A`Vgm-Me|PJC{X8e#8^^2q>&jIFr$UEjHrdGUcqbs7ZW!)2qs#mHrA0(tT2L zvE_>&>18Pi{FFSbRhsjqE`s{?6r|0~-&5Fb9-rU1`TDX@@9~DIl-Bbi z!=?bHllPu{cbKZV(`%yqNCm}%vc zXUAZQy7>?)nCm#L4)twd4sC>&G2Or6*0qeSJ=Zt|fzU0g4c|q#g>=b}5DPa$m<}bK}B~FD|v+cV1lGL>-F{xDX z**lIJk5@}0kBZ3%$&s7p8t^(%{swq9_|}c92CCwy`;`+8;?x0G0P`w(%ui;5fJfJx zzsxA4mN#+-VJ4lLI339*NwZE~?MAe&srazej>^ z1<7%}V@zYNLG=Zs)@0O86P)3fdS7oL=?XQt!N;A|yiszBx|W5NgDTG&pStEY&T+P| z<;~o)M30*DZ#RzE7goGf&EMZd3Le^>Ji%XELQ89DpiYx!_--`k-pf!vx^1D+obK)2 z>LG6J+|URn?**-zA^GxJEu9-e?P=*c$>yY}KC!}PZ*-veF+Y^j_t*hO80I(Au5tN` zF7!F9pcKJKy?li1E5ca!WYsC;ybi*M_Hi`wkoMDdw(l?n?Dc}SoIr?PTJT?5rtW^# zQLA0gT$>hcEuO>S17q3XAUt4WmbGB|eOr)!1Q>-IMvjI(nY>ya^LF>T`j1?*%8!yP zPj0^AoLrBFMBLw$S|aNWBu}(p6_%Z|SLX!S+Ju*8H3uI(?Ni^pSP|Tpm?ocnNe!UbCMlnd>4rbUHLCrY-Emxvgz9Y*fuHspF;N?Lci z1ahv}d+TTJFCdS9$AK{@8n`Oh2h|kRZ!E%&*C z-cx3^26e)dn_sfwttd(wh6&FHY*QpUpK-Fow zF+Xih&Vo1fomc$BJS3&QW0Ak0=8Arg*6=>h@$$z5?2c^pTN;HnlrzvVhcx6Q%u{0G z!sMd&TN>v;oAz{uBXLvlBgYH;w<0>)0Z%^QQe%>UuGBPL1Dh-jzUM4_`gK5CHO-2w zgnyE8dQ8R&m>Oa|q-GE15GRRKjzUBu7f4&@1zt>(&Nj9P6QtZXn=C##n@ z$)0M2k+&RKx)cumQ^8G5C9v!CA}mg*xA^$kavO~jlmPrPM@I^h_8xSt@7f|__(E1BbAAa2Be?p_}n9HB1X2X3( z$x5$o^X>ko9(AYK0UzHfLzsEuEr*8++iE|jk#Q~}uIF1^-j)(U!^}l* zW0-`pVDzMVi3!)M$(c3oktt`|O$&CQiwni?L(rO@H@ROh%?B$lB^hpmqQDp=BSRA} zu&w;Sy1tI|%|bG@X|)qVb`jjeq6REyl-ZjEZq2O=LnT?cywW6LLive`XuHXWXt>f& za1dK~4hd-e!_dl~@#VVHzUlL*#xc>D7@dfrp4oG|ZVAKTkGP!PZ1>gQt1w@dJU5^j zEqj%sr!Vt>x4Eq4xBC9y6+|F(VW3X(2pe`nJ3JfwbYX9I(>rAKdyuKEzOsWHgz8qv9>!y!&Cs-qa_6MF4SBAH70q8?WpPVynXo{vhc`j;tu3{d zp5M{$d?0_8g))GHeb@Cv?dQ^@gFePNCrZfpOM6;rl9oK{TDZu3k^sQp8EOf6kfbuA{My&H_z7TQd?w#4=U|2hKN8XgVAT_0SOdsD&>+nAXR7GI zh?Ej3%M&SmO94Qcy6j0W)&s`p=EKbhw528>b;nVEcs!FUr=|s?nh$aK5MQmTG=+S? z#sVy7Sg;HrvW*g@i^RbfTsb3I8t3ZS(G@(<{H^8eBnzHQ#vS-5`v-`S%CVIed6i)s zh{5GcUFcCc|BI|+41wM#ly88nql*<>J1eP4Z$7aoE!36|b%IdD#9@V6CfT^jOXaKymB=*(6cSPKrO?7lt!ZdQtsS6@&__m~L@FT^&>*-3t*C#`G$G z^$a%~jWWQ-OSel^2obnWt94oh??@m+?lz$6^8USxl+t8B%Xz|uriD=n^7J1p^#cdc zN)MME|9ru)T+q^YJCe16$xE7Qx`r_;R>9dJRv=aFGao6_!f#vyj}vs>R3*6?8vC$8 znK#JjWJO>X#n@{3yRN^Xd{I3B20RNxs3;Y9T;&L%`6!K>`@NcT=O%_laygY|y|r?R z-A$X;tBRac?N-FT^L8%0<@xXM$jf`nWmHF&wc+dK)Ff0y81MesG63+=VGmwgKS6GE zd)rUmPvUY~v54E%nl@Lt<_G56$87nX{9+ry#uI)!2Y||2_<--*54^+ds?4MMvm{dc zi^YXr*C`~poXv64A^En98rCqI(s*4W8i!yUZqE~NnTmENKLtAA2r#TjwJzU-5X0S! zlL!2Yf*f!kF&|!lJF;+=hPNS4=4WiZI3CLG$!%=e9eJONuS-x2>?3AEQtOY|k_(?| z^BEV?9j_9|dk_zptW!QuNsj&@oxq%8E3JL~?|FAY^|Jb z>-X4w%WRK`jNZqOcdI%+G}O%9CpC#h5f%VuKV)ma!{SfjmW(;c?ol44btz-l|Jw>` zCvf^Q=o)u+i5P)Z52VrfEOxq%!RznmR_$AL)&^tEBN=wzwuK;&-C6^yT~`)4w9qY! z@_at*yLQd~IaiZbn_JwTkau?Cu4`%N+A|y&@0@~wXt#%$P(Cg~5&1KD41Di#Esp^$ z06Eep)e6S|0F^3dH=SRgC!J-2%+q#?_eiOGQ{CR_e7Tfy7Tt>N9o?0 zdQp9P+`aA$$Bo#%^qIAFQxW%pIws{_0t(s*r^*!bM46$_=EX}}9t=Hux~=LA2Uhp{ zMxJi9iZDEbQA-dayaM4&VUp>LOdHX2n%!|J1b-#CF4Fs9UC$tonWyt(u&0@m>42+6 zy97ZUMZxU{(6Jr?Mp zyNf_*0Tc1IX>E_xvt(4zKjVI0-CK6LobUj_f^O4J<;pp!B?(Sry@tL>g;67ptuF;a ziCJi~y1pPgK<|`;18i4Wz*Pg5fyCJ_wcQ8-MQRSli}^30Op>QRe$v3I0idCm!rJ=9!vLt4-R>;{G9~)kfm9k zgYp0}9%d|+r{FW|MZ$QudZuM?<5Aw>{~O>TjWnam1w4RTuvE&x#hq7$@pCrp-<@^! zSO3j&6WC=h^aaqqjxhYE&Yj$%tg?6JSzWtT7jK_B-vGT2EjmE2=WL81MQL_K3U9(}@*I;Pdk(MJujzRD z!^hruthV&DpD_T)H{S`TsodIF-Dz=)^Idy`w;gK#A!FCV#r0o(=3iK45ajUwGAvdhK;D2g(lvu8}1P*SO;I|0B0@W_H;#LGkI2|2nzWlVq?y14Ab1u8eB z=~?T*U7ws{%X-O(MrhkiQ Date: Sat, 11 Apr 2020 14:39:51 +0200 Subject: [PATCH 249/479] Update jungle_background.png --- datasrc/mapres/jungle_background.png | Bin 34406 -> 33700 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/datasrc/mapres/jungle_background.png b/datasrc/mapres/jungle_background.png index 3b37a182d3fe26a3e6bb3d387f24eb72b5d01e62..095928f793d7b4dfc410c16ec1a89c3a0141527c 100644 GIT binary patch literal 33700 zcmeFZcTiNz_bksB!eVDaug&e43a^HIOHQL8Qf$90VQV%5+tbz z3`111gi)9wNRmOqzyNoT-&b|()_eEXuU^&t=hn5#(!FMNuh8AQ*ZTD89cyHuO?#2; zA^-riI(IZo0N}hJ08sw(Hx)$Dcy}!e`sc#qJ665`K=+yamm*!5jvWA^EOa!~%!0mc z%wL#$J8g4`F|ChBvnUx==`b=9S{K;=jQ=G@8b+`?m!zV={OZW)4J; zGdu@xJa1h%!*j4YW~{X4hsYg-MRetlZ13(fOC9(Q`wxeml+} z3*4+;>*oR0z)X-8Ua1j~KoUWQ$+$46LSdwzt0&G=v3pJ%~<%Oihj- zXor$OA`zy~C;{N7rQUNbnWS7}v7Nh~b}<~RR-enx0g>M@{UlHwHnPg%zxSvWN8lrN z+|XhJ0KK-{s;vs0F;Z!0jdKx54FKDs{O)O$zF$IX)0&?Qd0syU6y!2CbIup=o0U{? zaIrce&HgNL<(Qk*B!0$1mkVHXt%UOn^Ja=AjqX*e;QSk=5(zd0^B45BaGJ z?Y{h*bG-(wtEB({n?^>=Nj9!@SSG@*CiQji8fu{66D58C-zKvvmZ{B*{0jh#ijk6z zIQr$EwwuLhgCuBjR~Q*(B+oe~8LYLSjkF;`wUEGUMy1lnqUMN1Lm#P03%}sZW^ts%?tn+FPbBD5ij7EfXGhfG)+cE zw$(td6R4FqrBhlo&h<$YhbI91E-4t~Xq_Qt^UZuQrUpKYU&IukTbGA!eqjd_Im4il zDlg)28rGv}=dfD1{5SBSh|-D0*U5Ud4&9!l0RRhP0>aw8+5BS;mfFwdVH5yk+6;_7 zo7?oVijUbjz%NjZl|gQ#J?mmN!_4@X3&3axual*(gV5>>dM?Qbh};qu*p5$-;VyY| zn%53;0R@$i0t6nXvU+hjYYO0fX;J79DO2W`1Ajp(A88yA&vr&uPyTM%)84TA}RTX zCVBQDI0KK@u!yN*nh_w(pbbEA?fsVm)LL|+yM^dFu$%vA8@Zp4!}im-h6>g@A)?T1 zcx?LFFbMt_E&x>FeDYE7gPfJG%boK)eM^_XV)(jtQ(|bL2qVANaQqwx3MN@|d-imX zAT@ub^#;-n7lZBu&*DAUtd!~_@9zSU3kGpbvR%dJak5`VMydK{N72+6VXn3`OUYpo z@8-}Zn*A|$P#b2M;lyX(L3Bebq3bu_(o;nC8fFpV*|%l7iq$uaUpumtM1~q-JegWBp-r zv%=4!GwbP2hxQF;4ty*hSAsIU;36F znh9C7Dku@23{6QBbRA{2!a0Z<2rVofF#0W}KAm`hQ$(fkhM&+=_QD&|xwc{9A4xM56;huu~r>=;U>}?@RmsgD|MzNyUa6B22y| zb!ITZ&xf`Fs%N?w)@2sJe@_F~g4XI+um%c7D4p)qSFotU@l1<^cx4q<*5w>(pv2Zh z+2a%#y-CF9uM|1Nx>r7<_`s-(Sy;XVi0&Y9%D$$Rz)_~t#otZffpg^=e zD{l5<#{MRyDnCn_6HN|Xj5p{$tUbHGA?GaVm zsK};F`)ep81O+w}Fnj&FtVTuO5?A(R*Chf6^>bh=ZNeOW3Gvf8fd zbfQ?jD?#+a4WduVgBY#=KRx}R74oSQMUkZ|%X-DCv+sZp&`10Eun z?6Cl+rS7s`kI;u`t(wqdAsuf4LBOoMs_LgZXF+vsT4po8}#=S-Fl_%Bm8=C-Sg!FVLz4L&OxgK-U2BRFDU{cr#q%i^&9-%l(uvL#1ur|@9 z(wt0$_GrTfgHuTO<^w&UEuXxZG>U>BJ%}J7t{@c|0z%l}i2NHa8|?+YF1ZZ&i}Dd) zA5_C5#3CfdO~^m3E}*qan1B-@J~%8tmLwtBq|1-urHl;NpF$t&Ndv*QdQ>a+1Pz1u zc9V(Jwv=2L=*&xG` z;{NP!%GK}4dKaO*0rq(ves3~emWN6F`tAdzQNbRBDy|Up#rWFvLGD^*PS%!@>Y(`6 zl6xuEgS)kG%y1eqZGIVtt}0PbWlv8f$sCf}`{DD*Hx>}P7BT)5UZSkpGtfU+e(x__ ztCxZfS)a=0d~?=^LVub4!t~pLD{Xs!RTlxHn}m*e;VfnfCISAj(nWl{q5pBLl@3K@ znq4vn11sX?UyTL1m!MHXeOkK*k#%g@vZvB6xHzcIC?cE3YE#Yurn`QKFjM}5k9b5n zx+@o%&IqhllZ;MY_ix&(o(%MRln1Gkatz)#4V%7!JokMUC0ZMlB$__IXQVo0H(jC@n88NW+eMFmwHt$l(fklq%o>@%3gOLuxO zw$vqyL}_TYxs*3!OC?8d(!Osh7-Vn#v}OeHRmcfTzFK4RvsJT_B@~$!K;4=9`ylwn zWLD#lk~iuj2$Mm)l)$$So*+v9M?oQtu3g9ah(RD^Tw`i9EItRL)~6hSEF8;)T5hgp zqoeiK3JNb`+`!V@1+q}*Lil>lH#Kd>G<}o0ja%e)9X=?eV;r@otx;2a`<7n`WL7Ct zy1xEifhY}TDwU}nYG-5?8ONA*lKUR||EeD`036akDGw0aj_n@~C}nb~Y=K(^LM^VPpB=P`Q&xe3+d zs-r^zm;}qzKNW;EHWsvt6LQBu$cXl(I`r+5xY3j+l8TUBFUX{+d9W1@hi@D9RP(cI zG$n*e)SKe&gB`GF4Z2siJ1tM8LZH2!Wk6-A5HyF~)m%=zB&GDMSr;Q{paQ9D#3`=1 z6-yE(WTK714*0CrWSqzqRyVf0)GTT9xm1w41t+-lB(4~e64DQGfYt(^L9@Zvb?HgH zA5J>D1yaE;BNJ|^9nML#Ms%P(O1c`=)L7Yw&Fat`1>W~v1$|-EMT=HhmrHugs){&% z-Y_?Tf+HDarb>R!%QGU9(XNuBA_BsE;vQyD49+LPgS;=qH9jJoJmmIMFZCiO5^YYW z295IrYl8PX?>jxBx7;*F{kDH&9s~ z^tVb^7P6>Z=0rg7SS}Z`B{G#4DVHkxFbwLtBajC^}muV4c!lK{Va&6mizFkh0yzJR$HzN0MnyQyR+btR6=T(!BV-=N%Afl#VMYR7vuc zYiM6)8Z~VoWM#oCMUxCB`kA%~8uF7#9<-0KK61kv^EySS--kTv5=g}8+I0rK5DeE& zON+ncN@g>iW1W$d{9xAQNrU;0c2S4k8o=sJOAU*gc<+0$SyJ@~#1Og<<8b&4+R#GM zXT*`K2;_H-v%zK)AIc41FcH44*(4bXt?NjGy+^ny5UkLwr9oc;@$ekYfOrmOIbI|R zw}9S#&IHXF)w7Nlap@o09r3Ru>s1lm=sa-A)Ca$&qfSXyrqwI9YR<_C@c4;Y8+*;2qin1=n zRB;hC>whwnRkdtWu76B3&@Tyg!_Vr3ji50Mx^H*cJ)Vy_HQRJ&a!=SZ80r%!LEILq zak=F6K+Z}UiNu-butTOqF1%NitVn`3Ib1x*?qN-4blWpR%!Fs8%9+&3Pc_K!LqdSP z8}ju!w0Hyvtsw~+ogPu5s2TM6lc zlg=TpvPg^8TawO*T6DY&^?xSSbA5o^Q2{iW0WyW$@IOyv@}DO%`F~{kAD{kLP5vhx z{NE=3Qz!p#_1K?b{$C92|HrueAKzs3pJXk*X(-E2IcN592(*H6$15TrL{0bNsP2K* z@`hkfL>>9*V2*=JV5bLbuwyN|x>f+- zrF3ys%Py)KWRa6bz2yRoOd_d*S|H>=vN>}8!PRq6??&Q*8q4cz(T4}rTAfg|wfq+p z5f`Y`#11Z)^6xm)CWlH98ue+&{oB7{&wgD>VN!?KSpZi&9s#O46v0a@pqdgbb3~sW zxUHG@uAc%Dnw2XHvtM_uKUC1x=wxffiUClc-#v+wm9)Xu0;i{HpeStW8ztak5=(jOwe3_Y3`7dIkfDa2LZHCFTUR%>J)6A^)UhTbQ?+hP=5cOfsR z9var6=#o_`-Pi07f)j6HTD@vY1 z%Excf%U}b%cJ`I$k1y!gApQ7{)?!}ReJ#3#T&`AL!b|;2kcT$~4Oe$lx}rklHAo_} z8Vil?!fPt!_lD)|X<4VAYO*lv_f$J#lSnd1e;j2S1>}p0^(3?|rHPufo;VfF6Tvla6 zyj}%u?wK+b|>Fl%PD?dbc`?$UML~U=IuZN3xxRMoLpTEzY@^ zpyI15lrb9)^Y2A&5H-6GiWlP?m80>LqWi+lJ-y{Y<=dg)>r@VSgVvU00<<{x@(g-J zud6FOzMX-s+)1+~sSuk>i4QkPy?gCP<6ppzfkn{!+3^EnvC^Pl9^u+ciTXQouaEBu z*@d^73Nh#1y3SR%Eh#KO#KP_oMutzE@j)qzHR< z8&{W$ZqLL@sMx*g+|g~LQ(Ki7j;lmRE0cq)ptmgDL74jQpE4u}nvueU(-o6R}g{9u+>E^_fjeyLTJ zh}?Q6@5|-J6@%4)%RrvI% z&|-ej^-y!SP6gC6z{(e7_@gzA6jGcDZ>l1U;= z%^7sRvNLbl<~uznpK7N$Y(=r%x!YD;*5K7s8!)+Oaq_vM zvUsARtE@z9XuMu{qyqNT*F(rlpX5Ny+2}E$R#vApYbxVdO{*$0Qt31Fdpu-uN_E1M zQ|yj&mKYv(DtN}f7pfB6Nejb9yP0#NR8`;C;3*TbM-seH58; zltYNmokHSHFTx66ahAJTzL@Ud)+nl?*%C_g4S z_cV>MM6}D$;XxGLXSMPc-i-qEUVnTdn`mvMznhSqfQ);TVLg!&ahz`H5_!}wyn(+D zAJOZ5_cVi)Vp9jeFc)Msj+b{#!*E?mo^wK;G0OsP9x%{+e^c zS_p3~W14p{hJHFsnegxU=gh%k2lF?nCUs@!MwJQT|JLaDVB!@@7Ei?DXw2HmaP~J8 z7k?KQz4$6uu6ZEahiz*dIuj#iRL{blixw>^NOWK*d*2J@jhxH)qGhc%O8Kq00X*0Z z%h6nx5q*kbN^gbB-m(=GoEK3sym6O?{?p#(lV+T3mH3x9Ny+RmNnb=hdMtp(FEJY4 zl^iNsugf&7Sx{EA29NLwHZgf`Y#Fx$u@cL}O8Z#R^!r>dV9mtfrVpUL!Js`@xy`QU_ zmKLyM7m__YcbjyOxAAF>#0a+%XlUhq0PZc z)Q4aUER1FH1?iP7d=aQh1o731$r}DHIocRyfwJ1xXj!JF9{#avm5Z} z>ZaqVziLbW2&g8)xD9#+Iy;IhyZpe^RaCsqG1 zzepdvhP+B-mkYJt^_AFA0jBMaLkBCWaJ!6z0eGOcomb(>E|wr=f0^hD;R#U~IkoW9 zRmbvs#z;EpH?EEz?{KVUyv1(}FrM#|s!8YZ{eA}ojbJZa4Gwh$cqwie6OkK-U8S%2 z{+GnrIqy@#?uot776;lA+7|L?Iqq+Dg}U3@Y5e$LrYO~Fhxmy8hpDipIb_Azy!V!q zfS~z{%=D8-6+fO??`-RFTeXs^hoQJEhZvG7%mbKB(SRz@5?q|IzH!;+I#Y8IzIcAu z{OPQTPkPR`1mU}Sot~m+CO5l$`R!w^R5!~|31at#*NjZ8mqD~!*tNGgTKmZ)L8LuS zKZhYw27ax#*PB zSdX+KIpbo?6u;+NMzdFB=mpp$Ls(dV7lo+_o0lHy9G4MYXS>Bdp}a*g*jk9If-2H0 zW1A5j--?@k&611JwMJ25xHW1FddykBS$2Ag*!#=L6NqS&{`$$Q$p`JLU$#@)povWd zg{R&OBf__E19`;LAr?<&AnVNqJkGziK5ZjE4*Ti;-zB^F%7>X5nm5IZ731p(ljfye z>}g0 zXKlnsI7eFuyIZnokWCBEkKf2$K%rK|;iV;u9rDBzHPq#3c9^U-SBxSXO4(}58p3%B zmT9%toitg95*?Yx7t`g8Kun>#U{}ci>M9+*HuG9}%V7eI_I{iV_QEqV z(i_W$GN`9&Zfb4q%1(nATPqnbkNk;}BCMl5Y)uTFYwagNXN#O~ zAjZ+5nz*VtO-n=NmqNjN&>0L+FgwpS(+;I-p`g?^rxo&0_@xTN^7ZtCe>hNLbi&n7 z^1v^fjj3eSelA;%kc|qu;A$#O5At&5U>tMmZ6rKB8TJES)er zbr6&AvmTj(O(ayBiTrKkWT>gE@P#QqSu-hCG5ah&l(@p`cnxrIq}S|B=XW;EY8+x9 z2H^_K+PNJX^(X7Rk~i3`8cS)47kd)TBV3oBqIX;`R+jffsQlVIyAg(ZpyFY39`Ib; zL+6|BgnlegHo#G7Tf~I6=8E8BH*;iM@3W*v!3Tc(l^@QqB;`&~9sfK-rBupq51eq zer*k{amVa>Qc9)*CpDn@tZMf2h3|gQ!TYH=)5v?9j5$8+MZ=8Z>nis3CO?42I>M$hMgIm0%qMF<;2uw+qv7^?J>5iS?JfP9_VMlpuuGdR z(IfjkNw?oDgXz=`VZ**LGRMvA)vJ{)%XHwq9I{~N%RvF?@9$hR2+vX{0Y#n<7$vwy2xG@I2gCDWmO!!fY=1 zEY-{gb?AuuWTu$>I1mS-cfmTQ1#kBXHtFQpbWoct0Tn{*xSBCPX15^Ye0jvB6%x5P=fDyP5P9o(ti%zkOHg&E0f?4C#^eI4hW z4U1Zt{Y*IVBc|AQ{)B3DG*@hZ0+yy5Vb#ZTRjk`nXkkTtXZM5Pd=a+R_q0iUq$>09 z5*H)>t*5pr=H1ZA2eC@fV}8ZKUB(sb>EwRk7J=if)o%V+m&KwS6j8eMl#>xU8l-QM zN%TbLZV>o3+TuOe%D1A7%Y$m#eiAUYSe;i#oi7hRP8w|1bxJ|!jI-IpG6=gSYd4a3 z(r$iNS+&y4=2@&+)s}^SbE#1E+(bdiVbQJ#Fshv|TkJVa+DPNu=z@E$1$yq19*5dJ zsQ7u;aODZg1EEp6{h~{*?;IdK{bjuA;cf#FR(mt(46hO)bN{${v*Uq~MNh^1&}Yuw zUei4J0pXN@TVunTr}~QPvGhakEq8@deb||2)RL(Ey=xP+3Wz&6wG~UCK&!3n3hk>( z+T^*Z?_pW?igI@|y|9Wbr#=;@pNxsEJKkDUegjFwC%(eKD1BSS725pT>anLfzdzcx z*sdho%uw}BcZ2kSv%{_ZtxUjb^!!9j$>5BE$FK0gZHnxM_@))AawV^Ac_~TLX4-wH zTuX|`@NeqRTrlmPN$3XJg-q>${-(iZ{SM=uCAZL@C9`dOGiq2LJ4)cl)sX3pt8X(W zTf6wKFFj4*uYGoAxlY=oa%b4O|E_A+C<+o-8a5tXGBi)6!R7kvRIyIId0w$xDTAd` zMAEXE{&(rCKk_WYTz--^Td1~2NRg)%oJ~U(Ns4wmO9I{p?U?EBUfkcM6iUwl{*NPn zj*iRCmFQ2GPH9sGp!dIt5!`x`UuVMdW!}eg%GCM_0Y=o+*;dm2beY&3g6`G*^(4-> z)pQ`hlJ*Ua--K6}@ryFJO-BvSurIeR9{Ru5h7yc`oy7R8-oB^|~k zdsirf#;cK3lZ2mjX&cO_IHMwlRxT`S?TiQFBL3KVlx<~xciG2T+V#wig>{^27A`Ik z3iX-Z{%M*zalv(au<}2At$+A(Zu)R2sEjz{YyXp)xKcEGCmA13*4RTaFu zEg!+smyOBx34^v@Hs9W^IGtB3)qKwWt^-@nE?)~RQojT%^MPfgir2D6+Y^;DWcj^k zRTYHuglIl`^Z}~RfQ5B)?jrEJ+k3FWS|;=U`~Kr2$BVkPiLo9J(YU1MJ?JbPs;79>YGQQ*YhX9@XMUv)mRZYZ&bIa+AGa`{wGX86 z7F2A-i?|^sot^D}ke~{WRkMcjjNv7%qGjy9pAn6>cO_B{I$Hf&R)wWIE7}zXj0#n< z^xuVw9Yis29CX9ga}K4#g$RDnlA}l&$CtGn!vc>Y(Z$1cfGX|q%^WwPjaV1@u?@}s z$-I-*jO!b6^5RWhQ}0W%*f=iYvP5!#dA*W#tmfL&fkDu zx6>m7+WgF+^f;%`ZK=6$x?(BGB@P$x@emwCQY3Vs#lRtWB}7@H&%7A=Tq!6>XWbutkf-neLj8w)W3EJx6QyQUNzur^=c9b9}2giKRT6+=>iDQ>fVY zdAYHr?IQiD1|k|Q3y;rX$2mC;OjBWW>rzD#x2uzdG`mJ3B+pdiwul@ zDyOGk`>djH3;86B9?-)*k}k9#IpccKE|}LF3`06Vg=^XF7n1{V&h`OuBmqJnX(0OM zmy1Xx(ZkWg0YZxXX@e%>)UN8tzaoqlNb@q4brTXG;^U`Sm2X;wvn*DF_8O-Qt-?$L z!iMHh

TrwD}Zm0fH7#(Jz!crWcM-@^-m9HojJGTP^?Yj5&CRA5cOmt?=@R&`e_ zOldDI7-U3EjzVWU4!LlK=lir=O8sld9G&d3-d+6 z*tHDe6Pl>ibk?dXQ$my}3T!WVq$2B$aNp5|0jvUo?^^z;x4_BdoCAcsA48RIabPNJ zX;a9^ZQd>-~NAyOiR#KwkR~{8-J6cH< zMkPZztCJL4tY1UpA!Wj`=E7TcsH=kaUa=lrtfTSw9rtxNPtLUo!z=ZdIj>EzQ|U|J zkH3gXD8F}^5i-B5Y#`XwpybAvV*^~a%#oFNtjCS?eAia=J@q%P%PvrXQ+izGQz$i4 z?ZGuWo$(oB)_;%g(18P{()MKve1utaTn7o&q-%F+PNeXqjggktR^5ymq=0n~t`S{o z8kG^As1jIb)}DQwbdfQY#4!{Avbr705xQ2w?kCCyrds}bkKv<+N)abR749~-%(fsQ>4J8f}rN@_EKY!UAyR?JIVTYV!4YwEVr~fNL zwq6V2^2{!+`2nHi|MN~?J0d!%*92OPwO;5}OY=v>hR524*HJ~go6!EVX6KEIOnR=<=xz*bX$KKD; zV=~gvbQ-s}^ZAK|Cew9$-kIytYt5tcVokei&+WTKzCJx^jvl%MO{FkdF+z~lZGt&S z`t&*U?l@g}OS)_4cpv`X^7ZQn;?G^WMZSFx%fyE5X8qycMtgfJ)`;`<~) zB3!DRB3)c?g&jlNa4+g$zCuO<65bBCXSMpo*ag?c6hHUv7Wwi$thq~{EOGnZ!0%2+ z-MB#ao5Low3xQqDvCwdQ=UmTO2-MSQ?SJf*Rm|SLEmrp*vi;4D?W`1J+mE>$1JXfQ z+lN=7s;&%b+rv&L|&%`M}+rgF#ys~S@p!(#l3fqMjOD-U4` z&5gNW)_Kv_2r5O&gwJZr#8)v}-H_B1Ewj+X&flWetq#KqnY&TFMs8*%TG(rgt#{>h-Ua;-QiNTSVg!1;n`t)!JdfF;gG& zN9$&Dr;-}QE_ZaYu`kY(*WFMhSP4^!4;8C_8)uxELI_u@Li~*@i>qF(IzUAZk^6pDh~jWY@FPeMRcmrE$VnkBg%)p7LhD6d3Et@tCU=FR*kg8nJQh4J&Qo#n4q^b z;PNa4eyqiuRa6#g32jn<_1X}$U2MXkxDl2q1Z^a$Oo}XW*X#9g7G(CaxG6Y`rkyFY zV@1}GD>DCJRDUFscbz{^Moh%by+24#fskDiG)V=K#VID-^x8==8y==mkNUmZ%2-Gx zF;2N#`b*DV=wjMBUdCmPZE#w>E@eDJ^`ifRZXW<{1T92PUhLS9lt>Dl-Gb>`(waZq*^_HjNu!D5{ z(y@eCo2znsOwHb5HzbQnGZ*tuN_`-6P6%d*ygcjAUAJ!5o8iX5Fc`m9O(LmzQRVkK zNDXJnbV4LUs8eqS>nnFCrEG%#6>tyo1c zu9UbgX#Yb_7AjOP1-(lh-bIqEnBy*OxxO&735G`Kh+k#BL)WmfCpt@7(h^Gf_fHQ0 zwR8P3@-}woF97iO(K1Z`Ol@7wtunaE9KQ7|ffsUnJWGXzNyd5~{jN#8%CTebRmkKX zMROs+_}@#^sJfo~ljPnjWSS5}^WBGNuY2;t=p8RWH{BM`L$tAjC2FEKyNcm?=+c#4 z?4@cG9aaWZLofGoD|5vD8myL;Y?^rKzL|c-$%){I#rFp613d~rb%@YLpIPmogR1Z4 zUR`63*g~cL0SCFG_son#-yXY>{>^jSSvk#?fcz<~pdeXR!HdUApBfo9{*p>gNRX(3 zCMBP<#`8Th^UxMyH_}Hg?;p;}pIe~YcFG}2^??Xg!}K0%#jalNUv|!4dzu>=biH$)=OGJZz=Ql5RUW!aJmwU zUW4X4JVaiTbmMrUMUBgau#zi{LcsxGetiwC0#}I*<$HHLk>aX%+GV_?^}ee=e>c7t z8Wm0$&C+YTo{t8hnDry!?lo#xsAmeA z$rcH3&#x=T={_`oDs_m3Fv|NvR!46l$~RRRd;U+)8wS<54&Dd%64`gL`iCCzYz+`T z+A{Dir9bmuYc9R6@(cOyA&$&|kT~|`$vgBb8Om{-AzMFg;KQ!8#~^#ouht})M-&AF zx>u`hA&F=muug`i=t2i+CF#o@K6@&z@`r`?*ry}@g>|$*`aySpX!HmNu?yXGbi+8x z04mAF*qt^|yIxNfKOZ>p_D8MzFK4#PtlpvLRgcrtbUMdYl0!Rk-wKNOMLELHAK&O( z(1&M}`j?K_WKQ4Fp6a=?VS&+8UZ<4pgC6KL=Jj@F)hJq%DsAax#_m+%zWeo5m4`Og z-E=MQKjynyI&v(eaBJ-4Xcu7U*81AM1;mm>QO}?4XKn-EoZjpx2{4JfZY1tWr}XDv zA1;5WZ8PzGQ8)HI`=*4)(4)2Agr8p5V#N zt{GH5bS71P%wM~`#JPYRMGu|c`iq^S&Dtx!mzd4AB|`5_$ z9m3zRVmlEX4*qM(I*`AH&)<6^BZ*H8dQ7XZQco40$CMBjl({~T`a>SPeA1G*7zQT7 zun8PjTdxyZhG@)+A?+*kzZIEHUoB^$f8VFFJ7ITwu?dp1F9uKqb^z(c6fmn7=dOw#BYD@Z>@oF=vC)9Cf8(dJ(D z$g8?{$2}o-<1(w+()5Y5_*tI%J5bR3Gp+ly&zZ~j6}bT)3V&ZsM4~)r4tJy6zmGD~ z2y?r!Xki&CeLrIa7@jn%5KIi*e4VI=g4bAe54RQko4?}FM>Rfg55K#&J8d)l=&zTM zZM!3J;Mw%}&FNHd(elq1Q8l$O9ib09)jpq)I0FCG*^z)%+n8u z&@P?b^!CVTd&Jkji85>L_4q-5w#q1&_da2J;SOZrbDOH?uTXZ7fkR15E@k)O0~0}^ z!7)rOIy!ao!{n!`lf7!wsE4D<$qPq!y`3#kTk;%cdTbkIJH2Pe)4GEH{7Rr)^5<^PPh| z5g2x)2Cc$jEoAeETzEk_-OuhFlxxmu!iwHQr|z8ql}2ZsY+TZdtESue6a@-U?IX)` zde=``Bt3DJv8*%iZRHQV8bKV90kxK{J?AS`b$NPNuvUFH6_m)amCO29F1+U`&jcR@U8x-$$^}XM2~>?!5Ji{>dUJ zx)l7nY^PGNF}NNTF8A^8<;5hO*^)o~RDIa&GgOTc{}?oQ>zppqWFS|{C+0rK6@fvD zumHQO5#`8NUaUce(bHm>Lydu4xgga~G7IH@nids!)?QiUS^8UGMoiR@ity=PnGg6C znY8n4IVg~I`ax_2FSeegN9XR=s~2ypEh{zR#7)G8TZgO`{jX_%_?u|$yCsKy9r;nf z#Clk6IgTx}G1xuqWS%X8b%I(h@ZqQZyy`!41eTh#o*gE|p1bzY@pcubbe;> zout!vi{*#o>7VNh%Kh)KydK-h=CB?XK^DZc0qM|iD&}0rThka>4ytQ&FekKJ|00jU zrJcB~%Ji-Sop7bBw;dsWbQ(5nO`K3~M{EE}gd}yKnE3G7$iK?04zCzko*ib^RJ9-0 z5l$YrT7LCis5T?_zfyefY?w#+rWc?Je(hUPPklE1&*xSiyRqtYY1`yofp9m^uhG&~ z#boW}WIqNkm9BEQR{@c*Vuuy2owivEx4b@*K8qzLRB8B?VX@14iV(OMpJso(MeUSv z=`X;|`;6k25J{A}V@s^Fb&i*eP7-LhC1#I3}7v1_2 zp+-v~bI$xwqdm#?T$qzbjyL70TOL*9zYVnw<$1YXyr@cIBc`z`ify3@l;2p>oXLG?+W1UWW<>Z{uM za4sfns)A|Evp2m;968UYML+*AUV7!z^|y~t%z9z35`SQHkcit{Ai*s&sD?OmtUkxI zxV#*^$RE>@QQ-YZ+=ZLI+(_BZ=3o032eDL<@;h>^PDD9%MUNy%+ux}#^ZE6!Icz%I#cqE&z41_C%Jf;9DU@gZ{#|rqg*d`Ebd_)j*6r|`)vjaCu5c&M z-p*xP9K87MIDu<<{I}q@)?6VC@Enk~Qu1(Eyq8|$ZcMRy6^la-L&)=6B5sN$(w+88 z8)ZAVvdL?+q~^o$DRuRY%MS4j?lM!-mNBuCx!a$`Ep1dj#~Lq{?9%(&iiXujuZ-`O zx~#NUFla(I3-b zgn@gt;@`J+^dse#cfJg-nen{J*Q)c1amPakhj4N2e!GA>CsmW(zU#DCnk2-&YgcNW z9st9arMcn{0#TO$)x@fWZr=^gD@{9^O#KnuEycG<@}K(%EI=fib!GI*H)vumMG2+$ zQrzeJoQ`A$B45syMX${9^LZ@kN7?0yTz1H{fo>S8dQ5ctZqr!UARjinl$d5{j@3YC{l&$7|sYrF>4`@y*h8l$qe6{I_Ff! zu#HiJ5_92BPFSb&@c~cx<;4O9c8x@P#a{6rq|m6Rn@6`k|K%@Y#7DOi(+;IKdJ8l@ z-q7Oq;9B&h%q`r0@p!g&a?dg?49^55dp~CwR-PR`igA_9Ej+vNBjD7!@0?Q#LoJ#I zx`8%C&Es{c&OOHJYF=sni^ucL<8^mtG@yLyLrg5U+1_l~&bQ0d^3=#wj> z_RQ7m103RCo1w}T9jU2zce3H1*N>ovLe7hZU=-SY-f}k|`a%shMD8;w%A_oT#bN4^KlHVe z-?gRcgTG?cE(Zj>XV88YbQeqJdN2K%Uq#~1Cpts+Md~3T=nE&SDy0z)44R1p9~S$V zl4*BR6d|2E>v#C6tQsCzNqpYn;Yx>c%2D6i=UJy$NnLN8N*LIm-QxLtp6Mq#SzVE9 zk-)%@afd9}@|(~(e&Up(yk2&ou6T7ZgJI?AErHLyJj{u+@;D_4$Ydw(XZMWEP4qyd zE&0WLZSfm}tVZI&I}$(F#hnKOXA!>8+a;HKF^xg{`LwK?qC9Gsp)&g3_0I`BTKpad zJV>^0!Afq5($~4%XQK}T#t)gU0IP;8mAY|)CNi5*0oZ@?Ss(0(Cnd{t-MCd}^{e)Z zL&n420arR!;P)POFWZcd7@wwp^j!@&OB=aV=6^dOA33PUxhN4$2OLd?3#F1YF}+G& zyPpVI6f&N@K2rAMEsU2SA4QmC4Z5Iay1h@hD6{En6`scPKza$%A*eLzN(o3+s)$tSO#~7;2uLqdLQrZ5kU&Cm7JmEMd!Oq%`|Pv-pPw$* z+|PYKWo9yKW{CTBM;ZMuZ7e3*&pombniSwnv5Z3Ly<5jQDV41p7%;#E9~ymRaUN(3M(&y9l@%Wg*Wa6VK0jOEl64Wd zH)tU)a5typj+jv$N5`R?cm*J{1gkDq`kOuDZ~Lfgu8WDQ@-#FoKKjua54rhG3pQ0= zZZ$s)Jx613hwGF4-MV{6Lx0ungdSa`xqTr-vsS8Fv(Hbf#4TUFMZ6ur%F}$v#cy7) zDW~q1`Pdz3WteN?_7r?xaM<%Jf#ZGMXW{x&iy|gm)0ba-l;Pezxm)5k+XLJJbZb4I zG5^owUozbL=KxHtJ`Z4Nt!qbpE@ii-;-l;y%UKzR^*jxgP0U z0_Y?8cOueT0;~cpA~Ddvr0xSmZxHWBo}+HOo&8c#btZMsI{LFl%ZdSw!8wK6ETme7 z%@NXs(lYVchF> zoQyjY;%E^)sPSObW|J~)b2e{z$myv0@EPj4MMYl^jBzsw^R#ePzSTAOHq2kD>$_nl zOgECFxnA+l$8GLzCppI)TU;~HlPBe<2uZZqII+2 zwhwx9eVRMXi)^(%az-Oq^!Kjt#IA=+1o2bnKOkaIw9~r)$gM6W$i(vkK$c;pBOuH4 z_15DV_V=3PPcw*|N-3x4t-lGXap7PG?si8-pRbH?p>$_t z12sDsq`8SffayRKoi1)nPM%9pe~rQG-s)tkvZH9=_26Zrop;o0Ugc-^ z^m0<*A<8Avdu$h=1D-#3z*VZsoI9VCubQg~#)3cf@?X-d*Ln1s--Q9RB&i~cpuIH?t{^GQ$4f8HaKSO8OharQ*AV@?Wz zeBQ!k+s;V!R213G;-`?HrMhZXmS2yNMyEUz`T(AyRjQ_(3g<-BaJ1p%@jWQnFdPdWOX|I^rk_ht|Qu515gv}7HIpg8QNJYMmIb4Lq2GP9V<KK|FvCqV!X9MLYd(d9 z^Nnt8`iC4|t*Zg_VSR=x_J+BMZ=r1pl!Iqv#ud$Yv;eD9a@L9;&&MlQybOU*9Z767 zg!W)p(4FO+%S}DaKkga@@3oohKp%jBiOp=(W%b~|^AhGchN*Abg%#C0Um%LQ4pr>v z+3%4Y2aq?1Ct!kFYUSD9(1o6=&mYxQQazPP;q1nqAYfzb@2nMqs1XPI^4fVg`nTnT zR9$B^JW}!Ru73LGAD3Yu)E5XP*5nyzVf$@VzJ`j`NS)vxPwD{?&jo)J$0_jdWYAt5 zWsqJQu%nx3^-0LGP{o9{AmLZavUbfo{Ii%(p4Kd~N=CNdOnt$}t0(DKwrI~o5;W5y z|5FqX{8|?UDQ!l?fD~mqCD9?=UvrV>*+O--o&qGt^AzgJ@_$nA#UlYP(`v!^upZm;b02< z`v6}XXcl12H%!*w+)#@b)ka>mWql5lQu)Mp z=E^mylFA)qqg}JahM7FNg}EJ~5-PPQ+Vpo75m_Sh!6sCd!#lXRWU5V9ZXmQPv4c{Q z=SJ52qtQL`6*W-X?Qw650i?cYeX(At46Dom7wnbmf%Uve?q`!bQ#7}&{=G*{4zv9d zwJRHWegyTvaxG!LSq$oO20s>VxN?1AtSQ(@etj9n#Cp%mLQCsMpnpeP=O%jTg8Pau z%UvlU7PhB~M32<*G~I!#sc_2}QoK@#MwKxtD?s%Q7hC_EWF1FE!CZ-FDx0z|Pa6F0 zxaE9JqM0#k=%1_dh_YXa3XC(|J-SQw>B4+Kxv*1;f+!(QhXH)7z5XhTr6X;j<+>!H z*D)cx-{fw^*LY(I-g~R z+C4)qedI&ZH?m<)HZyfpB!U1B)&Qp9w%^*a3;P4xQi05{pl!Au3ep&TQu)*C8We&# zx=!+}csWaIusL(3N(UKW=Ne@{{2LcAN*n~2(SN)H?P3sSZx6TIFTTX{%0BW-NayuB zuZBzc>0QUVD0=pJEw}f62@j^~b9bt92Bocxv%1I-Z|Qy}EGyW?wM)NPWaIAfFw5Ko zl#BH%Bdu?S!q8yT=3hDBZo;Dl7%tSTw!luNTpewV;d5)RS!^eBt^SQc#qmhqp>t~- zRb_jAxy{ppHgTqaQ74MoCV9aGaj2nHyewQ4&Em8%dzxz%bCx# z+G@{EJpvNk);`4L;2(i6-L;!PYD~YiS(dK9mJyQ)0PH673t@XaA3VC{R90@NPThK} zu3RA}7RD#BF7074X)_Hbe1{kZ|C+R;BS1nc`-^AF>`EDPFIU|g_gC!i8=SJfSN5H} zBPs_~HYfX43?3iqd}o+V@v)F7HIQ&08Qtc(E`fg%Eo9_srva3}>(qmyx!(KiL{J7= z)Dane((H{qD9hz@EYh1oHNsahjxyZIKXf=hnX=CL;Z9U)7>FQI>!))`E8g!R$D1uq z{mi73{AM#ezPPoN$ReqpvnB08wok|8{2GH7KR4ba z^$OJ6Pcpk5Icd8omZ>+ggDQR)2ZxR^CKt}3EP!ghzVRY1TP37p%dDH*N_#_abMbRi znPcsBaQ8cLEh|0bQo5_*x5A`h);SMcp;fN9lOALo$R7Xt{uZgZLfI8(&&FV~DDkX7 z9sgkLUkEEBuEUQ85-244L~6-#=c<$vrMd=*?RjNUppsRU>?qd2lbPNr>QoCv$QXGL z*PA2*2NsITAbZ}WSI|#qU!qY;0{gRDA>JXfl8S;Gk{)EcbbH`lN36cnwo^k9lu08seRo!fJ<_m6`9*^>zB!OnJSOd1=DQf(E=T26U z8Bb$vx2fvLqd?z&%I7rO#(ERBZh?tp4rPytm$P0CN6l~3?oGAR`aB-?=J0mt2zSd8 z0eqIVl)m}+XG1i?Rs#Rgk9x(+;>`-=zTc@JR*=IG`#gD~DVv`}=5|gi@q!0m2S*Wo z=-j4cH9>R6qh3>a4voim$Gy7^i0ukGRhu=XvCG#*H)^-x%yS821BG0)?^O(uBcV5xMQmZkr3k@eyHYX;KQXQg5b8Yp%r4btElyim4DNqnDF0C3 z>&g(=hQw7gMX?j$dG*6N?b9r_LH*~MADUjT57bfgSsgj}eGH#r&wtnxPN57BwuCl5MAztY%bSyuj@ zM9b8beCph)UP<`;K2I8?;Vjk=2i{IBR;1rxZaI-9h__jcN|_bi4G7eV{;qKd9vtg; zH?(9%npHgA>#W3Iycl@HwUd#r(^A&0&U+%sv0g10DFQlyO6@-6;kH z4Ng2YH7g0XEEbaEHFyL6SZmB3h5W#c?KVgjhGTmO~L=h~N zh|wuikoH|Yd!c^C5br0Tn_P()-l)#elwKXUq*+(h>ARpC@F4WjNP5Gaz%z2*U4W8c zp0w$Db*wR4fg-CyBzr~PR{6VXkf4aoBDPFBVOx2CVwq;k({6C8!^3g2Cj!usxwdov zT|-{~5$iybjHr<7%0mbo|2YNy)b-2?A0_{!YX7YBYMjklvtFX#d@}%!3#zqx;H8ov z_N-a7a5IWSXNth#oRnK1#g0fn;X>M~qCcH-CrJCQ*bsVqWGju#*WEmmUC+gLPOz}b!I<+9&mqZM_V)} z6UTN4_nT^OFEE?r`&ZJ{*Xl4&MNSXQ|KJ`MIVMg>Y`jy}SSU-a%udD(3?m9uB-mEx ztb&<-wHL4%$oSb4zd6-k$}!E(T~2Rdvi+DfYhG=N^$>T921(-$Bj9kf1PQrD*;0MT z)_wDbKSar=_v~y{Lu2z>%9{^~)Ny-D_|u-u=S+3*(X6A4LppQQ)wzW>frCjcBi8lz z#WDk!=7+m;x3=tIxcGf|!cWL}`rE_iQsfpoaS`+bV*wdl9R7UTZ;lJWeSTM8sI!xU z`w6Hf1K2b6mNoW0nH55=*e(cOW~({8e6Z>>v8r|Q2PMtDGoKkz7XH-lMY%6JRO68hB@DqnjH}Mp2^9|&e;b9X=p%pDH{W1G?wN&ry zjgOLnh^tGN0IP7o>WR1}2s&nODdX6asSA8sNe05v3xuPHdv>O*pl!xIeQOZ-3Z%p! zdA-P4hQV!i2|xRApZpunkua#iS2SGt`N-JavF7dJQ3XqXH_@nBlWB7@SY)#KEijb` ze|Jj@TmH~mxy@yvynxnt->ZHD;@FdaGr1ec?f4a)}+hI7x8 zAIFPS@@Qq$i;9HyF8R=rh}l36NN6m$W>;qCYY}JP2T8j-#=kxOwJ$Misd?)h|I_Id z!jhZS61=R8z=lHViYM7B*A!b&%LTS}ELr+Gjg2=ak3}X=Ai#i1mx^ti_{27qP%|)_ zTKo7Vg@@-kB4%!!W6yyU?#7)e0|h+@c)&Z*knJUK@ck{__NxFrz=ZXQJbdImk6OD^ z_i$CU+DBYr!D3I;@L-nr{36&1u~TBetM|^fy-ufb+sWiK8wMas{)1;{aV~gYd&{gm zgpf{Uj)?T?pak6n$?MF~5jF+A`u)nRSy2I{5xR7!aIdoblX}*O3NPq>$cZ8(cYAkHNv2F#iCgu7Ss|XG|OrcT*4u&N}W-0?@$+4mpE?Zdt zmx-JnkOZL}9rZb;Ws}Y`>&su|;lm<;*wF6bnxcf!R=X7hB{G6&HGXuhajd`s`(0pb z!wqokFTk;0PM36mo}5n3G=bi#{j0Bv(?a|IHFc1-{ z<}|EyMmrcZA}ca`oehL*RYOMj-*C2g$qJpaT@LR@GptN~PojzR^3Duc$)eAN6<@?Y zX=d@98vhbM>oWlZ9qGxu-+$_)8$7D=%jx3n9&WISEQs=2kN#20E0kOndX$ zZ2P62@0rHDi3H=aprw*5n4xVy;h7cA`;oOG;+c%21yE|Aeyj$&6uwMYB=H?ymJ01} zLhCms;P20%7fpm2*zQ-s2nA+4gQuOK^BZoSmdAJ8(r2?QFUR_>uh=(>k?x@8AhLIw z7jE6q^62qYxhrHrzz7_mVfk75a{XQ{D0cd*>KB;KfPL-4|d%9z|9h1 zC#rjy0dJ^Ccc^N%ZL4Vs(2bV>7ai}WU8uEr4EGf$S89O#f*8=ik3?+G`K`d3Fz!}~ zPF%WTM<82lABhDMq?%>=NS-^a03R}bbixTM{|=cf<6Dr}H49~wbN`*Nb0HWET>F*! z1=0T5fVbRWRGbcK3JgXDI+*pJ9&F>02ZPhKo_l3*9`*y-cGtgb#Gmz+?dPv9 z)~j5o&RJ)HA`vsZL!vOi41E!&w4=)SQceGl%@&u%>j{ozy;Rx62$1P$+ewi+q~Xc8 zkauF3K*Wb8VTt!?!{0k*S%Jyfz+|lyRx+f;35l^9PFIHNj1-w(?)eV0S7goIt{wtw zVoqYby%VviELSe%y$XmN;Lv|g+%%F?-gzf{-|xtPWBZoVV)%4| zA@DGVtI=1u`2EYjkP$Wa`0iSoC;y46pf~Kygl6beF^guMMn_Xa=X@iIt?gMQE1pUGT_paf=#04 zJNI$rmT5s!cH3ELdAeY>qvkBan$r^&1DQt@_D>=6xWEypWh02 zAI5!RAGuO#9R<~6Nb@I~?f~c_oiyt|mBsPhB_;U6ipxLt$u5(;ywrB&7yb591N!ZB z&s=%HCAEJ_VFsc^Y`##tB#(donR}`zk>Pjsz!;D`b8ph)I+ccoJh|JFaHI7qlyLupVP~D+WxVu^P!&9V}MQgs!?@2$}}I9dNwnP_}~l)?iAte*&a^vG3z^! zC}2;XNL3GBM81-w>fsitfiKitta?Rav%{k*?xw7A9qn{7)93GNl)y*m<4l9k5< zIvQItE8LbJ{N6!gt32r)_)+U~m=vleirK>@R|wuqf@&|w>^(da5D2Vh?Ec`}h!!Ff zbX3-~4!*ZkSMt&L?AE6p+2%;(X1AiS)-r?uXg63YZqXG4+iP(g_h0W<=PT;*dalu~ zSo9UFVXph}RG90V{8tROtV!_nPcFZ-}&<>h9o4g znJZgynJE1G6-j+VR8*AX!HL;RMd z8XGk7xJjOR(yF)kL9>?^b~1T(Z-4g+sm&5Ty`rOrQrKT=kxm?^Z6aEI1B(`aJ_?xf zHhM2qes4q}KOZGvp*^2pE$r*LnU?=55%307R?m6sg9CJN5(8gZhMIMfXRUblutVqF z{2Ktyik)o;A!myrqG2!EKSC|bbnWf&Z8o$5HdePO*u4+%y{_6>gb)!nDX^aDR7xqd z`9X^&0L7tyd5ZEHrTw{E!3Uj)4F1xOb&rWe)T259aDBR&UF*b{UnlwAi((*BNbZm* zZ}b@-{HL|xs^`dIU3nU;ErWK{H3I4UiL_(ibE^*kW9wk37HzJ<*F&(Bo-;V~%?jR9 z4L{4sbT=N&Q-?3K*~7j#Ka0o9~Iig@2GrAu*ap5+CDrS`I#-bRhbl4JfLac`)C5jYHX|DHz8Oq~J89UiCBNU6D>E z1XoC(3u(}$SIxDa_hXgR^Zi}3a!{+5YwD0RdiyM{HCo7zNFZEXwGg9>`WEEw*1FJ< zydFk)@1&k5)p+zhcQ36LmVckn`@N%mpmFQM;IORa)WGYH%E4>pfG%%9m(^FrU&Vx@ zu0%NR4=lc~xIi}Pwu-4wlM{LCj1nm5d3fTitS6RIhPJ?jdWp;P^0* zco!h`tuaR#MffLswhhI$-H9?ePw&yU=2*|y17zFgwb0I;mj*<~w4H9eAYQ9r1IQ{| zTo2xSeNF9^#Fc+-k&aKfcs&|M4tySkKs*l{LT~dd*&&|NkvyMu?|FQX zAi)Fr4#e|LJ%CzUpX>K_4}#)lbRFwfyG?l12=jc9{ZPOI245AA901UYM^CLX?%zL0 z*VSGyH@CD1Gf1QOm+Z6dP=h6ikpO97ykwT*JrAnFfvkq$u2dc6RM3aqP+7 z@;-g8vfn*=fyVE<3K!y%31Wo5OICiG#M%55#aKs20`=37_>#&vjCIF923*Rm9=a zhILas=S@!|GqJJ)f84#6`WgWI%58|{Lgjku-``7KP04Nl5*|`AV^79EpU#!t*$dJ( zF$`9>%*uy*^fYc^2Zm)&z5sZt+8gsFN3sdK?a2bb^b-&)7wGT0T>Ng(yehz6UF7P` zBSB?O%IkzGEf$g2CsG(}g}4pq@S_<;{LxRO8^YLxIoBXSqVd>rC^G%Qe5C zEp3m78v_$s0RZvG@%yk(BQ4TxK$z3Tfm6t266`d4h9QZV?;=nHoQ_oK2Shr9p0t;d zveBgRhiPg)9F3XU-duBd!u{hd*W%W0Be8L9MFEQ3k9ffbc(ZLZe`W7}w9_rcinuhO zipHKFecO8hBzrR$?G-F@pQ=`&e19rR6$p~3-xTr-n421Z>eD6(E$l*?U2}hCrqjvA z5&;FJR_py-@!U+2r6$DVuZoXbwb1s(mxje@<{wOB7O9)alz*1bI^t9M=V0H|g6nOM z>K&p&9!p@FBp#lsS6E%2Q}%ZCGlt8EFGRmnsEnYt)^%ceoqOL;UoR(ZX4yUc$Ozv5 znck(}!qNT>9@`Ijp|@~Z$_+U@rwT+rAZPpF6C+o##oG7lhc<*5%+E-kLxHVxa6OYh z@YwaaX1J>#2rr|d!eYBt;`MsWQ^KwHJ%p*8Fu)za+1`bl=jBP1V#zgMK#ty~#aTdg zki%rJ(?S~Z5?dj}x+QsMU;$U`JQSl<*r)_A-ft}DH(}`(8vhJYA}nyvs`ioxBqQz% z(blhysL)M9fE$VdH!ScRVn$LnW~@$8=aci{prNXH(!g*5 zGfYj^Nrztit!Lv3)7okYqjHpgGn&+Bsk@d|Um!NpAq~QcMJX4Q8f1S{{0SSh0B9OF+WQlusDqjN=u3jlEWq_Oz?Gb`@kH0ekeuf) ztc6ue^U5?%&+N61);#|uh4#+_bOSVY#t*sd1d5i zN*9uV;p9u}t(^0@u+urg(%%7B-t6}yi)S;<>3U@n1*=fOUptLN~gTOdx8<AF=QQGXc z6Pc9D2a4{_8*KR24q&6Xv5}Q`19!Nw$D2SDF~d)Kx(9q`Jfj5cwm*4O%XW%b1t1C< zlGr?9GZvv8S3)WcI!KiP-QK$tpnq`gd#+nhDjaG+R@K6`WqDIR+DFWx)cI;0JpLMZZ#_gd#=#FdB7~UolmyzK|YU_Mdm7KfPz2%3?VuIsK0Cu z`P;xbW3WPmCVYddP4XA)W=u@>K}BtPIdwmAXvw)4{3@nyVofj#8)vNvhLul z5)wkdorexm3X`Y=@sq%}op1WyoRh3qDF*<_tq^^3OFveRrxIT6Yx>UOt>^SFnf=b9 z3-yRs0F)~LRSQ7X0#Ik(V7Yb^rCmKBaJZZ6{Ak74KfI94hhzs5j@H^e;2+a-oek{} zeT#7nTDa1R4%$s~s{tt&TA=AlW0q+-1B5}#Ek~|PlwKFuJ*a)rC$v$EaIVuVAIO*1 zek?ur*GBx_TAO14+dP*DX=(rEEF~4lmuqf^{9A0F?M|774>ON6$`nm4u;aZyw{jr( zugUEgU!peqj{7?;-B1nTPWotPuA$%thh_IJQo=MGZ= zKMK`OC(>50%5)2kxdKiU6RE4O2?)5M!XlR=#k<(0;QKYPd+JOMY+I5!%w}LBOQ@;! zlUpvJSixL;j@QYJo211Ewh%$nRI~W0PA^;fA~Rw2u~Zk?)c;PZa1n@(j2}f zc1)jBX`fU38M1>Zl58Pf#OVtX=W+mI5;JoIM`;n zr&}?gzwm%qc;VE-!J7TWfrwKSrJo@nsNzp04H^o1b`WCw`+V+v2n}|Kc)$pX@R#na zPAuMx&AjYRs%9BLo6mAnzX%$bFhdzxh4bK8?W)$|!NDu(q8I%`IrfEGx(Rk}PyhN# z^)G^G-E0K=PM*nzg0A9jM`9@Ns=?dB4f8stk{}R!HG@pC1x1`i6Y|P>>8z69i}2ZZ zV%|)0udq#kkK89tzDv=cAt#dF!MiNz)S6eqhH~34;i9he7q%{uUc8)beQFZBmKI_r ziP;-274G9WAImn zDb-+JQGm)rNzmdz0BrEwtr+i%cdoJQEL%zlHBST&(2zQ5hQSK!lyMJ4n)0K}~h z$M$SH`gbbMbA(X|hs(G|hk>cRMWLPKBbm1P6)Z=Z4yn5bf1y4IcWKQoICa=xoK&gT zhe3Z7?&CTi5b|*_a0U5K4)=4!mmA~rxd6eV_-)!5#e9fXS=P^*;_xYnE-OBI1~1!a zSa^f1vq~H`tpul6q@}LHvHU~$#C%dYptW&``2Cncp`OJO8@lB6Y~0^(uE}tPt*{|4 zqa-YV;3qPB=nh)gn7dq4zuD<$ED@COFXRQ9_F$lH7B3neYc1ZHSC#*Y@Bh&Rx{*pW z%_L5~69u+a$p*;{SFm1|GJY9AsOPAIG<^*~ypQ1}L_9fMs!ZvpJk&HC((d|w!DqAW z4YIDoGl%Qv5$4uBgF%U@I#~)hn?)bT=}}BIivINuzb(fx0dabPr<`R`E$;`YXp10K z&Hey9K`E#F1_239zE3z8mp-Z9l4{fV>rxg0`)R$({F6OM;$Gt>FA#XWzbE91_}&m_ ze$7gY5hj4RBY)&Af>Muf4-P*0*#gzqOzcpAtL$UU|GX?OEC2peY(7eZuR6;IAqnUc zkXt8Jje^+2+P#{ih~Cj3;X@?2$v*q$cr}Axp@pv{kmW+xGTAdn49U^GxXcyIhqw)P zkK0&etn&y}Ioy9*lICI$-f#tV!msYiYD;0vzYZWg^2tSvR5R!oSomuG3xO+EvP|Yf zT5(P|mDCcqk>LYCTy{=6hszfpmSPS&!?sunf!^uix8DjC> zH+PZTEaw(!Uu56Bk2_Db8?-^`Ok|cgf<}%oWt^+uJ`RR7qAF=hKD$US5J7DA zD?p(D^b%Uase4iME0}_~jVwPv;fiw-16Gb;PvUhYg>+uC{%39?YXkVpU5%3_OqlF{ zg7vMwA&vs0aC&XC-z z5o|ZY%SRCbFD))Jjqo?eWdd80NU`UXhBvKVwGb`)DRYo-vsUt5+QZXi{}`DIL>pf_QK2$ z9p7JDIIMqCr|J|fdc{0!G%k0kzog%U{Yalx{x94I@+<0IVhN5nPJ}5TUjz7lId~@9 z?@{TU1QqDhTwYLz8^WWfPAg)npG}vhFd78SI;`H7dB`!Xe|=f&qa}Ff2BK<|{D5_X zVVzuKcGY`jkXNm0GukF$!`X0UYnX-^3+D^X@y@V&$n{H~UXaeqESj*&ee=*ex>e(W z+CamM!b+e5&q%pH9AJxUN?lP(B92!6fyLj-yBzLbCdb%zpP zPLfN~w9DY%h)6y=mz}r`(qY(;=Gc#$AVH7mV!96~um}Irs05lYa)vz?oRJWwR`;oo z|ENB#Jq>J-PDJ+9Xbg;T+dWn~^+d?0mN9PemU52Dr}#3DXc zI;l5(t5hm~twXdB=CA$Qkc<8afpr&8>erJ(IC++ju1#$(HgnI~T@?>&W1@yMNIR2f zS|5-5M-Tk-YCj6m#@L=pYd}X!@A<|kDzh2sQ3FFKe)V14@ODKwKRfgA8;Nh5!7DTx z^iMnq%~oQ9yYB0NVibxZ-bQHHlb?mfrkJ~oAY8soSJ-Pkn@#pptP>J6QwxPoG)LaJ z4U5^C4OZ%kH(Uuts{-fm|%_vAd2YOr$;|_ZaP3oRSbS7|;u?pzd!H$Vw5XlEhev!Bs8sItZfAf}s zt`LLg8*lfk#~vFthg<2_rVed+61Jw!_ftP$@VT!!6DJPMU}3*w+x?Htqq%@}N8uHa zOdVa--RSO2IEAQ5H3YHPHZnSf6N}Zt`kIBh(!UACIx~w1P2^F1K@N*;if3nelkv!u znkX@*cC7tUiI=eu%>gS+?@&FOq;4@L=CB-9-UTjRP;(|r*Vv9Xw1`oDgzV`dMm#Rz zV(c!}GPj@i+`PdeX1J0`DxGcbWV^4Q(z4~@1NckGjFPqn%ExB{`#DN^!`!XnISGA0 zKX%ACiTJw|9XlMhdZFJ`-}V)p`#%g-gWoSF$Wc=-g$|@2tOH!zp(THaGfI2{FMK#>&>W`$SiD9-b=-Oe0NOzU;34Zc_ zvvk3nLmI+0e}7&!L& z^+qgg71%Sxr0&WA9Ftu+@OraX$jOc80$|RLUZ>H#^c4{c+v9|G{}SSpzgqPyTKl-* zUPkdnG+}`eA7v)c#maZ+!ur}Yyg|mf#q}}(Nn_as?`7gEkLLvQ#CbF%EVeVZ&pEYR z6EkucXE|lGzIMW>uNe=6g#w2xM;9SoGkj_BoJeqY_dwSLW)UXkxzo3VN0s?<5;^s` zx!9JE9lDT8mQ!&u`Ka09sLOax8e!nRo>N=EF=XJDmfOGq(f@b^IOg9T0Wkl1>%V_w zaC-I6X+uCVaFXw|;eY$+kL^Ei{h@Q(@V|fbUy%Mk==hIE{{tPT@c&aCdH1~7|4sOR z&;LKE{2!?P_g4RVsQyFZ{}1SYnXB}`4M+cP3HhJj`hQR3|7i991NwjIR{oE<+HC_A m&cD~(pXC0piuGbQl{Q-=$A5=t`v7P}qphj;Pr17F%l`$Tn5K>Z literal 34406 zcmeFYcU05Q^Dq1cL_P`#iu5K4NN+(vYCxKFq)LrK5T#0}q5Dw*Lo-w<5-fl;X#&!M z4G0~jNf87>kxoz`5a7P!_c`~R-+Au6&tJcPo^w6NqnVwVot>H8_wMX#pIDd~FrVc) z3jhGK;dNb00H6~G0QyV+oCYbnbzINDf6m;$ZXW;u=e|(?(qu@U;{||NE<;^y>(Gg{ zA7@&8+ak13Xea3Xu$se+y6XF zwd6T(e}%L`5QQL;Ba~6z#NPxowhVHDQCHG)kuRYPu;}}yOtChqqiz#>3F25CNV9%@ zVmUwB3Rzyk0syVf`gfAc1<2mSp9CC4+2C?ff7ikyh9C<;B$ab!k4@78F&mP?ZVxnqdhm0obkZqNr^Z+p7Xu=`o zH-Atp^G()VH#xz(yb1t546>(v#WF)hvy3UeG;es*)!1VjPmLZ$8Zc1~+TMrp1IL_ndymI@u{d#}$#r^1W2d)ta2l z-#etQ5A6C3W@#-2}>1Ax;G z794gKcVFR}|1bhE4=$!RY6zRt?*_f20S0mZ!n}wQJ021wdjoy|sI;@t*FC;9ZSvS9 z(R+EB4!9L2vLF|5NA+h3!6;b^0E%S9CUYf+wD)v5?hDfbTSnUU(y*`U+2@+C!Y0n2 z0SXFw1sXq7p5^XYcn&QzxPSWi#X_x$~77wtg=Ar zJbEJHS;FXV0 zk{!UbmlZF5w)ahL^(u-6Xlf{E>50fX-J}WocAg0sjHDN7V_SgjIPVtUKI%H=fxA}eiy4FHMCID zfUZ(X3%uqIIb@+N;4R^%hXqi;&-NUPo$L*`_ujdg7@8+ua}C)_$i&KKJ)YylDnRV? zHWEzAzt%^;pqSVh^e5)AstDH@5CgDD(9J}twNZ7Tpe^lXMX%p4TC(YH1;wACy!`g{ zEpye8Xp#AJQgBaP_$_!VSED5Aw*4K_NUp5DQesQvnL}3K?#UzZw)fkYcO09($SA7T z>t{6R`rMpW3i2kB2m!%EykX^2ww;-iGBcj_5t;}UFFGy1^z^>IxMc`g`S&Z;`+R+Q zn33(^CwVtHP7H%PpN4CqoY4#SQfdI1HIs9|4?D|#<;@p8-s6jImuKGoNhTyO1VGSd zh*{pd$q2NHDC$1ZswA{3`kjJ0aHY1OrF|+^Ch!-lpeUNYq7D+S-;YuEVpF~r_3Y#u zfyJ^qY<8~y02oY6MZHEdIj{6RyegxgS%|D8HSDl?_rKlNBEBPxK{w3=zA?m1u&4WD zMf>cRE#Z7Wx8*`4Y#Y_YN$>l{6i7yHcDi^@@-5^YI6qKOE8@<$!`5^&O8@rn)x?wA z*am&P{qzN5_Jx|3?;l05o3H2EGZYT)(EuZv=?c9D%P7H|j`s*fc3J(Fp~V-1qyTAh zq|BlIsF{oI8Nf$cEI_#D)wiQ$+0O7N?VkF^t`BkT$Y0!QGNy z7C0lL#9$rf0zl||D(Tz~Lrga@D>^?PBl5O_<1{cNF5aB000e%q!m>el_4Ub5P63sf z>F{h(AkfK0d@Y`k69uCgTm{qlL;vJEnw5nKf*o{+Y)B8ThUx9S^nmATyS3B$Gz2zk zE)9egzV`M!2MqpW{(3IBiks;O1OiS z)jMa@eipW5;G1N!6(CTsO=5)ZB}uJ`3Iai5La(64#jfMs&XBl5*B?i#kb(V1=0Ph` ztz@y@G$;3Bu`pocbRO+TOu!22AM-V~QXZTFteRD8f{xuYaW4U;`o!J~_L8K>gjs9= zgyqnlQ7d7?w7n;+^H7}egBGSs8B(n4Yux_uDIhnTpUii`zSrCZa4F7B#FP&&EnNoK zyBp5nev?=(0b#9AiJVQc?Bg)fLxKqQ2|4a@Dy^0%QF4zgbZB$*?DTTBCCmz(h0`UW z9Y@u_j-Far0?Y3dpk;^K%!5IN$b9Q^+LmbIC%d<)zvDpB=iS|tM>iSn{?14Z>aj$j zdA{sy7@Y-zc0Ana3(glJP3(=%#XDujZv7FalJPY)FYf_b6__qptPfPwAm4k81rVW+ zQO&(b_D8x{(ZwXEr=G{|>7GlTavJGE7}6A+$v17+=&#Lz0q6n#m9K$8 zWLt{V?NXY-O;;G~BvlmUO3ZG`pUSuhcS*)MNF5$O#~ z#24#RKjH1j2;>qW!&L2sq&N_m8$j}7GBuA8kP-FLPfk)F8)j<+dsfcj8ke-EXIg&l z3UeeHV|klqg{fNlND{X;VUaXV@AIUxF-xTUjiR&$kiQ`}55t*?t`bOHa9N{ zB!z0Q=#MG{(M~v-*``o_h}#*`#2k0CjBMhjj_H{qRkAhM{omHG%HgPVw=cv>fjuWe5BT&3F6K7@L7s&Liw4j`$ zaa`OI>3Vy&^Wp0`vLfi$%whEfQml<1ep!HgO=MH#=^@4C z#(zoqgd?*Dpo@k_#3%ko56gbxjcTZ z`BTs4v|llHi$Z0uJ{K1U27UD0-K;e3BDKd=>^~YC(g1q&Zw$4^hf2Wz$M|OXagGlU zv+&%o2=?!`v;+$5TDZuM#4imu6-11e7=bJ<3gR_SN-ho86hwR!|4Ycg-9WdA3k{bR zct69GJr@Hzsm)I+zwP-?otRjeUcSErs3;~~AX&-{^AEqYn6a*azbchv_k+!T*!sMx zrA3GS+xt9J(n+ut5>If#Di_X;rtKLhrFgTAE0IPBzStwkp}FXc)JgV_?r4u((!fpS znlL1pK#P?xD&9gFs!abf00*-&-$m%dwi!fmsz}v@BYOxF*mmeEQ@3Ap|JJ-3iUB=$ z#oXoB@-6`Zi8H`o9KTd^6Z!0(46}@wq;7slJUHpJLeLT@emfPFB9dzFfI%$z6ax%5-Ssy^|rPI zw_z|9l#hhK@PK4Wl5$Yd%YR`~D69^c4L~TA+%S<onY3}zhp-Dgv<;cojw ztQ$1<@<6RzAiaAg%KOD@0AT74C<*-s-u4V7W94)DhUISHRWO!-j*lxb5j?UeDPn2owM&vApfP++uYa4u2GUA6zp+3xp52@I7{8=X-_ zp>*FI3g}KH*;AKlz=DCLaBijhWzjDUgr!W#RWO`DQ0mM_lo677=uf_sm|ws@e`&#n z#8+5s(WZu#CEnvZ=sCdjz6ZE?F%@k)BP@^I-~T0{?CfpTk(;)%U>e6bG|G|+30zi( zZzaUTxhKG+)f!rmlth!~&KK=F->~e5y#{AMjIX~Aa)%&ib=1L;j>Q%;yHm}dbYit{ zPjB-Pam^>7uyv44$%NTrC?avq_Rav|c!;2BMNvSQwzF5I=qV+ZvyFe+0wV)7jTmF0 z(0~$-BbiGIdbSwv3*+)AE#f|bjCF*haNANx@^CLy!j^U?Im51p@Co||ib&vlj*&Fq zee{Xq@FATOy_V&+NWTSIwn4zvd`uB+6MYK+Eu4Z)RPN>oz+Tq0%itrnOsKiScG z<$V%TmurjWDpolsepC5O28h;9U%AFRP^4XgKX%F67wic*SfvoAbZ(k-=+{4S@*R2! zCe~o78pKZksgkY0UKXI?9YCeYUCdAR9=@hxua3G&w9jP)y&v;p*OKUUBqeIBn`}4@ zq<|)B(Vt6VvNNNa@FvX)s$g=%Y%zXK5ItQ)Lk*Wze{wI|xHRce9}P9k{4ICcsIw2C zS_gm>paAUY@2|h)zrU#D|H|}VfBm0C{x=H#ugL$_$^We$qlWqa6xjboT>gJA@~-O# zwo8eQn)yNZZIJbZLrBPXu%3}h8~9Bci#{;gJ{h=3)+UPNo(3!|V@eksTR7HpWA`^_ zxEsG-rUlY37IgnxqdT)2e-ar>5WsqP%K+f?Q+2Q?l8|K7H@hxS&Ol{i-r&2go!udQ zD{Jx*RXbD0DwJ`T`5NW$GZgn^$|HaloPcs%S-OkMypU~=q@)NDQh_NWI2k`^9SOm# z5WKHlyXJmCQ@;07#ea9QK%oZ{Qpd^mkeNhv?=(89xU{T(@JiWD%JX>$B5~>tCv{S9 zVIo#X4i8nuj*rh{`yg2p{8af?>8yVrA9@OF4&-1F`j;m({t_3e2+Q~!%z%=ggg{N( z$G0o0jWNfUNiPW9;6{`||Cpz7W|2nA@WJ#>ATj}e`pH1EgMFz$-67AqAeR3duaqDE z$)OYYg+?TUi*?q&W>sX+X9eM+PkMeUT1V{4V@;vOdM;IJyt5mGW2}4J&&EP`NUp)| zle~+Ks-zZECNK(p>7u{UT{GB7X9&JW6e2rbSND6jWh_(Wt*?(oto&EMzs2J8 zWRlf=l|lb#MLG-G*ClitMui`}z;*@uR5)c|B>BpQ*BXoVbnzC++3-Tw##O^$PHIr~ z@!eak1SV%|u*&4*F*f=s0IL91GvM&~ewByaUX|SrfltMhX+~dfhcFL}*MSZk6gWw2 zX-%N+2FFs}pQwqqZSB<5?Bn6Ex0S~2A-QmNoR&IOO8}X(O70k?eFdGIcBm%?*VqeU^j^ZL75RViAGGIbrgf+^$mY4 zy4m~M{zn2d*iU3(x5e5?gnScuCJ1RUAG|@3z$Wz|cp{Y9WyM?q0_wf>{dkJ+@Z)3az9&`&QF0+?y9*L1A2{X_JgM3A# zxW+xU7X9M|8<&fh5g%Jd7r`74>q>i;QmiDqJ@I0RroT4aQR0%ao=kjR4kil`rNM5j zSeZZllO8j?8~RL~R76m-+D>u2kh z;gFAn<&tFVHkOweDnh^9!eHgk*tIN^_jF;;Q~eg_3FxkSQ8(4v{52{ygF=yeHK9bu z*=dL4K>;^ab2L*QpM6W-V5=;paYQj7yEiv5^pt^0zUFAJc?Q+Z5{*@MX`vi$Ga~{5vXvq zFIuV&f2m7hp$)gQNgC*l-W6Gx$vEkE>#o6ePWzVJJQuM_Qoz?r-QLmFXC@uWo=1PL zva*cn50zkV(|%r(aM^m^a+_m&FCG5H;0=XQ83Y)i1o9W~Y zbJDPmN?GmM4DuybF6?Q**ax^4e6W?CKG~SU@-d_K^>D^QnVZO$EvoWC9m5obrO2P2 zFH>o)#ZIaQWV>=(AM8!FHBypJ>K8(;sYXVYxA7{Fs*yRUq@Q(|T zu!Lr4PgdKkwI^4pr22f1Bm>#V9RJv71cq*@P)qW5$b4P0Gfv7Q8EGm#kM`XmVcI35 zr`3w~)v{#aowN%}JnphV?N=uuL7f$TV&WEFWZMTnRu3E-t*0bUGD*sR5R%cKLxUxz zmwmWLH?V&6jkPTf0hYv{)>HbaqI6!FY#I%@G(qI?cdv%(Q$G!!1P9bwPsvge`@Rm5 zGQL^@g`Yj;v&*A3QrVz)Tu zLke9N>M5u9{4(9u5lLN=O^p>yT-~^Pacb)l;!G|ss)70U_-=i++P0l<@jVvKEseIe6%EyKCJ81mfO%qQ?c>&ZWwS`8ej#FN*1@Dd4wjbU3#IkAYQs9x$ zectSe(b=Ph9#(;vS3QO+<~@SFf%;Lw%TqPaq(&CgHe5?WKThD%8uUJE5f@rdQZdRg ze*E?#u!kjlfk8LALS9CU{W3S4OtgnP&xh20N=An~%#{${joLUv?yx_{S$=1!X(xw9Y2A=3` ztVz-&a}}@#(BfHnjz6(>^7m1y-P!I2%LRrtO?G=FoBh;A>vE$&ZwU??AP0JKVfmYN zdCUH|b<2#N|AR2j3<_gxa~?kZqNS=v(DL!(ez;u~83CQC334V9t*4AKW`t7x=D9{5 zL@K<^8+N+gpf%>~uL4JDA=3yEMUO3-U&0VXRI#K;Vb;RZnLDdLwcqDEZ`Dv@|G2B( z&@ZYszmpW9K`Qt`t1;hCkcF!0*;amT{O4lE6*pptnYodXY_~D3?D#C*eXr(O_p-5{ z$g3X2$*yLfm^r0tM(B)jJI0mq8SI)tloE?zUYnL5JKaKA z6Kfw>!``SDFD*Gtr?%X`FtNQ8ZbIxdQ#LYc=<<`9F2BPtIkTRb#qaWUSAch1mc1;V z=ABhk*3c#tfsyhHJEL>3qu$1J$X(1WQpih`6ca3&)eeqx-l;j9ICAW?mfDMWXv!RT z9j~#rgf-V)l<#|_ec}{tCE@ZDlltvu2x zvJAqoh%?7l7v&9p8`z^n{2J>)=)Zb>#mME%+`6Jh)nZk+%lx2{_xx9^o3}&3A}O`g zLoYa?JXL*wmhK3R!_hTQl;|4X!>C!tZPJ;wA58D)+9sCgV#3AR@-WK$;dhVgNH&F( zdh!mW?Fk<{*^F3*H8)VglxJhIH2Wt~eBc4ZN+robEtbr-TjNqN;}kR19fe0|#bO)q zo=1~)T%ElPwqe21L{XR7m%qmjYPon!3V0XWH^j~bq>p6FXngJe>zf78mPN6GYZ$tNP zN)z^8<#Uh?k(-3wh2#BV(^G*Do-F99!eiQyoF>9cDJ|0Mo2}oAr0C#c#vNpAF2r2% z?uoiX)FLCKEs2kNydjT`xRf%Tg<%(2vW80Vx_Jo?6iA3G26_7q>3r|bk~S|wNSMEl zj-Ps_ZceN9hxBMayktM=n80Jkx+A;AApxIRvh-il!dv>AlDvODLY*u)9+Dtu!6IUI zR}dsYSN{!{PFQnDldN{-7e-n!5GT*hl3&&&b`$)V+4dpy>f6~=Zv4FrVhHMZeJ0lNF-l z&*SrCJ>;IXdU4|$o^PA-Ew_n?SZu0g9lY?@)M_?{VG<=owndYoh8JlIdKQ|2ez2y# zxYHo_qK7dhLJnmikzW_ueYv8-iQ|MrMVOsse`#b^zf5F^Z*1PuKjFFKhxGLN@OpI` z7D)z#i)47AwUdB`JUfdGotA7*$XQ~$6KQ=gp{3u*0ZrfSXCPzNZo{1;Iir+W*~BM6 zwnmbX_N(HZ;V!?Im%5y<7#Za{1afXNsUMQU=iH`+C7_nVbI zHFQK8sS4AG|71(mPWcK<*Y<;+l)UG{T1*ihLj=1FhBX zXfsnX&6KhQ3qEfObD?mv_5{hLHLYv{9VvL z!E{dl_v$Dc;x6F_wlj6%Em-dYn#}OuQ0@}bU1@&Id)X>HrQZu`N-CTbIfkyzs^CPfXU$t1t2nAnh*RDeM}CQl&y4V5+Isw@nF_}m`yOqzWF&zHvY zd$5%{Eh@w0Ys`_lh^!}@SEOnzC43osB;!oM8%dyGnnXw1+*m!o?VJ@q^_r^WsO6#x z3>KaOUK}NE+d<98g5s#2_+66#Df=@xl2&KAy^-l)1qv_gjp-__zW^_eN>C=A1kx9( zVXee}32~NsvQFjND%=9(2;$ev>%!F9s_$L|@ezS1QbQQO`ORIttl7h=x-n?6oqhK)h9wzu$464Qs=`E3I&@cPKNt5IPDqKDt z^4hiT<#>_8y$k-`wCfPyD3@f0QY z0nWs`v&wyv2K5Pi&Su_-8be-Z6Fj?pb)`Xjh@e&G7N;k^(l?=e5+{2K7!+1Ez;k4W z#EYU8z++>C3MxWnJ1F<2hK2yySwi3+#Oun=cBPvdsK~xOdl#Fvr-b*%QQ{zW2W|d1 zt&JPvmlPqxKG2lMi6+RrnL2V8?;6M|&p92sP~L;+-j8M$8)~%ng$>FwfIY1a-$Gs0 zBqbA+N*uy#W42Z7izI7C@*1EZd~ay0p; zZa7gpDIsFj@y86$NrVcB#B1j~4PN&#o7&IZk5YD%$j|MvzgiP2k$?MU5D)pT-r@T7 z@S=rw-l%Ue^RTunL5(jcbKu2GO?AoYQ}aia<+s{2&U1TtvD|HwviXYVPK@{?)Al3k zi$ydV^vd|~?;wKcXGHnk8J{~|d*QeU2q~~HrM+eAW9~#92(-)jq8qZj^srVxzvR}; z(dg*L*t&DvD21z+QHUt=(x5It2ZUO68JM_F!bB7r%D&d7&W)HFjY5YHaFE^lQW_}a z#f>i=;B8rIg{j}9k}Ti(#=?Ii-^ckp&rF`On4gz|^R2T<=^_Wp!h(^1)t}<$xo&nKSo73viMHk#ztDU;@~PGFk^lt4p2J6 zCFAZP<^I^&-FYF6dQ$^~ zZ;s%7D}b)*=(LPdnSayds}6>aoO<>~7vFXk*dAd#ZsOc@q{)|UG32(~1!gy%h6dEY z`B%f9Sn!#qqK{s8f z_nJ+Ez7o130bi0pVc8;8&G#Bx>lrf-P`6A|vMDZ^t(MN2oZvnuM&@_hU%o=gsbYlh zem&25m71bX{%-3I!($eu*AB@Lipao0vrA{V;hJR8*tRV04g*w0hY?Ju9L#tJ^2QBeFv zL#9#xU3-H#P=fbTqXSxf;D27!G|t9JOgH%Xd{E+MQ+XBJ*qOR@?X=^)xJ9INQ%|b6*KLtyi^XE{sD__7XBs8X&McWF*dL=|PCyd%tMw z`SquEYHD?{ou4bPBFw|-9P!>+m>#DAHFH{kUF~|%o4}2|$+LUwGoF;|y8Kz(cwt!9 zje{9A?;`7#q~AXY8C?M&Xzq~To5S{3#3nEM#^j;b{!tv5XtVxX&4jDachPG85y&I! za*3y#W6hoDivX8vTuzXUYMW!j+>u&968^A?a6?i3^tqHoIaP*+fTaZRDqdvm_-Sct z<#}LPGcNnKjcQg;W$82P*<>L9nJW?czJ7My%l;Q;P_tp3Z!?=-9FQcpMISIm>N?FHH44H{wj zmqo3O7LZn*_AZ6)G%!m{b>iOaH!s+D;3~WJ`z1?~l;=tXe}W$d@>y`#BARm}2zf4R zCd+c9_Dh`Ye(Rm&Da*9#$S5Sos|p1=%20m=@ZnM(Qh%fxJ=Ms*K3^t5F%um|I^i-B z3T})xempW?vITCjn#sRf`L4bZEjiJN7O6%{?rY*ox}F{DfEd{F0J?C!B^%(@(2_x z581XBt8cr+u$$dq23qsn*LLJ9dCHJ|V|8I-i@ZY%oV@vXRZ{}?DZaF`AZifJ4sgAO z=hy@VYVM7n-TNc2Lm4;FH7onbrFjX~d$+VRCVxZ)sHV{At3a=_Bq zt-Rsc>RirK-$%qs$6{PQ{D)7mc4fb1qv-5jhzob{6f32Ml6Wp<(hzITtMP}oH$kHu{GNe+~t~X1~O&Iq8k% zhwcsEDqqxlWh?Kx0xuBs2jSGGf6>;KI`pm{fBPtZ-Qgg zLtooJL`Tkpnfp5Wna#)@-;js1`#c_cca&f`%1=9W^I=gmG1~8^%1f03nm2ipPqupq zVy|8{J|qjfaRFS9B>UcYDpZDN&Fc;Y(?-S@P+atjDP*$(LVXxUw zjwK;)osSWC_f!9`$eomy?>h6c(PQS5J3rJ4vM}nK>Wl!>VBa0fy4*46?@%{CSENFC z%OS(>hCC0N7@DRLsnXzprpi6S_sOr*8%Z=8N~oj&X+REW$kiM1HERfFNorGr8W?DD z+kcqe+?d4Y2jc00gJ0(q-Z=EmWso7AMUU;-CsV+&>fv$_XaH{UF<{ zS#5E0?-=Qm0U6V!jdf)Dd@qNU?2IfUl7Iz zfI@NoK##t@QgU8?*rDy)BD54Lgt%hevN4~971YIZkK?7Z{Ze`bx$nH*JBi_9C%@XJ z2U?QD`*J3fIC~O!*7FhyZjb&Up}J2nd7LUrHGUE;?}l)Neh#T4}VVM;*EJ=6SQjL^}-mM=DrN%BA( zo*U?i93UK&INLeTu^it*t`h7Zhk8*LK}fSTk$8`|Op1o9vu8cVI~^bL7R?FeQ{)EY zh4!7?AZ_yJfS3~Xau=p9J~{Z)Bfrm2w8O+v&LCi^7-GzVa$0Ps&)oDHihG`p;r!vm z3cd*Na_4rCV*V-g+*Mw zgb-+3vJ)1=aDo^ed%$uOXzzm0!tA}08cwlkGpnkkiTUPMs^3Gu5P&Ua5|T)tc^qm= zjKd=Id`*sS%D=6=ET}1)0V1~(2u`*~w17(|+e$}FPnQ%njfp?!Wo0Z*d}b_Dc8~Zc zFDrMYW)L0B4g78?9!{oVPcMWh^D2pn>#QCSz#X@Ohs&Q;+Gb`TY+|U?ppCKH0c*g- zou0niwO9L`cU%V5=*$3UtlIy1g`jtDC7k+9FH)#FFd0O}pIK>7R~59_X;Y7tZ~AvU z39B6G?vNDT%hV&=2wIyx+gCeV5tS?SFL=4bmJp2=Tknk>RE-hw zJ3+YlY$iMqlS8Cav*j z-_4@72W=sdlZ168y@ka}ZEdujgiAdY95(zt5*w{Alj6juqQKtp0ff~PnOJ`ID%Qx0O@>@<-9k=VLk7PlE^UHaQT^P|sxSk@wLh1^Ca-D{znhkY)v zWDI#z(3^*0*9L8f$x*F@FCbOfT2GSHhYL2t%!o&oJI|*tWZ$}OeFu9Ed^KU^pTSDi zm`$l)!z~(;Sv3M%f`}CB0nQaoUa~zhBPt3foytjP=U$Cr>~_ND`UF$i?c_n<%{oa< zTsh+;!S1(+$DalvzXm&91QY3q6v`%g#`aM9#`akk&T%3bvO%=DUKBSO7tEeEmVHr1 zU|f@wOE~fYOB5EwCBt(`5qHJ#UJ|yEO(U$HWg?P%DV^g}R55O{r(x8keO|00^p)4| zmo0jbTyQl~5kcwk?C(eo6uOrDtcAj#tZ~^(!rXE-cis>Lnab+zOJ7zul$bJu={eGs zMj3)O>)WOzu6aFkdJWmp&rB*mZy$mwXR{Ztx!;Vr4%eKijVhPE z-5unZ@1t+U2BsdW>AdsF^xMJrY~mX`@0j7jVp5r4jB(ZY#=LG4UmyexIF8u%*@86?A&&$VAbevz29wp~JW0;?t@#nq~Ic%phm!j@4gM2yeenZ5YTI^&ifafxq1e!15*+`F*BCc)$P0 zzE#uB=Azf?_pUbdsZF+QcIXP!XM-!pGQI5XJPzIc*O;Byh{0*)WH|znkMsI zR4K=uP`r!wlVrs{cORLBmpgyd%u{IOIc;=SD=SRB=AO#0@mAbP|JfpPlB~D_*MZNU z4VtwCf9zvunLc>a0R!QX4Uj{Fw?wy_$NUck;6MA?`X zkZhhsLYwvK6TI2Sg=_SYSOQmFL9mFstxj9TwAzSGS-a(S)uGwKHffb~mE?2=^iAL( zv?LULOGc+t|6KeUD;i;sj4e5rk(u7e+*PkCL8=AI5$2P8)WkGlgV^bt8MWJFrxefa zX5Em`b2RF{7Rv|Db1kp@1gDECS4q_bSBZ|N>FLVc4j}Rb&{=w5tupBerLoLZ6^fVj`;*tWvUT{um6!bL1uc~|`xD9&`I$&V zp(q6P5pYb5RH%L!VW2t!UK7ERnN|pmRy+k_nt+viDB=J%$n)mqSc8tNY}uN9>ue9q zNu(3}xaB-n!^&Up3{~_rL3Sb>k(6LBAy^{B1wept~C{rEYVB91E_in+_Dv%*fu8M*HdO*ur9el}A<3qeA;(m9ETSb_J&IS8$fQgez z@T?~xj|mOmcw1O44bc@#mfNVDA5h7?jJXq>3T%84Eazr|;BnoVi*s<<3*(w7edMQM z5qC=#zw#FO{*(yO8W*JZOyHN3;L2*yInq6?ZqI-9)^+NRCPpZdaw&+!gmV6I=@U+@ zV^7hLPkxfq1+t-p?@X8%(i#D8haW1>gX1~9@PI&xtcZ{H4+PQRaZp4Gh;q6|{F)Q} zixYgkndh8|bq3$-WMUGRc^~cXrCccjfLnuR>%5-Zas3zVFM}wo`uGTOl$Jdbd>EsS z3LxUG)%)P-B=&r`ZgLWshu|X4NWi&&B@pmRhV6x-p!|JO?R42*kV8cLHWm#{FsSGG z!WmZdaOO62{tWms_Dfe}&;`M}N!k(F#cKPFoQj#C%yo5_hE!4}NE20~jBm>4Q)#`3 z;?$b`OLzhs|M6Oz(qF!Em*P~|07#n$Y0X^5ARt#bv%<=*l231NUi_%}_Vm0Y)poE0z&j$5 z@C@ICVF}SrK&(xli&{KNlmvBDaYCBG()@^h#0PlYKKU19 z!UvmX?Ps0HA_?Fpmmf@Z2V_0o^r0h+Nv7~yrhn^@cDBc(qQRx%{iybi}6FawWG4MPG2w=-T6T zxl$S^t9vh0S+=|bzU^ap0!GHMuQ0o%{*=_rTx?7I%YlX`@{E8MXOHY{z88P#-{v}6 zie3)vxq;`+7@6HFThffktz-`6MH}`={A7|NXxVpWhpy=OyXJ0eH&J&>#(hxjJ!LTvzlYG9a7-7@7Rj6 z=AwY|M*iDJdk+OaX~f+X9+II8sjK=bTlO=+`L;Km)_SA|5B#$SSh^?e(U=Su`Og%3G&C<9m8UYq>ciTnj3T6=tynuckxw--XA--F-1PQ}!FIJthG+YC-q ziv#Z-%Ab?%VR?Db2et4xWS(>OnKU?lrvCZb&VpJ@Jfnaaoa^vg-GnU&>Z#WDqQR_X$XOA&+g)t2b^x3*|J(ujhVnIz7EGbws12 zjT0KKAKTV{^Y}Xaq+IkJ_Ltumzq+b`ey{l@`|7nkunJ8 zkR{!XI`o64^mJ0hpUB*Fo@UuU^V)m+9{BGA@J%Hje$9!KzCqYp)$m+M5%nQZ$u z!Ls_1hs^KKvCAv&$F;|zqy_Nhnw8b|g?dWCv2HGZDE|!49Qwm|f~k_EVxR-^ZB+7n z>mk|0r98#KL^LsbaB%QUr!Hx@)F6)2fKc;E1oD^5c7}GX&UWxb)+sz|KES& zby9^d*r57vJT*CL_T4)=-VHSiX&-VP**sKV-F7Kz_8gn`+O#TbE-RhfV3N0srL>C8 z?wVUAG5vV5>cLgTYvet!y+}vAfCvn`9pBEFpDVfQaEp~8Bh;+QjF|j5u=7x8_aAw) zj;SN7Pe*)jdAOU{?7HOcM~hW!WaV&LJgXMUl(_3FQ>yl0R?0HRYrs=zdZ>@-6+HHt zqQ|sm-hD*)8~xagFNF$B(?KHjOZowHXG7fM(E+drR5|WFji~AKJf`1Ul0u$Gv zDE!**&rD-aFPnd~FExv|vjNA34YjjSOXz^_N$^%wLWFAh&mA=XH^_8&#tk5pg z_6y(QOJi}*+J34ZSz?Z&ofTn$24=Y1T9q=@8Yfo}1%ca}&B_EhIHG)cTjFiOX+5JJ zhbz(X;ei?|Uj)BbSX)N*=f31e*d$#%WJ@jsd)irKW=a^)S;L{CG%dcmwW@vz6jEaJ zH;d0=hF@Hak$K*hc(yv6h?aQGHuE+*L2TZ+`NHBNN_;{A>xo=W&XfBLAnaYkU6iA5 z-Q-Vqjhc4)>ek{Juf`kYy8j|auR8|uD34vF?R3oXZ{%?3t^N0(pQiB&dk-B-VCNFj zdyMaPz89)brby8>%_+Bo z>ug27Z$2VfEwS;v+qe1>U5u=yjO6{3ZGP4{+%5In0yH8j)$V=Sm%daqojO|^o$`F_ zi(sjf-_3*RTA}&`*z{MJ$GHt$RZ>XVUs3V9Gm?)(zo^q1)f@Lbf1obM;pz1HU7lM+ ztIEs~Q+eB$nN+{=q`B83d&%bCN4=~e?VRGAOH)gU+e*FAThAhj8+ZBMNEW~`>6rn^ zDla?C9W?6j$G!>h#FYnm&2qQH2W+2QM7(xN_eVglQ3kKkFx7q)8pZI0T%kL7bN!wQ zL$;KsljKjd_n)BX6ygN#Lj7LWU*|Bw)^EneRi5O3bc3s}7Vy+t1UA~ee4?;GF15%*T4zpJ& z)l2=RRX_G+R6CzZ0tMGgzBk^WtktvUEXki-`H}%M&k9&F7N2N(Z}fT}ve0lw<|%w! zohD}D&|WZ4vhTti!;N{zOipIBx#QcOMwlO_zW?n7ar||a;?GLax08VwNMX^ES%6+r z@iQFzoT2!j)#y6PS1RjeMcUs8^?TN~^7pb(t^C?(O<}|BU)F{*`rF5Qyw)4@9$9d@ z3BRodKP!Jt#4-Ylx|3V^eu|$CIOvS(FFLIuiox~Ngbwd#f0xy9;+(5y72G4dZ)KgE zU}exv@-U2){c=x80F#Q?|B zWZ59?gX#8sFPC}YqIfZL&2#CBA<&C2ssi5atH>addB#3Sak#c;hRS^WZsK5}=38o^ zDKNGmucmoh&F|?fDCBmUZ2ePk^d7LRcBq=W(oJ?uEzU8w8N|z!TWID_FZef#-BugO zX#Z^Wy4*GCG@y6(bMWzQ!znj~NbN(_>TBds->lAs#YgMvwj5bjuk+Mz@ftY3qA8H& z|Gul(E@^lJ7`NfOA>O=#eVIE-qTv61~fs;y~4ZRJyoiIRE%r zt$mC)=iC-6=cD(MUnDg&m9~9+aTp%X0i56*fptWBi|P0N zb!#DT=q!)kU;eT>dIwnc@)%vt6T`2Lt_Ve4m}_~n&D_zcDA2rb`*~Zz**BRdgzNA| zZA`YmR-3oO3%9271Tq`q)zQ6A!EejXiWgr8_kAmdxBGW+hPk4|ZE3f8oJFgT*on@R zU_;zhkuTiro_oKXdrR(Fz6;>CiHFbwVgr3Td5FZb@^0}WI_12sxvb%_SFd5u69 zw7kfQ<0{2h`Em}FWEp?$FR>9?-_)-*i(e%wfS03{dR+p+*N@7-wFj*JVXK#y`Dsw9 zf80#xk-*c?9&RW=2lA8!Z}Wx6J@Sdr(<9;d8+7Am;`W`6!6K`USMat|_zBo@)BW3W zRpB)!5f899+sND;+8=rClhX9mW_y>bP)D~7_*C(Wt+V)=Jn~U5z@1IsFDc>d0Z&c`-?7f> zg3;2qc|+E+Xx%@urt}zs)Tt6@RY5^fqo|Vh(?=Es-WTWS$o~MqR}p7bQQT!cUb{Ep z4{Chk2Z#^=pj75I1-fXOW0a1~pEIU2vx@=1mY~2Hc~j2*KF~!Szg8Ryq%O?qsDK(C zVr1juE60xm;%8#7%6&PwG0&TFLnIGZiK}wP#c?$x(|4Z|5=aXHfTvvsLK`gpp7DJ; zy$&B#4$hs~JG$fCrZ;ZqLIY^M$Y=3)i8s|T$)4pq`XAMNXH=8Vw=SsY4?#cy=^!dy zy7VfD2vP(@Ksty>Z_*?X6a++iSDF+76)7qmf|x**78C@e1rkD$5<*KLf!x7+*7>iy z);;Ik^Wm;_@5j9J&a^<|&OlD@0p175&dR~+@E=-pR6nbdV2UsN7>-J}Ds2`AG zCt(dKdc8e?;QpF8V@TOMtsBY6sHCw4^@FdmlWpywYazET^84dM_+4D~U|? z{ikutwmPT;rN9=a?uCCTdHP3}ZXaDI8p2Zc-1cS>+wb^+Mka$u14>tqwh#*R1G6as{fmESDGQ6-MCF@>s#bio<#I%;-!^saCp(JOsXmTTDXxwzBso1rHChmjge+a18VtlUfLWshEw#D zPIbOXXi6dsi10JYDk3b+u)=Je&$-9qX=yqpF1o>`n)bX^7-_Tzyg#UZw<`A@ z!YOJAgBPk^W?G8uC1&lkjn7Db2NQnJht+>BJEnhh;FxTypwQ90jw`Y%oR=^kU3Q6J z&Hy(mjSNM+%lva*%3Syj_}@#tZeYe?Jr<(R&O~NLrMh#+pq3jcgyI!xfjAQ5&m)Nh`R5cY&MJX zq;(xNWba?!ge(n$r3;|CN8Ove(%YNj`vqBboy+smfXh}uLb&DSZgw#=*Mee==wERT zEH8DR7h7Qr;t9=$1K+I$TEhDo)eTAeo+q)*9|8>USun!w_(mF3T$>>UM z%o(Ghxii8bc>ZoMqiOm_xJ)CSBanwC`gE%_Vp}|APQpBdzh~E8yb}oYI{6L{+_s$J z&pAnaO*u*P`YG(g1n0~}oIZS{@vPuXE*fAB>AXvxlQiGuu4o*%&;)8#)xJ~w$Z;(5 z{?bNd+*_Z%J|7wyaZkBlH+FTL5*hhmXqg5do|ZGHh?Z);hzQk5Qktb~zl_Cqn!ZV|Wyw>3zvh!Q@`)IxfIfyHhi883Q4Jfu)9i1d zJpA=RAm@a_+ZND`=6Y*=+gp|rn}I$DmSts3F?WW*Gr@t9Tk#p z#9iZ&XIxY5`CE9XK0CENl!Zsz{H-YtYHBjBwf6rl>|s(?>JY(^l`K8xB~IoH$UJn9 zxB-?p6+$ff!k0$`HE-=5D%|1TOMJpE$2iealnxHzC)+9mCTp1WL`zxN*&lZG}TGEee?n> zw*(7y49wqEPt0NT5 zz-q^(S3yL}>0{bwR!1pqjkkM(btQCc*!BAIxKT(eeBp>-m+B2lJ0~K#bDYCD)*Fp z(s?IaZf2)d%H%7- z!;<_ZTIpwbA7AEP(oxTLwbiczUeQH7SRzG$xpKzBKav=~Ux#=m9@b~$Qi0QOf6|Sf zy@=MD<0tdvyC!5|zNLMd4E2GxOr(l}BFKL$YYhw$h`HlM!2_(XFl}Dmir0(!c`&oz znk3x9WD(zzwusi#rx@$*JZ*42H+?;qPx*p~X@5%x-yN>K7f*|Uo~OWSLdpXD0LFFi z#NMX6y=8M|U_Ux0SU~2BD*b4R^onrn(nu9f1o$GQR=QdLYZTgdGv2o=*{6_9kqq(5X%0bBh7|q#1UYdh1p94-xjI%0=BN7KNyL z!8%=&QA!AoNY>MAON)SCxSBT>&O&|`W*=%ktD;XKLJ=4C!i;Gr9d$rJMU~}rky>Uh z5jApt`{odghN>>?a`?vLrdT7fn`JBBS_0uKShHRqmH48H&US+Q{%I4`d2p}o<(-o! zl{LF22s=!ZB=FZra!mLNeO6QyK$(@EdW z0d0tjJ_SLCHIms+Xr&D6Lat0Y^C&TfMM5IRvvutR!W$?26HRAAy}05%bSNKPkp9;a zq?zHUoJtF~dFj(BeM1CP_IS}^HErawJJ*)b_l}+1-t<(jH|i;&fvaAdEU3#!6ZM|)K1m*1Grx6t`7sLi_U}lO@jqg=sTbK*R;gk(2pS24b|M>g|d?F`0n>_StNN6oRvucBmr7$qzIAzz5x3QpUKKe2%DF z@}yf^)MdXR`>gA&&Aa7{3Ayax*C7}$QQu^44)sQImRD_(%9i(2#VbXZM67!K`!59z z#<;d#y{pC{6Tg_f`Gv-h&0k}(LTs#*ONVk9fewaB5ej8G(Q}BX{Y1WDl26K;s+HT0 zcb(ZRI14O$o?=f_`XM+5y3r5RSuiPJKB}zhX%~7H`cBiij|7`|pcZkz|K;Ve`;bfe zCN;O`kLCFn6DprD2RmPJmvUl4-8ZB;jzEJgaL#MvHE_k8!Fs7~Q>Ijbeqvn7%`1n( zf3_bc_?e#E#+S3JHGYp*P9Z6d7qfp(?R+njD8@KAFtq2FJCeg*&5#{rn@EVP9SDia zlXcIaoZMSc2@L#Qdj3lm+5Q6eOk2g2?GSI#&n%jgvXSu(u0$q$@!RMf4=_Vzov~1Z zJRHSi{8$%m{iwZE<~iN&)GC;Qtvf~xs61Vkmzl^Q_vkP}sKL$EOBZKXjCouZQha+g zOV)kHWT;0kaDG06Yk$6vZXmueE`XOPRW*Qpb?(cB^Q(0stCI^I1Y?aJF%skwObsJv zhLvTcUR9@(hgY|Bu4L6~q2CYH531fIizFp>5WY5uC%Fj!5#my%#$-%XL48|DD+a<;c9AfW~8!lqVjvj54k8)_{lkL`?<8MIAyn zT1`LMz2V?}YL5`CW-FS-ao{&p+G;6pk*oYbjjcU(>kenPQNILm3n|oq`)4H#S7140 ze712gPu^htWRrGEL4TlEw+cf6D*-Nq7Y%2`i-qx%x#(nuZt#sJhoHRM!t+osFvZWh z(WS_y$DK8CdVMQ`CNH>^;<#*X7i&0_U>)zL`Ta`tr9KBfom+XuSV*-o@KKpmbx;wx z%sa`Y=DkSf3KIT~cUnY+``o;@#i1^ZQLAjX#&E7%`bQLBm5inhS+4UvYFP4ZkfN*a z_MZIeQs9gyoun%>Tq^6lTg9BiJ+ynqa2)CU*90@yDX06)4bRq9F3ycdeSn83_L1^2 zmlp=oGi}zDn;y~!fe;wmaQsBw^S7lwxJPrGcgT5KS!pFAo&XVpHEwn#rowxLb_T{z z?{p;|pNI;rg_6cldcDQ~cY$t^9h*V0%X`t~V` z_EIkku_6o~dh1WFmqgYJug{+&_A++sKY+wT^zM)RA>4ZS0{zhn`^_wj=-F~w0D=^J@io;HX_nvW5` z%P0$jUUL4Y>hYwVQ;0tURG7|IgFF&SJo$SjO035@KVu(PdK!n>mt2F%&PB|eCfrGk z^nU$SRJi`5LzY?qJu6inq{?cBKg4Rau5d?gzMqYLQrSJFo#F|&G?ceIw(N4{a74-9 zDyG&Si$f->L`hw>O)XUNd5LL;$}+C~R?~}!vNPu~sl6@bn=@ydrBT*XIF!Nt;jfLu z^L`(nPRe#Dv}Z)6`9sEl4gCFYFQtXNv8yVZfpLtHA4BN3u0~~$E9p|F?GLSK;q!+~ zD?PWhY!bEFd25k_`Ir?!0fVq9!j^7@WQ#^bIcI!~p(nf+2s>Fp@z|6HV<;Teq&~G9 zG=R%@N7dwv%>32Pe~h#G*+Y*cM({O$dK_157C75==?)`ifm;jpd zhI4$dYgO^jqz_#v9M-REQKFvDga3NiT?3!-N??YnzAjDg7y(U4C&U*{tLv{XUc~)K zicz=kS{ondb})Eh1n0uHdDHGmm?3dTyrsQl<|>5sz1{jBn`fH+h~jy%xU_}%*e$pvUh=z zuE|wtB~(Z<*B?RzA@Xzk_OhjS@R#U;ReQZXu;4Z&xsuGH_54NMxzVg?V+JP{N1so= zj5`rj*T)pzKNvP-r!(;5q8^X0)Y~(*qcV;tUlo|8c{@JxmtMg0oku-g`EO@Kcpn_p zly?Kg4uN7uz!5EHo=Q}DF6;fJObvzt4uVy`+sw|oqhN|;pr-zEl)#zoRK0j>`5TH_ z4gCFQHKLdlTt}LfHJ^{^Kw4rIy)#@G*CpNxjMm!Jz*rk7E}|54{+lrT*1H#&a}q0l z)9w<@e3kb)B|HvevE&y_lQwd?gI5abl7|<*^_g+)-|swq9#8PAfC{*jJxn9-S9))m zRM5#JWXD;{3wv%A!NvXgcRsO2`bW`|(HFW8i$&iu-+gOS<6Dg7IL7=|D)Clzt~}Fh z0bLXJG*EA#$R7e7c2-08r^&wn37#7`k4s>T47_H_JTKR z_>2-!dB;$k5rTsH`v(C zdVK0F)k8Y3j52|E>xXGrp3DWm(m$omh{qyW?LjMlHU6e3tDjlGRy(jI3T#>3=b2nx zgl9!==09CPB>!ZnN{0ha7Jw&_5|1>4uO-5o#SqGLYoWL-tc)`~QZvFh@DW-t1^^HHNQ#9$TduW$8*jhf z=|c^XU#!K~Q*SEwC_NevA2Q_cKP4EaLMp2;62_N_GHa^WWwH{7NB>AjE{PAZ9XWB zT`LfEkE-Z^kFu)}oBRy0J1?{7T9z0!$%toDERUIVN_E&Iv&`v^u*`yY0dS z^1TZ<*r>#Eo@14hNl#Ns(MNbdq!>eQrX+G?0Fe1w@?-Fm0K}6AwC(25#VgMxQi=hfRvL=yzWityA5WiuHB-^8&Sk zDyEQ)LVS2fiJTW`(=fZfimCOB;z^h&rI){!j!g!X2e)Nl;(1L9{gbqo>OQ=cpC1^d zpHvCV)8cED#zx(h_9!q}sY7R%%gGq!n1u7qEU;@Ldml$SQ$D@jGhcPj$(lqrlw&(8 zb;8386S4QCagFYl&TN^t!`Hn!JfEy754YOe^jOA=aG6 z&0QBu@oLMOEHVUN1)YI3*XS|PI=;>(U#rn>`kqkCiOH8&b!S#HoZ5;x(u$#=C8oNM zBh7`9Q8Dzy&Zwt8_Iw!911Lm%=Lus7@BIUnih&iSYEt;Ku25WKMCpeg!Q@|LI!PJ?*HO z{EwzZsJhhmhTO&W=AWIn9xk1-azLvN5{?Nd6b151&*a87OC$0tjt_Ow##C#FG=(2L zX4gW!x@bsDN~Z4foW~%|$hPw)F9Y-SvmaGAS&1@N8U)xOE5xo?a&!xg@T!~)>o_(^ z_#E8!^RCou&O?{D_TLg+AzD%ww5S;$wH$7>98jNs)VkA9NK$<*X3;1lrHS#1lwu&< z9wE`+gSft+KL^u-aUoMGPRPV&p0rUK^w`>O@ba%|u%$f+IlNtb7*Eyo==I@q{24HF zuSC5-tUI7E-=z&z1v-wZmLSHBPzG=0snInjadf--`+Jx z^PkO>##<}Bo<|n?%xj)_jm+A4O^F^fB*#3*pKlz$Fj;&77h)p4tV{*pddj^-Y^!E> z2(_YBRH|eFCHsYkeI)LC_3vz=_sHSQ++AC+O40gSKei4k0%vq`+m8;RX)! z;+!ooloQPg&8Hz9R@x~uc_msmgr|0KLdi&Q zvrMQ$-w($!<5N!mn7*N$h|h2@K9#iNY^>`)cs>+F9` z)B_W4*L`JTceIN@5)l*+|xZ8MS=^lMQ=0<4$E*Dsodqf05xFIIXJD~_i< z>PVf?a>Uvys4l(|Ly+lqaU$Ta!gbQUFR5UpvY(NHPi60g;|yCb&s_n-7W#(kAT6%} zD=1)v*vN%#0FHD3M;-x3EVNS|wCL@!(Kp(T@^xUyo2I|IgK@SX|9a++k0$9)w1>QW zRT#Qvs{`#p-7yHVCDjY@O$vx-#k{|)Uhy0>1*^ZF{05%*T=Nt|=8C&GjZeRV(?D3ofLCtS@9;5_S!*$K z_FPd$%3AAb-0TE>st4#krX9h!KnK^7<`w^R!ar@NRdJWwC8=q71EwUmFlYea9|L%g zI9Of_T(Pg+5=*gnu*#8Tk5aD&z zN~le{+16Xve3X9!;zTCdp0D2F2arxOx{eS@BnrJr(q*oexb^C^HV+Sz zwfv0N)`Xr{*t&vAf_~dL)imdkot2g7sV2iPBMvWf%iD23`o+p(|VVQ^L`TZ>PC^f{K8-hyq+`O zr=YMz09Hh(^b4nG7>2E2Gsd$0@=j{=#5YxQu!e-KK@>EouP%B{&6o3F4tlhR0+t)H z_6{Yy6tl0c6B@XX+@oQ}?Ue=2*$xIzI4kfVT#kDKlCnV+_%)}2S7dm}Udo2rO~^Q4 zTzPgZaC@8apl;;CM|P2)fb8*l{_8x?qn% zxH<=j4YNU*kt_I)J^+n^^?oLh@6)ket@?)6oI!q>LH7y>6teg}fOXz9V=+nHLc6Fa zt%Uh5PhE0Y7quCosr4~_G@H(t_H{C}v6>?&IBe~Tg666G5+qVAD#4j@pG*=#Mchcv zhh1TD`N`YqyTq=~L2`ch{`(z{ZsRn`K*o(HbgNKBuVBdzw5plBl%1AonwG)(_rp81 z;rlC$YmV+;6n#bOJGGYInEL719wLEL2?FZMQ9&Kn&2TUGcYEREuIzkp(j@tm?i4Sk zv?`!-RQv!!MZ{t=7XoOD^)&qL9~KHDnSm)mx>dA&^dGPIoB)_=mq7Isj33{^a+;Qs z@Ixdk-TbmFR|>Q&hgfS7=;%1&y3z~zDX=sPeYMhU&gY;MIe>ykiLkd~l47x2M7BwY zg`3&x{J0d7M!@0A;h3VSrvz+ZJz+r^Ju=ro)KB(vJgNFg_i!rXHD4-wTBZI20GZU{>HXDONm>oDJUMX#=Y|1((&*0K`FGF zAN%yqb>M9W0$`uuE11dKj#}TK)T-&qhh`rqt*B+u>Ka$z^?qXze1H&liFhqz5Qs0~8VFitA*h zG_9~E4P;qThwA=hVv#B*Nn>=Y)Dv6fqZo!(?Bp%YnYmykeO)bE><`7gt+5k6Va>O? zw^5~m#a9H#L8&zoz6rFC0^Nc-##`Yl!s{_X_4?)TI&#p{fR`FLMQJm@ST-udH9A$= ziJF@y(!inhjnK_hyXTrfDD7EeI<++*xVczzf()&SRzL8F!$!Gr?(a@&wAS=rTzkUg z>s7-6y02+cq`y>1<0H;`D2!&yQ#GXt^g7y z9pqsvL7O(b)rxs{rBI{2rvD0n<2NBWFN=11mYiS~=FH7D_ua}Bf8iq1^8~m(a%`6x z8?LiKexOP5On^c)J!izOfE;ktE?WN)6WMr=xmH5n(BpLs$2o^BrBdd>?z?L`RAlI{ zBxoYIc5DHSrSEZrXH8C-9#K=iiliw{4?uQj-dtU>1ZAzvhE_D%B^8@qqtF9y(SCxSt4Ij835w#+3%%K?MlBihQ;-1F) zShA}Tf5oY2`{xz}GpUlgLW)L0YNl0?z?e5JC-}s)nB@=1%FVDx?1=ngTtyRd^+{y{1B49G18TG>;5qR za^)}ak2OY8Z=RgM_?i29Y~gEnf9#D%!l#IxVso5K@2n4vXXe6sDyC+v?ws!y9^q0s zNqkp8-u)bYh$9mUu)5dmR3fS87E;@X(P>P6hW4E;uPW!2S?33P_G$*uILF~I}h6U{K=ed*; zPc3Y5C7e(mo`Zh>E)m1}2g4f^;W`-E=>%duc7$hgPvFKtTR<$ePUrbZf;g>XHBf@c%{o;)6FLWjRzK%W)L0R-uGX{ zfkg<&1Aw}eGqtpBl=1ylZT>}oC^_{rYzA|&z zVa~Y}XFO2S+$RMmA=VU}`>vD}+p3D3O&O?1+f)yHR{kiY1a6EACPWVCD>&wEKY7Bz zCSwYleiIdb36aHaXLZBS{;7ppsR76+fSl-)BD8iKNqzlJ zRI{W8CEMJzIFA1~`rw`xt>^dT5N6H;tG<;A)8;iayNv1GHS^BZJ97kMZw1R#n4+ipy|UCakCGA$YdaL>|c>3k+UoAk5bW1tTUOXp8?XyabhPm&G$Pr<2)F(s!{(7`mHR}GxS`M$_W3$QUVnOmSp@nfN zepkwH)3R4xBjkep6GcpAxb)PV0(AW-8RnPz;5yYgn;HUH{)}ptS56UqgRaDvPmS*W zl>x>ZLw=ZYpy?DT{D!os%i1tMq(hGmwfkDYd)8%<1s}Sn-1PqY#AZJc(8n$~Zic*&8I`$mRiXTFtm zpM&AYPwX{^jZFKQ9-`Lts6Uo46Pq`*NR&%UTG1JWM4)v<1-PPi4VpBj0dWbS2 z1#8}D;a9IAjb>s;y?w%sTaWo5#%Mww8}8$dvf)NNj08!b@}mt1FU%J6Sr{J-0!{jW zCgY08&Fj5B#+C0xqs-@3oFl}rnxRdKV_#YAXQ1{)@Uv(-uNm$d$=bY&+C1oFRrJSQ z3}CBPq3h_)d*+a4{Z>A{SPRa1<@ScGH)t1-x`F!kmw~q6MwP^3HfbE^)R^4*ma$@e&Kcte zq{zQ})TSZwqwwZpFuihhghL>0ZceTBrSSYyoulSc#?We2KBzZLC$$rkQQ zNAc~6Je;1eV~9{hZr!j?H-He|+jzD&s(U3oQLLa3xC0QU0pc2r{&y8Fm>}OVdZvCg znuscJX1pr_K&!2pqBO@(J>xnJ)3;>986~PS+mS=#4w93&Il|2%wY*b2AoVkqt(SJb zHs2i>%c(pgFB5B;zj(ZmKQHt#5TTo+lQ{(Woz&WGz}gPoXT;VybRp}m(FFx;UQ2PU z&zfx3)iWC`Cy64zL}fWc&aQa7DVeI)Q)%Nu)O*Ijo z)m-7+%Mkokt{&&ir<0vg0BQk1WoJ#2Iuc6@=+hTjH&Ak`eq3HbKHk%EH5NB~Rlqvi zeX?0(U8DMgswaZ#<8~rae>PfK$*TpcKd5n@dN zMTw=P?=l~wyZBxP7TX?C+oE-COO{#|g-PPA_U}jTRnDD^^Vbb3Bt^!L9kikb`ww|d(@Dqf#aT&>Zvm@Wfjr2g1Y*Rp%QR!(Of6m;U6>eum{v+ewYuFT ze7Km4FWbSH=`wvL&#O@I1AGplM#Y7>K38W+$Q+1CQ)t(k>8^?toRyzfAE z%NbdJnKelZEao_3*Kw^UG)ELY!1>2}Qq$IvUvXZ$4ReWtcLdsf)3jCM;Pt0y853sC za`ntb1MMCI?XbYtJfK}YXprA!JZNLoJbEJ^lN=){4-;f(?8hj%aI$}7_)y((-EomQ z)qt?#5BY@SJhrv$4yrh^mVpYBKHJoxr9|EfHKssb_ll_=#iLFGeus{6JxgqtgUY*v z9$mP%r+am_^ivg~e6+rGf!d<{ZuvNmT0fC|Mnfj{!>bhpEAZA|pr-J{*p_k5W`_r= zK1HH=O~SIliQk{ss(h;FWjn>JgvfD?_g|X zD{RW0^hB_F#!kcmMELl=|5|%{_^M5j9?_&XK>5RLBed;lOBm?_GJQ8@^v7RJtJ9oQ z%K-CpaLedSvQ~P+t1+=>RC@_e_0M(1d}GL!K8>RlzFMWR=b>utzMYzOYRo?TWC^aB z{9Sk#ntf`QT|DoF2=JcS?Yn!Tam7nOlFMS%&wVA(F-+KV%2gef;Ad1!?9S74a9o#T zj~48ovJ+9&c<)mTu#`Ob$uGEO$br29&DFDw(vDqr>V9e1Fj<`9!fi`7t+Nj#oc!Gl z>N~O3eUZ39lEo`ce9R|uSY*p56mkY`?EH{GhjBF8Xw@M5uh}(+ucF+-@Ihk8xz?wX zFmJjb!YdGAFh$9`0lpB|^WH~y6<+E-^sSQ`c9&Yk?%*0V1<0fx+Ohm&8;&!6HD@g@ zhpnwgHiz`2#*?lfz-Bq}{oeZKH-MRa7o^=M?aOeU^%*ZfXZ5=UwXZ3S9*-y)5AJJjV$Jn1Fcm z^b4zohrTLtdloQiIJ=%orqd6=rt1XRMg@*|qDrz5sFhaYiBe*YzBcvK?$Y_28xua{ zM+Z|Peerg48c<`E^QLT5>)qmcsrZHVngzilh}Q{;p+A_kMA`-)8ws?P0UA7Kpnod0 zbhVnRTW(xQpKZ|kR)5m?oI*_m*OdoMvR?8PUVHe=?Qi>Bj*|g*q2^osg`D0O7xri3l}Dn!KLcvBYUGyZ-+wHfb`690-T8D0R@-t6Sd%E zT8QB8=>Y2lRvn5W;*A;hfqK)8WOq4@^O$88zZ=WNtuup@13o=XqtMSSwPBqE*6+|U zZ*;m~)OnZ6ssQpq_A8MU$1}1XJv%}7?GSE2DxREn%Z=7ff4!i<-W*p_R4>utO{wVO z<n9thQhB%A~(vi@EZCcmIl|)nnpV+f|lcVAbRit z|9ZV>3HZqkXHGMud@!c?41kT>wy!!~En2;Z&C~2^B_kQhyf(9~o!WZj$R|0j%2#m_ z&<{r(U49)q8G`<%JLx1U4afyH%$*V);SoGMhnYG$vs5_@l}C&W1QRD1Ckv{+1Vdqo zyDJ|hk^U~dME>%>0LEKEa`924{MrlD1Fn&-zWR3&Pl45(`!idD+)u3h$-N6=mV=|4M`CSrGorj&=#W z69faN;CQgx%lm<5XL_LVEVVCBY72zRdfGKZ!x9E``gvTge+`E2Ch~8Y+NR9C1qcpD z;vyCnE;24}SK(?z=BS#|*bw1A!#lXA-1FKHiQXV1y4R>~j#XqRlbX1vU9}dP8X2wR zG+q3r6d8KGPqsaKvxDKiXs^n1(v$F0F|8i6#|p6bgL^gY9S7fE<6jkU(HN$k?L?rU z;mU~Lf+1(>?~IT}-z1v&9!_(!D->xL_goQA3^cjesDPa9R2RV9is{dlm-F@82MAHN zF?PzTh|7YSS0!mw_uEU?G&}b~z1}h63(fyBPg!84~&+!K-e7AE-Sh0C~lbe&2wOV#Al)JIaiZPXmO1+a`b}0pcjANuKhR>S#jx0 zU2{jvDD)DJJagALEA$+}HJqM0*9I#1$@vC#0Xj@o*EH>ZspoK&&QZB^Ay$RC#s<+p zHKy!VtW5S`m6ojC#p(!-lWS)&j=+``&6JwDJf)3KM+UTGXqPnDv!_;B>C z_&iC3YlVpRTZe}=TRd+d=!18OE~dQanF&gJ|4>(kS(M_eg}bIy zs_OPyt+8aZAxRk#BRI%R7_JI9AVC_$9lmxMabU{9p*Fv&B**Q5^g!D)J$^gaQoNR( zCy1AQ_IG1X;8TlJcS^+m8Op@0C>Eayuo!8c2|%%|+(?c;WqK!DYdiCqvdlXqzO4jJ zd6)VkOLeLr8xg~6MaisPjB`di`V2RTh=ft`VBU^V64aDorxnLNV`;jc?BxPIr@%kR zPlc@Zb!?o{jM~RtGsEUoX)6?tAoY4%6gWFS#49(J#XF;4d|sZErJtcr=8QpwJg4qW z`b5&clRlhXE*A7n;$|*M>g*pEM*I;x?^Cl^mUvjEc@ZHeXu?d8cBRPvnZeHg!K5f9?2g9R49C5x&zB*AFc{kKlfxr?W)rco1+*V}i#lMfy8VH#px zWIvxnS=G)x{oW6MXqV;(sscXr!v)tF1K=E`kJU+xHy!G#&$~S3<`9ecIGQWuUdg`n+m8rWQNC&bv{PX|B}Bz5}*TnhN5%waY$nw|A<*+CIW+S}zc zluD9dEy2DZirobyX?$LteqvUO=TIjxK2Hf@DA@Q{xiaFmvI>4L+p zqSFEPBVkKUkgi|~*A_DPXKnfvmwp9hB9}WtRp00m1LfSL8 z>o>Zsoi6ue{pirFcDm+21ecL!?D#l~($!0cZ-<`^D1)6I2au||8d|^{9909yJZMCZ zt`K4a_q+V-5#aDYAJHTp-63@J)_?g3Sp2uQfXg(0EB@Dy{@OmO_}BK|ivQ)K|A_Se z#*cr0^xyE~U*7&V{77V*20s70xqm77pFh(35A^@fYW?4L1$gq`49UL&_rK=Rf9A)( zH2N=7>t7)`g8x5Et)tBSw*>qF4v+rJ-2WLVQS<*NT>Hh%bAl4TE From b49ba607a648bc9463f2b97e31c69c052ac037cd Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Mon, 30 Dec 2019 22:27:14 +0100 Subject: [PATCH 250/479] Improved the inline server info text outline --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_browser.cpp | 27 +++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 15781b62..d6398fad 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -715,7 +715,7 @@ class CMenus : public CComponent void RenderServerbrowserInfoTab(CUIRect View); void RenderServerbrowserFriendList(CUIRect View); void RenderDetailInfo(CUIRect View, const CServerInfo *pInfo); - void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor = vec4(1,1,1,1)); + void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor, vec4 TextOutlineColor); void RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pInfo); void RenderServerbrowserBottomBox(CUIRect View); void RenderServerbrowserOverlay(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 3707287f..0522506a 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -437,10 +437,11 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } vec3 TextBaseColor = vec3(1.0f, 1.0f, 1.0f); + vec4 TextBaseOutlineColor = vec4(0.0, 0.0, 0.0, 0.3f); if(Selected || Inside) { TextBaseColor = vec3(0.0f, 0.0f, 0.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + TextBaseOutlineColor = vec4(0.8f, 0.8f, 0.8f, 0.25f); } float TextAlpha = (pEntry->m_NumClients == pEntry->m_MaxClients) ? 0.5f : 1.0f; @@ -510,6 +511,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { @@ -521,6 +523,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else @@ -553,6 +556,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else @@ -564,6 +568,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn else if(ID == COL_BROWSER_PLAYERS) { TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); CServerFilterInfo FilterInfo; pFilter->GetFilter(&FilterInfo); @@ -640,6 +645,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn str_format(aTemp, sizeof(aTemp), "%d", pEntry->m_Latency); TextRender()->TextColor(Color.r, Color.g, Color.b, Color.a); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); Button.y += 2.0f; Button.w -= 4.0f; UI()->DoLabel(&Button, aTemp, 12.0f, CUI::ALIGN_RIGHT); @@ -674,7 +680,11 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); } else + { + TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); + } } } @@ -691,7 +701,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn RenderDetailInfo(Info, pEntry); UI()->ClipEnable(&View); - RenderDetailScoreboard(View, pEntry, 4, vec4(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha)); + RenderDetailScoreboard(View, pEntry, 4, vec4(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha), TextBaseOutlineColor); UI()->ClipDisable(); } @@ -2089,7 +2099,7 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) } } -void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor) +void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor, vec4 TextOutlineColor) { CBrowserFilter *pFilter = GetSelectedBrowserFilter(); CServerFilterInfo FilterInfo; @@ -2097,6 +2107,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int pFilter->GetFilter(&FilterInfo); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); // server scoreboard CTextCursor Cursor; @@ -2199,9 +2210,11 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else @@ -2221,9 +2234,11 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else @@ -2261,7 +2276,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pI //RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); ServerHeader.HMargin(2.0f, &ServerHeader); UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), FontSize + 2.0f, CUI::ALIGN_CENTER); - RenderDetailScoreboard(ServerScoreboard, pInfo, 0); + RenderDetailScoreboard(ServerScoreboard, pInfo, 0, vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.0f, 0.0f, 0.0f, 0.3f)); } void CMenus::FriendlistOnUpdate() From 494f74902dcb0271235d3a0831ecd4c6db58b7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 12 Apr 2020 17:12:20 +0200 Subject: [PATCH 251/479] delete incomplete map file when download is aborted --- src/engine/client/client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index fa16f648..58b0622e 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -572,7 +572,10 @@ void CClient::DisconnectWithReason(const char *pReason) // disable all downloads m_MapdownloadChunk = 0; if(m_MapdownloadFile) + { io_close(m_MapdownloadFile); + Storage()->RemoveFile(m_aMapdownloadFilename, IStorage::TYPE_SAVE); + } m_MapdownloadFile = 0; m_MapdownloadSha256 = SHA256_ZEROED; m_MapdownloadSha256Present = false; From b67b55448ad1fdb76e5a0d89133589c287ba5e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 13 Apr 2020 23:23:05 +0200 Subject: [PATCH 252/479] also remove incomplete map when restarting download --- src/engine/client/client.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 58b0622e..89290202 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1161,6 +1161,12 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } else { + if(m_MapdownloadFile) + { + io_close(m_MapdownloadFile); + Storage()->RemoveFile(m_aMapdownloadFilename, IStorage::TYPE_SAVE); + } + // start map download FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename)); @@ -1169,8 +1175,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf); str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName)); - if(m_MapdownloadFile) - io_close(m_MapdownloadFile); m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); m_MapdownloadChunk = 0; m_MapdownloadChunkNum = MapChunkNum; From 0da0cb80449d0aa01fe21737b5330beddfdc9975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 14 Apr 2020 12:00:20 +0200 Subject: [PATCH 253/479] download to .%pid%.tmp, rename to .map when done --- src/engine/client/client.cpp | 56 ++++++++++++++++++++++-------------- src/engine/client/client.h | 3 +- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 89290202..f5fc06f8 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -278,8 +278,9 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD // map download m_aMapdownloadFilename[0] = 0; + m_aMapdownloadFilenameTemp[0] = 0; m_aMapdownloadName[0] = 0; - m_MapdownloadFile = 0; + m_MapdownloadFileTemp = 0; m_MapdownloadChunk = 0; m_MapdownloadSha256 = SHA256_ZEROED; m_MapdownloadSha256Present = false; @@ -571,12 +572,12 @@ void CClient::DisconnectWithReason(const char *pReason) // disable all downloads m_MapdownloadChunk = 0; - if(m_MapdownloadFile) + if(m_MapdownloadFileTemp) { - io_close(m_MapdownloadFile); - Storage()->RemoveFile(m_aMapdownloadFilename, IStorage::TYPE_SAVE); + io_close(m_MapdownloadFileTemp); + Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE); } - m_MapdownloadFile = 0; + m_MapdownloadFileTemp = 0; m_MapdownloadSha256 = SHA256_ZEROED; m_MapdownloadSha256Present = false; m_MapdownloadCrc = 0; @@ -834,17 +835,27 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, const SHA } -static void FormatMapDownloadFilename(const char *pName, const SHA256_DIGEST *pSha256, int Crc, char *pBuffer, int BufferSize) +static void FormatMapDownloadFilename(const char *pName, const SHA256_DIGEST *pSha256, int Crc, bool Temp, char *pBuffer, int BufferSize) { + char aSuffix[32]; + if(Temp) + { + str_format(aSuffix, sizeof(aSuffix), ".%d.tmp", pid()); + } + else + { + str_copy(aSuffix, ".map", sizeof(aSuffix)); + } + if(pSha256) { char aSha256[SHA256_MAXSTRSIZE]; sha256_str(*pSha256, aSha256, sizeof(aSha256)); - str_format(pBuffer, BufferSize, "downloadedmaps/%s_%s.map", pName, aSha256); + str_format(pBuffer, BufferSize, "downloadedmaps/%s_%s%s", pName, aSha256, aSuffix); } else { - str_format(pBuffer, BufferSize, "downloadedmaps/%s_%08x.map", pName, Crc); + str_format(pBuffer, BufferSize, "downloadedmaps/%s_%08x%s", pName, Crc, aSuffix); } } @@ -872,7 +883,7 @@ const char *CClient::LoadMapSearch(const char *pMapName, const SHA256_DIGEST *pW return pError; // try the downloaded maps - FormatMapDownloadFilename(pMapName, pWantedSha256, WantedCrc, aBuf, sizeof(aBuf)); + FormatMapDownloadFilename(pMapName, pWantedSha256, WantedCrc, false, aBuf, sizeof(aBuf)); pError = LoadMap(pMapName, aBuf, pWantedSha256, WantedCrc); if(!pError) return pError; @@ -880,7 +891,7 @@ const char *CClient::LoadMapSearch(const char *pMapName, const SHA256_DIGEST *pW // backward compatibility with old names if(pWantedSha256) { - FormatMapDownloadFilename(pMapName, 0, WantedCrc, aBuf, sizeof(aBuf)); + FormatMapDownloadFilename(pMapName, 0, WantedCrc, false, aBuf, sizeof(aBuf)); pError = LoadMap(pMapName, aBuf, 0, WantedCrc); if(!pError) return pError; @@ -1161,21 +1172,22 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } else { - if(m_MapdownloadFile) + if(m_MapdownloadFileTemp) { - io_close(m_MapdownloadFile); - Storage()->RemoveFile(m_aMapdownloadFilename, IStorage::TYPE_SAVE); + io_close(m_MapdownloadFileTemp); + Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE); } // start map download - FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename)); + FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, false, m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename)); + FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, true, m_aMapdownloadFilenameTemp, sizeof(m_aMapdownloadFilenameTemp)); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilename); + str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilenameTemp); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf); str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName)); - m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); + m_MapdownloadFileTemp = Storage()->OpenFile(m_aMapdownloadFilenameTemp, IOFLAG_WRITE, IStorage::TYPE_SAVE); m_MapdownloadChunk = 0; m_MapdownloadChunkNum = MapChunkNum; m_MapDownloadChunkSize = MapChunkSize; @@ -1196,7 +1208,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_DATA) { - if(!m_MapdownloadFile) + if(!m_MapdownloadFileTemp) return; int Size = min(m_MapDownloadChunkSize, m_MapdownloadTotalsize-m_MapdownloadAmount); @@ -1204,7 +1216,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Unpacker.Error()) return; - io_write(m_MapdownloadFile, pData, Size); + io_write(m_MapdownloadFileTemp, pData, Size); ++m_MapdownloadChunk; m_MapdownloadAmount += Size; @@ -1213,12 +1225,14 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) // map download complete m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map"); - if(m_MapdownloadFile) - io_close(m_MapdownloadFile); - m_MapdownloadFile = 0; + if(m_MapdownloadFileTemp) + io_close(m_MapdownloadFileTemp); + m_MapdownloadFileTemp = 0; m_MapdownloadAmount = 0; m_MapdownloadTotalsize = -1; + Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE); + // load map const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadSha256Present ? &m_MapdownloadSha256 : 0, m_MapdownloadCrc); if(!pError) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 812c8bfe..36fafac8 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -125,8 +125,9 @@ class CClient : public IClient, public CDemoPlayer::IListener // map download char m_aMapdownloadFilename[IO_MAX_PATH_LENGTH]; + char m_aMapdownloadFilenameTemp[IO_MAX_PATH_LENGTH]; char m_aMapdownloadName[IO_MAX_PATH_LENGTH]; - IOHANDLE m_MapdownloadFile; + IOHANDLE m_MapdownloadFileTemp; int m_MapdownloadChunk; int m_MapdownloadChunkNum; int m_MapDownloadChunkSize; From 816e94b82d9511dc71e167962826b7d5786af8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 14 Apr 2020 12:35:24 +0200 Subject: [PATCH 254/479] show small warmup if motd/scoreboard/stats active, minor refactoring --- src/game/client/components/hud.cpp | 35 ++++++++++++++++++++---------- src/game/client/components/hud.h | 3 +++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index f999ca54..11e40475 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -17,6 +17,9 @@ #include "hud.h" #include "voting.h" #include "binds.h" +#include "motd.h" +#include "scoreboard.h" +#include "stats.h" CHud::CHud() { @@ -33,6 +36,14 @@ void CHud::OnReset() m_CheckpointTime = 0; } +bool CHud::IsLargeWarmupTimerShown() +{ + return !m_pClient->m_pMotd->IsActive() + && !m_pClient->m_pScoreboard->IsActive() + && !m_pClient->m_pStats->IsActive() + && (m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10); // inactivity based +} + void CHud::RenderGameTimer() { float Half = 300.0f*Graphics()->ScreenAspect()/2.0f; @@ -347,22 +358,22 @@ void CHud::RenderWarmupTimer() if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP) { char aBuf[256]; - float FontSize = 20.0f; - float w = 0.0f; const char *pText = Localize("Warmup"); + const bool LargeTimer = IsLargeWarmupTimerShown(); + const float FontSizeTitle = LargeTimer ? 20.0f : 8.0f; + const float FontSizeMessage = LargeTimer ? 16.0f : 6.0f; - if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) + if(LargeTimer) { - w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 50, FontSize, pText, -1.0f); + float TextWidth = TextRender()->TextWidth(0, FontSizeTitle, pText, -1, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - TextWidth/2, 50, FontSizeTitle, pText, -1.0f); } else { TextRender()->TextColor(1, 1, 0.5f, 1); - TextRender()->Text(0x0, 10, 45, 8, pText, -1.0f); + TextRender()->Text(0, 10, 45, FontSizeTitle, pText, -1.0f); } - FontSize = 16.0f; if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) { if(m_pClient->m_Snap.m_NotReadyCount == 1) @@ -391,14 +402,14 @@ void CHud::RenderWarmupTimer() str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds)); } - if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) + if(LargeTimer) { - w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); - TextRender()->Text(0, 150*Graphics()->ScreenAspect() - w/2, 75, FontSize, aBuf, -1.0f); + float TextWidth = TextRender()->TextWidth(0, FontSizeMessage, aBuf, -1, -1.0f); + TextRender()->Text(0, 150*Graphics()->ScreenAspect() - TextWidth/2, 75, FontSizeMessage, aBuf, -1.0f); } else { - TextRender()->Text(0x0, 10, 54, 6, aBuf, -1.0f); + TextRender()->Text(0, 10, 54, FontSizeMessage, aBuf, -1.0f); TextRender()->TextColor(1, 1, 1, 1); } } @@ -441,7 +452,7 @@ void CHud::RenderTeambalanceWarning() TextRender()->TextColor(1,1,0.5f,1); else TextRender()->TextColor(0.7f,0.7f,0.2f,1.0f); - TextRender()->Text(0x0, 5, 50, 6, pText, -1.0f); + TextRender()->Text(0, 5, 50, 6, pText, -1.0f); TextRender()->TextColor(1,1,1,1); } } diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index 9e6c2189..77b4a766 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -8,7 +8,10 @@ class CHud : public CComponent { float m_Width, m_Height; float m_AverageFPS; + + int64 m_WarmupHideTick; + bool IsLargeWarmupTimerShown(); int m_CheckpointDiff; int64 m_CheckpointTime; From e040cd70c9a2ac3fc8cb9dec802c9afcc136bb99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 15 Apr 2020 11:54:59 +0200 Subject: [PATCH 255/479] set address in active browser tab to connected address --- src/game/client/components/menus.cpp | 1 + src/game/client/components/menus.h | 3 ++- src/game/client/components/menus_browser.cpp | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 568a700c..af5fed68 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1512,6 +1512,7 @@ void CMenus::OnInit() Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this); Console()->Chain("br_sort", ConchainServerbrowserSortingUpdate, this); Console()->Chain("br_sort_order", ConchainServerbrowserSortingUpdate, this); + Console()->Chain("connect", ConchainConnect, this); Console()->Chain("add_friend", ConchainFriendlistUpdate, this); Console()->Chain("remove_friend", ConchainFriendlistUpdate, this); Console()->Chain("snd_enable", ConchainUpdateMusicState, this); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index d6398fad..229f6bdd 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -722,6 +722,7 @@ class CMenus : public CComponent void RenderFilterHeader(CUIRect View, int FilterIndex); int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected); void RenderServerbrowser(CUIRect MainView); + static void ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); 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); static void ConchainServerbrowserSortingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); @@ -750,7 +751,7 @@ class CMenus : public CComponent bool DoResolutionList(CUIRect* pRect, CListBox* pListBox, const sorted_array& lModes); - // found in menu_callback.cpp + // found in menus_callback.cpp float RenderSettingsControlsMouse(CUIRect View); float RenderSettingsControlsJoystick(CUIRect View); float RenderSettingsControlsMovement(CUIRect View); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 0522506a..851465e0 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2463,6 +2463,17 @@ void CMenus::ServerBrowserSortingOnUpdate() m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; } +void CMenus::ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + if(pResult->NumArguments() == 1) + { + CMenus *pMenus = (CMenus*)pUserData; + pMenus->SetServerBrowserAddress(pResult->GetString(0)); + pMenus->m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; + } + pfnCallback(pResult, pCallbackUserData); +} + void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { pfnCallback(pResult, pCallbackUserData); From 305a09d503d1047ee90cb8dc3052ec6b2da1f971 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 12:48:51 +0300 Subject: [PATCH 256/479] Handle completion and execution separately. Fix #2560 --- src/game/client/components/chat.cpp | 58 ++++++++++++++--------------- src/game/client/components/chat.h | 3 +- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 22bb97a8..95e306ce 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -258,7 +258,7 @@ bool CChat::OnInput(IInput::CEvent Event) else if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)) { bool AddEntry = false; - if(IsTypingCommand() && m_SelectedCommand >= 0 && ExecuteCommand(true)) + if(IsTypingCommand() && ExecuteCommand()) { AddEntry = true; } @@ -291,7 +291,7 @@ bool CChat::OnInput(IInput::CEvent Event) } if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_TAB) { - if(IsTypingCommand() && m_SelectedCommand >= 0 && ExecuteCommand(false)) + if(IsTypingCommand() && CompleteCommand()) { // everything is handled within } @@ -1358,11 +1358,7 @@ void CChat::HandleCommands(float x, float y, float w) NextActiveCommand(&m_CommandStart); } - if(!DisplayCount) - { - m_SelectedCommand = -1; - } - else + if(DisplayCount > 0) // at least one command to display { CUIRect Rect = {x, y-(DisplayCount+1)*LineHeight, LineWidth, (DisplayCount+1)*LineHeight}; RenderTools()->DrawUIRect(&Rect, vec4(0.125f, 0.125f, 0.125f, Alpha), CUI::CORNER_ALL, 3.0f); @@ -1506,34 +1502,36 @@ void CChat::HandleCommands(float x, float y, float w) } } -bool CChat::ExecuteCommand(bool Execute) +bool CChat::ExecuteCommand() +{ + const char *pCommandStr = m_Input.GetString(); + char aCommand[16]; + str_format(aCommand, sizeof(aCommand), "%.*s", str_span(pCommandStr + 1, " "), pCommandStr + 1); + const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(aCommand); + if(!pCommand) + return false; + + // execute command + return !m_CommandManager.OnCommand(pCommand->m_aName, str_skip_whitespaces_const(str_skip_to_whitespace_const(pCommandStr)), -1); +} + +bool CChat::CompleteCommand() { - if(!Execute && m_CommandManager.CommandCount() - m_FilteredCount == 0) + if(m_CommandManager.CommandCount() - m_FilteredCount == 0) return false; const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(m_SelectedCommand); - const char *pCommandStr = m_Input.GetString(); - bool IsFullMatch = str_find(pCommandStr + 1, pCommand->m_aName); // if the command text is fully inside pCommandStr (aka, not a shortcut) + if(!pCommand) + return false; - if(IsFullMatch && Execute) - { - // execute command - return !m_CommandManager.OnCommand(pCommand->m_aName, str_skip_whitespaces_const(str_skip_to_whitespace_const(pCommandStr)), -1); - } - else if(!IsFullMatch && !Execute) - { - // autocomplete command - char aBuf[128]; - str_copy(aBuf, "/", sizeof(aBuf)); - str_append(aBuf, pCommand->m_aName, sizeof(aBuf)); - str_append(aBuf, " ", sizeof(aBuf)); - - m_Input.Set(aBuf); - m_Input.SetCursorOffset(str_length(aBuf)); - m_InputUpdate = true; - return true; - } - return false; + // autocomplete command + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "/%s ", pCommand->m_aName); + + m_Input.Set(aBuf); + m_Input.SetCursorOffset(str_length(aBuf)); + m_InputUpdate = true; + return true; } // callback functions for commands diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 7c041126..29ba858b 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -95,7 +95,8 @@ class CChat : public CComponent CCommandManager m_CommandManager; bool IsTypingCommand() const; void HandleCommands(float x, float y, float w); - bool ExecuteCommand(bool Execute); + bool ExecuteCommand(); + bool CompleteCommand(); static void Com_All(IConsole::IResult *pResult, void *pContext); static void Com_Team(IConsole::IResult *pResult, void *pContext); From ddae137bf446bed31ea62d90b773beffbde60f6f Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 13:10:46 +0300 Subject: [PATCH 257/479] Reverted whisper as per #2525 --- src/game/client/components/chat.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 95e306ce..5dc97a0d 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -82,8 +82,8 @@ void CChat::OnReset() m_CommandManager.AddCommand("mute", "Mute a player", "s[name]", &Com_Mute, this); m_CommandManager.AddCommand("r", "Reply to a whisper", "?r[message]", &Com_Reply, this); m_CommandManager.AddCommand("team", "Switch to team chat", "?r[message]", &Com_Team, this); - m_CommandManager.AddCommand("w", "Whisper another player", "s[name] ?r[message]", &Com_Whisper, this); - m_CommandManager.AddCommand("whisper", "Whisper another player", "s[name] ?r[message]", &Com_Whisper, this); + m_CommandManager.AddCommand("w", "Whisper another player", "s[name]", &Com_Whisper, this); + m_CommandManager.AddCommand("whisper", "Whisper another player", "s[name]", &Com_Whisper, this); } void CChat::OnMapLoad() @@ -1605,13 +1605,7 @@ void CChat::Com_Whisper(IConsole::IResult *pResult, void *pContext) if(TargetID != -1) { pChatData->m_WhisperTarget = TargetID; - pChatData->m_ChatCmdBuffer[0] = 0; - if(pResult->NumArguments() > 1) - { - // save the parameter in a buffer before EnableMode clears it - str_copy(pChatData->m_ChatCmdBuffer, pResult->GetString(1), sizeof(pChatData->m_ChatCmdBuffer)); - } - pChatData->EnableMode(CHAT_WHISPER, pChatData->m_ChatCmdBuffer); + pChatData->EnableMode(CHAT_WHISPER); } } From 18cdc9a3a0f60ccfeede7a12892a79dc72126862 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 13:14:00 +0300 Subject: [PATCH 258/479] Scroll instantly if selected command is not in view --- src/game/client/components/chat.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 5dc97a0d..b2b1437a 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1371,11 +1371,12 @@ void CChat::HandleCommands(float x, float y, float w) for(int i = End - m_CommandManager.CommandCount(); i >= 0; i--) PreviousActiveCommand(&m_CommandStart); - if(m_SelectedCommand < m_CommandStart) + while(m_SelectedCommand < m_CommandStart) { PreviousActiveCommand(&m_CommandStart); } - else if(m_SelectedCommand > End) + + while(m_SelectedCommand > End) { NextActiveCommand(&m_CommandStart); NextActiveCommand(&End); From 0d413d89d815834047d0290136940832940f4949 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 15:00:06 +0300 Subject: [PATCH 259/479] Don't send commands, ever --- src/game/client/components/chat.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index b2b1437a..b405e48f 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -258,9 +258,10 @@ bool CChat::OnInput(IInput::CEvent Event) else if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)) { bool AddEntry = false; - if(IsTypingCommand() && ExecuteCommand()) + if(IsTypingCommand()) { - AddEntry = true; + if(ExecuteCommand()) + AddEntry = true; } else { From fd15e55351b6df30f9dc7b43e0d4a1fbde4c0cf7 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 15:46:59 +0300 Subject: [PATCH 260/479] Fix regression from 0.7.3 (always display command) --- src/game/client/components/chat.cpp | 7 +++++-- src/game/commands.h | 14 ++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index b405e48f..8fe9ffcf 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1331,7 +1331,7 @@ void CChat::Say(int Mode, const char *pLine) bool CChat::IsTypingCommand() const { - return m_Input.GetString()[0] == '/' && !m_IgnoreCommand; + return m_Input.GetString()[0] == '/' && !m_IgnoreCommand && m_CommandManager.CommandCount() - m_FilteredCount; } // chat commands handlers @@ -1666,7 +1666,10 @@ int CChat::FilterChatCommands(const char *pLine) { m_aFilter.set_size(m_CommandManager.CommandCount()); - m_FilteredCount = m_CommandManager.Filter(m_aFilter, pLine + 1); + char aCommand[16]; + str_format(aCommand, sizeof(aCommand), "%.*s", str_span(pLine + 1, " "), pLine + 1); + m_FilteredCount = m_CommandManager.Filter(m_aFilter, aCommand, str_find(pLine, " ") ? true : false); + return m_FilteredCount; } diff --git a/src/game/commands.h b/src/game/commands.h index 283f0a5b..7f2b9200 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -116,7 +116,7 @@ class CCommandManager m_aCommands.clear(); } - int CommandCount() + int CommandCount() const { return m_aCommands.size(); } @@ -140,7 +140,7 @@ class CCommandManager return m_pConsole->ParseCommandArgs(pArgs, pCom->m_aArgsFormat, pCom->m_pfnCallback, &Context); } - int Filter(array &aFilter, const char *pStr) + int Filter(array &aFilter, const char *pStr, bool Exact) { dbg_assert(aFilter.size() == m_aCommands.size(), "filter size must match command count"); if(!*pStr) @@ -151,9 +151,15 @@ class CCommandManager } int Filtered = 0; - for(int i = 0; i < m_aCommands.size(); i++) + if(Exact) + { + for(int i = 0; i < m_aCommands.size(); i++) + Filtered += (aFilter[i] = str_comp(m_aCommands[i].m_aName, pStr)); + } + else { - Filtered += (aFilter[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); + for(int i = 0; i < m_aCommands.size(); i++) + Filtered += (aFilter[i] = str_find_nocase(m_aCommands[i].m_aName, pStr) != m_aCommands[i].m_aName); } return Filtered; From a077b6c3b1555330de08f023f384d7d32e76d9a7 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 16:32:31 +0300 Subject: [PATCH 261/479] Always render the scrollbar handle. Fix #2563 --- src/game/client/components/menus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 568a700c..1c3399bb 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -857,7 +857,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) // layout CUIRect Handle; pRect->VSplitLeft(max(min(pRect->w/8.0f, 33.0f), pRect->h), &Handle, 0); - Handle.x += (pRect->w-Handle.w)*Current; + Handle.x += (pRect->w-Handle.w)*clamp(Current, 0.0f, 1.0f); Handle.HMargin(5.0f, &Handle); CUIRect Rail; From 820813ec5508d0de980a8cd3106eba711dddf596 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 16:45:57 +0300 Subject: [PATCH 262/479] Fix circular logic Hopefully the last issue here... --- src/game/client/components/chat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 8fe9ffcf..c19955ae 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -258,7 +258,7 @@ bool CChat::OnInput(IInput::CEvent Event) else if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)) { bool AddEntry = false; - if(IsTypingCommand()) + if(IsTypingCommand() && m_CommandManager.CommandCount() - m_FilteredCount) { if(ExecuteCommand()) AddEntry = true; @@ -1331,7 +1331,7 @@ void CChat::Say(int Mode, const char *pLine) bool CChat::IsTypingCommand() const { - return m_Input.GetString()[0] == '/' && !m_IgnoreCommand && m_CommandManager.CommandCount() - m_FilteredCount; + return m_Input.GetString()[0] == '/' && !m_IgnoreCommand; } // chat commands handlers From bf6c125891f9c44f3851088c5595c569b99d5faa Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 17:00:18 +0300 Subject: [PATCH 263/479] Only complete while in the command part of the message --- src/game/client/components/chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index c19955ae..2c3f67cf 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1523,7 +1523,7 @@ bool CChat::CompleteCommand() return false; const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(m_SelectedCommand); - if(!pCommand) + if(!pCommand || str_find(m_Input.GetString(), " ")) return false; // autocomplete command From cd32ed45428927414a70ee632c086cba582f9ba5 Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 15 Apr 2020 17:04:32 +0300 Subject: [PATCH 264/479] Only require double escape when the command menu is rendered --- src/game/client/components/chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 2c3f67cf..042f6741 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -245,7 +245,7 @@ bool CChat::OnInput(IInput::CEvent Event) if(Event.m_Flags&IInput::FLAG_PRESS && (Event.m_Key == KEY_ESCAPE || Event.m_Key == KEY_MOUSE_1 || Event.m_Key == KEY_MOUSE_2)) { - if(IsTypingCommand()) + if(IsTypingCommand() && m_CommandManager.CommandCount() - m_FilteredCount) { m_IgnoreCommand = true; } From 1b0e9abd41aaeb4ed8372f7fb6680984aaafa358 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 16 Apr 2020 20:02:22 +0200 Subject: [PATCH 265/479] changed default map download speed to 8. closes #2352 --- src/engine/shared/config_variables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 29996757..7a5211e5 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -85,7 +85,7 @@ MACRO_CONFIG_INT(SvExternalPort, sv_external_port, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG MACRO_CONFIG_STR(SvMap, sv_map, 128, "dm1", CFGFLAG_SAVE|CFGFLAG_SERVER, "Map to use on the server") MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, 8, 1, MAX_CLIENTS, CFGFLAG_SAVE|CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server") MACRO_CONFIG_INT(SvMaxClientsPerIP, sv_max_clients_per_ip, 4, 1, MAX_CLIENTS, CFGFLAG_SAVE|CFGFLAG_SERVER, "Maximum number of clients with the same IP that can connect to the server") -MACRO_CONFIG_INT(SvMapDownloadSpeed, sv_map_download_speed, 2, 1, 16, CFGFLAG_SAVE|CFGFLAG_SERVER, "Number of map data packages a client gets on each request") +MACRO_CONFIG_INT(SvMapDownloadSpeed, sv_map_download_speed, 8, 1, 16, CFGFLAG_SAVE|CFGFLAG_SERVER, "Number of map data packages a client gets on each request") MACRO_CONFIG_INT(SvHighBandwidth, sv_high_bandwidth, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVER, "Use high bandwidth mode. Doubles the bandwidth required for the server. LAN use only") MACRO_CONFIG_INT(SvRegister, sv_register, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVER, "Register server with master server for public listing") MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SAVE|CFGFLAG_SERVER, "Remote console password (full access)") From 8b51b46c5ab32afbd15c98596bffcaf2142fe68a Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 16 Apr 2020 20:09:17 +0200 Subject: [PATCH 266/479] updated map submodule (ctf5, dm7) --- datasrc/maps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datasrc/maps b/datasrc/maps index 7fefdb4c..1d3401a3 160000 --- a/datasrc/maps +++ b/datasrc/maps @@ -1 +1 @@ -Subproject commit 7fefdb4c643f4e623f179460b8e68cd51f4d5e9d +Subproject commit 1d3401a37a3334e311faf18a22aeff0e0ac9ee65 From 5e275d6a033f4282882bfa41ed2e3b5b49c38b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Apr 2020 21:06:56 +0200 Subject: [PATCH 267/479] add CFGFLAG_STORE to connect command --- src/engine/client/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index f5fc06f8..35fe1dd1 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2500,7 +2500,7 @@ void CClient::RegisterCommands() m_pConsole->Register("quit", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds"); m_pConsole->Register("exit", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds"); m_pConsole->Register("minimize", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Minimize, this, "Minimize Teeworlds"); - m_pConsole->Register("connect", "s[host|ip]", CFGFLAG_CLIENT, Con_Connect, this, "Connect to the specified host/ip"); + m_pConsole->Register("connect", "s[host|ip]", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Connect, this, "Connect to the specified host/ip"); m_pConsole->Register("disconnect", "", CFGFLAG_CLIENT, Con_Disconnect, this, "Disconnect from the server"); m_pConsole->Register("ping", "", CFGFLAG_CLIENT, Con_Ping, this, "Ping the current server"); m_pConsole->Register("screenshot", "", CFGFLAG_CLIENT, Con_Screenshot, this, "Take a screenshot"); From 91058c2aa93de033fb00cb2a3e595f6cf4075065 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Thu, 16 Apr 2020 21:58:33 +0200 Subject: [PATCH 268/479] Extend comment to include world deaths --- src/game/server/gamecontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 942d4b56..1f649b29 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -221,7 +221,7 @@ int IGameController::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int if(!pKiller || Weapon == WEAPON_GAME) return 0; if(pKiller == pVictim->GetPlayer()) - pVictim->GetPlayer()->m_Score--; // suicide + pVictim->GetPlayer()->m_Score--; // suicide or world else { if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam()) From a0ce7da9d5fe319e4a7f89e7987dfeda87131c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 17 Apr 2020 12:14:53 +0200 Subject: [PATCH 269/479] fix stored commands always using the original callback instead of the chain --- src/engine/shared/console.cpp | 5 ++--- src/engine/shared/console.h | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 07caaf84..35fde225 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -367,8 +367,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr) else if(m_StoreCommands && pCommand->m_Flags&CFGFLAG_STORE) { m_ExecutionQueue.AddEntry(); - m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback; - m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData; + m_ExecutionQueue.m_pLast->m_pCommand = pCommand; m_ExecutionQueue.m_pLast->m_Result = Result; } else @@ -1033,7 +1032,7 @@ void CConsole::StoreCommands(bool Store) if(!Store) { for(CExecutionQueue::CQueueEntry *pEntry = m_ExecutionQueue.m_pFirst; pEntry; pEntry = pEntry->m_pNext) - pEntry->m_pfnCommandCallback(&pEntry->m_Result, pEntry->m_pCommandUserData); + pEntry->m_pCommand->m_pfnCallback(&pEntry->m_Result, pEntry->m_pCommand->m_pUserData); m_ExecutionQueue.Reset(); } m_StoreCommands = Store; diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index 25671c25..f7be671c 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -140,8 +140,7 @@ class CConsole : public IConsole struct CQueueEntry { CQueueEntry *m_pNext; - FCommandCallback m_pfnCommandCallback; - void *m_pCommandUserData; + CCommand *m_pCommand; CResult m_Result; } *m_pFirst, *m_pLast; From 2b10007cc8f02fd2b5ffdaa05c20c9491d0e4535 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 17 Apr 2020 10:19:00 +0200 Subject: [PATCH 270/479] Add make_release.py to ci (closed #2545) --- .github/workflows/build.yaml | 5 +++++ scripts/make_release.py | 36 +++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ca51cb72..22a3d7ac 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -152,3 +152,8 @@ jobs: run: ./bam/bam conf=release all - name: Test release run: ./build/x86_64/release/teeworlds_srv shutdown + + - name: Create MacOS app using make_release.py + if: contains(matrix.os, 'macOS') + run: | + sudo python3 scripts/make_release.py 0.7.4 osx diff --git a/scripts/make_release.py b/scripts/make_release.py index 862584e6..59b13049 100644 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -85,7 +85,13 @@ def clean(): os.remove(src_package_languages) os.remove(src_package_maps) except: pass - + +def shell(cmd): + if os.system(cmd) != 0: + clean() + print("Non zero exit code on: os.system(%s)" % cmd) + sys.exit(1) + package = "%s-%s-%s" %(name, version, platform) package_dir = package @@ -154,7 +160,7 @@ def clean(): if os.path.isfile(fname): to_lipo.append(fname) if to_lipo: - os.system("lipo -create -output "+bin+" "+" ".join(to_lipo)) + shell("lipo -create -output "+bin+" "+" ".join(to_lipo)) # create Teeworlds appfolder clientbundle_content_dir = os.path.join(package_dir, "Teeworlds.app/Contents") @@ -173,12 +179,12 @@ def clean(): copy_tree(maps_dir, clientbundle_resource_dir+"/data/maps") shutil.copy("other/icons/Teeworlds.icns", clientbundle_resource_dir) shutil.copy(source_package_dir+name+exe_ext, clientbundle_bin_dir) - os.system("install_name_tool -change /usr/local/opt/freetype/lib/libfreetype.6.dylib @executable_path/../Frameworks/libfreetype.6.dylib " + binary_path) - os.system("install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/../Frameworks/libSDL2-2.0.0.dylib " + binary_path) - os.system("cp /usr/local/opt/freetype/lib/libfreetype.6.dylib " + clientbundle_framework_dir) - os.system("cp /usr/local/opt/libpng/lib/libpng16.16.dylib " + clientbundle_framework_dir) - os.system("cp /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib " + clientbundle_framework_dir) - os.system("install_name_tool -change /usr/local/opt/libpng/lib/libpng16.16.dylib @executable_path/../Frameworks/libpng16.16.dylib " + freetypelib_path) + shell("install_name_tool -change /usr/local/opt/freetype/lib/libfreetype.6.dylib @executable_path/../Frameworks/libfreetype.6.dylib " + binary_path) + shell("install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/../Frameworks/libSDL2-2.0.0.dylib " + binary_path) + shell("cp /usr/local/opt/freetype/lib/libfreetype.6.dylib " + clientbundle_framework_dir) + shell("cp /usr/local/opt/libpng/lib/libpng16.16.dylib " + clientbundle_framework_dir) + shell("cp /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib " + clientbundle_framework_dir) + shell("install_name_tool -change /usr/local/opt/libpng/lib/libpng16.16.dylib @executable_path/../Frameworks/libpng16.16.dylib " + freetypelib_path) open(os.path.join(clientbundle_content_dir, "Info.plist"), "w").write(""" @@ -256,18 +262,18 @@ def clean(): zf.write(n, n) #zf.printdir() zf.close() - + if use_gz: print("making tar.gz archive") - os.system("tar czf %s.tar.gz %s" % (package, package_dir)) + shell("tar czf %s.tar.gz %s" % (package, package_dir)) if use_dmg: print("making disk image") - os.system("rm -f %s.dmg %s_temp.dmg" % (package, package)) - os.system("hdiutil create -srcfolder %s -volname Teeworlds -quiet %s_temp" % (package_dir, package)) - os.system("hdiutil convert %s_temp.dmg -format UDBZ -o %s.dmg -quiet" % (package, package)) - os.system("rm -f %s_temp.dmg" % package) + shell("rm -f %s.dmg %s_temp.dmg" % (package, package)) + shell("hdiutil create -srcfolder %s -volname Teeworlds -quiet %s_temp" % (package_dir, package)) + shell("hdiutil convert %s_temp.dmg -format UDBZ -o %s.dmg -quiet" % (package, package)) + shell("rm -f %s_temp.dmg" % package) clean() - + print("done") From 39ee9bdefd7810ef8569509b5b705dff7166e871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Apr 2020 11:53:32 +0200 Subject: [PATCH 271/479] add TextColor and TextOutlineColor with vec4 argument --- src/engine/textrender.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/textrender.h b/src/engine/textrender.h index 3ce260c3..f0340491 100644 --- a/src/engine/textrender.h +++ b/src/engine/textrender.h @@ -52,6 +52,8 @@ class ITextRender : public IInterface // old foolish interface virtual void TextColor(float r, float g, float b, float a) = 0; virtual void TextOutlineColor(float r, float g, float b, float a) = 0; + inline void TextColor(const vec4 *pColor) { TextColor(pColor->r, pColor->g, pColor->b, pColor->a); } + inline void TextOutlineColor(const vec4 *pColor) { TextOutlineColor(pColor->r, pColor->g, pColor->b, pColor->a); } virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, float LineWidth, bool MultiLine=true) = 0; virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int StrLength, float LineWidth) = 0; virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) = 0; From ed327edca53da0ae8c893719c02489964dfc0463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Apr 2020 11:55:18 +0200 Subject: [PATCH 272/479] refactor usage of TextColor and TextOutlineColor in chat --- src/game/client/components/chat.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 042f6741..b01dae91 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1298,13 +1298,8 @@ void CChat::OnRender() if(pLine->m_Highlighted) { - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - - TextRender()->TextOutlineColor(ColorHighlightOutline.r, - ColorHighlightOutline.g, - ColorHighlightOutline.b, - ColorHighlightOutline.a); - + TextRender()->TextColor(&TextColor); + TextRender()->TextOutlineColor(&ColorHighlightOutline); TextRender()->TextEx(&Cursor, pLine->m_aText, -1); } else From bb8462c9800f0ac02815e0973cbace9eede707d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Apr 2020 16:31:16 +0200 Subject: [PATCH 273/479] pass color by const reference instead --- src/engine/textrender.h | 4 ++-- src/game/client/components/chat.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/textrender.h b/src/engine/textrender.h index f0340491..e0bfb15c 100644 --- a/src/engine/textrender.h +++ b/src/engine/textrender.h @@ -52,8 +52,8 @@ class ITextRender : public IInterface // old foolish interface virtual void TextColor(float r, float g, float b, float a) = 0; virtual void TextOutlineColor(float r, float g, float b, float a) = 0; - inline void TextColor(const vec4 *pColor) { TextColor(pColor->r, pColor->g, pColor->b, pColor->a); } - inline void TextOutlineColor(const vec4 *pColor) { TextOutlineColor(pColor->r, pColor->g, pColor->b, pColor->a); } + inline void TextColor(const vec4 &Color) { TextColor(Color.r, Color.g, Color.b, Color.a); } + inline void TextOutlineColor(const vec4 &Color) { TextOutlineColor(Color.r, Color.g, Color.b, Color.a); } virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, float LineWidth, bool MultiLine=true) = 0; virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int StrLength, float LineWidth) = 0; virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) = 0; diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index b01dae91..9b4a0ee0 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1298,8 +1298,8 @@ void CChat::OnRender() if(pLine->m_Highlighted) { - TextRender()->TextColor(&TextColor); - TextRender()->TextOutlineColor(&ColorHighlightOutline); + TextRender()->TextColor(TextColor); + TextRender()->TextOutlineColor(ColorHighlightOutline); TextRender()->TextEx(&Cursor, pLine->m_aText, -1); } else From f60a6937f4b8d1f4daa086283152861ba71a0672 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 19 Apr 2020 10:11:42 +0200 Subject: [PATCH 274/479] fixed setting the server address on the correct page when using an initial connect command --- src/game/client/components/menus.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 9542978d..2b2d516d 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1519,6 +1519,8 @@ void CMenus::OnInit() Console()->Chain("snd_enable_music", ConchainUpdateMusicState, this); RenderLoading(1); + + ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); } void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton, int Next) @@ -1554,7 +1556,6 @@ int CMenus::Render() // else the increased rendering time at startup prevents // the network from being pumped effectively. ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET|IServerBrowser::REFRESHFLAG_LAN); - ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); } } From 236d99341ef96a65854ba341b2c2b779647c0b00 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 19 Apr 2020 11:25:37 +0200 Subject: [PATCH 275/479] Add cl_showchat to toggle chat rendering --- src/game/client/components/chat.cpp | 2 ++ src/game/variables.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 9b4a0ee0..2f709209 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -745,6 +745,8 @@ void CChat::OnRender() { if(Client()->State() < IClient::STATE_ONLINE) return; + if(!Config()->m_ClShowChat) + return; // send pending chat messages if(m_PendingChatCounter > 0 && m_LastChatSend+time_freq() < time_get()) diff --git a/src/game/variables.h b/src/game/variables.h index 85305699..2becd0d4 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(ClShowChat, cl_showchat, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show chat") MACRO_CONFIG_INT(ClFilterchat, cl_filterchat, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show chat messages from: 0=all, 1=friends only, 2=no one") MACRO_CONFIG_INT(ClDisableWhisper, cl_disable_whisper, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable completely the whisper feature.") MACRO_CONFIG_INT(ClShowsocial, cl_showsocial, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show social data like names, clans, chat etc.") From a7bd5306d063d16e14619ec817ad954f83656041 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 19 Apr 2020 14:56:44 +0200 Subject: [PATCH 276/479] fixed broken background. closes #2552 --- src/engine/client/client.cpp | 2 -- src/game/client/components/menus.cpp | 9 ++++-- src/game/client/components/menus.h | 1 + src/game/client/gameclient.cpp | 47 ++++++++++++++++++++++++---- src/game/client/gameclient.h | 2 ++ 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 35fe1dd1..c53154d1 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -778,8 +778,6 @@ void CClient::Render() } else { - if(Config()->m_GfxClear) - Graphics()->Clear(1,1,0); GameClient()->OnRender(); } DebugRender(); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 2b2d516d..6aaf254b 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1279,7 +1279,7 @@ void CMenus::RenderLoading(int WorkedAmount) s_LastLoadRender = Now; static int64 s_LoadingStart = Now; - Graphics()->Clear(0.45f, 0.45f, 0.45f); + m_pClient->StartRendering(); RenderBackground((Now-s_LoadingStart)/Freq); CUIRect Screen = *UI()->Screen(); @@ -1560,7 +1560,7 @@ int CMenus::Render() } // render background only if needed - if(Client()->State() != IClient::STATE_ONLINE && !m_pClient->m_pMapLayersBackGround->MenuMapLoaded()) + if(IsBackgroundNeeded()) RenderBackground(Client()->LocalTime()); CUIRect TabBar, MainView; @@ -2534,6 +2534,11 @@ bool CMenus::CheckHotKey(int Key) const Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); } +bool CMenus::IsBackgroundNeeded() const +{ + return !m_pClient->m_InitComplete || (Client()->State() != IClient::STATE_ONLINE && !m_pClient->m_pMapLayersBackGround->MenuMapLoaded()); +} + void CMenus::RenderBackground(float Time) { float sw = 300*Graphics()->ScreenAspect(); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 229f6bdd..1dbfb919 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -782,6 +782,7 @@ class CMenus : public CComponent public: void InitLoading(int TotalWorkAmount); void RenderLoading(int WorkedAmount = 0); + bool IsBackgroundNeeded() const; struct CSwitchTeamInfo { diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 8c35eb1f..cc4676fb 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -205,6 +205,7 @@ static CGameMsg gs_GameMsgList[NUM_GAMEMSGS] = { void CGameClient::OnConsoleInit() { + m_InitComplete = false; m_pEngine = Kernel()->RequestInterface(); m_pClient = Kernel()->RequestInterface(); m_pTextRender = Kernel()->RequestInterface(); @@ -393,18 +394,19 @@ void CGameClient::OnInit() m_pEditor->Init(); m_pMenus->RenderLoading(2); - OnReset(); - - int64 End = time_get(); - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End-Start)*1000)/(float)time_freq()); - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); + OnReset(); m_ServerMode = SERVERMODE_PURE; m_IsXmasDay = time_isxmasday(); m_IsEasterDay = time_iseasterday(); m_pMenus->RenderLoading(); + m_InitComplete = true; + + int64 End = time_get(); + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End - Start) * 1000) / (float)time_freq()); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); } void CGameClient::OnUpdate() @@ -550,11 +552,44 @@ void CGameClient::EvolveCharacter(CNetObj_Character *pCharacter, int Tick) TempCore.Write(pCharacter); } +void CGameClient::StartRendering() +{ + if(Config()->m_GfxClear) + { + if(m_pMenus->IsBackgroundNeeded()) + Graphics()->Clear(0.45f, 0.45f, 0.45f); + else + Graphics()->Clear(1.0f, 1.0f, 0.0f); + } + else if(m_pMenus->IsBackgroundNeeded()) + { + // render background color + float sw = 300 * Graphics()->ScreenAspect(); + float sh = 300; + Graphics()->MapScreen(0, 0, sw, sh); + Graphics()->TextureClear(); + Graphics()->QuadsBegin(); + vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); + vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), + IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a) }; + Graphics()->SetColorVertex(Array, 4); + IGraphics::CQuadItem QuadItem(0, 0, sw, sh); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } +} + void CGameClient::OnRender() { // update the local character and spectate position UpdatePositions(); + StartRendering(); + // render all systems for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnRender(); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 4b60d0e1..74db48a3 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -212,6 +212,7 @@ class CGameClient : public IGameClient bool m_IsXmasDay; float m_LastSkinChangeTime; bool m_IsEasterDay; + bool m_InitComplete; struct CGameInfo { @@ -270,6 +271,7 @@ class CGameClient : public IGameClient void GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName); bool IsXmas() const; bool IsEaster() const; + void StartRendering(); int RacePrecision() const { return m_Snap.m_pGameDataRace ? m_Snap.m_pGameDataRace->m_Precision : 3; } From 79ab3c5e183b3c93ba03985f298c0f7c19b8eef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 21:30:57 +0100 Subject: [PATCH 277/479] remove hardcoded 3 second timer which restarts before the warmup is up --- src/game/server/gamecontroller.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 1f649b29..917841dc 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -789,8 +789,6 @@ void IGameController::Tick() // check if player ready mode was disabled and it waits that all players are ready -> end warmup if(!Config()->m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE) SetGameState(IGS_WARMUP_USER, 0); - else if(m_GameStateTimer == 3 * Server()->TickSpeed()) - StartMatch(); break; case IGS_START_COUNTDOWN: case IGS_GAME_PAUSED: From 0b90c80cb12e240c229d4574241480bdd32f4b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 4 Feb 2020 12:24:54 +0100 Subject: [PATCH 278/479] fix world not being unpaused after warmup/restart cancels pause --- src/game/server/gamecontroller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 917841dc..292eb9ce 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -540,6 +540,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) if(GameServer()->m_apPlayers[i]) GameServer()->m_apPlayers[i]->m_RespawnDisabled = false; } + GameServer()->m_World.m_Paused = false; } else { From c66563dc75007d5215525be5ad3c5b65a79735b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 16 Jan 2020 22:14:00 +0100 Subject: [PATCH 279/479] fix restart timer and pause not working when alone (closes #2154), allow restarting paused game (closes #1809) --- src/game/server/gamecontroller.cpp | 10 +++++----- src/game/server/gamecontroller.h | 5 +---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 292eb9ce..998c70fb 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -510,8 +510,8 @@ void IGameController::SetGameState(EGameState GameState, int Timer) } break; case IGS_WARMUP_USER: - // user based warmup is only possible when the game or a user based warmup is running - if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_WARMUP_USER) + // user based warmup is only possible when the game or any warmup is running + if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER) { if(Timer != 0) { @@ -583,8 +583,8 @@ void IGameController::SetGameState(EGameState GameState, int Timer) } break; case IGS_GAME_PAUSED: - // only possible when game is running or paused - if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED) + // only possible when game is running or paused, or when game based warmup is running + if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_WARMUP_GAME) { if(Timer != 0) { @@ -597,7 +597,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) } else { - // pauses for a specific time intervall + // pauses for a specific time interval m_GameStateTimer = Timer*Server()->TickSpeed(); } diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 2a1db743..ca467b30 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -183,10 +183,7 @@ class IGameController void DoPause(int Seconds) { SetGameState(IGS_GAME_PAUSED, Seconds); } void DoWarmup(int Seconds) { - if(m_GameState==IGS_WARMUP_GAME) - SetGameState(IGS_WARMUP_GAME, 0); - else - SetGameState(IGS_WARMUP_USER, Seconds); + SetGameState(IGS_WARMUP_USER, Seconds); } void SwapTeamscore(); From 0199227ca1833eb1bb2e68d49f6ff1811c3ce22a Mon Sep 17 00:00:00 2001 From: Learath Date: Sun, 19 Apr 2020 19:50:43 +0300 Subject: [PATCH 280/479] Don't add commands with malformed arglists. Fix #2573 --- src/engine/console.h | 1 + src/engine/shared/console.cpp | 59 ++++++++++++++++++++++------- src/engine/shared/console.h | 7 ++-- src/game/client/components/chat.cpp | 3 ++ src/game/commands.h | 3 ++ 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/engine/console.h b/src/engine/console.h index de5de45f..9d34864c 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -83,6 +83,7 @@ class IConsole : public IInterface virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0; virtual void StoreCommands(bool Store) = 0; + virtual bool ArgStringIsValid(const char *pFormat) = 0; virtual bool LineIsValid(const char *pStr) = 0; virtual void ExecuteLine(const char *pStr) = 0; virtual void ExecuteLineFlag(const char *pStr, int FlagMask) = 0; diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 35fde225..80d7f018 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -86,6 +86,41 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length) return 0; } +bool CConsole::ArgStringIsValid(const char *pFormat) +{ + char Command = *pFormat; + bool Valid = true; + bool Last = false; + + while(Valid) + { + if(!Command) + break; + + if(Last && *pFormat) + return false; + + if(Command == '?') + { + if(!pFormat[1]) + return false; + } + else + { + if(Command == 'i' || Command == 'f' || Command == 's') + ; + else if(Command == 'r') + Last = true; + else + return false; + } + + Valid = !NextParam(&Command, pFormat); + } + + return Valid; +} + int CConsole::ParseArgs(CResult *pResult, const char *pFormat) { char Command = *pFormat; @@ -95,7 +130,7 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) pStr = pResult->m_pArgsStart; - while(1) + while(!Error) { if(!Command) break; @@ -173,13 +208,13 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) } // fetch next command - Command = NextParam(pFormat); + Error = NextParam(&Command, pFormat); } return Error; } -char CConsole::NextParam(const char *&pFormat) +bool CConsole::NextParam(char *pNext, const char *&pFormat) { if(*pFormat) { @@ -188,21 +223,19 @@ char CConsole::NextParam(const char *&pFormat) if(*pFormat == '[') { // skip bracket contents - for(; *pFormat != ']'; pFormat++) - { - if (!*pFormat) - return *pFormat; - } + pFormat += str_span(pFormat, "]"); + if(!*pFormat) + return true; // skip ']' pFormat++; - - // skip space if there is one - if (*pFormat == ' ') - pFormat++; } + + // skip space if there is one + pFormat = str_skip_whitespaces_const(pFormat); } - return *pFormat; + *pNext = *pFormat; + return false; } int CConsole::ParseCommandArgs(const char *pArgs, const char *pFormat, FCommandCallback pfnCallback, void *pContext) diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index f7be671c..c5c121d6 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -125,12 +125,12 @@ class CConsole : public IConsole /* This function will set pFormat to the next parameter (i,s,r,v,?) it contains and - return the parameter. + pNext to the command. Descriptions in brackets like [file] will be skipped. - Returns '\0' if there is no next parameter. + Returns true on failure. Expects pFormat to point at a parameter. */ - char NextParam(const char *&pFormat); + bool NextParam(char *pNext, const char *&pFormat); class CExecutionQueue { @@ -196,6 +196,7 @@ class CConsole : public IConsole virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser); virtual void StoreCommands(bool Store); + virtual bool ArgStringIsValid(const char *pFormat); virtual bool LineIsValid(const char *pStr); virtual void ExecuteLine(const char *pStr); virtual void ExecuteLineFlag(const char *pStr, int FlagMask); diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 9b4a0ee0..1a73d9f9 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -548,6 +548,9 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) CNetMsg_Sv_CommandInfo *pMsg = (CNetMsg_Sv_CommandInfo *)pRawMsg; if(!m_CommandManager.AddCommand(pMsg->m_Name, pMsg->m_HelpText, pMsg->m_ArgsFormat, ServerCommandCallback, this)) dbg_msg("chat_commands", "adding server chat command: name='%s' args='%s' help='%s'", pMsg->m_Name, pMsg->m_ArgsFormat, pMsg->m_HelpText); + else + dbg_msg("chat-commands", "failed to add command '%s'", pMsg->m_Name); + } else if(MsgType == NETMSGTYPE_SV_COMMANDINFOREMOVE) { diff --git a/src/game/commands.h b/src/game/commands.h index 7f2b9200..6c1f5f38 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -87,6 +87,9 @@ class CCommandManager if(pCom) return 1; + if(!m_pConsole->ArgStringIsValid(pArgsFormat)) + return 1; + int Index = m_aCommands.add(CCommand(pCommand, pHelpText, pArgsFormat, pfnCallback, pContext)); if(m_pfnNewCommandHook) m_pfnNewCommandHook(&m_aCommands[Index], m_pHookContext); From 903ec7a7914e71c940f8c07fe50947c2f9edf2b5 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 19 Apr 2020 20:07:14 +0200 Subject: [PATCH 281/479] Turn off chat sounds when chat is not rendered --- src/game/client/components/chat.cpp | 37 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 2f709209..88b48c90 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -703,29 +703,32 @@ void CChat::AddLine(const char *pLine, int ClientID, int Mode, int TargetID) m_LastWhisperFrom = ClientID; // we received a a whisper // play sound - int64 Now = time_get(); - if(ClientID < 0) + if(Config()->m_ClShowChat) { - if(Now-m_aLastSoundPlayed[CHAT_SERVER] >= time_freq()*3/10) + int64 Now = time_get(); + if(ClientID < 0) { - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); - m_aLastSoundPlayed[CHAT_SERVER] = Now; + 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 || Mode == CHAT_WHISPER) - { - if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) + else if(Highlighted || Mode == CHAT_WHISPER) { - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); - m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; + 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 - { - if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10) + else { - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); - m_aLastSoundPlayed[CHAT_CLIENT] = Now; + 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; + } } } } From 4fc25a17fef3e6c2bf4d52b0421e0d69ecaa1e79 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 19 Apr 2020 22:23:41 +0200 Subject: [PATCH 282/479] made 0.7.5 release --- datasrc/languages | 2 +- scripts/cmd5.py | 2 +- src/game/version.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/datasrc/languages b/datasrc/languages index 4ba6f824..4ed69dd7 160000 --- a/datasrc/languages +++ b/datasrc/languages @@ -1 +1 @@ -Subproject commit 4ba6f824e9c34565e61340d25bc8c3cc004d40fb +Subproject commit 4ed69dd7497ca6e04bab0b042f137bf97f3c5d0a diff --git a/scripts/cmd5.py b/scripts/cmd5.py index f419a0df..07ee484b 100644 --- a/scripts/cmd5.py +++ b/scripts/cmd5.py @@ -30,6 +30,6 @@ def cstrip(lines): hash = hashlib.md5(f).hexdigest().lower()[16:] #TODO 0.8: improve nethash creation -if hash == "7d93423b228c5fb8": +if hash == "cb14bf6dc197d153": hash = "802f1be60a05665f" print('#define GAME_NETVERSION_HASH "%s"' % hash) diff --git a/src/game/version.h b/src/game/version.h index 0eddd703..5070174e 100644 --- a/src/game/version.h +++ b/src/game/version.h @@ -3,10 +3,10 @@ #ifndef GAME_VERSION_H #define GAME_VERSION_H #include -#define GAME_VERSION "0.7.4" +#define GAME_VERSION "0.7.5" #define GAME_NETVERSION_HASH_FORCED "802f1be60a05665f" #define GAME_NETVERSION "0.7 " GAME_NETVERSION_HASH_FORCED -#define CLIENT_VERSION 0x0704 +#define CLIENT_VERSION 0x0705 #define SETTINGS_FILENAME "settings07" -static const char GAME_RELEASE_VERSION[8] = "0.7.4"; +static const char GAME_RELEASE_VERSION[8] = "0.7.5"; #endif From c394607eceb1527032dfe70a1462aee53fadb680 Mon Sep 17 00:00:00 2001 From: Learath Date: Mon, 20 Apr 2020 14:02:55 +0300 Subject: [PATCH 283/479] Use r not s for whisper --- src/game/client/components/chat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 1a73d9f9..a90aafdb 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -82,8 +82,8 @@ void CChat::OnReset() m_CommandManager.AddCommand("mute", "Mute a player", "s[name]", &Com_Mute, this); m_CommandManager.AddCommand("r", "Reply to a whisper", "?r[message]", &Com_Reply, this); m_CommandManager.AddCommand("team", "Switch to team chat", "?r[message]", &Com_Team, this); - m_CommandManager.AddCommand("w", "Whisper another player", "s[name]", &Com_Whisper, this); - m_CommandManager.AddCommand("whisper", "Whisper another player", "s[name]", &Com_Whisper, this); + m_CommandManager.AddCommand("w", "Whisper another player", "r[name]", &Com_Whisper, this); + m_CommandManager.AddCommand("whisper", "Whisper another player", "r[name]", &Com_Whisper, this); } void CChat::OnMapLoad() From 630a44fa273213ae24ea8b36bfed1b3977b041c5 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Mon, 20 Apr 2020 21:12:11 +0200 Subject: [PATCH 284/479] Print game version in addition to netversion --- src/engine/client/client.cpp | 4 +++- src/engine/server/server.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index c53154d1..6c37515f 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1980,12 +1980,14 @@ void CClient::Run() GameClient()->OnInit(); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion()); + str_format(aBuf, sizeof(aBuf), "netversion %s", GameClient()->NetVersion()); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); if(str_comp(GameClient()->NetVersionHashUsed(), GameClient()->NetVersionHashReal())) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", "WARNING: netversion hash differs"); } + str_format(aBuf, sizeof(aBuf), "game version %s", GameClient()->Version()); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); // m_FpsGraph.Init(0.0f, 120.0f); diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index f01f7cc6..b2a9a965 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1354,12 +1354,14 @@ int CServer::Run() Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); GameServer()->OnInit(); - str_format(aBuf, sizeof(aBuf), "version %s", GameServer()->NetVersion()); + str_format(aBuf, sizeof(aBuf), "netversion %s", GameServer()->NetVersion()); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); if(str_comp(GameServer()->NetVersionHashUsed(), GameServer()->NetVersionHashReal())) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "WARNING: netversion hash differs"); } + str_format(aBuf, sizeof(aBuf), "game version %s", GameServer()->Version()); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); // process pending commands m_pConsole->StoreCommands(false); From d62d6e577dcfca5b32ba5e0638d5d8140eadf38d Mon Sep 17 00:00:00 2001 From: Learath Date: Tue, 21 Apr 2020 02:55:51 +0300 Subject: [PATCH 285/479] Chat history improvements. Fix #2588 --- src/game/client/components/chat.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index a90aafdb..f7b7660e 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -251,6 +251,7 @@ bool CChat::OnInput(IInput::CEvent Event) } else { + m_pHistoryEntry = 0x0; m_Mode = CHAT_NONE; m_pClient->OnRelease(); } @@ -427,7 +428,7 @@ bool CChat::OnInput(IInput::CEvent Event) if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_UP) { - if(IsTypingCommand()) + if(IsTypingCommand() && !m_pHistoryEntry) { PreviousActiveCommand(&m_SelectedCommand); if(m_SelectedCommand < 0) @@ -451,7 +452,7 @@ bool CChat::OnInput(IInput::CEvent Event) } else if (Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_DOWN) { - if(IsTypingCommand()) + if(IsTypingCommand() && !m_pHistoryEntry) { NextActiveCommand(&m_SelectedCommand); if(m_SelectedCommand >= m_CommandManager.CommandCount()) @@ -530,6 +531,7 @@ void CChat::ServerCommandCallback(IConsole::IResult *pResult, void *pContext) Msg.m_Arguments = pComContext->m_pArgs; pChatData->Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + pChatData->m_pHistoryEntry = 0x0; pChatData->m_Mode = CHAT_NONE; pChatData->m_pClient->OnRelease(); } From 097be1620dd92146dd61e9762cfd31c8551ba4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 22 Apr 2020 19:25:26 +0200 Subject: [PATCH 286/479] reset server details scroll, remove highlight outline, refactoring --- src/game/client/components/menus.h | 7 +- src/game/client/components/menus_browser.cpp | 311 +++++++++---------- 2 files changed, 160 insertions(+), 158 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 1dbfb919..0ef56360 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -614,7 +614,7 @@ class CMenus : public CComponent enum { - COL_BROWSER_FLAG=0, + COL_BROWSER_FLAG = 0, COL_BROWSER_NAME, COL_BROWSER_GAMETYPE, COL_BROWSER_MAP, @@ -622,6 +622,11 @@ class CMenus : public CComponent COL_BROWSER_PING, NUM_BROWSER_COLS, + SIDEBAR_TAB_INFO = 0, + SIDEBAR_TAB_FILTER, + SIDEBAR_TAB_FRIEND, + NUM_SIDEBAR_TABS, + ADDR_SELECTION_CHANGE = 1, ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND = 2, ADDR_SELECTION_REVEAL = 4, diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 851465e0..d2954d2a 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -169,7 +169,7 @@ void CMenus::LoadFilters() if(rSettingsEntry["sidebar_active"].type == json_integer) m_SidebarActive = rSettingsEntry["sidebar_active"].u.integer; if(rSettingsEntry["sidebar_tab"].type == json_integer) - m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), 0, 2); + m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), int(SIDEBAR_TAB_INFO), int(SIDEBAR_TAB_FRIEND)); if(rSettingsEntry["filters"].type == json_array) { for(unsigned i = 0; i < IServerBrowser::NUM_TYPES; ++i) @@ -511,7 +511,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); + TextRender()->TextOutlineColor(TextBaseOutlineColor); if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { @@ -523,7 +523,6 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else @@ -556,7 +555,6 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); } else @@ -568,7 +566,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn else if(ID == COL_BROWSER_PLAYERS) { TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); + TextRender()->TextOutlineColor(TextBaseOutlineColor); CServerFilterInfo FilterInfo; pFilter->GetFilter(&FilterInfo); @@ -644,8 +642,8 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } str_format(aTemp, sizeof(aTemp), "%d", pEntry->m_Latency); - TextRender()->TextColor(Color.r, Color.g, Color.b, Color.a); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); + TextRender()->TextColor(Color); + TextRender()->TextOutlineColor(TextBaseOutlineColor); Button.y += 2.0f; Button.w -= 4.0f; UI()->DoLabel(&Button, aTemp, 12.0f, CUI::ALIGN_RIGHT); @@ -682,7 +680,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn else { TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor.r, TextBaseOutlineColor.g, TextBaseOutlineColor.b, TextBaseOutlineColor.a); + TextRender()->TextOutlineColor(TextBaseOutlineColor); TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); } } @@ -1332,7 +1330,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_aSelectedServers[BrowserType] = ServerIndex; m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); if(Config()->m_UiAutoswitchInfotab) - m_SidebarTab = 0; + m_SidebarTab = SIDEBAR_TAB_INFO; UpdateServerBrowserAddress(); // update now instead of using flag because of connect if(Input()->MouseDoubleClick()) Client()->Connect(GetServerBrowserAddress()); @@ -1482,10 +1480,10 @@ void CMenus::RenderServerbrowserSidebar(CUIRect View) if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT)) { m_SidebarTab--; - if(m_SidebarTab < 0) m_SidebarTab = 2; + if(m_SidebarTab < SIDEBAR_TAB_INFO) m_SidebarTab = NUM_SIDEBAR_TABS-1; } else - m_SidebarTab = (m_SidebarTab+1)%3; + m_SidebarTab = (m_SidebarTab+1)%NUM_SIDEBAR_TABS; } // header @@ -1493,32 +1491,32 @@ void CMenus::RenderServerbrowserSidebar(CUIRect View) float Width = Header.w; Header.VSplitLeft(Width*0.30f, &Button, &Header); static CButtonContainer s_TabInfo; - if(DoButton_SpriteID(&s_TabInfo, IMAGE_SIDEBARICONS, m_SidebarTab!=0?SPRITE_SIDEBAR_INFO_A: SPRITE_SIDEBAR_INFO_B, m_SidebarTab==0 , &Button, CUI::CORNER_TL, 5.0f, true)) + if(DoButton_SpriteID(&s_TabInfo, IMAGE_SIDEBARICONS, m_SidebarTab != SIDEBAR_TAB_INFO ? SPRITE_SIDEBAR_INFO_A : SPRITE_SIDEBAR_INFO_B, m_SidebarTab == SIDEBAR_TAB_INFO, &Button, CUI::CORNER_TL, 5.0f, true)) { - m_SidebarTab = 0; + m_SidebarTab = SIDEBAR_TAB_INFO; } Header.VSplitLeft(Width*0.30f, &Button, &Header); static CButtonContainer s_TabFilter; - if(DoButton_SpriteID(&s_TabFilter, IMAGE_SIDEBARICONS, m_SidebarTab!=1?SPRITE_SIDEBAR_FILTER_A: SPRITE_SIDEBAR_FILTER_B, m_SidebarTab==1, &Button, 0, 0.0f, true)) + if(DoButton_SpriteID(&s_TabFilter, IMAGE_SIDEBARICONS, m_SidebarTab != SIDEBAR_TAB_FILTER ? SPRITE_SIDEBAR_FILTER_A : SPRITE_SIDEBAR_FILTER_B, m_SidebarTab == SIDEBAR_TAB_FILTER, &Button, 0, 0.0f, true)) { - m_SidebarTab = 1; + m_SidebarTab = SIDEBAR_TAB_FILTER; } static CButtonContainer s_TabFriends; - if(DoButton_SpriteID(&s_TabFriends, IMAGE_SIDEBARICONS, m_SidebarTab!=2?SPRITE_SIDEBAR_FRIEND_A:SPRITE_SIDEBAR_FRIEND_B, m_SidebarTab == 2, &Header, CUI::CORNER_TR, 5.0f, true)) + if(DoButton_SpriteID(&s_TabFriends, IMAGE_SIDEBARICONS, m_SidebarTab != SIDEBAR_TAB_FRIEND ? SPRITE_SIDEBAR_FRIEND_A : SPRITE_SIDEBAR_FRIEND_B, m_SidebarTab == SIDEBAR_TAB_FRIEND, &Header, CUI::CORNER_TR, 5.0f, true)) { - m_SidebarTab = 2; + m_SidebarTab = SIDEBAR_TAB_FRIEND; } // tabs switch(m_SidebarTab) { - case 0: + case SIDEBAR_TAB_INFO: RenderServerbrowserInfoTab(View); break; - case 1: + case SIDEBAR_TAB_FILTER: RenderServerbrowserFilterTab(View); break; - case 2: + case SIDEBAR_TAB_FRIEND: RenderServerbrowserFriendTab(View); } } @@ -2049,10 +2047,14 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) "Game type:", "Version:", "Difficulty:" }; - static CLocConstString s_aDifficulty[] = { + static CLocConstString s_aDifficultyLabels[] = { "Casual", "Normal", "Competitive" }; + static int s_aDifficultySpriteIds[] = { + SPRITE_LEVEL_A_ON, + SPRITE_LEVEL_B_ON, + SPRITE_LEVEL_C_ON }; CUIRect LeftColumn, RightColumn; View.VMargin(2.0f, &View); @@ -2084,18 +2086,8 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) RightColumn.HSplitTop(15.0f, &Row, &RightColumn); Row.VSplitLeft(Row.h, &Icon, &Row); Icon.y -= 2.0f; - switch(pInfo->m_ServerLevel) - { - case 0: - DoIcon(IMAGE_LEVELICONS, SPRITE_LEVEL_A_ON, &Icon); - break; - case 1: - DoIcon(IMAGE_LEVELICONS, SPRITE_LEVEL_B_ON, &Icon); - break; - case 2: - DoIcon(IMAGE_LEVELICONS, SPRITE_LEVEL_C_ON, &Icon); - } - UI()->DoLabel(&Row, s_aDifficulty[pInfo->m_ServerLevel], FontSize, CUI::ALIGN_LEFT, Row.w, false); + DoIcon(IMAGE_LEVELICONS, s_aDifficultySpriteIds[pInfo->m_ServerLevel], &Icon); + UI()->DoLabel(&Row, s_aDifficultyLabels[pInfo->m_ServerLevel], FontSize, CUI::ALIGN_LEFT, Row.w, false); } } @@ -2106,165 +2098,171 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int if(pFilter) pFilter->GetFilter(&FilterInfo); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); + TextRender()->TextColor(TextColor); + TextRender()->TextOutlineColor(TextOutlineColor); // server scoreboard CTextCursor Cursor; - const float FontSize = 10.0f; + const float FontSize = 8.0f; int ActColumn = 0; RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); View.Margin(2.0f, &View); - if(pInfo) - { - int Count = 0; + if(!pInfo) + return; + static const CServerInfo *s_pLastInfo = pInfo; + bool ResetScroll = s_pLastInfo != pInfo; + s_pLastInfo = pInfo; - CUIRect Scroll; + CUIRect Scroll; - float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); - float LineHeight = 20.0f; - - static CScrollRegion s_ScrollRegion; - vec2 ScrollOffset(0, 0); - CScrollRegionParams ScrollParams; - ScrollParams.m_ClipBgColor = vec4(0,0,0,0); - ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); - ScrollParams.m_ScrollbarWidth = 5; - ScrollParams.m_ScrollbarMargin = 1; - ScrollParams.m_ScrollSpeed = 15; - s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); - View.y += ScrollOffset.y; - if(RowCount != 0) + float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); + float LineHeight = 20.0f; + + static CScrollRegion s_ScrollRegion; + vec2 ScrollOffset(0, 0); + CScrollRegionParams ScrollParams; + ScrollParams.m_ClipBgColor = vec4(0,0,0,0); + ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); + ScrollParams.m_ScrollbarWidth = 5; + ScrollParams.m_ScrollbarMargin = 1; + ScrollParams.m_ScrollSpeed = 15; + s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); + View.y += ScrollOffset.y; + if(RowCount != 0) + { + const float Width = RowWidth * ((pInfo->m_NumClients+RowCount-1) / RowCount); + static float s_ScrollValue = 0.0f; + if(ResetScroll) { - float Width = RowWidth * ((pInfo->m_NumClients+RowCount-1) / RowCount); - static float s_ScrollValue = 0.0f; - if(Width > View.w) - { - View.HSplitBottom(14.0f, &View, &Scroll); - Scroll.VMargin(5.0f, &Scroll); - s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); - View.x += (View.w - Width) * s_ScrollValue; - LineHeight = 0.25f*View.h; - } + s_ScrollValue = 0.0f; } + if(Width > View.w) + { + View.HSplitBottom(14.0f, &View, &Scroll); + Scroll.VMargin(5.0f, &Scroll); + s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); + View.x += (View.w - Width) * s_ScrollValue; + LineHeight = 0.25f*View.h; + } + } - CUIRect Row = View; + CUIRect Row = View; - for(int i = 0; i < pInfo->m_NumClients; i++) - { - if(pFilter && (FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) && (pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT)) - continue; + int Count = 0; + for(int i = 0; i < pInfo->m_NumClients; i++) + { + if(pFilter && (FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) && (pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT)) + continue; - CUIRect Name, Clan, Score, Flag, Icon; + CUIRect Name, Clan, Score, Flag, Icon; - if(RowCount > 0 && Count % RowCount == 0) - { - View.VSplitLeft(RowWidth, &Row, &View); - ActColumn++; - } + if(RowCount > 0 && Count % RowCount == 0) + { + View.VSplitLeft(RowWidth, &Row, &View); + ActColumn++; + } + + Row.HSplitTop(LineHeight, &Name, &Row); + s_ScrollRegion.AddRect(Name); + if(Count == 0 && ResetScroll) + { + s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + } - Row.HSplitTop(LineHeight, &Name, &Row); - s_ScrollRegion.AddRect(Name); - RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); + RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); - // friend - if(UI()->DoButtonLogic(&pInfo->m_aClients[i], &Name)) - { - if(pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_PLAYER) - m_pClient->Friends()->RemoveFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); - else - m_pClient->Friends()->AddFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); - FriendlistOnUpdate(); - Client()->ServerBrowserUpdate(); - } - Name.VSplitLeft(Name.h-8.0f, &Icon, &Name); - Icon.HMargin(4.0f, &Icon); - if(pInfo->m_aClients[i].m_FriendState != CContactInfo::CONTACT_NO) - DoIcon(IMAGE_BROWSEICONS, SPRITE_BROWSE_HEART_A, &Icon); - - Name.VSplitLeft(2.0f, 0, &Name); - Name.VSplitLeft(25.0f, &Score, &Name); - Name.VSplitRight(2*(Name.h-8.0f), &Name, &Flag); - Flag.HMargin(4.0f, &Flag); - Name.HSplitTop(LineHeight*0.5f, &Name, &Clan); - - // score - if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)) - { - char aTemp[16]; - FormatScore(aTemp, sizeof(aTemp), pInfo->m_Flags&IServerBrowser::FLAG_TIMESCORE, &pInfo->m_aClients[i]); - TextRender()->SetCursor(&Cursor, Score.x, Score.y + (Score.h - FontSize-2) / 4.0f, FontSize-2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Score.w; - TextRender()->TextEx(&Cursor, aTemp, -1); - } + // friend + if(UI()->DoButtonLogic(&pInfo->m_aClients[i], &Name)) + { + if(pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_PLAYER) + m_pClient->Friends()->RemoveFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); + else + m_pClient->Friends()->AddFriend(pInfo->m_aClients[i].m_aName, pInfo->m_aClients[i].m_aClan); + FriendlistOnUpdate(); + Client()->ServerBrowserUpdate(); + } + Name.VSplitLeft(Name.h-8.0f, &Icon, &Name); + Icon.HMargin(4.0f, &Icon); + if(pInfo->m_aClients[i].m_FriendState != CContactInfo::CONTACT_NO) + DoIcon(IMAGE_BROWSEICONS, SPRITE_BROWSE_HEART_A, &Icon); + + Name.VSplitLeft(2.0f, 0, &Name); + Name.VSplitLeft(25.0f, &Score, &Name); + Name.VSplitRight(2*(Name.h-8.0f), &Name, &Flag); + Flag.HMargin(4.0f, &Flag); + Name.HSplitTop(LineHeight*0.5f, &Name, &Clan); + + // score + if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)) + { + char aTemp[16]; + FormatScore(aTemp, sizeof(aTemp), pInfo->m_Flags&IServerBrowser::FLAG_TIMESCORE, &pInfo->m_aClients[i]); + TextRender()->SetCursor(&Cursor, Score.x, Score.y + (Score.h - FontSize) / 4.0f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = Score.w; + TextRender()->TextEx(&Cursor, aTemp, -1); + } - // name - TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Name.w; - const char *pName = pInfo->m_aClients[i].m_aName; - if(Config()->m_BrFilterString[0]) + // name + TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = Name.w; + const char *pName = pInfo->m_aClients[i].m_aName; + if(Config()->m_BrFilterString[0]) + { + // highlight the part that matches + const char *s = str_find_nocase(pName, Config()->m_BrFilterString); + if(s) { - // highlight the part that matches - const char *s = str_find_nocase(pName, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); - TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pName, -1); + TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); + TextRender()->TextColor(TextColor); + TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pName, -1); + } + else + TextRender()->TextEx(&Cursor, pName, -1); - // clan - TextRender()->SetCursor(&Cursor, Clan.x, Clan.y, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Clan.w; - const char *pClan = pInfo->m_aClients[i].m_aClan; - if(Config()->m_BrFilterString[0]) + // clan + TextRender()->SetCursor(&Cursor, Clan.x, Clan.y, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = Clan.w; + const char *pClan = pInfo->m_aClients[i].m_aClan; + if(Config()->m_BrFilterString[0]) + { + // highlight the part that matches + const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); + if(s) { - // highlight the part that matches - const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); - TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); - TextRender()->TextOutlineColor(TextOutlineColor.r, TextOutlineColor.g, TextOutlineColor.b, TextOutlineColor.a); - TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pClan, -1); + TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); + TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); + TextRender()->TextColor(TextColor); + TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); } else TextRender()->TextEx(&Cursor, pClan, -1); + } + else + TextRender()->TextEx(&Cursor, pClan, -1); - // flag - Flag.w = Flag.h*2; - vec4 Color(1.0f, 1.0f, 1.0f, 0.5f); - m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &Color, Flag.x, Flag.y, Flag.w, Flag.h); + // flag + Flag.w = Flag.h*2; + vec4 FlagColor(1.0f, 1.0f, 1.0f, 0.5f); + m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &FlagColor, Flag.x, Flag.y, Flag.w, Flag.h); - ++Count; - } - s_ScrollRegion.End(); + ++Count; } + + s_ScrollRegion.End(); } void CMenus::RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pInfo) { CUIRect ServerHeader, ServerDetails, ServerScoreboard; - const float FontSize = 10.0f; // split off a piece to use for scoreboard - //View.HMargin(2.0f, &View); View.HSplitTop(80.0f, &ServerDetails, &ServerScoreboard); // server details @@ -2273,9 +2271,8 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pI // server scoreboard ServerScoreboard.HSplitTop(GetListHeaderHeight(), &ServerHeader, &ServerScoreboard); RenderTools()->DrawUIRect(&ServerHeader, vec4(1, 1, 1, 0.25f), CUI::CORNER_T, 4.0f); - //RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); ServerHeader.HMargin(2.0f, &ServerHeader); - UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), FontSize + 2.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), 12.0f, CUI::ALIGN_CENTER); RenderDetailScoreboard(ServerScoreboard, pInfo, 0, vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.0f, 0.0f, 0.0f, 0.3f)); } From 7e479b03f3e2ad9aa1fea26ddbf0e43d707fdd4f Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 23 Apr 2020 17:25:39 +0300 Subject: [PATCH 287/479] Query size after creating the context This fixes a bug on macOS 10.13 --- src/engine/client/backend_sdl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 5f92d58a..cd097dd8 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -740,7 +740,6 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin } SDL_GetWindowSize(m_pWindow, pWindowWidth, pWindowHeight); - SDL_GL_GetDrawableSize(m_pWindow, pScreenWidth, pScreenHeight); // drawable size may differ in high dpi mode // create gl context m_GLContext = SDL_GL_CreateContext(m_pWindow); @@ -750,6 +749,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin return -1; } + SDL_GL_GetDrawableSize(m_pWindow, pScreenWidth, pScreenHeight); // drawable size may differ in high dpi mode + #if defined(CONF_FAMILY_WINDOWS) glTexImage3DInternal = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D"); if(glTexImage3DInternal == 0) From 62bc879fc4bcc758f4a503897706d43ec9b15e32 Mon Sep 17 00:00:00 2001 From: Learath Date: Thu, 23 Apr 2020 17:41:55 +0300 Subject: [PATCH 288/479] Require restart on fullscreen toggle [macOS] --- src/engine/client.h | 6 +++--- src/engine/client/backend_sdl.cpp | 6 ++++-- src/engine/client/client.cpp | 8 +++++++- src/engine/client/client.h | 2 +- src/game/client/components/menus_settings.cpp | 11 ++++++++--- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index 369efdbe..d23022c2 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -88,10 +88,10 @@ class IClient : public IInterface virtual void AutoStatScreenshot_Start() = 0; virtual void AutoScreenshot_Start() = 0; virtual void ServerBrowserUpdate() = 0; - + // gfx virtual void SwitchWindowScreen(int Index) = 0; - virtual void ToggleFullscreen() = 0; + virtual bool ToggleFullscreen() = 0; virtual void ToggleWindowBordered() = 0; virtual void ToggleWindowVSync() = 0; @@ -130,7 +130,7 @@ class IClient : public IInterface virtual const void *SnapFindItem(int SnapID, int Type, int ID) const = 0; virtual const void *SnapGetItem(int SnapID, int Index, CSnapItem *pItem) const = 0; virtual void SnapInvalidateItem(int SnapID, int Index) = 0; - + virtual void *SnapNewItem(int Type, int ID, int Size) = 0; virtual void SnapSetStaticsize(int ItemType, int Size) = 0; diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index cd097dd8..6f82aa19 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -699,9 +699,11 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWin SdlFlags |= SDL_WINDOW_BORDERLESS; if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN) #if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen) + { SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; // always use "fake" fullscreen - *pWindowWidth = *pDesktopWidth; - *pWindowHeight = *pDesktopHeight; + *pWindowWidth = *pDesktopWidth; + *pWindowHeight = *pDesktopHeight; + } #else SdlFlags |= SDL_WINDOW_FULLSCREEN; #endif diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 6c37515f..811b9683 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2439,10 +2439,16 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, pfnCallback(pResult, pCallbackUserData); } -void CClient::ToggleFullscreen() +bool CClient::ToggleFullscreen() { +#ifndef CONF_PLATFORM_MACOSX if(Graphics()->Fullscreen(Config()->m_GfxFullscreen^1)) Config()->m_GfxFullscreen ^= 1; + return true; +#else + Config()->m_GfxFullscreen ^= 1; + return false; +#endif } void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 36fafac8..92762118 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -326,7 +326,7 @@ class CClient : public IClient, public CDemoPlayer::IListener // gfx void SwitchWindowScreen(int Index); - void ToggleFullscreen(); + bool ToggleFullscreen(); void ToggleWindowBordered(); void ToggleWindowVSync(); }; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index c4f59192..d8dceaf8 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1001,7 +1001,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) if(DoButton_CheckBox(&s_EnableColoredBroadcasts, Localize("Enable colored server broadcasts"), Config()->m_ClColoredBroadcast, &Button)) Config()->m_ClColoredBroadcast ^= 1; - + GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); static int s_DisableWhisperFeature = 0; @@ -1644,6 +1644,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) { bool CheckSettings = false; + static int s_GfxFullscreen = Config()->m_GfxFullscreen; static int s_GfxScreenWidth = Config()->m_GfxScreenWidth; static int s_GfxScreenHeight = Config()->m_GfxScreenHeight; static int s_GfxFsaaSamples = Config()->m_GfxFsaaSamples; @@ -1692,7 +1693,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); static int s_ButtonGfxFullscreen = 0; if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), Config()->m_GfxFullscreen, &Button)) - Client()->ToggleFullscreen(); + CheckSettings |= !Client()->ToggleFullscreen(); if(!Config()->m_GfxFullscreen) { @@ -1903,7 +1904,11 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) s_GfxScreenHeight == Config()->m_GfxScreenHeight && s_GfxFsaaSamples == Config()->m_GfxFsaaSamples && s_GfxTextureQuality == Config()->m_GfxTextureQuality && - s_GfxTextureCompression == Config()->m_GfxTextureCompression) + s_GfxTextureCompression == Config()->m_GfxTextureCompression + #ifdef CONF_PLATFORM_MACOSX + && s_GfxFullscreen == Config()->m_GfxFullscreen + #endif + ) m_NeedRestartGraphics = false; else m_NeedRestartGraphics = true; From dc56ab6d93e60f1a4bf26196a76b9e12df65529c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 23 Apr 2020 19:02:10 +0200 Subject: [PATCH 289/479] set m_MapReload instead of polling sv_map, use bool, remove dead code --- src/engine/server/server.cpp | 63 +++++++++++++----------------------- src/engine/server/server.h | 7 ++-- 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index b2a9a965..0c430c23 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -275,7 +275,7 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_pGameServer = 0; m_CurrentGameTick = 0; - m_RunServer = 1; + m_RunServer = true; m_pCurrentMapData = 0; m_CurrentMapSize = 0; @@ -285,7 +285,7 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_pLastMapEntry = 0; m_pMapListHeap = 0; - m_MapReload = 0; + m_MapReload = false; m_RconClientID = IServer::RCON_CID_SERV; m_RconAuthLevel = AUTHED_ADMIN; @@ -1375,21 +1375,14 @@ int CServer::Run() // start game { - int64 ReportTime = time_get(); - int ReportInterval = 3; - - m_Lastheartbeat = 0; m_GameStartTime = time_get(); while(m_RunServer) { - int64 t = time_get(); - int NewTicks = 0; - - // load new map TODO: don't poll this - if(str_comp(Config()->m_SvMap, m_aCurrentMap) != 0 || m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range + // load new map + if(m_MapReload || m_CurrentGameTick >= 0x6FFFFFFF) // force reload to make sure the ticks stay within a valid range { - m_MapReload = 0; + m_MapReload = false; // load map if(LoadMap(Config()->m_SvMap)) @@ -1424,10 +1417,12 @@ int CServer::Run() } } - while(t > TickStartTime(m_CurrentGameTick+1)) + int64 Now = time_get(); + bool NewTicks = false; + while(Now > TickStartTime(m_CurrentGameTick+1)) { m_CurrentGameTick++; - NewTicks++; + NewTicks = true; // apply new input for(int c = 0; c < MAX_CLIENTS; c++) @@ -1463,31 +1458,6 @@ int CServer::Run() PumpNetwork(); - if(ReportTime < time_get()) - { - if(Config()->m_Debug) - { - /* - static NETSTATS prev_stats; - NETSTATS stats; - netserver_stats(net, &stats); - - perf_next(); - - if(config.dbg_pref) - perf_dump(&rootscope); - - dbg_msg("server", "send=%8d recv=%8d", - (stats.send_bytes - prev_stats.send_bytes)/reportinterval, - (stats.recv_bytes - prev_stats.recv_bytes)/reportinterval); - - prev_stats = stats; - */ - } - - ReportTime += time_freq()*ReportInterval; - } - // wait for incomming data m_NetServer.Wait(5); } @@ -1597,7 +1567,7 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser) void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser) { - ((CServer *)pUser)->m_RunServer = 0; + ((CServer *)pUser)->m_RunServer = false; } void CServer::DemoRecorder_HandleAutoStart() @@ -1646,7 +1616,7 @@ void CServer::ConStopRecord(IConsole::IResult *pResult, void *pUser) void CServer::ConMapReload(IConsole::IResult *pResult, void *pUser) { - ((CServer *)pUser)->m_MapReload = 1; + ((CServer *)pUser)->m_MapReload = true; } void CServer::ConLogout(IConsole::IResult *pResult, void *pUser) @@ -1759,6 +1729,16 @@ void CServer::ConchainRconPasswordSet(IConsole::IResult *pResult, void *pUserDat } } +void CServer::ConchainMapUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + if(pResult->NumArguments() >= 1) + { + CServer *pThis = static_cast(pUserData); + pThis->m_MapReload = str_comp(pThis->Config()->m_SvMap, pThis->m_aCurrentMap) != 0; + } +} + void CServer::RegisterCommands() { // register console commands @@ -1782,6 +1762,7 @@ void CServer::RegisterCommands() Console()->Chain("mod_command", ConchainModCommandUpdate, this); Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this); Console()->Chain("sv_rcon_password", ConchainRconPasswordSet, this); + Console()->Chain("sv_map", ConchainMapUpdate, this); // register console commands in sub parts m_ServerBan.InitServerBan(Console(), Storage(), this); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 4516f0e6..8c380e0d 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -152,14 +152,12 @@ class CServer : public IServer IEngineMap *m_pMap; int64 m_GameStartTime; - int m_RunServer; - int m_MapReload; + bool m_RunServer; + bool m_MapReload; int m_RconClientID; int m_RconAuthLevel; int m_PrintCBIndex; - int64 m_Lastheartbeat; - // map enum { @@ -277,6 +275,7 @@ class CServer : public IServer static void ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainRconPasswordSet(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + static void ConchainMapUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); void RegisterCommands(); From 313fd08dc76351fd05801519b09c002cb9e936e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 23 Apr 2020 19:55:33 +0200 Subject: [PATCH 290/479] dynamically adjust server throttle based on time until next tick --- src/engine/server/server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 0c430c23..41b88b08 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1458,8 +1458,8 @@ int CServer::Run() PumpNetwork(); - // wait for incomming data - m_NetServer.Wait(5); + // wait for incoming data + m_NetServer.Wait(clamp(int((TickStartTime(m_CurrentGameTick+1)-time_get())*1000/time_freq()), 1, 1000/SERVER_TICK_SPEED)); } } // disconnect all clients on shutdown From 97d907304c56f643a9ed99e60c35052f950b27fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 23 Apr 2020 21:34:55 +0200 Subject: [PATCH 291/479] add IServer::ChangeMap to fix change_map command --- src/engine/server.h | 1 + src/engine/server/server.cpp | 6 ++++++ src/engine/server/server.h | 1 + src/game/server/gamecontroller.cpp | 5 +++-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/engine/server.h b/src/engine/server.h index bd24e639..6ac20abb 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -64,6 +64,7 @@ class IServer : public IInterface virtual bool IsAuthed(int ClientID) const = 0; virtual bool IsBanned(int ClientID) = 0; virtual void Kick(int ClientID, const char *pReason) = 0; + virtual void ChangeMap(const char *pMap) = 0; virtual void DemoRecorder_HandleAutoStart() = 0; virtual bool DemoRecorder_IsRecording() = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 41b88b08..d00039c7 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1244,6 +1244,12 @@ const char *CServer::GetMapName() return pMapShortName; } +void CServer::ChangeMap(const char *pMap) +{ + str_copy(Config()->m_SvMap, pMap, sizeof(Config()->m_SvMap)); + m_MapReload = str_comp(Config()->m_SvMap, m_aCurrentMap) != 0; +} + int CServer::LoadMap(const char *pMapName) { char aBuf[IO_MAX_PATH_LENGTH]; diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 8c380e0d..2f7c82f3 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -251,6 +251,7 @@ class CServer : public IServer void PumpNetwork(); + virtual void ChangeMap(const char *pMap); const char *GetMapName(); int LoadMap(const char *pMapName); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index a175ff13..f9d5ee95 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -932,7 +932,8 @@ void IGameController::CycleMap() char aBuf[256]; str_format(aBuf, sizeof(aBuf), "rotating map to %s", m_aMapWish); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(Config()->m_SvMap, m_aMapWish, sizeof(Config()->m_SvMap)); + Server()->ChangeMap(m_aMapWish); + m_aMapWish[0] = 0; m_MatchCount = 0; return; @@ -991,7 +992,7 @@ void IGameController::CycleMap() char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - str_copy(Config()->m_SvMap, &aBuf[i], sizeof(Config()->m_SvMap)); + Server()->ChangeMap(&aBuf[i]); } // spawn From f173ed37faaf357ae2cf339ac558c6f8a8b68a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 24 Apr 2020 13:05:58 +0200 Subject: [PATCH 292/479] fix 50hz effects timer also being 100hz, refactoring --- src/game/client/components/effects.cpp | 47 +++++++++----------------- src/game/client/components/effects.h | 17 +++++----- 2 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index 9442cc67..72fb5199 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -285,47 +285,25 @@ void CEffects::HammerHit(vec2 Pos) void CEffects::OnRender() { - static int64 LastUpdate100hz = 0; - static int64 LastUpdate50hz = 0; + static int64 s_LastUpdate100hz = 0; + static int64 s_LastUpdate50hz = 0; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - - if(time_get()-LastUpdate100hz > time_freq()/(100*pInfo->m_Speed)) - { - m_Add100hz = true; - LastUpdate100hz = time_get(); - } - else - m_Add100hz = false; - - if(time_get()-LastUpdate50hz > time_freq()/(100*pInfo->m_Speed)) - { - m_Add50hz = true; - LastUpdate50hz = time_get(); - } - else - m_Add50hz = false; - - if(m_Add50hz) - m_pClient->m_pFlow->Update(); - - return; - } + const float Speed = GetEffectsSpeed(); + const int64 Now = time_get(); + const int64 Freq = time_freq(); - if(time_get()-LastUpdate100hz > time_freq()/100) + if(Now-s_LastUpdate100hz > Freq/(100*Speed)) { m_Add100hz = true; - LastUpdate100hz = time_get(); + s_LastUpdate100hz = Now; } else m_Add100hz = false; - if(time_get()-LastUpdate50hz > time_freq()/100) + if(Now-s_LastUpdate50hz > Freq/(50*Speed)) { m_Add50hz = true; - LastUpdate50hz = time_get(); + s_LastUpdate50hz = Now; } else m_Add50hz = false; @@ -333,3 +311,10 @@ void CEffects::OnRender() if(m_Add50hz) m_pClient->m_pFlow->Update(); } + +float CEffects::GetEffectsSpeed() +{ + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + return DemoPlayer()->BaseInfo()->m_Speed; + return 1.0f; +} diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h index d46da9a8..80941489 100644 --- a/src/game/client/components/effects.h +++ b/src/game/client/components/effects.h @@ -14,19 +14,18 @@ class CEffects : public CComponent public: CEffects(); - virtual void OnRender(); - - void BulletTrail(vec2 Pos); - void SmokeTrail(vec2 Pos, vec2 Vel); - void SkidTrail(vec2 Pos, vec2 Vel); - void Explosion(vec2 Pos); - void HammerHit(vec2 Pos); void AirJump(vec2 Pos); void DamageIndicator(vec2 Pos, int Amount); + void PowerupShine(vec2 Pos, vec2 Size); + void SmokeTrail(vec2 Pos, vec2 Vel); + void SkidTrail(vec2 Pos, vec2 Vel); + void BulletTrail(vec2 Pos); void PlayerSpawn(vec2 Pos); void PlayerDeath(vec2 Pos, int ClientID); - void PowerupShine(vec2 Pos, vec2 Size); + void Explosion(vec2 Pos); + void HammerHit(vec2 Pos); - void Update(); + virtual void OnRender(); + float GetEffectsSpeed(); }; #endif From 56900d7644c1f49aa6d085f57dd025a8f8416e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Apr 2020 11:16:49 +0200 Subject: [PATCH 293/479] fix ticks not being snapped if skipped over --- src/engine/server/server.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index d00039c7..b4bae405 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1425,10 +1425,13 @@ int CServer::Run() int64 Now = time_get(); bool NewTicks = false; + bool ShouldSnap = false; while(Now > TickStartTime(m_CurrentGameTick+1)) { m_CurrentGameTick++; NewTicks = true; + if((m_CurrentGameTick%2) == 0) + ShouldSnap = true; // apply new input for(int c = 0; c < MAX_CLIENTS; c++) @@ -1452,7 +1455,7 @@ int CServer::Run() // snap game if(NewTicks) { - if(Config()->m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) + if(Config()->m_SvHighBandwidth || ShouldSnap) DoSnapshot(); UpdateClientRconCommands(); From 3f8365c797d4627face31275d423514de106d096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Apr 2020 11:27:49 +0200 Subject: [PATCH 294/479] change upper bound --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index d2954d2a..66ce5e6e 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -169,7 +169,7 @@ void CMenus::LoadFilters() if(rSettingsEntry["sidebar_active"].type == json_integer) m_SidebarActive = rSettingsEntry["sidebar_active"].u.integer; if(rSettingsEntry["sidebar_tab"].type == json_integer) - m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), int(SIDEBAR_TAB_INFO), int(SIDEBAR_TAB_FRIEND)); + m_SidebarTab = clamp(int(rSettingsEntry["sidebar_tab"].u.integer), int(SIDEBAR_TAB_INFO), int(NUM_SIDEBAR_TABS-1)); if(rSettingsEntry["filters"].type == json_array) { for(unsigned i = 0; i < IServerBrowser::NUM_TYPES; ++i) From 724fae6f1c644b417dc48b141d88fb20b2445bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Apr 2020 11:58:52 +0200 Subject: [PATCH 295/479] half the maximum server wait time to effectively 10 ms --- src/engine/server/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index b4bae405..99d9d8ef 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1468,7 +1468,7 @@ int CServer::Run() PumpNetwork(); // wait for incoming data - m_NetServer.Wait(clamp(int((TickStartTime(m_CurrentGameTick+1)-time_get())*1000/time_freq()), 1, 1000/SERVER_TICK_SPEED)); + m_NetServer.Wait(clamp(int((TickStartTime(m_CurrentGameTick+1)-time_get())*1000/time_freq()), 1, 1000/SERVER_TICK_SPEED/2)); } } // disconnect all clients on shutdown From 54283dd4443a43bbddf65ff936083a769da540c8 Mon Sep 17 00:00:00 2001 From: maplebeats Date: Sat, 25 Apr 2020 19:43:01 +0800 Subject: [PATCH 296/479] fixed system.c compile need option -std=c99/gnu99 --- src/base/system.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index 9a1a042a..860e1f3c 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2325,7 +2325,8 @@ int mem_comp(const void *a, const void *b, int size) int mem_has_null(const void *block, unsigned size) { const unsigned char *bytes = block; - for(unsigned i = 0; i < size; i++) + unsigned i; + for(i = 0; i < size; i++) { if(bytes[i] == 0) { From 128c56639ed6be2eb5e967aa0de8ac29ce9293b9 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 25 Apr 2020 13:46:08 +0200 Subject: [PATCH 297/479] Remove unneeded `str_format` Discovered by @stichstich#5551 on Discord while doing the Russian translation. It capped the string at 127 bytes. --- src/game/client/components/chat.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index f7b7660e..71ebfd9f 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -989,10 +989,8 @@ void CChat::OnRender() CTextCursor InfoCursor; TextRender()->SetCursor(&InfoCursor, 2.0f, y+12.0f, CategoryFontSize*0.75, TEXTFLAG_RENDER); - char aInfoText[128]; - str_format(aInfoText, sizeof(aInfoText), Localize("Press Tab to cycle chat recipients. Whispers aren't encrypted and might be logged by the server.")); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); - TextRender()->TextEx(&InfoCursor, aInfoText, -1); + TextRender()->TextEx(&InfoCursor, Localize("Press Tab to cycle chat recipients. Whispers aren't encrypted and might be logged by the server."), -1); } } } From 13ed6fbeb28df01894aeaeb2478217680358758f Mon Sep 17 00:00:00 2001 From: Learath Date: Sat, 25 Apr 2020 19:08:16 +0300 Subject: [PATCH 298/479] Fix unused variable --- src/game/client/components/menus_settings.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d8dceaf8..a9c696a5 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1643,6 +1643,10 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, void CMenus::RenderSettingsGraphics(CUIRect MainView) { bool CheckSettings = false; + bool CheckFullscreen = false; + #ifdef CONF_PLATFORM_MACOSX + CheckFullscreen = true; + #endif static int s_GfxFullscreen = Config()->m_GfxFullscreen; static int s_GfxScreenWidth = Config()->m_GfxScreenWidth; @@ -1904,10 +1908,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) s_GfxScreenHeight == Config()->m_GfxScreenHeight && s_GfxFsaaSamples == Config()->m_GfxFsaaSamples && s_GfxTextureQuality == Config()->m_GfxTextureQuality && - s_GfxTextureCompression == Config()->m_GfxTextureCompression - #ifdef CONF_PLATFORM_MACOSX - && s_GfxFullscreen == Config()->m_GfxFullscreen - #endif + s_GfxTextureCompression == Config()->m_GfxTextureCompression && + (!CheckFullscreen || s_GfxFullscreen == Config()->m_GfxFullscreen) ) m_NeedRestartGraphics = false; else From 6522a6c2d79db42e0c8c48fc1db8785b136ebc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 25 Apr 2020 19:42:59 +0200 Subject: [PATCH 299/479] add generic message and confirmation popups, refactoring --- src/game/client/components/menus.cpp | 336 +++++------------- src/game/client/components/menus.h | 52 ++- src/game/client/components/menus_browser.cpp | 29 +- src/game/client/components/menus_demo.cpp | 20 +- src/game/client/components/menus_settings.cpp | 191 ++++++---- 5 files changed, 293 insertions(+), 335 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 6aaf254b..24fd0075 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -46,7 +46,6 @@ IInput *CMenus::CUIElementBase::m_pInput = 0; CMenus::CMenus() { m_Popup = POPUP_NONE; - m_NextPopup = POPUP_NONE; m_ActivePage = PAGE_INTERNET; m_GamePage = PAGE_GAME; @@ -1523,16 +1522,34 @@ void CMenus::OnInit() ServerBrowser()->SetType(Config()->m_UiBrowserPage == PAGE_LAN ? IServerBrowser::TYPE_LAN : IServerBrowser::TYPE_INTERNET); } -void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton, int Next) +void CMenus::PopupMessage(const char *pTitle, const char *pMessage, const char *pButtonLabel, int NextPopup, FPopupButtonCallback pfnButtonCallback) { // reset active item UI()->SetActiveItem(0); - str_copy(m_aMessageTopic, pTopic, sizeof(m_aMessageTopic)); - str_copy(m_aMessageBody, pBody, sizeof(m_aMessageBody)); - str_copy(m_aMessageButton, pButton, sizeof(m_aMessageButton)); + str_copy(m_aPopupTitle, pTitle, sizeof(m_aPopupTitle)); + str_copy(m_aPopupMessage, pMessage, sizeof(m_aPopupMessage)); + str_copy(m_aPopupButtons[BUTTON_CONFIRM].m_aLabel, pButtonLabel, sizeof(m_aPopupButtons[BUTTON_CONFIRM].m_aLabel)); + m_aPopupButtons[BUTTON_CONFIRM].m_NextPopup = NextPopup; + m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback = pfnButtonCallback; m_Popup = POPUP_MESSAGE; - m_NextPopup = Next; +} + +void CMenus::PopupConfirm(const char *pTitle, const char *pMessage, const char *pConfirmButtonLabel, const char *pCancelButtonLabel, + FPopupButtonCallback pfnConfirmButtonCallback, int ConfirmNextPopup, FPopupButtonCallback pfnCancelButtonCallback, int CancelNextPopup) +{ + // reset active item + UI()->SetActiveItem(0); + + str_copy(m_aPopupTitle, pTitle, sizeof(m_aPopupTitle)); + str_copy(m_aPopupMessage, pMessage, sizeof(m_aPopupMessage)); + str_copy(m_aPopupButtons[BUTTON_CONFIRM].m_aLabel, pConfirmButtonLabel, sizeof(m_aPopupButtons[BUTTON_CONFIRM].m_aLabel)); + m_aPopupButtons[BUTTON_CONFIRM].m_NextPopup = ConfirmNextPopup; + m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback = pfnConfirmButtonCallback; + str_copy(m_aPopupButtons[BUTTON_CANCEL].m_aLabel, pCancelButtonLabel, sizeof(m_aPopupButtons[BUTTON_CONFIRM].m_aLabel)); + m_aPopupButtons[BUTTON_CANCEL].m_NextPopup = CancelNextPopup; + m_aPopupButtons[BUTTON_CANCEL].m_pfnCallback = pfnCancelButtonCallback; + m_Popup = POPUP_CONFIRM; } @@ -1572,7 +1589,7 @@ int CMenus::Render() if(!s_SoundCheck && m_Popup == POPUP_NONE) { if(Client()->SoundInitFailed()) - m_Popup = POPUP_SOUNDERROR; + PopupMessage(Localize("Sound error"), Localize("The audio device couldn't be initialised."), Localize("Ok")); s_SoundCheck = true; } @@ -1681,28 +1698,22 @@ int CMenus::Render() } else { - // make sure that other windows doesn't do anything funnay! - //UI()->SetHotItem(0); - //UI()->SetActiveItem(0); - char aBuf[128]; + // render full screen popup const char *pTitle = ""; const char *pExtraText = ""; - const char *pButtonText = ""; - CUI::EAlignment ExtraAlign = CUI::ALIGN_CENTER; int NumOptions = 4; - if(m_Popup == POPUP_MESSAGE) + if(m_Popup == POPUP_MESSAGE || m_Popup == POPUP_CONFIRM) { - pTitle = m_aMessageTopic; - pExtraText = m_aMessageBody; - pButtonText = m_aMessageButton; + pTitle = m_aPopupTitle; + pExtraText = m_aPopupMessage; } else if(m_Popup == POPUP_CONNECTING) { pTitle = Localize("Connecting to"); - pButtonText = Localize("Abort"); if(Client()->MapDownloadTotalsize() > 0) { + char aBuf[128]; str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Downloading map"), Client()->MapDownloadName()); pTitle = aBuf; pExtraText = ""; @@ -1712,75 +1723,24 @@ int CMenus::Render() else if(m_Popup == POPUP_LANGUAGE) { pTitle = Localize("Language"); - pButtonText = Localize("Ok"); NumOptions = 7; } else if(m_Popup == POPUP_COUNTRY) { pTitle = Localize("Country"); - pButtonText = Localize("Ok"); NumOptions = 8; } - else if(m_Popup == POPUP_DISCONNECTED) - { - pTitle = Localize("Disconnected"); - pExtraText = Client()->ErrorString(); - pButtonText = Localize("Ok"); - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_PURE) - { - pTitle = Localize("Disconnected"); - pExtraText = Localize("The server is running a non-standard tuning on a pure game type."); - pButtonText = Localize("Ok"); - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_DELETE_DEMO) - { - pTitle = Localize("Delete demo"); - pExtraText = Localize("Are you sure that you want to delete the demo?"); - ExtraAlign = CUI::ALIGN_LEFT; - } else if(m_Popup == POPUP_RENAME_DEMO) { pTitle = Localize("Rename demo"); pExtraText = Localize("Are you sure you want to rename the demo?"); NumOptions = 6; - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_REMOVE_FRIEND) - { - pTitle = Localize("Remove friend"); - pExtraText = m_pDeleteFriend->m_FriendState == CContactInfo::CONTACT_PLAYER - ? Localize("Are you sure that you want to remove the player from your friends list?") - : Localize("Are you sure that you want to remove the clan from your friends list?"); - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_REMOVE_FILTER) - { - pTitle = Localize("Remove filter"); - pExtraText = Localize("Are you sure that you want to remove the filter from the server browser?"); - ExtraAlign = CUI::ALIGN_LEFT; } else if(m_Popup == POPUP_SAVE_SKIN) { pTitle = Localize("Save skin"); pExtraText = Localize("Are you sure you want to save your skin? If a skin with this name already exists, it will be replaced."); NumOptions = 6; - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_DELETE_SKIN) - { - pTitle = Localize("Delete skin"); - pExtraText = Localize("Are you sure that you want to delete the skin?"); - ExtraAlign = CUI::ALIGN_LEFT; - } - else if(m_Popup == POPUP_SOUNDERROR) - { - pTitle = Localize("Sound error"); - pExtraText = Localize("The audio device couldn't be initialised."); - pButtonText = Localize("Ok"); - ExtraAlign = CUI::ALIGN_LEFT; } else if(m_Popup == POPUP_PASSWORD) { @@ -1796,31 +1756,30 @@ int CMenus::Render() { pTitle = Localize("Welcome to Teeworlds"); pExtraText = Localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server."); - pButtonText = Localize("Enter"); NumOptions = 6; - ExtraAlign = CUI::ALIGN_LEFT; } - CUIRect Box, Part, BottomBar; - float ButtonHeight = 20.0f; - float ButtonHeightBig = ButtonHeight+5.0f; - float SpacingH = 2.0f; - float SpacingW = 3.0f; - Box = Screen; + const float ButtonHeight = 20.0f; + const float FontSize = ButtonHeight*ms_FontmodHeight*0.8f; + const float SpacingH = 2.0f; + const float SpacingW = 3.0f; + CUIRect Box = Screen; Box.VMargin(Box.w/2.0f-(365.0f), &Box); - float ButtonWidth = (Box.w/6.0f)-(SpacingW*5.0)/6.0f; + const float ButtonWidth = (Box.w/6.0f)-(SpacingW*5.0)/6.0f; Box.VMargin(ButtonWidth+SpacingW, &Box); Box.HMargin(Box.h/2.0f-((int)(NumOptions+1)*ButtonHeight+(int)(NumOptions)*SpacingH)/2.0f-10.0f, &Box); // render the box RenderTools()->DrawUIRect(&Box, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - // headline - Box.HSplitTop(ButtonHeightBig, &Part, &Box); + // headline and title + CUIRect Part; + Box.HSplitTop(ButtonHeight+5.0f, &Part, &Box); Part.y += 3.0f; UI()->DoLabel(&Part, pTitle, Part.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); // inner box + CUIRect BottomBar; Box.HSplitTop(SpacingH, 0, &Box); Box.HSplitBottom(ButtonHeight+5.0f+SpacingH, &Box, &BottomBar); BottomBar.HSplitTop(SpacingH, 0, &BottomBar); @@ -1828,24 +1787,23 @@ int CMenus::Render() if(m_Popup == POPUP_QUIT) { - CUIRect Yes, No; - // additional info if(m_pClient->Editor()->HasUnsavedData()) { Box.HSplitTop(12.0f, 0, &Part); - UI()->DoLabel(&Part, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Part, pExtraText, FontSize, CUI::ALIGN_CENTER); Part.HSplitTop(20.0f, 0, &Part); Part.VMargin(5.0f, &Part); - UI()->DoLabel(&Part, Localize("There's an unsaved map in the editor, you might want to save it before you quit the game."), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT, Part.w); + UI()->DoLabel(&Part, Localize("There's an unsaved map in the editor, you might want to save it before you quit the game."), FontSize, CUI::ALIGN_LEFT, Part.w); } else { Box.HSplitTop(27.0f, 0, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Box, pExtraText, FontSize, CUI::ALIGN_CENTER); } // buttons + CUIRect Yes, No; BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonAbort; @@ -1858,18 +1816,20 @@ int CMenus::Render() } else if(m_Popup == POPUP_PASSWORD) { - CUIRect Label, EditBox, Save, TryAgain, Abort; - Box.HMargin(4.0f, &Box); + CUIRect Label; Box.HSplitTop(20.0f, &Label, &Box); - UI()->DoLabel(&Label, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Label, pExtraText, FontSize, CUI::ALIGN_CENTER); + CUIRect EditBox; Box.HSplitTop(20.0f, &EditBox, &Box); static float s_OffsetPassword = 0.0f; DoEditBoxOption(Config()->m_Password, Config()->m_Password, sizeof(Config()->m_Password), &EditBox, Localize("Password"), ButtonWidth, &s_OffsetPassword, true); Box.HSplitTop(2.0f, 0, &Box); + + CUIRect Save; Box.HSplitTop(20.0f, &Save, &Box); CServerInfo ServerInfo = {0}; str_copy(ServerInfo.m_aHostname, m_aPasswordPopupServerAddress, sizeof(ServerInfo.m_aHostname)); @@ -1881,6 +1841,7 @@ int CMenus::Render() Config()->m_ClSaveServerPasswords = Config()->m_ClSaveServerPasswords == OnValue ? 0 : OnValue; // buttons + CUIRect TryAgain, Abort; BottomBar.VSplitMid(&Abort, &TryAgain, SpacingW); static CButtonContainer s_ButtonAbort; @@ -1900,7 +1861,7 @@ int CMenus::Render() else if(m_Popup == POPUP_CONNECTING) { static CButtonContainer s_ButtonConnect; - if(DoButton_Menu(&s_ButtonConnect, pButtonText, 0, &BottomBar) || m_EscapePressed || m_EnterPressed) + if(DoButton_Menu(&s_ButtonConnect, Localize("Abort"), 0, &BottomBar) || m_EscapePressed || m_EnterPressed) { Client()->Disconnect(); m_Popup = POPUP_NONE; @@ -1932,7 +1893,7 @@ int CMenus::Render() Box.HSplitTop(15.f, 0, &Box); Box.HSplitTop(ButtonHeight, &Part, &Box); str_format(aBuf, sizeof(aBuf), "%d/%d KiB (%.1f KiB/s)", Client()->MapDownloadAmount()/1024, Client()->MapDownloadTotalsize()/1024, m_DownloadSpeed/1024.0f); - UI()->DoLabel(&Part, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Part, aBuf, FontSize, CUI::ALIGN_CENTER); // time left int SecondsLeft = max(1, m_DownloadSpeed > 0.0f ? static_cast((Client()->MapDownloadTotalsize()-Client()->MapDownloadAmount())/m_DownloadSpeed) : 1); @@ -1947,7 +1908,7 @@ int CMenus::Render() } Box.HSplitTop(SpacingH, 0, &Box); Box.HSplitTop(ButtonHeight, &Part, &Box); - UI()->DoLabel(&Part, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Part, aBuf, FontSize, CUI::ALIGN_CENTER); // progress bar Box.HSplitTop(SpacingH, 0, &Box); @@ -1960,7 +1921,7 @@ int CMenus::Render() else { Box.HSplitTop(27.0f, 0, &Box); - UI()->DoLabel(&Box, Client()->ServerAddress(), ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Box, Client()->ServerAddress(), FontSize, CUI::ALIGN_CENTER); } } else if(m_Popup == POPUP_LANGUAGE) @@ -1968,7 +1929,7 @@ int CMenus::Render() RenderLanguageSelection(Box, false); static CButtonContainer s_ButtonLanguage; - if(DoButton_Menu(&s_ButtonLanguage, pButtonText, 0, &BottomBar) || m_EscapePressed || m_EnterPressed) + if(DoButton_Menu(&s_ButtonLanguage, Localize("Ok"), 0, &BottomBar) || m_EscapePressed || m_EnterPressed) m_Popup = POPUP_FIRST_LAUNCH; } else if(m_Popup == POPUP_COUNTRY) @@ -2028,7 +1989,7 @@ int CMenus::Render() Part.VMargin(120.0f, &Part); static CButtonContainer s_ButtonCountry; - if(DoButton_Menu(&s_ButtonCountry, pButtonText, 0, &BottomBar) || m_EnterPressed) + if(DoButton_Menu(&s_ButtonCountry, Localize("Ok"), 0, &BottomBar) || m_EnterPressed) { FilterInfo.m_Country = s_ActSelection; pFilter->SetFilter(&FilterInfo); @@ -2041,47 +2002,13 @@ int CMenus::Render() m_Popup = POPUP_NONE; } } - else if(m_Popup == POPUP_DELETE_DEMO) - { - CUIRect Yes, No; - Box.HSplitTop(27.0f, 0, &Box); - Box.VMargin(10.0f, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); - - // buttons - BottomBar.VSplitMid(&No, &Yes, SpacingW); - - static CButtonContainer s_ButtonNo; - if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) - m_Popup = POPUP_NONE; - - static CButtonContainer s_ButtonYes; - if(DoButton_Menu(&s_ButtonYes, Localize("Yes"), 0, &Yes) || m_EnterPressed) - { - m_Popup = POPUP_NONE; - // delete demo - if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir) - { - char aBuf[IO_MAX_PATH_LENGTH]; - str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); - if(Storage()->RemoveFile(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType)) - { - DemolistPopulate(); - DemolistOnUpdate(false); - } - else - PopupMessage(Localize("Error"), Localize("Unable to delete the demo"), Localize("Ok")); - } - } - } else if(m_Popup == POPUP_RENAME_DEMO) { - CUIRect Yes, No, EditBox; - Box.HSplitTop(27.0f, 0, &Box); Box.VMargin(10.0f, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); + UI()->DoLabel(&Box, pExtraText, FontSize, CUI::ALIGN_LEFT); + CUIRect EditBox; Box.HSplitBottom(Box.h/2.0f, 0, &Box); Box.HSplitTop(20.0f, &EditBox, &Box); @@ -2089,6 +2016,7 @@ int CMenus::Render() DoEditBoxOption(m_aCurrentDemoFile, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), &EditBox, Localize("Name"), ButtonWidth, &s_OffsetRenameDemo); // buttons + CUIRect Yes, No; BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonNo; @@ -2123,74 +2051,13 @@ int CMenus::Render() } } } - else if(m_Popup == POPUP_REMOVE_FRIEND) - { - CUIRect NameLabel, Yes, No; - - Box.Margin(5.0f, &Box); - Box.HSplitMid(&Box, &NameLabel); - - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, Box.w); - UI()->DoLabel(&NameLabel, m_pDeleteFriend->m_FriendState == CContactInfo::CONTACT_PLAYER ? m_pDeleteFriend->m_aName : m_pDeleteFriend->m_aClan, - ButtonHeight*ms_FontmodHeight*1.2f, CUI::ALIGN_CENTER, NameLabel.w); - - // buttons - BottomBar.VSplitMid(&No, &Yes, SpacingW); - - static CButtonContainer s_ButtonNo; - if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) - { - m_Popup = POPUP_NONE; - m_pDeleteFriend = 0; - } - - static CButtonContainer s_ButtonYes; - if(DoButton_Menu(&s_ButtonYes, Localize("Yes"), 0, &Yes) || m_EnterPressed) - { - m_Popup = POPUP_NONE; - // remove friend - if(m_pDeleteFriend) - { - m_pClient->Friends()->RemoveFriend(m_pDeleteFriend->m_FriendState == CContactInfo::CONTACT_PLAYER ? m_pDeleteFriend->m_aName : "", m_pDeleteFriend->m_aClan); - FriendlistOnUpdate(); - Client()->ServerBrowserUpdate(); - m_pDeleteFriend = 0; - } - } - } - else if(m_Popup == POPUP_REMOVE_FILTER) - { - CUIRect Yes, No; - Box.HSplitTop(27.0f, 0, &Box); - Box.VMargin(5.0f, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, Box.w); - - // buttons - BottomBar.VSplitMid(&No, &Yes, SpacingW); - - static CButtonContainer s_ButtonNo; - if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) - m_Popup = POPUP_NONE; - - static CButtonContainer s_ButtonYes; - if(DoButton_Menu(&s_ButtonYes, Localize("Yes"), 0, &Yes) || m_EnterPressed) - { - m_Popup = POPUP_NONE; - // remove filter - if(m_RemoveFilterIndex) - { - RemoveFilter(m_RemoveFilterIndex); - } - } - } else if(m_Popup == POPUP_SAVE_SKIN) { - CUIRect Yes, No, EditBox; - Box.HSplitTop(24.0f, 0, &Box); Box.VMargin(10.0f, &Part); - UI()->DoLabel(&Part, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, Box.w-20.0f); + UI()->DoLabel(&Part, pExtraText, FontSize, CUI::ALIGN_LEFT, Box.w-20.0f); + CUIRect EditBox; Box.HSplitBottom(Box.h/2.0f, 0, &Box); Box.HSplitTop(20.0f, &EditBox, &Box); @@ -2198,6 +2065,7 @@ int CMenus::Render() DoEditBoxOption(m_aSaveSkinName, m_aSaveSkinName, sizeof(m_aSaveSkinName), &EditBox, Localize("Name"), ButtonWidth, &s_OffsetSaveSkin); // buttons + CUIRect Yes, No; BottomBar.VSplitMid(&No, &Yes, SpacingW); static CButtonContainer s_ButtonAbort; @@ -2216,48 +2084,13 @@ int CMenus::Render() } } } - else if(m_Popup == POPUP_DELETE_SKIN) - { - CUIRect Yes, No; - Box.HSplitTop(27.0f, 0, &Box); - Box.VMargin(10.0f, &Box); - UI()->DoLabel(&Box, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign); - - // buttons - BottomBar.VSplitMid(&No, &Yes, SpacingW); - - static CButtonContainer s_ButtonNo; - if(DoButton_Menu(&s_ButtonNo, Localize("No"), 0, &No) || m_EscapePressed) - m_Popup = POPUP_NONE; - - static CButtonContainer s_ButtonYes; - if(DoButton_Menu(&s_ButtonYes, Localize("Yes"), 0, &Yes) || m_EnterPressed) - { - m_Popup = POPUP_NONE; - // delete demo - if(m_pSelectedSkin) - { - char aBuf[IO_MAX_PATH_LENGTH]; - str_format(aBuf, sizeof(aBuf), "skins/%s.json", m_pSelectedSkin->m_aName); - if(Storage()->RemoveFile(aBuf, IStorage::TYPE_SAVE)) - { - m_pClient->m_pSkins->RemoveSkin(m_pSelectedSkin); - m_RefreshSkinSelector = true; - m_pSelectedSkin = 0; - } - else - PopupMessage(Localize("Error"), Localize("Unable to delete the skin"), Localize("Ok")); - } - } - } else if(m_Popup == POPUP_FIRST_LAUNCH) { - CUIRect EditBox; - Box.HSplitTop(20.0f, 0, &Box); Box.VMargin(10.0f, &Part); - UI()->DoLabel(&Part, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, Box.w-20.0f); + UI()->DoLabel(&Part, pExtraText, FontSize, CUI::ALIGN_LEFT, Box.w-20.0f); + CUIRect EditBox; Box.HSplitBottom(ButtonHeight*2.0f, 0, &Box); Box.HSplitTop(ButtonHeight, &EditBox, &Box); @@ -2266,7 +2099,7 @@ int CMenus::Render() // button static CButtonContainer s_EnterButton; - if(DoButton_Menu(&s_EnterButton, pButtonText, 0, &BottomBar) || m_EnterPressed) + if(DoButton_Menu(&s_EnterButton, Localize("Enter"), 0, &BottomBar) || m_EnterPressed) { if(Config()->m_PlayerName[0]) m_Popup = POPUP_NONE; @@ -2274,16 +2107,41 @@ int CMenus::Render() PopupMessage(Localize("Error"), Localize("Nickname is empty."), Localize("Ok"), POPUP_FIRST_LAUNCH); } } - else + else if(m_Popup == POPUP_MESSAGE || m_Popup == POPUP_CONFIRM) { + // message Box.HSplitTop(27.0f, 0, &Box); Box.VMargin(5.0f, &Part); - UI()->DoLabel(&Part, pExtraText, ButtonHeight*ms_FontmodHeight*0.8f, ExtraAlign, ExtraAlign == CUI::ALIGN_CENTER ? -1.0f : Part.w); + UI()->DoLabel(&Part, pExtraText, FontSize, CUI::ALIGN_LEFT, Part.w); - // button - static CButtonContainer s_Button; - if(DoButton_Menu(&s_Button, pButtonText, 0, &BottomBar) || m_EscapePressed || m_EnterPressed) - m_Popup = m_NextPopup; + if(m_Popup == POPUP_MESSAGE) + { + static CButtonContainer s_ButtonConfirm; + if(DoButton_Menu(&s_ButtonConfirm, m_aPopupButtons[BUTTON_CONFIRM].m_aLabel, 0, &BottomBar) || m_EscapePressed || m_EnterPressed) + { + m_Popup = m_aPopupButtons[BUTTON_CONFIRM].m_NextPopup; + (this->*m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback)(); + } + } + else if(m_Popup == POPUP_CONFIRM) + { + CUIRect CancelButton, ConfirmButton; + BottomBar.VSplitMid(&CancelButton, &ConfirmButton, SpacingW); + + static CButtonContainer s_ButtonCancel; + if(DoButton_Menu(&s_ButtonCancel, m_aPopupButtons[BUTTON_CANCEL].m_aLabel, 0, &CancelButton) || m_EscapePressed) + { + m_Popup = m_aPopupButtons[BUTTON_CANCEL].m_NextPopup; + (this->*m_aPopupButtons[BUTTON_CANCEL].m_pfnCallback)(); + } + + static CButtonContainer s_ButtonConfirm; + if(DoButton_Menu(&s_ButtonConfirm, m_aPopupButtons[BUTTON_CONFIRM].m_aLabel, 0, &ConfirmButton) || m_EnterPressed) + { + m_Popup = m_aPopupButtons[BUTTON_CONFIRM].m_NextPopup; + (this->*m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback)(); + } + } } if(m_Popup == POPUP_NONE) @@ -2413,7 +2271,7 @@ void CMenus::OnStateChange(int NewState, int OldState) UI()->SetActiveItem(&Config()->m_Password); } else - m_Popup = POPUP_DISCONNECTED; + PopupMessage(Localize("Disconnected"), Client()->ErrorString(), Localize("Ok")); } } else if(NewState == IClient::STATE_LOADING) @@ -2462,7 +2320,7 @@ void CMenus::OnRender() { Client()->Disconnect(); SetActive(true); - m_Popup = POPUP_PURE; + PopupMessage(Localize("Disconnected"), Localize("The server is running a non-standard tuning on a pure game type."), Localize("Ok")); } if(!IsActive()) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 0ef56360..f83f43ad 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -287,20 +287,14 @@ class CMenus : public CComponent enum { POPUP_NONE=0, + POPUP_MESSAGE, // generic message popup (one button) + POPUP_CONFIRM, // generic confirmation popup (two buttons) POPUP_FIRST_LAUNCH, POPUP_CONNECTING, - POPUP_MESSAGE, - POPUP_DISCONNECTED, - POPUP_PURE, POPUP_LANGUAGE, POPUP_COUNTRY, - POPUP_DELETE_DEMO, POPUP_RENAME_DEMO, - POPUP_REMOVE_FRIEND, - POPUP_REMOVE_FILTER, POPUP_SAVE_SKIN, - POPUP_DELETE_SKIN, - POPUP_SOUNDERROR, POPUP_PASSWORD, POPUP_QUIT, }; @@ -348,6 +342,31 @@ class CMenus : public CComponent bool m_KeyReaderWasActive; bool m_KeyReaderIsActive; + // generic popups + typedef void (CMenus::*FPopupButtonCallback)(); + void DefaultButtonCallback() { /* do nothing */ }; + enum + { + BUTTON_CONFIRM = 0, // confirm / yes / close + BUTTON_CANCEL, // cancel / no + NUM_BUTTONS + }; + char m_aPopupTitle[128]; + char m_aPopupMessage[256]; + struct + { + char m_aLabel[64]; + int m_NextPopup; + FPopupButtonCallback m_pfnCallback; + } m_aPopupButtons[NUM_BUTTONS]; + + void PopupMessage(const char *pTitle, const char *pMessage, + const char *pButtonLabel, int NextPopup = POPUP_NONE, FPopupButtonCallback pfnButtonCallback = &CMenus::DefaultButtonCallback); + void PopupConfirm(const char *pTitle, const char *pMessage, + const char *pConfirmButtonLabel, const char *pCancelButtonLabel, + FPopupButtonCallback pfnConfirmButtonCallback = &CMenus::DefaultButtonCallback, int ConfirmNextPopup = POPUP_NONE, + FPopupButtonCallback pfnCancelButtonCallback = &CMenus::DefaultButtonCallback, int CancelNextPopup = POPUP_NONE); + // images struct CMenuImage { @@ -401,14 +420,6 @@ class CMenus : public CComponent int64 m_LastInput; - // - char m_aMessageTopic[512]; - char m_aMessageBody[512]; - char m_aMessageButton[512]; - int m_NextPopup; - - void PopupMessage(const char *pTopic, const char *pBody, const char *pButton, int Next=POPUP_NONE); - // some settings static float ms_ButtonHeight; static float ms_ListheaderHeight; @@ -668,6 +679,7 @@ class CMenus : public CComponent // video settings + bool m_CheckVideoSettings; enum { MAX_RESOLUTIONS=256, @@ -698,6 +710,7 @@ class CMenus : public CComponent void RenderDemoPlayer(CUIRect MainView); void RenderDemoList(CUIRect MainView); float RenderDemoDetails(CUIRect View); + void PopupConfirmDeleteDemo(); // found in menus_start.cpp void RenderStartMenu(CUIRect MainView); @@ -716,6 +729,7 @@ class CMenus : public CComponent void RenderServerbrowserServerList(CUIRect View); void RenderServerbrowserSidebar(CUIRect View); void RenderServerbrowserFriendTab(CUIRect View); + void PopupConfirmRemoveFriend(); void RenderServerbrowserFilterTab(CUIRect View); void RenderServerbrowserInfoTab(CUIRect View); void RenderServerbrowserFriendList(CUIRect View); @@ -725,6 +739,7 @@ class CMenus : public CComponent void RenderServerbrowserBottomBox(CUIRect View); void RenderServerbrowserOverlay(); void RenderFilterHeader(CUIRect View, int FilterIndex); + void PopupConfirmRemoveFilter(); int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected); void RenderServerbrowser(CUIRect MainView); static void ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); @@ -748,10 +763,15 @@ class CMenus : public CComponent void RenderSettingsTee(CUIRect MainView); void RenderSettingsTeeBasic(CUIRect MainView); void RenderSettingsTeeCustom(CUIRect MainView); + void PopupConfirmDeleteSkin(); void RenderSettingsControls(CUIRect MainView); void RenderSettingsGraphics(CUIRect MainView); void RenderSettingsSound(CUIRect MainView); void RenderSettings(CUIRect MainView); + void ResetSettingsGeneral(); + void ResetSettingsControls(); + void ResetSettingsGraphics(); + void ResetSettingsSound(); bool DoResolutionList(CUIRect* pRect, CListBox* pListBox, const sorted_array& lModes); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 66ce5e6e..1f6eaabf 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -738,7 +738,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) UI()->DoLabel(&View, pFilter->Name(), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); View.VSplitRight(20.0f, &View, 0); // little space - char aBuf[64]; + char aBuf[128]; str_format(aBuf, sizeof(aBuf), Localize("%d servers, %d players"), pFilter->NumSortedServers(), pFilter->NumPlayers()); UI()->DoLabel(&View, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); @@ -749,7 +749,8 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_A, &Button)) { m_RemoveFilterIndex = FilterIndex; - m_Popup = POPUP_REMOVE_FILTER; + str_format(aBuf, sizeof(aBuf), Localize("Are you sure that you want to remove the filter '%s' from the server browser?"), pFilter->Name()); + PopupConfirm(Localize("Remove filter"), aBuf, Localize("Yes"), Localize("No"), &CMenus::PopupConfirmRemoveFilter); } } else @@ -800,6 +801,15 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) } } +void CMenus::PopupConfirmRemoveFilter() +{ + // remove filter + if(m_RemoveFilterIndex) + { + RemoveFilter(m_RemoveFilterIndex); + } +} + static void FormatScore(char *pBuf, int BufSize, bool TimeScore, const CServerInfo::CClient *pClient) { if(TimeScore) @@ -1727,10 +1737,23 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // delete friend if(m_pDeleteFriend) { - m_Popup = POPUP_REMOVE_FRIEND; + const bool IsPlayer = m_pDeleteFriend->m_FriendState == CContactInfo::CONTACT_PLAYER; + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), + IsPlayer ? Localize("Are you sure that you want to remove the player '%s' from your friends list?") : Localize("Are you sure that you want to remove the clan '%s' from your friends list?"), + IsPlayer ? m_pDeleteFriend->m_aName : m_pDeleteFriend->m_aClan); + PopupConfirm(Localize("Remove friend"), aBuf, Localize("Yes"), Localize("No"), &CMenus::PopupConfirmRemoveFriend); } } +void CMenus::PopupConfirmRemoveFriend() +{ + m_pClient->Friends()->RemoveFriend(m_pDeleteFriend->m_FriendState == CContactInfo::CONTACT_PLAYER ? m_pDeleteFriend->m_aName : "", m_pDeleteFriend->m_aClan); + FriendlistOnUpdate(); + Client()->ServerBrowserUpdate(); + m_pDeleteFriend = 0; +} + void CMenus::RenderServerbrowserFilterTab(CUIRect View) { CUIRect ServerFilter = View, FilterHeader, Button, Icon, Label; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 663aaf4e..71877cc1 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -474,7 +474,9 @@ void CMenus::RenderDemoList(CUIRect MainView) if(m_DemolistSelectedIndex >= 0) { UI()->SetActiveItem(0); - m_Popup = POPUP_DELETE_DEMO; + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), Localize("Are you sure that you want to delete the demo '%s'?"), m_lDemos[m_DemolistSelectedIndex].m_aFilename); + PopupConfirm(Localize("Delete demo"), aBuf, Localize("Yes"), Localize("No"), &CMenus::PopupConfirmDeleteDemo); return; } } @@ -532,6 +534,22 @@ void CMenus::RenderDemoList(CUIRect MainView) } } +void CMenus::PopupConfirmDeleteDemo() +{ + if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir) + { + char aBuf[IO_MAX_PATH_LENGTH]; + str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); + if(Storage()->RemoveFile(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType)) + { + DemolistPopulate(); + DemolistOnUpdate(false); + } + else + PopupMessage(Localize("Error"), Localize("Unable to delete the demo"), Localize("Ok")); + } +} + float CMenus::RenderDemoDetails(CUIRect View) { // render demo info diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index a9c696a5..f9b20408 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1072,22 +1072,8 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->m_ClDynamicCamera = 0; - Config()->m_ClMouseMaxDistanceStatic = 400; - Config()->m_ClMouseMaxDistanceDynamic = 1000; - Config()->m_ClMouseFollowfactor = 60; - Config()->m_ClMouseDeadzone = 300; - Config()->m_ClAutoswitchWeapons = 1; - Config()->m_ClShowhud = 1; - Config()->m_ClFilterchat = 0; - Config()->m_ClNameplates = 1; - Config()->m_ClNameplatesAlways = 1; - Config()->m_ClNameplatesSize = 50; - Config()->m_ClNameplatesTeamcolors = 1; - Config()->m_ClAutoDemoRecord = 0; - Config()->m_ClAutoDemoMax = 10; - Config()->m_ClAutoScreenshot = 0; - Config()->m_ClAutoScreenshotMax = 10; + PopupConfirm(Localize("Reset general settings"), Localize("Are you sure that you want to reset the general settings to their defaults?"), + Localize("Reset"), Localize("Cancel"), &CMenus::ResetSettingsGeneral); } } @@ -1256,13 +1242,11 @@ void CMenus::RenderSettingsTee(CUIRect MainView) BottomView.HSplitTop(20.f, 0, &BottomView); // render skin preview background - float SpacingH = 2.0f; - float SpacingW = 3.0f; - float ButtonHeight = 20.0f; - float SkinHeight = 50.0f; - float BackgroundHeight = ButtonHeight+SpacingH+SkinHeight; - if(!s_CustomSkinMenu) - BackgroundHeight = (ButtonHeight+SpacingH)*2.0f+SkinHeight; + const float SpacingH = 2.0f; + const float SpacingW = 3.0f; + const float ButtonHeight = 20.0f; + const float SkinHeight = 50.0f; + const float BackgroundHeight = (ButtonHeight+SpacingH)*(s_CustomSkinMenu ? 1.0f : 2.0f) + SkinHeight; if(this->Client()->State() == IClient::STATE_ONLINE) Background = MainView; @@ -1430,7 +1414,11 @@ void CMenus::RenderSettingsTee(CUIRect MainView) BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static CButtonContainer s_CustomSkinDeleteButton; if(DoButton_Menu(&s_CustomSkinDeleteButton, Localize("Delete"), 0, &Button)) - m_Popup = POPUP_DELETE_SKIN; + { + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), Localize("Are you sure that you want to delete the skin '%s'?"), m_pSelectedSkin->m_aName); + PopupConfirm(Localize("Delete skin"), aBuf, Localize("Yes"), Localize("No"), &CMenus::PopupConfirmDeleteSkin); + } BottomView.VSplitLeft(SpacingW, 0, &BottomView); } @@ -1438,10 +1426,24 @@ void CMenus::RenderSettingsTee(CUIRect MainView) static CButtonContainer s_CustomSwitchButton; if(DoButton_Menu(&s_CustomSwitchButton, s_CustomSkinMenu ? Localize("Basic") : Localize("Custom"), 0, &Button)) { - if(s_CustomSkinMenu) - s_CustomSkinMenu = false; + s_CustomSkinMenu = !s_CustomSkinMenu; + } +} + +void CMenus::PopupConfirmDeleteSkin() +{ + if(m_pSelectedSkin) + { + char aBuf[IO_MAX_PATH_LENGTH]; + str_format(aBuf, sizeof(aBuf), "skins/%s.json", m_pSelectedSkin->m_aName); + if(Storage()->RemoveFile(aBuf, IStorage::TYPE_SAVE)) + { + m_pClient->m_pSkins->RemoveSkin(m_pSelectedSkin); + m_RefreshSkinSelector = true; + m_pSelectedSkin = 0; + } else - s_CustomSkinMenu = true; + PopupMessage(Localize("Error"), Localize("Unable to delete the skin"), Localize("Ok")); } } @@ -1530,7 +1532,10 @@ void CMenus::RenderSettingsControls(CUIRect MainView) Button = BottomView; static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) - m_pClient->m_pBinds->SetDefaults(); + { + PopupConfirm(Localize("Reset controls"), Localize("Are you sure that you want to reset the controls to their defaults?"), + Localize("Reset"), Localize("Cancel"), &CMenus::ResetSettingsControls); + } } float CMenus::RenderSettingsControlsStats(CUIRect View) @@ -1642,18 +1647,17 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, void CMenus::RenderSettingsGraphics(CUIRect MainView) { - bool CheckSettings = false; bool CheckFullscreen = false; #ifdef CONF_PLATFORM_MACOSX CheckFullscreen = true; #endif - static int s_GfxFullscreen = Config()->m_GfxFullscreen; - static int s_GfxScreenWidth = Config()->m_GfxScreenWidth; - static int s_GfxScreenHeight = Config()->m_GfxScreenHeight; - static int s_GfxFsaaSamples = Config()->m_GfxFsaaSamples; - static int s_GfxTextureQuality = Config()->m_GfxTextureQuality; - static int s_GfxTextureCompression = Config()->m_GfxTextureCompression; + static const int s_GfxFullscreen = Config()->m_GfxFullscreen; + static const int s_GfxScreenWidth = Config()->m_GfxScreenWidth; + static const int s_GfxScreenHeight = Config()->m_GfxScreenHeight; + static const int s_GfxFsaaSamples = Config()->m_GfxFsaaSamples; + static const int s_GfxTextureQuality = Config()->m_GfxTextureQuality; + static const int s_GfxTextureCompression = Config()->m_GfxTextureCompression; CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView, Background; @@ -1697,7 +1701,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft); static int s_ButtonGfxFullscreen = 0; if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), Config()->m_GfxFullscreen, &Button)) - CheckSettings |= !Client()->ToggleFullscreen(); + m_CheckVideoSettings |= !Client()->ToggleFullscreen(); if(!Config()->m_GfxFullscreen) { @@ -1757,7 +1761,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) Config()->m_GfxFsaaSamples = 0; else Config()->m_GfxFsaaSamples *= 2; - CheckSettings = true; + m_CheckVideoSettings = true; } } @@ -1799,7 +1803,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), Config()->m_GfxTextureQuality, &Button)) { Config()->m_GfxTextureQuality ^= 1; - CheckSettings = true; + m_CheckVideoSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); @@ -1808,7 +1812,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), Config()->m_GfxTextureCompression, &Button)) { Config()->m_GfxTextureCompression ^= 1; - CheckSettings = true; + m_CheckVideoSettings = true; } Texture.HSplitTop(Spacing, 0, &Texture); @@ -1866,8 +1870,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) static CListBox s_RecListBox; static CListBox s_OthListBox; - CheckSettings |= DoResolutionList(&ListRec, &s_RecListBox, m_lRecommendedVideoModes); - CheckSettings |= DoResolutionList(&ListOth, &s_OthListBox, m_lOtherVideoModes); + m_CheckVideoSettings |= DoResolutionList(&ListRec, &s_RecListBox, m_lRecommendedVideoModes); + m_CheckVideoSettings |= DoResolutionList(&ListOth, &s_OthListBox, m_lOtherVideoModes); } // reset button @@ -1882,38 +1886,21 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->m_GfxScreenWidth = Graphics()->DesktopWidth(); - Config()->m_GfxScreenHeight = Graphics()->DesktopHeight(); - Config()->m_GfxBorderless = 0; - Config()->m_GfxFullscreen = 1; - Config()->m_GfxVsync = 1; - Config()->m_GfxFsaaSamples = 0; - Config()->m_GfxTextureQuality = 1; - Config()->m_GfxTextureCompression = 0; - Config()->m_GfxHighDetail = 1; - - if(Config()->m_GfxDisplayAllModes) - { - Config()->m_GfxDisplayAllModes = 0; - UpdateVideoModeSettings(); - } - - CheckSettings = true; + PopupConfirm(Localize("Reset graphics settings"), Localize("Are you sure that you want to reset the graphics settings to their defaults?"), + Localize("Reset"), Localize("Cancel"), &CMenus::ResetSettingsGraphics); } // check if the new settings require a restart - if(CheckSettings) + if(m_CheckVideoSettings) { - if(s_GfxScreenWidth == Config()->m_GfxScreenWidth && - s_GfxScreenHeight == Config()->m_GfxScreenHeight && - s_GfxFsaaSamples == Config()->m_GfxFsaaSamples && - s_GfxTextureQuality == Config()->m_GfxTextureQuality && - s_GfxTextureCompression == Config()->m_GfxTextureCompression && - (!CheckFullscreen || s_GfxFullscreen == Config()->m_GfxFullscreen) - ) - m_NeedRestartGraphics = false; - else - m_NeedRestartGraphics = true; + m_NeedRestartGraphics = + s_GfxScreenWidth != Config()->m_GfxScreenWidth || + s_GfxScreenHeight != Config()->m_GfxScreenHeight || + s_GfxFsaaSamples != Config()->m_GfxFsaaSamples || + s_GfxTextureQuality != Config()->m_GfxTextureQuality || + s_GfxTextureCompression != Config()->m_GfxTextureCompression || + (CheckFullscreen && s_GfxFullscreen != Config()->m_GfxFullscreen); + m_CheckVideoSettings = false; } } @@ -2067,16 +2054,68 @@ void CMenus::RenderSettingsSound(CUIRect MainView) static CButtonContainer s_ResetButton; if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - Config()->m_SndEnable = 1; - Config()->m_SndInit = 1; - Config()->m_SndMusic = 1; - Config()->m_SndNonactiveMute = 0; - Config()->m_SndRate = 48000; - Config()->m_SndVolume = 100; - UpdateMusicState(); + PopupConfirm(Localize("Reset sound settings"), Localize("Are you sure that you want to reset the sound settings to their defaults?"), + Localize("Reset"), Localize("Cancel"), &CMenus::ResetSettingsSound); } } +void CMenus::ResetSettingsGeneral() +{ + Config()->m_ClDynamicCamera = 0; + Config()->m_ClMouseMaxDistanceStatic = 400; + Config()->m_ClMouseMaxDistanceDynamic = 1000; + Config()->m_ClMouseFollowfactor = 60; + Config()->m_ClMouseDeadzone = 300; + Config()->m_ClAutoswitchWeapons = 1; + Config()->m_ClShowhud = 1; + Config()->m_ClFilterchat = 0; + Config()->m_ClNameplates = 1; + Config()->m_ClNameplatesAlways = 1; + Config()->m_ClNameplatesSize = 50; + Config()->m_ClNameplatesTeamcolors = 1; + Config()->m_ClAutoDemoRecord = 0; + Config()->m_ClAutoDemoMax = 10; + Config()->m_ClAutoScreenshot = 0; + Config()->m_ClAutoScreenshotMax = 10; +} + +void CMenus::ResetSettingsControls() +{ + m_pClient->m_pBinds->SetDefaults(); +} + +void CMenus::ResetSettingsGraphics() +{ + Config()->m_GfxScreenWidth = Graphics()->DesktopWidth(); + Config()->m_GfxScreenHeight = Graphics()->DesktopHeight(); + Config()->m_GfxBorderless = 0; + Config()->m_GfxFullscreen = 1; + Config()->m_GfxVsync = 1; + Config()->m_GfxFsaaSamples = 0; + Config()->m_GfxTextureQuality = 1; + Config()->m_GfxTextureCompression = 0; + Config()->m_GfxHighDetail = 1; + + if(Config()->m_GfxDisplayAllModes) + { + Config()->m_GfxDisplayAllModes = 0; + UpdateVideoModeSettings(); + } + + m_CheckVideoSettings = true; +} + +void CMenus::ResetSettingsSound() +{ + Config()->m_SndEnable = 1; + Config()->m_SndInit = 1; + Config()->m_SndMusic = 1; + Config()->m_SndNonactiveMute = 0; + Config()->m_SndRate = 48000; + Config()->m_SndVolume = 100; + UpdateMusicState(); +} + void CMenus::RenderSettings(CUIRect MainView) { // handle which page should be rendered From aa4539b9f26a35b916d219094846199e01c57b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 27 Apr 2020 17:04:40 +0200 Subject: [PATCH 300/479] add forward/backward skipping to demo player, refactoring --- src/game/client/components/menus.h | 12 +- src/game/client/components/menus_demo.cpp | 172 +++++++++++++++------- 2 files changed, 127 insertions(+), 57 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index f83f43ad..bfcee50f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -97,8 +97,6 @@ class CMenus : public CComponent float ButtonFade(CButtonContainer *pBC, float Seconds, int Checked=0); - - int DoButton_DemoPlayer(CButtonContainer *pBC, const char *pText, const CUIRect *pRect); int DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners=CUI::CORNER_ALL, float r=5.0f, bool Fade=true); int DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect); int DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, const CUIRect *pRect, bool Blend=true); @@ -472,6 +470,16 @@ class CMenus : public CComponent bool m_Valid; CDemoHeader m_Info; + int GetMarkerCount() const + { + if(!m_Valid || !m_InfosLoaded) + return -1; + return ((m_Info.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | + ((m_Info.m_aNumTimelineMarkers[1]<<16)&0xFF0000) | + ((m_Info.m_aNumTimelineMarkers[2]<<8)&0xFF00) | + (m_Info.m_aNumTimelineMarkers[3]&0xFF); + } + bool operator<(const CDemoItem &Other) const { return !str_comp(m_aFilename, "..") ? true diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 71877cc1..19831bf4 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -20,15 +20,7 @@ #include "maplayers.h" #include "menus.h" -int CMenus::DoButton_DemoPlayer(CButtonContainer *pBC, const char *pText, const CUIRect *pRect) -{ - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds); - RenderTools()->DrawUIRect(pRect, vec4(1,1,1, 0.5f+(Fade/Seconds)*0.25f), CUI::CORNER_ALL, 5.0f); - UI()->DoLabel(pRect, pText, 14.0f, CUI::ALIGN_CENTER); - return UI()->DoButtonLogic(pBC->GetID(), pRect); -} void CMenus::RenderDemoPlayer(CUIRect MainView) { @@ -38,8 +30,8 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) const float ButtonbarHeight = 20.0f; const float NameBarHeight = 20.0f; const float Margins = 5.0f; - float TotalHeight; + float TotalHeight; if(m_MenuActive) TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3; else @@ -56,22 +48,27 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) CUIRect SeekBar, ButtonBar, NameBar; + const bool CtrlDown = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL); + static bool s_LastCtrlDown = CtrlDown; + int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick; int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick; + int64 Now = time_get(); // we can toggle the seekbar using CTRL - if(!m_MenuActive && (Input()->KeyPress(KEY_LCTRL) || Input()->KeyPress(KEY_RCTRL))) + if(!m_MenuActive && !s_LastCtrlDown && CtrlDown) { if (m_SeekBarActive) m_SeekBarActive = false; else { m_SeekBarActive = true; - m_SeekBarActivatedTime = time_get(); // stores at which point of time the seekbar was activated, so we can automatically hide it after few seconds + m_SeekBarActivatedTime = Now; // stores at which point of time the seekbar was activated, so we can automatically hide it after few seconds } } + s_LastCtrlDown = CtrlDown; - if(m_SeekBarActivatedTime < time_get() - 5*time_freq()) + if(m_SeekBarActivatedTime < Now - 5*time_freq()) m_SeekBarActive = false; if(m_MenuActive) @@ -81,28 +78,27 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar); NameBar.HSplitTop(4.0f, 0, &NameBar); m_SeekBarActive = true; - m_SeekBarActivatedTime = time_get(); + m_SeekBarActivatedTime = Now; } else SeekBar = MainView; // do seekbar + float PositionToSeek = -1.0f; if(m_SeekBarActive || m_MenuActive) { - static int s_SeekBarID = 0; static bool s_PausedBeforeSeeking = false; static float s_PrevAmount = -1.0f; - char aBuffer[128]; const float Rounding = 5.0f; // draw seek bar - RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, Rounding); + RenderTools()->DrawUIRect(&SeekBar, vec4(0.0f, 0.0f, 0.0f, 0.5f), CUI::CORNER_ALL, Rounding); // draw filled bar float Amount = CurrentTick/(float)TotalTicks; CUIRect FilledBar = SeekBar; FilledBar.w = (FilledBar.w-2*Rounding)*Amount + 2*Rounding; - RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, Rounding); + RenderTools()->DrawUIRect(&FilledBar, vec4(1.0f, 1.0f , 1.0f, 0.5f), CUI::CORNER_ALL, Rounding); // draw markers for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++) @@ -117,6 +113,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } // draw time + char aBuffer[64]; 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); @@ -125,7 +122,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // do the logic bool Inside = UI()->MouseInside(&SeekBar); - if(UI()->CheckActiveItem(&s_SeekBarID)) + if(UI()->CheckActiveItem(&s_PrevAmount)) { if(!UI()->MouseButton(0)) { @@ -140,20 +137,15 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) if(absolute(s_PrevAmount-Amount) >= (0.1f/UI()->Screen()->w)) { s_PrevAmount = Amount; - m_pClient->OnReset(); - m_pClient->m_SuppressEvents = true; - DemoPlayer()->SetPos(Amount); - m_pClient->m_SuppressEvents = false; - m_pClient->m_pMapLayersBackGround->EnvelopeUpdate(); - m_pClient->m_pMapLayersForeGround->EnvelopeUpdate(); + PositionToSeek = Amount; } } } - else if(UI()->HotItem() == &s_SeekBarID) + else if(UI()->HotItem() == &s_PrevAmount) { if(UI()->MouseButton(0)) { - UI()->SetActiveItem(&s_SeekBarID); + UI()->SetActiveItem(&s_PrevAmount); s_PausedBeforeSeeking = pInfo->m_Paused; if(!pInfo->m_Paused) DemoPlayer()->Pause(); @@ -161,19 +153,21 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } if(Inside) - UI()->SetHotItem(&s_SeekBarID); + UI()->SetHotItem(&s_PrevAmount); } + // rewind when reaching the end if(CurrentTick == TotalTicks) { m_pClient->OnReset(); DemoPlayer()->Pause(); - DemoPlayer()->SetPos(0); + PositionToSeek = 0.0f; } - bool IncreaseDemoSpeed = false, DecreaseDemoSpeed = false; + bool IncreaseDemoSpeed = Input()->KeyPress(KEY_MOUSE_WHEEL_UP) || Input()->KeyPress(KEY_PLUS) || Input()->KeyPress(KEY_KP_PLUS); + bool DecreaseDemoSpeed = Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN) || Input()->KeyPress(KEY_MINUS) || Input()->KeyPress(KEY_KP_MINUS); - //add spacebar for toggling Play/Pause + // add spacebar for toggling Play/Pause if(Input()->KeyPress(KEY_SPACE)) { if(!pInfo->m_Paused) @@ -182,6 +176,78 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) DemoPlayer()->Unpause(); } + // skip forward/backward using left/right arrow keys + const bool ShiftDown = Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT); + const bool SkipBackwards = Input()->KeyPress(KEY_LEFT); + const bool SkipForwards = Input()->KeyPress(KEY_RIGHT); + if(SkipBackwards || SkipForwards) + { + int DesiredTick = 0; + if(CtrlDown) + { + // Go to previous/next marker if ctrl is held. + // Go to start/end if there is no marker. + + // Threshold to consider all ticks close to a marker to be that markers position. + // Necessary, as setting the demo players position does not set it to exactly the desired tick. + const int Threshold = 10; + + if(SkipForwards) + { + DesiredTick = TotalTicks-1; // jump to end if no markers, or after last one + for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++) + { + const int MarkerTick = pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick; + if(abs(MarkerTick-CurrentTick) < Threshold) + { + if(i+1 < pInfo->m_NumTimelineMarkers) + DesiredTick = pInfo->m_aTimelineMarkers[i+1]-pInfo->m_FirstTick; + break; + } + else if(CurrentTick < MarkerTick) + { + DesiredTick = MarkerTick; + break; + } + } + } + else + { + DesiredTick = 0; // jump to start if no markers, or before first one + for(int i = pInfo->m_NumTimelineMarkers-1; i >= 0; i--) + { + const int MarkerTick = pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick; + if(abs(MarkerTick-CurrentTick) < Threshold) + { + if(i > 0) + DesiredTick = pInfo->m_aTimelineMarkers[i-1]-pInfo->m_FirstTick; + break; + } + else if(CurrentTick > MarkerTick) + { + DesiredTick = MarkerTick; + break; + } + } + } + + // Skipping to previous marker/the end is inconvenient if demo continues running + DemoPlayer()->Pause(); + } + else + { + // Skip longer time if shift is held + const int SkippedTicks = (ShiftDown ? 30 : 5) * SERVER_TICK_SPEED; + DesiredTick = CurrentTick + (SkipBackwards ? -1 : 1) * SkippedTicks; + } + + PositionToSeek = clamp(DesiredTick, 0, TotalTicks-1)/(float)TotalTicks; + + // Show the seek bar for a few seconds after skipping + m_SeekBarActive = true; + m_SeekBarActivatedTime = Now; + } + if(m_MenuActive) { // do buttons @@ -202,7 +268,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } // stop button - ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static CButtonContainer s_ResetButton; @@ -210,7 +275,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) { m_pClient->OnReset(); DemoPlayer()->Pause(); - DemoPlayer()->SetPos(0); + PositionToSeek = 0.0f; } // slowdown @@ -230,16 +295,13 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // speed meter ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar); char aBuffer[64]; - if(pInfo->m_Speed >= 1.0f) - str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed); - else - str_format(aBuffer, sizeof(aBuffer), "x%.2f", pInfo->m_Speed); + str_format(aBuffer, sizeof(aBuffer), pInfo->m_Speed >= 1.0f ? "x%.0f" : "x%.2f", pInfo->m_Speed); UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, CUI::ALIGN_LEFT); // close button ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button); static CButtonContainer s_ExitButton; - if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), &Button)) + if(DoButton_Menu(&s_ExitButton, Localize("Close"), 0, &Button)) Client()->Disconnect(); // demo name @@ -253,7 +315,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) TextRender()->TextEx(&Cursor, aBuf, -1); } - if(IncreaseDemoSpeed || Input()->KeyPress(KEY_MOUSE_WHEEL_UP) || Input()->KeyPress(KEY_PLUS) || Input()->KeyPress(KEY_KP_PLUS)) + if(IncreaseDemoSpeed) { if(pInfo->m_Speed < 0.1f) DemoPlayer()->SetSpeed(0.1f); else if(pInfo->m_Speed < 0.25f) DemoPlayer()->SetSpeed(0.25f); @@ -264,7 +326,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f); else DemoPlayer()->SetSpeed(8.0f); } - else if(DecreaseDemoSpeed || Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN) || Input()->KeyPress(KEY_MINUS) || Input()->KeyPress(KEY_KP_MINUS)) + else if(DecreaseDemoSpeed) { if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f); else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f); @@ -275,6 +337,16 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) else if(pInfo->m_Speed > 0.1f) DemoPlayer()->SetSpeed(0.1f); else DemoPlayer()->SetSpeed(0.05f); } + + if(PositionToSeek >= 0.0f && PositionToSeek <= 1.0f) + { + m_pClient->OnReset(); + m_pClient->m_SuppressEvents = true; + DemoPlayer()->SetPos(PositionToSeek); + m_pClient->m_SuppressEvents = false; + m_pClient->m_pMapLayersBackGround->EnvelopeUpdate(); + m_pClient->m_pMapLayersForeGround->EnvelopeUpdate(); + } } int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser) @@ -322,15 +394,6 @@ void CMenus::DemolistOnUpdate(bool Reset) m_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_lDemos[m_DemolistSelectedIndex].m_IsDir; } -inline int DemoGetMarkerCount(CDemoHeader Demo) -{ - int DemoMarkerCount = ((Demo.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | - ((Demo.m_aNumTimelineMarkers[1]<<16)&0xFF0000) | - ((Demo.m_aNumTimelineMarkers[2]<<8)&0xFF00) | - (Demo.m_aNumTimelineMarkers[3]&0xFF); - return DemoMarkerCount; -} - void CMenus::RenderDemoList(CUIRect MainView) { CUIRect BottomView; @@ -394,9 +457,7 @@ void CMenus::RenderDemoList(CUIRect MainView) CListboxItem Item = s_ListBox.DoNextItem(&r.front(), (&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex); // marker count const CDemoItem& DemoItem = r.front(); - int DemoMarkerCount = 0; - if(DemoItem.m_Valid && DemoItem.m_InfosLoaded) - DemoMarkerCount = DemoGetMarkerCount(DemoItem.m_Info); + const int DemoMarkerCount = DemoItem.GetMarkerCount(); if(Item.m_Visible) { @@ -408,9 +469,10 @@ void CMenus::RenderDemoList(CUIRect MainView) vec4 IconColor = vec4(1, 1, 1, 1); if(!DemoItem.m_IsDir) { - IconColor = vec4(0.6f, 0.6f, 0.6f, 1.0f); // not loaded - if(DemoItem.m_Valid && DemoItem.m_InfosLoaded) - IconColor = DemoMarkerCount > 0 ? vec4(0.5, 1, 0.5, 1) : vec4(1,1,1,1); + if(DemoMarkerCount < 0) + IconColor = vec4(0.6f, 0.6f, 0.6f, 1.0f); // not loaded + else if(DemoMarkerCount > 0) + IconColor = vec4(0.5, 1, 0.5, 1); } DoIconColor(IMAGE_FILEICONS, DemoItem.m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); @@ -587,7 +649,7 @@ float CMenus::RenderDemoDetails(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - const int MarkerCount = DemoGetMarkerCount(m_lDemos[m_DemolistSelectedIndex].m_Info); + const int MarkerCount = m_lDemos[m_DemolistSelectedIndex].GetMarkerCount(); str_format(aBuf, sizeof(aBuf), "%d", MarkerCount); if(MarkerCount > 0) TextRender()->TextColor(0.5, 1, 0.5, 1); From b28147ddaf39d0bf586a8b63df32b8550a9fae17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Piwi=C5=84ski?= Date: Thu, 30 Apr 2020 16:42:01 +0200 Subject: [PATCH 301/479] [bind] remove unneeded space at the end of string --- src/game/client/components/binds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 14658a32..506478bc 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -437,7 +437,7 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) if(pSelf->m_aaaKeyBindings[Key][Modifier][0] == 0) { // explicitly unbind keys that were unbound by the user - str_format(aBuffer, sizeof(aBuffer), "unbind %s%s ", GetModifierName(Modifier), pSelf->Input()->KeyName(Key)); + str_format(aBuffer, sizeof(aBuffer), "unbind %s%s", GetModifierName(Modifier), pSelf->Input()->KeyName(Key)); pConfigManager->WriteLine(aBuffer); } } From 1688ad4210f105d0d0cd15adef6b1eac3e75d5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Piwi=C5=84ski?= Date: Fri, 1 May 2020 16:00:58 +0200 Subject: [PATCH 302/479] [bind] remove unneeded space at the end of string v2 --- src/game/client/components/binds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 506478bc..2b3cece1 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -411,7 +411,7 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) if(pSelf->m_aaaKeyBindings[i][m][0] == 0) continue; - str_format(aBuffer, sizeof(aBuffer), "bind %s%s ", GetModifierName(m), pSelf->Input()->KeyName(i)); + str_format(aBuffer, sizeof(aBuffer), "bind %s%s", GetModifierName(m), pSelf->Input()->KeyName(i)); // process the string. we need to escape some characters const char *pSrc = pSelf->m_aaaKeyBindings[i][m]; From 0b9726106dd6126aa65cf818b942dc509467f118 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Fri, 1 May 2020 23:44:33 +0200 Subject: [PATCH 303/479] Add network.png by @leovilok Co-authored-by: lvgx --- datasrc/ui/icons/network.png | Bin 0 -> 3961 bytes license.txt | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 datasrc/ui/icons/network.png diff --git a/datasrc/ui/icons/network.png b/datasrc/ui/icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..5af6416c72d67cde3967db95e5a906f50f7dc06d GIT binary patch literal 3961 zcmV-<4~FoGP)B3=lyn6 z&*rAxv>a4ywRY>7b!F>pS!d7Ly7iQ)RK<^K+c^~}ln)aEgitV{fshZ9{gLO@*O*Vp z3n6mP$vOFalHc#S_j&HU@4ZieX_=P$TBtC^6$fAz00{sG03(2I00ZGp03X0Z0OCEo zt_9G{eu5Wf;J*wYe(~bPF|Dnw&zQ~Tzne^^zcn>AZBr_hGXNw4NDfDp=L5(FK(AZ3 zZtc*}kjCL6eSLkO2n2#60EOiJVIu+n3jxrjrKR5=9v<#?c#xM~dTAQ~8o-yr#RLQZ z766FZxN+mGS6_Yg#mLCWS)SgUo}QjW?ux^K00w;YrcImVue|cgfyl_nL~kFseED)K zxjQ`7)jk414gh-d=FLAcnM^u|59#RWc%P{M*QdJXM*zqLK$n-7mzqqbK40LqTJ47l zh2mjCKzt~JlK@Zv$Rz5$06+!+IRFtG{MM~oOGidV`~iQF1wK7g9idnNX#k>qyw3(e zux;BmMO9T*wNNOOd3&=~tG$?$lk=#bj9b8*`ZghTD9in$&=L`9UbrK zbh?kUTJ49;&CSPaYioC;r>Cz3Kvz^$lvym60beuU+1YtoCX+2EW6ufIIAlHmIw2up z#nr1<-xwVoHG2YNu~-aOu3Y)E#bVL>0sfR!DqTjvr-d~5+}zyN{r&y_a|B6LD%FW8 z1%6;);6@O^pJahgz2CsIXMXm51-`AV?O$TCcqsv|2x;(nd3lfM_4=TJHy8{p;{nf~ zAn=(0;`8$IBz1LlRZ^)mGgyO*M50);+1zmE%$WfIy#R*p3$=GKfp>`pEC@C5nT(U8 z)9F5Ta3of%^$TJKg@Jmvd=A0SBY}ql02LP(r^(OHFXHid!eDII8ytWd3kw~ojZ4C zut>0P-@d(Z-@bhnqoboiU#M(0nz4*;W245KT#y~^z>X{ZGobY1kaT@ z==J&=+1c5v$#^LfJ^K%h#ls7hCKwEc=EaK_KT5`#H__me0MJUMa@AM@8=K8$tgNiu zLVo<>KuK@`KYyZgn-Szk(_LL%4P&)k7ZUu|gvkaEl4+rj9Xs~R@vh#1nnNgn2Y@^P zbYEZJm0;}QE+lv~hfo18U~J#vaEu1ajq_y=p#mP{!Uer!$Bv%_JEZkQ!p@yLf0CD% z_edy!2Y?s=^#1+(w{j8Jdol+u!3P=*jsk#6r5fadT|S>L-m+!O?#jx_EE1|a0N6>4 z-$Wiys_+0Tk;!DsZ8n>Us|=4$r~8;S^O;<#eV`g(2Qb**-*4;b>AAqg4>A}GO(i8I zJIKR60H1O>^J7Vfd=3D|jvf1Zuz$?p;9yHhNy+w0mo6D6O6>(>@B$M7U|?XtWVhSR zJRVOJteGz^E`DYr!H>lS&ILek+qP|k*=+6);>C@S+2_4!N)AY6hS_ZX{JsQVUS953 zSxUHpU&ICY{{H@Jxw*NkLm50DqyqDaC!YABKh;>Rt*!6Y)z$6uW+HaG-P+XD^tN0s zUoj=Xmz9;RH({SOICA930dM7}0HD!mPGx3h{?=$T+5s3y%-{{!Fo1Rd z{h>DV6o9XQR9z1b4|n-dkW|mA%t&$Z7ak;JE+DF&20)4smQ(=r+O=!HH#9Wl5BLv4 zy(}dV5dv5ul}eZC_4+1X;JdoIPKOhC0FVKoYieqK;RpCLtRlqJsSKJO3`GJ!T3T9? zw-5C6^qgC?Xwk0z{(c((HGrGpLVyVXT3T9Ep5Cn0YA-HaxbQc3QAMOPB zIzOPx;c&E46y-J+nCimx635dt9n;p<_RPr0$lJri!^f^&yH=i_o-PKEL{ZeNa8&u* z+3V8M((k)V=IC^~%jEok#bGw_cN(cl_FC&HkMY6_FO-vbCWg&iD2M8C@baZrtRd+D=z5>t4C!c&$gFCec_lMfE#cVbY5c~IeZrFqc z1rCP;aCVc%0l<+XM>a^MQchZ3ghFBLv(G-8LGVRSIspVc91ce>oX6Q<#flYw)M~XC zxcbhVoE+u?&WuSVfB_ExYPA{)g`y3Brnk4(nw_1!qr1EN92eg!kw~IhNs`GSfDK-w z(V(!f5Nfp=a2{x+>Fw>cE?TtcH(ZclGMShI)9jN%02@32EMLBy0nf-?Bm~LZJXjPv?>(L?!^CznU-> z67+g~b3s8t2_~U%i}CR0u)wF_PDLnl%Lfq21qlNK1J_xN)R~h3o@Rxf3IMcNEMEHA zXP^DUWHR;c+qdth3G&;J|h_eSt#(YJyjDaHIB<2cBI)%8+pU`0+#Tnj-_$1h*uF68I)} zWwZP2OsW84~L2>-PkKgxi{+R4P|Z*31W#z~q30G;rKY z>`ms6C6g1NIeZO(z#R$6$;oJIYhy^5aPX-t@B!!W*d&}ebEeAO?!dZoo9gN|GvJx$ z3HWSsX#d)+l(FaZoZcBrkbg-WHmE1n>!HO3TXa!o)M0J@=} z;qZ8)G*6mfwOWn4cI|qC@!`Eiltgk_1bmfC@B#pZQmJ&AKc_hdO2YBu#}8SpR^y&M zdo~j=c>wq|H8tMA%K*?anRvNOCT2WO8CL|z0MLgH9r{@?)7ESfR;^m~DBCFlfQ*a` zPv8O4&iAi3^DF=P*MdFdvx~SQAeq?g!C>d^*(8uHPy_%9g~FZ9GZG7cmPiCk_3b5U zeS3*oEEX`Az`isVfWC5qe3D@edSXE?moK?`_393pOeP@U<;ls(sIRYQ!fB`TLEW{; zD*)iN0}G2JQT!B16hGxphZYvHUkf$?4gfHl&1Npt%Y_7mMx#laGiQz`@G;CRKU_5P z2h5Wzi)L;R2tX0-hzT|UCIDz{ZB=n)V{*BCNnKrCDKm={Ma8=Te|v_H9?U6-juvDv zPew-z(hpZ<=Z;kid=W4R0F{-M|FzrgoM^$VTeq%n+_VOx@sX>`kSq%$k&MNe&+yTOn33KRw2&o<9xv|twQ)EE0r zfC7NDw6rwg<(FTs7K_DR|CLFtR-ZB$3@yIC4DmlF4Kdb#-<7B@&6(?WDcE{ok3HnJ?_!yZ2qWT;3QP z8*3K|g^>b*KtfTJV`OARr_pE{jvhVw;_B6_-`4B(qj3K1Ws4u+`6T_ud+SK!a?2kYG z_$2_BynMt0XQ#Q=PaH`A1mAshR$SWbsFi`5+q`s1$%?{+znnPRtB3P%y43!dKqLUn zo;};E+GsSIQ%a?B4*}l}-~xcp;5=l_%$i*@oPToKLdfwK{B70!bw%b6c$9BDzGna) zCEoMvdEa51l0O6t13+6_n@7LDySw{rc6Rn|a$3wyIL{EU5jATBa1p>60H?|QYXEvc z4r25-JOB_u=f}l7G*|M-SQlMoX3TeUvty&!i>WUH1_9WgeDcW)w{G2Pa(!b@PtSRm zlOwnYkSJ#M_wQD&<@2e?u?{2<@S+adA=7y|3TNkKC%Esmv2aL$1=BJu_sIVN<$asq TA(18&00000NkvXXu0mjf7dC=3 literal 0 HcmV?d00001 diff --git a/license.txt b/license.txt index 1be4a824..8129bcae 100644 --- a/license.txt +++ b/license.txt @@ -18,13 +18,13 @@ freely, subject to the following restrictions: ------------------------------------------------------------------------ -All content under 'data' and 'datasrc' except the font (which has its own license) is -released under CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/). +All content under 'data' and 'datasrc' except the font (which has its own +license) is released under CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/). Authors: android272, Chi11y (chi1), Crises, Daniel, Echchouik, Fisico, - Landil, Lappi, LordSk, maikka, matricks, Pocram, red_com, - serpis, SkizZ, somerunce, Sonix, Stephanator, teetow, Ubu, - Zatline + leovilok, Landil, Lappi, LordSk, maikka, matricks, Pocram, + red_com, serpis, SkizZ, somerunce, Sonix, Stephanator, teetow, + Ubu, Zatline ------------------------------------------------------------------------ From 2057cda40430ecc22d7bca9fa887ed9a8f86a097 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 2 May 2020 00:59:00 +0200 Subject: [PATCH 304/479] Implement a network stability indicator (based on prediction time) --- datasrc/content.py | 7 ++++ src/engine/client.h | 3 ++ src/engine/client/client.cpp | 17 ++++++-- src/engine/client/client.h | 3 ++ src/game/client/components/hud.cpp | 47 ++++++++++++++-------- src/game/client/components/hud.h | 1 - src/game/client/components/scoreboard.cpp | 48 +++++++++++++++++++++-- src/game/client/components/scoreboard.h | 4 +- 8 files changed, 106 insertions(+), 24 deletions(-) diff --git a/datasrc/content.py b/datasrc/content.py index a4375402..0a283f0b 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -245,6 +245,7 @@ def FileList(format, num): image_toolicons = Image("toolicons", "ui/icons/tools.png", 1) image_arrowicons = Image("arrowicons", "ui/icons/arrows.png", 1) image_friendicons = Image("friendicons", "ui/icons/friend.png", 1) +image_networkicons = Image("networkicons", "ui/icons/network.png", 1) image_levelicons = Image("levelicons", "ui/icons/level.png", 1) image_sidebaricons = Image("sidebaricons", "ui/icons/sidebar.png", 1) image_chatwhisper = Image("chatwhisper", "ui/icons/chat_whisper.png", 1) @@ -271,6 +272,7 @@ def FileList(format, num): container.images.Add(image_toolicons) container.images.Add(image_arrowicons) container.images.Add(image_friendicons) +container.images.Add(image_networkicons) container.images.Add(image_levelicons) container.images.Add(image_sidebaricons) container.images.Add(image_chatwhisper) @@ -308,6 +310,7 @@ def FileList(format, num): set_soundicons = SpriteSet("guiicons", image_soundicons, 1, 2) set_arrowicons = SpriteSet("arrowicons", image_arrowicons, 4, 3) set_friendicons = SpriteSet("friendicons", image_friendicons, 2, 2) +set_networkicons = SpriteSet("networkicons", image_networkicons, 1, 2) set_levelicons = SpriteSet("levelicons", image_levelicons, 4, 4) set_sidebaricons = SpriteSet("sidebaricons", image_sidebaricons, 4, 2) set_timerclock = SpriteSet("timerclock", image_timerclock, 1, 2) @@ -333,6 +336,7 @@ def FileList(format, num): container.spritesets.Add(set_toolicons) container.spritesets.Add(set_arrowicons) container.spritesets.Add(set_friendicons) +container.spritesets.Add(set_networkicons) container.spritesets.Add(set_levelicons) container.spritesets.Add(set_sidebaricons) container.spritesets.Add(set_timerclock) @@ -536,6 +540,9 @@ def FileList(format, num): container.sprites.Add(Sprite("friend_x_a", set_friendicons, 1,0,1,1)) container.sprites.Add(Sprite("friend_x_b", set_friendicons, 1,1,1,1)) +container.sprites.Add(Sprite("network_good", set_networkicons, 0,0,1,1)) +container.sprites.Add(Sprite("network_bad", set_networkicons, 0,1,1,1)) + container.sprites.Add(Sprite("level_a_on", set_levelicons, 0,0,1,1)) container.sprites.Add(Sprite("level_a_a", set_levelicons, 0,1,1,1)) container.sprites.Add(Sprite("level_a_b", set_levelicons, 0,2,1,1)) diff --git a/src/engine/client.h b/src/engine/client.h index 369efdbe..01e83ebb 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -98,6 +98,9 @@ class IClient : public IInterface // networking virtual void EnterGame() = 0; + // network stats + virtual int GetInputtimeMarginStabilityScore() = 0; + // virtual const char *GetCurrentMapName() const = 0; virtual const char *GetCurrentMapPath() const = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 6c37515f..b8bc5f8b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -146,6 +146,8 @@ void CSmoothTime::Init(int64 Target) m_aAdjustSpeed[0] = 0.3f; m_aAdjustSpeed[1] = 0.3f; m_Graph.Init(0.0f, 0.5f); + m_SpikeCounter = 0; + m_BadnessScore = -100; } void CSmoothTime::SetAdjustSpeed(int Direction, float Value) @@ -204,11 +206,13 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD { // ignore this ping spike UpdateTimer = 0; - pGraph->Add(TimeLeft, 1,1,0); + pGraph->Add(TimeLeft, 1,1,0.3f); // yellow + m_BadnessScore += 10; } else { - pGraph->Add(TimeLeft, 1,0,0); + pGraph->Add(TimeLeft, 1,0.3f,0.3f); // red + m_BadnessScore += 50; if(m_aAdjustSpeed[AdjustDirection] < 30.0f) m_aAdjustSpeed[AdjustDirection] *= 2.0f; } @@ -218,7 +222,7 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD if(m_SpikeCounter) m_SpikeCounter--; - pGraph->Add(TimeLeft, 0,1,0); + pGraph->Add(TimeLeft, 0.3,1,0.3f); // green m_aAdjustSpeed[AdjustDirection] *= 0.95f; if(m_aAdjustSpeed[AdjustDirection] < 2.0f) @@ -227,6 +231,8 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD if(UpdateTimer) UpdateInt(Target); + + m_BadnessScore -= 1+m_BadnessScore/100; } CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotDelta) @@ -380,6 +386,11 @@ bool CClient::ConnectionProblems() const return m_NetClient.GotProblems() != 0; } +int CClient::GetInputtimeMarginStabilityScore() +{ + return m_PredictedTime.GetStabilityScore(); +} + void CClient::SendInput() { int64 Now = time_get(); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 36fafac8..7b59dcd6 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -36,6 +36,7 @@ class CSmoothTime CGraph m_Graph; int m_SpikeCounter; + int m_BadnessScore; // ranges between -100 (perfect) and MAX_INT float m_aAdjustSpeed[2]; // 0 = down, 1 = up public: @@ -43,6 +44,7 @@ class CSmoothTime void SetAdjustSpeed(int Direction, float Value); int64 Get(int64 Now); + inline int GetStabilityScore() const { return m_BadnessScore; } void UpdateInt(int64 Target); void Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustDirection); @@ -217,6 +219,7 @@ class CClient : public IClient, public CDemoPlayer::IListener virtual void Rcon(const char *pCmd); virtual bool ConnectionProblems() const; + virtual int GetInputtimeMarginStabilityScore(); virtual bool SoundInitFailed() const { return m_SoundInitFailed; } diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 11e40475..c9ab9fdb 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -46,7 +46,8 @@ bool CHud::IsLargeWarmupTimerShown() void CHud::RenderGameTimer() { - float Half = 300.0f*Graphics()->ScreenAspect()/2.0f; + float x = 300.0f*Graphics()->ScreenAspect()/2.0f; + float FontSize; if(!(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH)) { @@ -65,7 +66,7 @@ void CHud::RenderGameTimer() char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%d:%02d", Time/60, Time%60); - float FontSize = 10.0f; + FontSize = 10.0f; float w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); // last 60 sec red, last 10 sec blink if(m_pClient->m_GameInfo.m_TimeLimit && Time <= 60 && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) @@ -73,9 +74,36 @@ void CHud::RenderGameTimer() float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f; TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha); } - TextRender()->Text(0, Half-w/2, 2, FontSize, aBuf, -1.0f); + x = x-w/2; + TextRender()->Text(0, x, 2, FontSize, aBuf, -1.0f); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } + else + { + const char *pText = Localize("Sudden Death"); + FontSize = 12.0f; + float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); + x = x-w/2; + TextRender()->Text(0, x, 2, FontSize, pText, -1.0f); + } + + // render network indicator when 2/5 and under + const int NetScore = Client()->GetInputtimeMarginStabilityScore(); + if(NetScore > 250) + { + float Margin = 2.0f; + x = x-5.0f-FontSize-Margin*2; + Graphics()->BlendNormal(); + CUIRect RectBox = {x, 4-Margin, FontSize+2*Margin, FontSize+2*Margin}; + vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.3f); + RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_ALL, 1.0f); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); + Graphics()->QuadsBegin(); + RenderTools()->SelectSprite(SPRITE_NETWORK_BAD); + IGraphics::CQuadItem QuadItem(x+Margin, 4, FontSize, FontSize); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } } void CHud::RenderPauseTimer() @@ -145,18 +173,6 @@ void CHud::RenderDeadNotification() } } -void CHud::RenderSuddenDeath() -{ - if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH) - { - float Half = 300.0f*Graphics()->ScreenAspect()/2.0f; - const char *pText = Localize("Sudden Death"); - float FontSize = 12.0f; - float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - TextRender()->Text(0, Half-w/2, 2, FontSize, pText, -1.0f); - } -} - void CHud::RenderScoreHud() { // render small score hud @@ -850,7 +866,6 @@ void CHud::OnRender() RenderPauseTimer(); RenderStartCountdown(); RenderDeadNotification(); - RenderSuddenDeath(); RenderScoreHud(); RenderWarmupTimer(); RenderFps(); diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index 77b4a766..958a98c4 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -28,7 +28,6 @@ class CHud : public CComponent void RenderPauseTimer(); void RenderStartCountdown(); void RenderDeadNotification(); - void RenderSuddenDeath(); void RenderScoreHud(); void RenderSpectatorHud(); void RenderSpectatorNotification(); diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 32568cab..99684190 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -656,13 +656,13 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c return HeadlineHeight+LineHeight*(PlayerLines+1); } -void CScoreboard::RenderRecordingNotification(float x) +void CScoreboard::RenderRecordingNotification(float x, float w) { if(!m_pClient->DemoRecorder()->IsRecording()) return; //draw the box - CUIRect RectBox = {x, 0.0f, 180.0f, 50.0f}; + CUIRect RectBox = {x, 0.0f, w, 50.0f}; vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.4f); Graphics()->BlendNormal(); RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_B, 15.0f); @@ -679,6 +679,47 @@ void CScoreboard::RenderRecordingNotification(float x) TextRender()->Text(0, x+50.0f, 10.0f, 20.0f, aBuf, -1.0f); } +void CScoreboard::RenderNetworkQuality(float x, float w) +{ + //draw the box + CUIRect RectBox = {x, 0.0f, w, 50.0f}; + vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.4f); + const float LineHeight = 17.0f; + int Score = Client()->GetInputtimeMarginStabilityScore(); + + Graphics()->BlendNormal(); + RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_B, 15.0f); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); + Graphics()->QuadsBegin(); + RenderTools()->SelectSprite(SPRITE_NETWORK_GOOD); + IGraphics::CQuadItem QuadItem(x+20.0f, 12.5f, 25.0f, 25.0f); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + + x += 50.0f; + TextRender()->Text(0, x, 10.0f, 20.0f, "NET", -1.0f); + x += 50.0f; + float y = 0.0f; + + const int NumBars = 5; + int ScoreThresolds[NumBars] = {__INT_MAX__, 1000, 250, 50, -80}; + CUIRect BarRect = { + x - 4.0f, + y + LineHeight, + 6.0f, + LineHeight + }; + + for(int Bar = 0; Bar < NumBars && Score <= ScoreThresolds[Bar]; Bar++) + { + BarRect.x += BarRect.w + 3.0f; + CUIRect LocalBarRect = BarRect; + LocalBarRect.h = BarRect.h*(Bar+2)/(float)NumBars+1.0f; + LocalBarRect.y = BarRect.y + BarRect.h - LocalBarRect.h; + RenderTools()->DrawUIRect(&LocalBarRect, vec4(0.9f,0.9f,0.9f,1.0f), 0, 0); + } +} + void CScoreboard::OnRender() { // don't render scoreboard if menu or statboard is open @@ -771,7 +812,8 @@ void CScoreboard::OnRender() } } - RenderRecordingNotification((Width/7)*4); + RenderRecordingNotification((Width/7.0f)*4, 180.0f); + RenderNetworkQuality((Width/7.0f)*4 + 180.0f + 90.0f, 170.0f); } bool CScoreboard::IsActive() const diff --git a/src/game/client/components/scoreboard.h b/src/game/client/components/scoreboard.h index c7b8398d..fb55b136 100644 --- a/src/game/client/components/scoreboard.h +++ b/src/game/client/components/scoreboard.h @@ -1,3 +1,4 @@ + /* (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 GAME_CLIENT_COMPONENTS_SCOREBOARD_H @@ -9,7 +10,8 @@ class CScoreboard : public CComponent void RenderGoals(float x, float y, float w); float RenderSpectators(float x, float y, float w); float RenderScoreboard(float x, float y, float w, int Team, const char *pTitle, int Align); - void RenderRecordingNotification(float x); + void RenderRecordingNotification(float x, float w); + void RenderNetworkQuality(float x, float w); static void ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData); From 1afb43493135887ba69b01545ad6319c7c7595c8 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 2 May 2020 01:18:52 +0200 Subject: [PATCH 305/479] Fix cmake not happy about the new file --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65dfdd3a..8b809416 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1137,6 +1137,7 @@ set(EXPECTED_DATA ui/icons/friend.png ui/icons/level.png ui/icons/menu.png + ui/icons/network.png ui/icons/sidebar.png ui/icons/timer_clock.png ui/icons/tools.png From eeca7a915aecd9f1b9c29c6da141735c3b8b63ee Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 2 May 2020 01:21:51 +0200 Subject: [PATCH 306/479] Use floats --- src/engine/client/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b8bc5f8b..325b6794 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -222,7 +222,7 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD if(m_SpikeCounter) m_SpikeCounter--; - pGraph->Add(TimeLeft, 0.3,1,0.3f); // green + pGraph->Add(TimeLeft, 0.3f,1,0.3f); // green m_aAdjustSpeed[AdjustDirection] *= 0.95f; if(m_aAdjustSpeed[AdjustDirection] < 2.0f) From 49a8d53b81d836a136db7bb32317f437792c07f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 2 May 2020 13:22:01 +0200 Subject: [PATCH 307/479] improve initial loading render, improve loading smoothness --- src/game/client/components/countryflags.cpp | 3 +- src/game/client/components/maplayers.cpp | 16 ++++---- src/game/client/components/menus.cpp | 41 ++++++++++++--------- src/game/client/components/menus.h | 3 +- src/game/client/components/skins.cpp | 5 ++- src/game/client/gameclient.cpp | 27 +++++++++----- 6 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index bf6a2401..edd519c1 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -132,7 +132,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() int CCountryFlags::GetInitAmount() const { - return 15; + return 10; } void CCountryFlags::OnInit() @@ -140,7 +140,6 @@ void CCountryFlags::OnInit() // load country flags m_aCountryFlags.clear(); LoadCountryflagsIndexfile(); - m_pClient->m_pMenus->RenderLoading(5); if(!m_aCountryFlags.size()) { Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "countryflags", "failed to load country flags. folder='countryflags/'"); diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 7f8c0cef..35255c39 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -38,9 +38,6 @@ void CMapLayers::OnStateChange(int NewState, int OldState) void CMapLayers::LoadBackgroundMap() { - if(!Config()->m_ClShowMenuMap) - return; - int HourOfTheDay = time_houroftheday(); char aBuf[128]; // check for the appropriate day/night map @@ -73,7 +70,7 @@ void CMapLayers::LoadBackgroundMap() int CMapLayers::GetInitAmount() const { if(m_Type == TYPE_BACKGROUND) - return 15; + return 1 + (Config()->m_ClShowMenuMap ? 14 : 0); return 0; } @@ -84,8 +81,11 @@ void CMapLayers::OnInit() m_pMenuLayers = new CLayers; m_pMenuMap = CreateEngineMap(); m_pClient->m_pMenus->RenderLoading(1); - LoadBackgroundMap(); - m_pClient->m_pMenus->RenderLoading(14); + if(Config()->m_ClShowMenuMap) + { + LoadBackgroundMap(); + m_pClient->m_pMenus->RenderLoading(14); + } } m_pEggTiles = 0; @@ -531,7 +531,7 @@ void CMapLayers::BackgroundMapUpdate() { // unload map m_pMenuMap->Unload(); - - LoadBackgroundMap(); + if(Config()->m_ClShowMenuMap) + LoadBackgroundMap(); } } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 24fd0075..28baaf5e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1272,9 +1272,6 @@ void CMenus::RenderLoading(int WorkedAmount) // because that will slow down loading if we have vsync if(s_LastLoadRender > 0 && Now-s_LastLoadRender < Freq/60) return; - if(!Graphics()->IsIdle()) - return; - s_LastLoadRender = Now; static int64 s_LoadingStart = Now; @@ -1348,7 +1345,14 @@ void CMenus::RenderBackButton(CUIRect MainView) } } -int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::MenuImageCountingScan(const char *pName, int IsDir, int DirType, void *pUser) +{ + if(!IsDir && str_endswith(pName, ".png")) + (*(int *)pUser)++; + return 0; +} + +int CMenus::MenuImageLoadingScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(IsDir || !str_endswith(pName, ".png")) @@ -1426,6 +1430,7 @@ int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser str_format(aBuf, sizeof(aBuf), "load menu image %s", MenuImage.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); pSelf->m_lMenuImages.add(MenuImage); + pSelf->RenderLoading(5); return 0; } @@ -1473,21 +1478,23 @@ void CMenus::UpdateVideoModeSettings() int CMenus::GetInitAmount() const { - return 10; + int NumMenuImages = 0; + Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageCountingScan, &NumMenuImages); + + return 6 + 5 * NumMenuImages; } void CMenus::OnInit() { UpdateVideoModeSettings(); - RenderLoading(5); + RenderLoading(3); m_MousePos.x = Graphics()->ScreenWidth()/2; m_MousePos.y = Graphics()->ScreenHeight()/2; // load menu images m_lMenuImages.clear(); - Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageScan, this); - RenderLoading(2); + Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageLoadingScan, this); // load filters LoadFilters(); @@ -2399,19 +2406,19 @@ bool CMenus::IsBackgroundNeeded() const void CMenus::RenderBackground(float Time) { - float sw = 300*Graphics()->ScreenAspect(); - float sh = 300; - Graphics()->MapScreen(0, 0, sw, sh); + float ScreenWidth = 300*Graphics()->ScreenAspect(); + float ScreenHeight = 300; + Graphics()->MapScreen(0, 0, ScreenWidth, ScreenHeight); // render the tiles Graphics()->TextureClear(); Graphics()->QuadsBegin(); - float Size = 15.0f; - float OffsetTime = fmod(Time*0.15f, 2.0f); - for(int y = -2; y < (int)(sw/Size); y++) - for(int x = -2; x < (int)(sh/Size); x++) + const float Size = 15.0f; + const float OffsetTime = fmod(Time*0.15f, 2.0f); + for(int y = -2; y < (int)(ScreenWidth/Size); y++) + for(int x = -2; x < (int)(ScreenHeight/Size); x++) { - Graphics()->SetColor(0,0,0,0.045f); + Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.045f); IGraphics::CQuadItem QuadItem((x-OffsetTime)*Size*2+(y&1)*Size, (y+OffsetTime)*Size, Size, Size); Graphics()->QuadsDrawTL(&QuadItem, 1); } @@ -2422,7 +2429,7 @@ void CMenus::RenderBackground(float Time) Graphics()->TextureSet(s_TextureBlob); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - IGraphics::CQuadItem QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200); + IGraphics::CQuadItem QuadItem = IGraphics::CQuadItem(-100, -100, ScreenWidth+200, ScreenHeight+200); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index bfcee50f..cc0fc313 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -374,7 +374,8 @@ class CMenus : public CComponent }; array m_lMenuImages; - static int MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser); + static int MenuImageCountingScan(const char *pName, int IsDir, int DirType, void *pUser); + static int MenuImageLoadingScan(const char *pName, int IsDir, int DirType, void *pUser); const CMenuImage *FindMenuImage(const char* pName); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 1086606b..fc3b08ac 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -212,7 +212,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) int CSkins::GetInitAmount() const { - return NUM_SKINPARTS*2 + 8; + return NUM_SKINPARTS*5 + 8; } void CSkins::OnInit() @@ -265,7 +265,8 @@ void CSkins::OnInit() DummySkinPart.m_BloodColor = vec3(1.0f, 1.0f, 1.0f); m_aaSkinParts[p].add(DummySkinPart); } - m_pClient->m_pMenus->RenderLoading(2); + + m_pClient->m_pMenus->RenderLoading(5); } // create dummy skin diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index cc4676fb..4c048a88 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -345,8 +345,11 @@ void CGameClient::OnInit() int64 Start = time_get(); - // set the language - g_Localization.Load(Config()->m_ClLanguagefile, Storage(), Console()); + // Render load screen at 0% to get graphics sooner. + // Render twice to clear front and back buffers and minimize initial flashing color. + m_pMenus->InitLoading(1); + m_pMenus->RenderLoading(); + m_pMenus->RenderLoading(); // TODO: this should be different // setup item sizes @@ -356,6 +359,14 @@ void CGameClient::OnInit() for(int i = 0; i < OLD_NUM_NETOBJTYPES; i++) Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); + // determine total work for loading all components + int TotalWorkAmount = g_pData->m_NumImages + 4 + 1 + 1 + 2; // +4=load init, +1=font, +1=localization, +2=editor + for(int i = m_All.m_Num-1; i >= 0; --i) + TotalWorkAmount += m_All.m_paComponents[i]->GetInitAmount(); + + m_pMenus->InitLoading(TotalWorkAmount); + m_pMenus->RenderLoading(4); + // load default font char aFontName[IO_MAX_PATH_LENGTH]; str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->m_ClFontfile); @@ -371,17 +382,15 @@ void CGameClient::OnInit() Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", aBuf); } } + m_pMenus->RenderLoading(1); - // determine total work for loading all components - int TotalWorkAmount = g_pData->m_NumImages + 2; // +2=editor - for(int i = m_All.m_Num-1; i >= 0; --i) - TotalWorkAmount += m_All.m_paComponents[i]->GetInitAmount(); + // set the language + g_Localization.Load(Config()->m_ClLanguagefile, Storage(), Console()); + m_pMenus->RenderLoading(1); - m_pMenus->InitLoading(TotalWorkAmount); - m_pMenus->RenderLoading(); // render initial loading screen // init all components for(int i = m_All.m_Num-1; i >= 0; --i) - m_All.m_paComponents[i]->OnInit(); + m_All.m_paComponents[i]->OnInit(); // this will call RenderLoading again // load textures for(int i = 0; i < g_pData->m_NumImages; i++) From cca832f588824c956a18875a7d822f729de5eddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 2 May 2020 15:25:01 +0200 Subject: [PATCH 308/479] fix inconsistent menu shadow rounding in start menu --- src/game/client/components/menus.cpp | 6 +++--- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_start.cpp | 20 +++++++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 24fd0075..4590c069 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2431,14 +2431,14 @@ void CMenus::RenderBackground(float Time) Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);} } -void CMenus::RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom) +void CMenus::RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom, float Rounding) { const vec4 Transparent(0.0f, 0.0f, 0.0f, 0.0f); const vec4 Background(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f); if(TopToBottom) - RenderTools()->DrawUIRect4(pRect, Background, Background, Transparent, Transparent, CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect4(pRect, Background, Background, Transparent, Transparent, CUI::CORNER_T, Rounding); else - RenderTools()->DrawUIRect4(pRect, Transparent, Transparent, Background, Background, CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect4(pRect, Transparent, Transparent, Background, Background, CUI::CORNER_B, Rounding); } void CMenus::ConchainUpdateMusicState(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index bfcee50f..ad0a3c8f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -811,7 +811,7 @@ class CMenus : public CComponent bool CheckHotKey(int Key) const; void RenderBackground(float Time); - void RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom); + void RenderBackgroundShadow(const CUIRect *pRect, bool TopToBottom, float Rounding = 5.0f); public: void InitLoading(int TotalWorkAmount); void RenderLoading(int WorkedAmount = 0); diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index 2cd7d447..90865e51 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -24,11 +24,13 @@ void CMenus::RenderStartMenu(CUIRect MainView) Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); + const float Rounding = 10.0f; + CUIRect TopMenu, BottomMenu; MainView.VMargin(MainView.w/2-190.0f, &TopMenu); TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); - RenderBackgroundShadow(&TopMenu, false); + RenderBackgroundShadow(&TopMenu, false, Rounding); TopMenu.HSplitTop(145.0f, 0, &TopMenu); @@ -37,7 +39,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_SettingsButton; - if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, Config()->m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_S)) + if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, Config()->m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, Rounding, 0.5f) || CheckHotKey(KEY_S)) NewPage = PAGE_SETTINGS; /*TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space @@ -45,13 +47,13 @@ void CMenus::RenderStartMenu(CUIRect MainView) static int s_LocalServerButton = 0; if(Config()->m_ClShowStartMenuImages) { - if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", 10.0f, 0.5f)) + if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", Rounding, 0.5f)) { } } else { - if(DoButton_Menu(&s_LocalServerButton, Localize("Local server"), 0, &Button, CUI::CORNER_ALL, 10.0f, 0.5f)) + if(DoButton_Menu(&s_LocalServerButton, Localize("Local server"), 0, &Button, CUI::CORNER_ALL, Rounding, 0.5f)) { } }*/ @@ -59,7 +61,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_DemoButton; - if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, Config()->m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || CheckHotKey(KEY_D)) + if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, Config()->m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, Rounding, 0.5f) || CheckHotKey(KEY_D)) { NewPage = PAGE_DEMOS; DemolistPopulate(); @@ -71,7 +73,7 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_MapEditorButton; - if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, Config()->m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) + if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, Config()->m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, Rounding, 0.5f) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E))) { Config()->m_ClEditor = 1; Input()->MouseModeRelative(); @@ -86,15 +88,15 @@ void CMenus::RenderStartMenu(CUIRect MainView) TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_PlayButton; - if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, Config()->m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) + if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, Config()->m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, Rounding, 0.5f) || m_EnterPressed || CheckHotKey(KEY_P)) NewPage = Config()->m_UiBrowserPage; BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); - RenderBackgroundShadow(&BottomMenu, true); + RenderBackgroundShadow(&BottomMenu, true, Rounding); BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static CButtonContainer s_QuitButton; - if(DoButton_Menu(&s_QuitButton, Localize("Quit"), 0, &Button, 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EscapePressed || CheckHotKey(KEY_Q)) + if(DoButton_Menu(&s_QuitButton, Localize("Quit"), 0, &Button, 0, CUI::CORNER_ALL, Rounding, 0.5f) || m_EscapePressed || CheckHotKey(KEY_Q)) m_Popup = POPUP_QUIT; // render version From e768fad43f11cc7f33e6b3122ac4fcf619f08f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 3 May 2020 13:59:44 +0200 Subject: [PATCH 309/479] swap twice instead of rendering twice, fix clear color flash --- src/game/client/gameclient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 4c048a88..1bb5889f 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -346,10 +346,10 @@ void CGameClient::OnInit() int64 Start = time_get(); // Render load screen at 0% to get graphics sooner. - // Render twice to clear front and back buffers and minimize initial flashing color. + // Swap again to minimize initial flashing color. m_pMenus->InitLoading(1); m_pMenus->RenderLoading(); - m_pMenus->RenderLoading(); + m_pGraphics->Swap(); // TODO: this should be different // setup item sizes From 66145d49335adfbae3114d7a5df593678e06f513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 4 May 2020 00:44:44 +0200 Subject: [PATCH 310/479] fix important message overflow --- src/game/client/components/menus_browser.cpp | 48 +++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 1f6eaabf..d5065f04 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1233,28 +1233,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } } - // display important messages in the middle of the screen so no user misses it - { - const char *pImportantMessage = NULL; - if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) - pImportantMessage = Localize("Refreshing master servers"); - else if(SelectedFilter == -1) - pImportantMessage = Localize("No filter category is selected"); - else if(ServerBrowser()->IsRefreshing() && !NumServers) - pImportantMessage = Localize("Fetching server info"); - else if(!ServerBrowser()->NumServers()) - pImportantMessage = Localize("No servers found"); - else if(ServerBrowser()->NumServers() && !NumServers) - pImportantMessage = Localize("No servers match your filter criteria"); - - if(pImportantMessage) - { - CUIRect MsgBox = View; - MsgBox.y += View.h/3; - UI()->DoLabel(&MsgBox, pImportantMessage, 16.0f, CUI::ALIGN_CENTER); - } - } - // scrollbar static CScrollRegion s_ScrollRegion; vec2 ScrollOffset(0, 0); @@ -1365,6 +1343,32 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) m_AddressSelection &= ~ADDR_SELECTION_UPDATE_ADDRESS; } + // display important messages in the middle of the screen so no user misses it + if(!NumServers) + { + CUIRect MsgBox = View; + if(MsgBox.h < 50.0f) + MsgBox.h = 50.0f; + s_ScrollRegion.AddRect(MsgBox); + if(!s_ScrollRegion.IsRectClipped(MsgBox)) + { + const char *pImportantMessage; + if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) + pImportantMessage = Localize("Refreshing master servers"); + else if(SelectedFilter == -1) + pImportantMessage = Localize("No filter category is selected"); + else if(ServerBrowser()->IsRefreshing()) + pImportantMessage = Localize("Fetching server info"); + else if(!ServerBrowser()->NumServers()) + pImportantMessage = Localize("No servers found"); + else + pImportantMessage = Localize("No servers match your filter criteria"); + + MsgBox.y += MsgBox.h/3.0f; + UI()->DoLabel(&MsgBox, pImportantMessage, 16.0f, CUI::ALIGN_CENTER); + } + } + s_ScrollRegion.End(); // bottom From ca622f16bae3366daed4f4fda911c92b82d858ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 4 May 2020 22:35:55 +0200 Subject: [PATCH 311/479] assume fixed number of menu images for loading amount --- src/game/client/components/menus.cpp | 15 +++------------ src/game/client/components/menus.h | 3 +-- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 28baaf5e..7dabab8a 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1345,14 +1345,7 @@ void CMenus::RenderBackButton(CUIRect MainView) } } -int CMenus::MenuImageCountingScan(const char *pName, int IsDir, int DirType, void *pUser) -{ - if(!IsDir && str_endswith(pName, ".png")) - (*(int *)pUser)++; - return 0; -} - -int CMenus::MenuImageLoadingScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(IsDir || !str_endswith(pName, ".png")) @@ -1478,9 +1471,7 @@ void CMenus::UpdateVideoModeSettings() int CMenus::GetInitAmount() const { - int NumMenuImages = 0; - Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageCountingScan, &NumMenuImages); - + const int NumMenuImages = 5; return 6 + 5 * NumMenuImages; } @@ -1494,7 +1485,7 @@ void CMenus::OnInit() // load menu images m_lMenuImages.clear(); - Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageLoadingScan, this); + Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/menuimages", MenuImageScan, this); // load filters LoadFilters(); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index cc0fc313..bfcee50f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -374,8 +374,7 @@ class CMenus : public CComponent }; array m_lMenuImages; - static int MenuImageCountingScan(const char *pName, int IsDir, int DirType, void *pUser); - static int MenuImageLoadingScan(const char *pName, int IsDir, int DirType, void *pUser); + static int MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser); const CMenuImage *FindMenuImage(const char* pName); From 066c2dbf7137a9a4eda30fa55daae821771b968c Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 5 May 2020 21:26:53 +0200 Subject: [PATCH 312/479] fixed bind saving and possible buffer overflow --- src/game/client/components/binds.cpp | 13 ++++++------- src/game/client/components/binds.h | 4 +++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 2b3cece1..264848fa 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -402,7 +402,7 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) { CBinds *pSelf = (CBinds *)pUserData; - char aBuffer[256]; + char aBuffer[512]; char *pEnd = aBuffer+sizeof(aBuffer)-8; for(int i = 0; i < KEY_LAST; i++) { @@ -411,21 +411,20 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) if(pSelf->m_aaaKeyBindings[i][m][0] == 0) continue; - str_format(aBuffer, sizeof(aBuffer), "bind %s%s", GetModifierName(m), pSelf->Input()->KeyName(i)); - // process the string. we need to escape some characters + char aBind[2*BIND_LENGTH]; const char *pSrc = pSelf->m_aaaKeyBindings[i][m]; - char *pDst = aBuffer + str_length(aBuffer); - *pDst++ = '"'; + const char *pEnd = aBind + sizeof(aBind) - 1; + char *pDst = aBind; while(*pSrc && pDst < pEnd) { if(*pSrc == '"' || *pSrc == '\\') // escape \ and " *pDst++ = '\\'; *pDst++ = *pSrc++; } - *pDst++ = '"'; - *pDst++ = 0; + *pDst = 0; + str_format(aBuffer, sizeof(aBuffer), "bind %s%s \"%s\"", GetModifierName(m), pSelf->Input()->KeyName(i), aBind); pConfigManager->WriteLine(aBuffer); } } diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index 1b302b9f..e832ed3e 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -29,6 +29,8 @@ class CBinds : public CComponent enum { + BIND_LENGTH=128, + MODIFIER_NONE=0, MODIFIER_SHIFT, MODIFIER_CTRL, @@ -54,7 +56,7 @@ class CBinds : public CComponent virtual bool OnInput(IInput::CEvent Event); private: - char m_aaaKeyBindings[KEY_LAST][MODIFIER_COUNT][128]; + char m_aaaKeyBindings[KEY_LAST][MODIFIER_COUNT][BIND_LENGTH]; static const int s_aaDefaultBindKeys[][2]; static const char s_aaDefaultBindValues[][32]; }; From 60bfb5615e26d07afa294e8af1e44808a036068d Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 5 May 2020 21:30:10 +0200 Subject: [PATCH 313/479] fixed warning --- src/game/client/components/binds.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 264848fa..620f621b 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -403,7 +403,6 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData) CBinds *pSelf = (CBinds *)pUserData; char aBuffer[512]; - char *pEnd = aBuffer+sizeof(aBuffer)-8; for(int i = 0; i < KEY_LAST; i++) { for(int m = 0; m < MODIFIER_COUNT; m++) From 9c6fd71bdaf8efe71b99775674ffa6a3e21de613 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Fri, 8 May 2020 03:41:37 +0200 Subject: [PATCH 314/479] Fix __INT_MAX not being defined for some compilers --- src/game/client/components/scoreboard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 99684190..5e5edcb1 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.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 From fb55afee15c97155b40c5cc1790f2d0de58becee Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Fri, 8 May 2020 04:09:43 +0200 Subject: [PATCH 315/479] Move Sudden Death notification below the timer --- src/game/client/components/hud.cpp | 98 ++++++++++++++++-------------- src/game/client/components/hud.h | 1 + 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index c9ab9fdb..941a8a48 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -47,62 +47,41 @@ bool CHud::IsLargeWarmupTimerShown() void CHud::RenderGameTimer() { float x = 300.0f*Graphics()->ScreenAspect()/2.0f; - float FontSize; + float FontSize = 10.0f; - if(!(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH)) + int Time = 0; + if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH) + Time = 0; + else if(m_pClient->m_GameInfo.m_TimeLimit && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) { - int Time = 0; - if(m_pClient->m_GameInfo.m_TimeLimit && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) - { - Time = m_pClient->m_GameInfo.m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameData->m_GameStartTick)/Client()->GameTickSpeed()); - - if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) - Time = 0; - } - else if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) - Time = m_pClient->m_Snap.m_pGameData->m_GameStateEndTick/Client()->GameTickSpeed(); - else - Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameData->m_GameStartTick)/Client()->GameTickSpeed(); + Time = m_pClient->m_GameInfo.m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameData->m_GameStartTick)/Client()->GameTickSpeed()); - char aBuf[32]; - str_format(aBuf, sizeof(aBuf), "%d:%02d", Time/60, Time%60); - FontSize = 10.0f; - float w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); - // last 60 sec red, last 10 sec blink - if(m_pClient->m_GameInfo.m_TimeLimit && Time <= 60 && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) - { - float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f; - TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha); - } - x = x-w/2; - TextRender()->Text(0, x, 2, FontSize, aBuf, -1.0f); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) + Time = 0; } + else if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) + Time = m_pClient->m_Snap.m_pGameData->m_GameStateEndTick/Client()->GameTickSpeed(); else + Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameData->m_GameStartTick)/Client()->GameTickSpeed(); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%d:%02d", Time/60, Time%60); + float w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); + // last 60 sec red, last 10 sec blink + if(m_pClient->m_GameInfo.m_TimeLimit && Time <= 60 && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP)) { - const char *pText = Localize("Sudden Death"); - FontSize = 12.0f; - float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); - x = x-w/2; - TextRender()->Text(0, x, 2, FontSize, pText, -1.0f); + float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f; + TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha); } + TextRender()->Text(0, x-w/2, 2, FontSize, aBuf, -1.0f); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - // render network indicator when 2/5 and under - const int NetScore = Client()->GetInputtimeMarginStabilityScore(); - if(NetScore > 250) + if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH) { - float Margin = 2.0f; - x = x-5.0f-FontSize-Margin*2; - Graphics()->BlendNormal(); - CUIRect RectBox = {x, 4-Margin, FontSize+2*Margin, FontSize+2*Margin}; - vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.3f); - RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_ALL, 1.0f); - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); - Graphics()->QuadsBegin(); - RenderTools()->SelectSprite(SPRITE_NETWORK_BAD); - IGraphics::CQuadItem QuadItem(x+Margin, 4, FontSize, FontSize); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + const char *pText = Localize("Sudden Death"); + FontSize = 12.0f; + float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); + TextRender()->Text(0, x-w/2, 2+FontSize, FontSize, pText, -1.0f); } } @@ -161,6 +140,30 @@ void CHud::RenderStartCountdown() } } +void CHud::RenderNetworkIssueNotification() +{ + float x = 300.0f*Graphics()->ScreenAspect()/2.0f - 15.0f; + float FontSize = 10.0f; + + // render network indicator when 2/5 and under + const int NetScore = Client()->GetInputtimeMarginStabilityScore(); + if(1 || NetScore > 250) + { + float Margin = 2.0f; + x = x-5.0f-FontSize-Margin*2; + Graphics()->BlendNormal(); + CUIRect RectBox = {x, 4-Margin, FontSize+2*Margin, FontSize+2*Margin}; + vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.3f); + RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_ALL, 1.0f); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); + Graphics()->QuadsBegin(); + RenderTools()->SelectSprite(SPRITE_NETWORK_BAD); + IGraphics::CQuadItem QuadItem(x+Margin, 4, FontSize, FontSize); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } +} + void CHud::RenderDeadNotification() { if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags == 0 && m_pClient->m_aClients[m_pClient->m_LocalClientID].m_Team != TEAM_SPECTATORS && @@ -865,6 +868,7 @@ void CHud::OnRender() RenderGameTimer(); RenderPauseTimer(); RenderStartCountdown(); + RenderNetworkIssueNotification(); RenderDeadNotification(); RenderScoreHud(); RenderWarmupTimer(); diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index 958a98c4..f216a2f3 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -27,6 +27,7 @@ class CHud : public CComponent void RenderGameTimer(); void RenderPauseTimer(); void RenderStartCountdown(); + void RenderNetworkIssueNotification(); void RenderDeadNotification(); void RenderScoreHud(); void RenderSpectatorHud(); From b0cdf7c26c802dfa2c10e45aea65ffe8f784e2e6 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sun, 10 May 2020 13:45:08 +0200 Subject: [PATCH 316/479] __INT_MAX__ -> INT_MAX, fix a oopsie --- src/game/client/components/hud.cpp | 2 +- src/game/client/components/scoreboard.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 941a8a48..a32ab612 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -147,7 +147,7 @@ void CHud::RenderNetworkIssueNotification() // render network indicator when 2/5 and under const int NetScore = Client()->GetInputtimeMarginStabilityScore(); - if(1 || NetScore > 250) + if(NetScore > 250) { float Margin = 2.0f; x = x-5.0f-FontSize-Margin*2; diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 5e5edcb1..e0dadffc 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -704,7 +704,7 @@ void CScoreboard::RenderNetworkQuality(float x, float w) float y = 0.0f; const int NumBars = 5; - int ScoreThresolds[NumBars] = {__INT_MAX__, 1000, 250, 50, -80}; + int ScoreThresolds[NumBars] = {INT_MAX, 1000, 250, 50, -80}; CUIRect BarRect = { x - 4.0f, y + LineHeight, From 1aa7023f00b460b1d4ad38c7587f60ef9866430b Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Mon, 11 May 2020 15:47:34 +0200 Subject: [PATCH 317/479] Update readme with instructions for bam, minor fixes --- readme.md | 107 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 18 deletions(-) diff --git a/readme.md b/readme.md index 342efe46..ff6d9a86 100644 --- a/readme.md +++ b/readme.md @@ -23,8 +23,11 @@ the game, including new versions, custom maps and much more. Originally written by Magnus Auvinen. +--- -Building on Linux or macOS +Teeworlds supports two build systems: CMake (widely used) and bam (fast build times). + +Building on Linux or macOS (CMake) ========================== Installing dependencies @@ -32,13 +35,13 @@ Installing dependencies # Debian/Ubuntu sudo apt install build-essential cmake git libfreetype6-dev libsdl2-dev libpnglite-dev libwavpack-dev python3 - + # Fedora sudo dnf install @development-tools cmake gcc-c++ git freetype-devel pnglite-devel python3 SDL2-devel wavpack-devel - + # Arch Linux (doesn't have pnglite in its repositories) sudo pacman -S --needed base-devel cmake freetype2 git python sdl2 wavpack - + # macOS brew install cmake freetype sdl2 @@ -48,7 +51,7 @@ Downloading repository git clone https://github.com/teeworlds/teeworlds --recurse-submodules cd teeworlds - + # If you already cloned the repository before, use: # git submodule update --init @@ -74,7 +77,7 @@ The following options can be passed to the `cmake ..` command line (between the `cmake` and `..`) in the "Building" step above. `-GNinja`: Use the Ninja build system instead of Make. This automatically -parallizes the build and is generally **faster**. (Needs `sudo apt install +parallelizes the build and is generally **faster**. (Needs `sudo apt install ninja-build` on Debian, `sudo dnf install ninja-build` on Fedora, and `sudo pacman -S --needed ninja` on Arch Linux.) @@ -84,12 +87,64 @@ pacman -S --needed ninja` on Arch Linux.) `-DCLIENT=OFF`: Disable generation of the client target. Can be useful on headless servers which don't have graphics libraries like SDL2 installed. +Building on Linux or macOS (bam) +========================== + +Installing dependencies +----------------------- -Building on Windows with Visual Studio -====================================== + # Debian/Ubuntu 19.10+ + sudo apt install bam git libfreetype6-dev libsdl2-dev libpnglite-dev libwavpack-dev python3 + + # Fedora + sudo dnf install bam gcc-c++ git freetype-devel pnglite-devel python3 SDL2-devel wavpack-devel + + # Arch Linux (doesn't have pnglite in its repositories) + sudo pacman -S --needed base-devel bam freetype2 git python sdl2 wavpack + + # macOS + brew install bam freetype sdl2 + + # other (add bam to your path) + git clone https://github.com/teeworlds/bam + cd bam + ./make_unix.sh + + +Downloading repository +---------------------- + + git clone https://github.com/teeworlds/teeworlds --recurse-submodules + cd teeworlds + + # If you already cloned the repository before, use: + # git submodule update --init + + +Building +-------- + + bam + +The compiled game is located in a sub-folder of `build`. You can run the client from there with `./teeworlds` and the server with `./teeworlds_srv`. + + +Build options +------------- + +One of the following targets can be added to the `bam` command line: `game` (default), `server`, `client`, `content`, `masterserver`, `tools`. + +The following options can also be added. + +`conf=release` to build in release mode (defaults to `conf=debug`). + +`arch=x86` or `arch=x86_64` to force select an architecture. + +Building on Windows with Visual Studio & CMake +====================== Download and install some version of [Microsoft Visual -Studio](https://www.visualstudio.com/) (as of writing, MSVS Community 2017) +Studio](https://www.visualstudio.com/) (as of writing, MSVS Community 2019) with the following components: * Desktop development with C++ (on the main page) @@ -110,9 +165,32 @@ arrow. Wait for the compilation to finish. For subsequent builds you only have to click the button with the green arrow again. +Building on Windows with MSVC build tools & bam +====================== + +Download and install [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) and [Python](https://www.python.org/downloads/). + +Download and unzip [Teeworlds stable sources](https://github.com/teeworlds/teeworlds/releases) or [Teeworlds latest sources](https://github.com/teeworlds/teeworlds/archive/master.zip). + +Download and unzip [bam](https://github.com/matricks/bam/archive/v0.5.1.tar.gz) to `teeworlds-version\bam`. + +Run the `x64 Native Tools Command Prompt` (or `x86` for 32-bit) from the start menu. -Building on Windows with MinGW -============================== + # Navigate to the Teeworlds source directory + cd ...\teeworlds-version + + # Build bam (use make_win32_msvc.bat for 32-bit) + cd bam + make_win64_msvc.bat + cd .. + + # Build Teeworlds + bam conf=release + +Use `conf=debug` to build the debug version instead. You can also provide a target after the `bam` command : `game` (default), `server`, `client`, `content`, `masterserver`, `tools`. + +Building on Windows with MinGW & CMake +====================== Download and install MinGW with at least the following components: @@ -133,10 +211,3 @@ click "Finish". Wait a bit (until the progress bar is full). Then click "Generate". You can now build Teeworlds by executing `mingw32-make` in the build directory. - - -Building with bam, guides for all operating systems -=================================================== - -You can also compile Teeworlds with bam, a custom build system. Instructions -for that can be found at https://www.teeworlds.com/?page=docs&wiki=hacking. From 733cf9db3d17dfd6843c0bad2bcc04c96f01427a Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Mon, 11 May 2020 16:19:13 +0200 Subject: [PATCH 318/479] Add copy bam .. for Windows --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index ff6d9a86..f0988e4e 100644 --- a/readme.md +++ b/readme.md @@ -182,6 +182,7 @@ Run the `x64 Native Tools Command Prompt` (or `x86` for 32-bit) from the start m # Build bam (use make_win32_msvc.bat for 32-bit) cd bam make_win64_msvc.bat + copy bam .. cd .. # Build Teeworlds From 31a30dac3758a4cbc2daabc1ecfb85959ccd0e2c Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 13 May 2020 12:45:39 +0200 Subject: [PATCH 319/479] Use consistent snake case for chat_commands --- src/game/client/components/chat.cpp | 2 +- src/game/commands.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index b0cf2f88..d7851f8c 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -551,7 +551,7 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) if(!m_CommandManager.AddCommand(pMsg->m_Name, pMsg->m_HelpText, pMsg->m_ArgsFormat, ServerCommandCallback, this)) dbg_msg("chat_commands", "adding server chat command: name='%s' args='%s' help='%s'", pMsg->m_Name, pMsg->m_ArgsFormat, pMsg->m_HelpText); else - dbg_msg("chat-commands", "failed to add command '%s'", pMsg->m_Name); + dbg_msg("chat_commands", "failed to add command '%s'", pMsg->m_Name); } else if(MsgType == NETMSGTYPE_SV_COMMANDINFOREMOVE) diff --git a/src/game/commands.h b/src/game/commands.h index 6c1f5f38..59598b2a 100644 --- a/src/game/commands.h +++ b/src/game/commands.h @@ -134,7 +134,7 @@ class CCommandManager int OnCommand(const char *pCommand, const char *pArgs, int ClientID) { - dbg_msg("chat-command", "calling '%s' with args '%s'", pCommand, pArgs); + dbg_msg("chat_command", "calling '%s' with args '%s'", pCommand, pArgs); const CCommand *pCom = GetCommand(pCommand); if(!pCom) return 1; From f847f0e37525d873d54fa643737ad8ccffc04f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 21 May 2020 16:22:57 +0200 Subject: [PATCH 320/479] delete existing corrupted map file before renaming tmp --- src/engine/client/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 811b9683..df3cc1aa 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1229,6 +1229,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) m_MapdownloadAmount = 0; m_MapdownloadTotalsize = -1; + Storage()->RemoveFile(m_aMapdownloadFilename, IStorage::TYPE_SAVE); Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE); // load map From 5e9ee025cd663ff852b715fb017e5bc6ba6fb21f Mon Sep 17 00:00:00 2001 From: Zwelf Date: Fri, 22 May 2020 16:38:20 +0200 Subject: [PATCH 321/479] Remove unused declaration --- src/game/editor/layer_quads.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/editor/layer_quads.cpp b/src/game/editor/layer_quads.cpp index 5a94fb3a..a83ab987 100644 --- a/src/game/editor/layer_quads.cpp +++ b/src/game/editor/layer_quads.cpp @@ -196,8 +196,6 @@ void CLayerQuads::GetSize(float *w, float *h) const } } -extern int gs_SelectedPoints; - int CLayerQuads::RenderProperties(CUIRect *pToolBox) { // layer props From ea7dad2db1cb86a3884a70e9b44c48daeea2b518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 23 May 2020 15:28:11 +0200 Subject: [PATCH 322/479] fix too fast joystick in menus, allow swapping axis, refactoring --- src/engine/client/input.cpp | 53 ++++++++----------- src/engine/client/input.h | 2 +- src/game/client/components/menus_callback.cpp | 14 ++++- src/game/client/ui.cpp | 6 +-- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index c75842ed..cb616e62 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -47,7 +47,7 @@ CInput::CInput() m_pGraphics = 0; m_InputCounter = 1; - m_InputGrabbed = 0; + m_MouseInputRelative = false; m_pClipboardText = 0; m_SelectedJoystickIndex = -1; @@ -100,10 +100,10 @@ void CInput::InitJoysticks() for(int i = 0; i < NumJoysticks; i++) { SDL_Joystick *pJoystick = SDL_JoystickOpen(i); - - if(!pJoystick) { + if(!pJoystick) + { dbg_msg("joystick", "Could not open joystick %d: %s", i, SDL_GetError()); - return; + continue; } m_apJoysticks.add(pJoystick); @@ -188,7 +188,7 @@ float CInput::GetJoystickAxisValue(int Axis) { SDL_Joystick* pJoystick = GetActiveJoystick(); dbg_assert((bool)pJoystick, "Requesting joystick axis value, but no joysticks were initialized"); - return static_cast(SDL_JoystickGetAxis(pJoystick, Axis)) / (float)(SDL_JOYSTICK_AXIS_MAX+1); + return (SDL_JoystickGetAxis(pJoystick, Axis)-SDL_JOYSTICK_AXIS_MIN)/float(SDL_JOYSTICK_AXIS_MAX-SDL_JOYSTICK_AXIS_MIN)*2.0f - 1.0f; } int CInput::GetJoystickNumAxes() @@ -200,43 +200,36 @@ int CInput::GetJoystickNumAxes() void CInput::MouseRelative(float *x, float *y) { - if(!m_InputGrabbed) + if(!m_MouseInputRelative) return; - int nx = 0, ny = 0; - float MouseSens = m_pConfig->m_InpMousesens/100.0f; - float JoystickSens = m_pConfig->m_JoystickSens/100.0f; - - SDL_GetRelativeMouseState(&nx,&ny); - - vec2 j = vec2(0.0f, 0.0f); + int MouseX = 0, MouseY = 0; + SDL_GetRelativeMouseState(&MouseX, &MouseY); + vec2 JoystickPos = vec2(0.0f, 0.0f); if(m_pConfig->m_JoystickEnable && GetActiveJoystick()) { - const float Max = 50.0f; - j = vec2(GetJoystickAxisValue(m_pConfig->m_JoystickX), GetJoystickAxisValue(m_pConfig->m_JoystickY)) * Max; - const float Len = length(j); - - if(Len/sqrtf(2.0f) <= m_pConfig->m_JoystickTolerance) + const vec2 RawJoystickPos = vec2(GetJoystickAxisValue(m_pConfig->m_JoystickX), GetJoystickAxisValue(m_pConfig->m_JoystickY)); + const float Len = length(RawJoystickPos); + const float DeadZone = m_pConfig->m_JoystickTolerance/50.0f; + const float JoystickSens = m_pConfig->m_JoystickSens/100.0f; + if(Len >= DeadZone) // >= to allow max tolerance value { - j = vec2(0.0f, 0.0f); - } - else - { - const vec2 nj = Len > 0.0f ? j / Len : vec2(0.0f, 0.0f); - j = nj * min(Len, Max) - nj * m_pConfig->m_JoystickTolerance; + JoystickPos = RawJoystickPos * (JoystickSens * max(Len - DeadZone, 0.001f) / Len); } } - *x = nx*MouseSens + j.x*JoystickSens; - *y = ny*MouseSens + j.y*JoystickSens; + const float MouseSens = m_pConfig->m_InpMousesens/100.0f; + + *x = MouseX * MouseSens + JoystickPos.x; + *y = MouseY * MouseSens + JoystickPos.y; } void CInput::MouseModeAbsolute() { - if(m_InputGrabbed) + if(m_MouseInputRelative) { - m_InputGrabbed = 0; + m_MouseInputRelative = false; SDL_ShowCursor(SDL_ENABLE); SDL_SetRelativeMouseMode(SDL_FALSE); } @@ -244,9 +237,9 @@ void CInput::MouseModeAbsolute() void CInput::MouseModeRelative() { - if(!m_InputGrabbed) + if(!m_MouseInputRelative) { - m_InputGrabbed = 1; + m_MouseInputRelative = true; SDL_ShowCursor(SDL_DISABLE); if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, m_pConfig->m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE) { diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 09e19ef0..b6d0dbc8 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -18,7 +18,7 @@ class CInput : public IEngineInput void InitJoysticks(); void CloseJoysticks(); - int m_InputGrabbed; + bool m_MouseInputRelative; char *m_pClipboardText; int m_PreviousHat; diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 898f0191..a19c3234 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -143,9 +143,11 @@ float CMenus::RenderSettingsControlsMouse(CUIRect View) { Config()->m_InpGrab ^= 1; } + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); DoScrollbarOption(&Config()->m_InpMousesens, &Config()->m_InpMousesens, &Button, Localize("Ingame mouse sens."), 1, 500, &LogarithmicScrollbarScale); + View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); DoScrollbarOption(&Config()->m_UiMousesens, &Config()->m_UiMousesens, &Button, Localize("Menu mouse sens."), 1, 500, &LogarithmicScrollbarScale); @@ -412,11 +414,19 @@ void CMenus::DoJoystickAxisPicker(CUIRect View) // Bind to X,Y Row.VSplitLeft(2*StatusMargin, 0, &Row); Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][0], "X", Config()->m_JoystickX == i, &Button, Config()->m_JoystickY == i)) + if(DoButton_CheckBox(&s_aActive[i][0], "X", Config()->m_JoystickX == i, &Button)) + { + if(Config()->m_JoystickY == i) + Config()->m_JoystickY = Config()->m_JoystickX; Config()->m_JoystickX = i; + } Row.VSplitLeft(BindWidth, &Button, &Row); - if(DoButton_CheckBox(&s_aActive[i][1], "Y", Config()->m_JoystickY == i, &Button, Config()->m_JoystickX == i)) + if(DoButton_CheckBox(&s_aActive[i][1], "Y", Config()->m_JoystickY == i, &Button)) + { + if(Config()->m_JoystickX == i) + Config()->m_JoystickX = Config()->m_JoystickY; Config()->m_JoystickY = i; + } Row.VSplitLeft(StatusMargin, 0, &Row); } } diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index f07113b0..3fbc23f1 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -63,9 +63,9 @@ bool CUI::MouseInsideClip() const void CUI::ConvertMouseMove(float *x, float *y) const { - float Fac = (float)(m_pConfig->m_UiMousesens)/m_pConfig->m_InpMousesens; - *x = *x*Fac; - *y = *y*Fac; + float Fac = m_pConfig->m_UiMousesens/100.0f; + *x = *x * Fac; + *y = *y * Fac; } CUIRect *CUI::Screen() From a01abd61a7a37cdea395777a04a9b77eb4da057b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 23 May 2020 15:52:57 +0200 Subject: [PATCH 323/479] add backwards compat SDL_JOYSTICK_AXIS_MIN --- src/engine/client/input.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index cb616e62..762df987 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -18,6 +18,9 @@ #undef KEYS_INCLUDE // support older SDL version (pre 2.0.6) +#ifndef SDL_JOYSTICK_AXIS_MIN + #define SDL_JOYSTICK_AXIS_MIN -32768 +#endif #ifndef SDL_JOYSTICK_AXIS_MAX #define SDL_JOYSTICK_AXIS_MAX 32767 #endif From ecd22c548cc4eb8d77735bea5049efdec98d1948 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 6 May 2020 13:56:07 +0200 Subject: [PATCH 324/479] Key argument for dump binds command (closed #2619) Inspired by ddnet code thanks to @marcelherd: https://github.com/ddnet/ddnet/commit/1f5859503329717b3f633b9331b353db133ca021 --- src/game/client/components/binds.cpp | 41 ++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 620f621b..101e4b1f 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -271,7 +271,7 @@ void CBinds::OnConsoleInit() Console()->Register("bind", "s[key] r[command]", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); - Console()->Register("binds", "", CFGFLAG_CLIENT, ConBinds, this, "Show list of key bindings"); + Console()->Register("binds", "?s[key]", CFGFLAG_CLIENT, ConBinds, this, "Show list of key bindings"); // default bindings SetDefaults(); @@ -326,15 +326,44 @@ void CBinds::ConBinds(IConsole::IResult *pResult, void *pUserData) { CBinds *pBinds = (CBinds *)pUserData; char aBuf[1024]; - for(int i = 0; i < KEY_LAST; i++) + if(pResult->NumArguments() == 1) { - for(int m = 0; m < MODIFIER_COUNT; m++) + char aBuf[256]; + const char *pKeyName = pResult->GetString(0); + + int Modifier; + int KeyID = pBinds->DecodeBindString(pKeyName, &Modifier); + if(!KeyID) { - if(pBinds->m_aaaKeyBindings[i][m][0] == 0) - continue; - str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetModifierName(m), pBinds->Input()->KeyName(i), i, pBinds->m_aaaKeyBindings[i][m]); + str_format(aBuf, sizeof(aBuf), "key '%s' not found", pKeyName); pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); } + else + { + if(pBinds->m_aaaKeyBindings[KeyID][Modifier][0] == 0) + str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, KeyID); + else + str_format( + aBuf, + sizeof(aBuf), + "%s (%d) = %s", + pKeyName, KeyID, pBinds->m_aaaKeyBindings[KeyID][Modifier] + ); + pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); + } + } + else if(pResult->NumArguments() == 0) + { + for(int i = 0; i < KEY_LAST; i++) + { + for(int m = 0; m < MODIFIER_COUNT; m++) + { + if(pBinds->m_aaaKeyBindings[i][m][0] == 0) + continue; + str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetModifierName(m), pBinds->Input()->KeyName(i), i, pBinds->m_aaaKeyBindings[i][m]); + pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); + } + } } } From 92d91f8ff48d6759add6d639b13f6f98f13553c7 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 25 May 2020 20:48:38 +0200 Subject: [PATCH 325/479] removed notices --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f0988e4e..367afa43 100644 --- a/readme.md +++ b/readme.md @@ -25,7 +25,7 @@ Originally written by Magnus Auvinen. --- -Teeworlds supports two build systems: CMake (widely used) and bam (fast build times). +Teeworlds supports two build systems: CMake and bam. Building on Linux or macOS (CMake) ========================== From f81eaa9d09c9c4066c05ccb8b55fbe09861c4e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 27 May 2020 18:38:27 +0200 Subject: [PATCH 326/479] add text and outline color constants, fix reset after loading --- src/game/client/components/chat.cpp | 4 +- src/game/client/components/menus.cpp | 81 +++++++++-------- src/game/client/components/menus_browser.cpp | 23 +++-- src/game/client/components/menus_demo.cpp | 17 ++-- src/game/client/components/menus_settings.cpp | 88 +++++++++---------- src/game/client/components/nameplates.cpp | 4 +- src/game/client/components/scoreboard.cpp | 4 +- src/game/client/ui.cpp | 5 ++ src/game/client/ui.h | 5 ++ 9 files changed, 124 insertions(+), 107 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index d7851f8c..62e2d1cf 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1314,8 +1314,8 @@ void CChat::OnRender() TextRender()->TextShadowed(&Cursor, pLine->m_aText, -1, ShadowOffset, ShadowColor, TextColor); } - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); HandleCommands(x+CategoryWidth, Height - 24.f, 200.0f-CategoryWidth); } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 44c9b500..e7216b8a 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -206,8 +206,8 @@ int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, UI()->DoLabel(&Text, pText, Text.h*ms_FontmodHeight, CUI::ALIGN_CENTER); if(TextFade) { - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } return UI()->DoButtonLogic(pBC->GetID(), pRect); } @@ -224,8 +224,8 @@ void CMenus::DoButton_KeySelect(CButtonContainer *pBC, const char *pText, int Ch TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) @@ -261,8 +261,8 @@ int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Ch TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, FontAlpha); TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f*FontAlpha); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); return UI()->DoButtonLogic(pBC->GetID(), pRect); } @@ -271,8 +271,8 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, if(Checked) { RenderTools()->DrawUIRect(pRect, vec4(0.9f, 0.9f, 0.9f, 0.5f), CUI::CORNER_ALL, 5.0f); - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); } else if(UI()->HotItem() == pID) { @@ -286,8 +286,8 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, if(Checked) { - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } return UI()->DoButtonLogic(pID, pRect); @@ -1225,11 +1225,11 @@ void CMenus::RenderMenubar(CUIRect Rect) // make the header look like an active tab RenderTools()->DrawUIRect(&Box, vec4(1.0f, 1.0f, 1.0f, 0.75f), CUI::CORNER_ALL, 5.0f); Box.HMargin(2.0f, &Box); - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); UI()->DoLabel(&Box, Localize("Demos"), Box.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } @@ -1279,28 +1279,30 @@ void CMenus::RenderLoading(int WorkedAmount) RenderBackground((Now-s_LoadingStart)/Freq); CUIRect Screen = *UI()->Screen(); - float w = 700; - float h = 200; - float x = Screen.w/2-w/2; - float y = Screen.h/2-h/2; - CUIRect Rect = {x, y, w, h}; + const float w = 700; + const float h = 200; + const float x = Screen.w/2-w/2; + const float y = Screen.h/2-h/2; + CUIRect Rect = { x, y, w, h }; Graphics()->BlendNormal(); RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 40.0f); Rect.y += 20; - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); UI()->DoLabel(&Rect, "Teeworlds", 48.0f, CUI::ALIGN_CENTER); - float Percent = m_LoadCurrent/(float)m_LoadTotal; - float Spacing = 40.0f; - float Rounding = 5.0f; - CUIRect FullBar = {x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f}; - RenderTools()->DrawRoundRect(&FullBar, vec4(1.0f, 1.0f, 1.0f, 0.1f), Rounding); + const float Percent = m_LoadCurrent/(float)m_LoadTotal; + const float Spacing = 40.0f; + const float BarRounding = 5.0f; + + CUIRect FullBar = { x+Spacing, y+h-75.0f, w-2*Spacing, 25.0f }; + RenderTools()->DrawRoundRect(&FullBar, vec4(1.0f, 1.0f, 1.0f, 0.1f), BarRounding); + CUIRect FillingBar = FullBar; - FillingBar.w = (FullBar.w-2*Rounding)*Percent+2*Rounding; - RenderTools()->DrawRoundRect(&FillingBar, vec4(1.0f, 1.0f, 1.0f, 0.75f), Rounding); + FillingBar.w = (FullBar.w-2*BarRounding)*Percent+2*BarRounding; + RenderTools()->DrawRoundRect(&FillingBar, vec4(1.0f, 1.0f, 1.0f, 0.75f), BarRounding); if(Percent > 0.5f) { @@ -1311,6 +1313,12 @@ void CMenus::RenderLoading(int WorkedAmount) str_format(aBuf, sizeof(aBuf), "%d%%", (int)(100*Percent)); UI()->DoLabel(&FullBar, aBuf, 20.0f, CUI::ALIGN_CENTER); + if(Percent > 0.5f) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); + } + Graphics()->Swap(); } @@ -1961,22 +1969,25 @@ 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(); + if(i == OldSelected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); + if(i == OldSelected) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } - else - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); } } diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index d5065f04..b6e6c25b 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -703,8 +703,8 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn UI()->ClipDisable(); } - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); return ReturnValue; } @@ -876,10 +876,9 @@ void CMenus::RenderServerbrowserOverlay() CUIRect Screen = *UI()->Screen(); float ButtonHeight = 20.0f; - vec4 TextColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); if(pInfo && pInfo->m_NumClients) { @@ -946,9 +945,9 @@ void CMenus::RenderServerbrowserOverlay() if(s) { TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextColor(CUI::ms_HighlightTextColor); TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextColor(CUI::ms_DefaultTextColor); TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); } else @@ -968,9 +967,9 @@ void CMenus::RenderServerbrowserOverlay() if(s) { TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); + TextRender()->TextColor(CUI::ms_HighlightTextColor); TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a); + TextRender()->TextColor(CUI::ms_DefaultTextColor); TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); } else @@ -1005,8 +1004,8 @@ void CMenus::RenderServerbrowserOverlay() UI()->DoLabel(&View, Localize("no players", "server browser message"), View.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } // deactivate it @@ -2300,7 +2299,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pI RenderTools()->DrawUIRect(&ServerHeader, vec4(1, 1, 1, 0.25f), CUI::CORNER_T, 4.0f); ServerHeader.HMargin(2.0f, &ServerHeader); UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), 12.0f, CUI::ALIGN_CENTER); - RenderDetailScoreboard(ServerScoreboard, pInfo, 0, vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.0f, 0.0f, 0.0f, 0.3f)); + RenderDetailScoreboard(ServerScoreboard, pInfo, 0, CUI::ms_DefaultTextColor, CUI::ms_DefaultTextOutlineColor); } void CMenus::FriendlistOnUpdate() diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 19831bf4..fc63ce4d 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -476,19 +476,18 @@ void CMenus::RenderDemoList(CUIRect MainView) } DoIconColor(IMAGE_FILEICONS, DemoItem.m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); + if(Item.m_Selected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); } - else + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + if(Item.m_Selected) { - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index f9b20408..bb3fe51d 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -727,17 +727,18 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) Rect.HMargin(3.0f, &Rect); 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, true); + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, r.front().m_Name, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); if(Item.m_Selected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - UI()->DoLabel(&Item.m_Rect, r.front().m_Name, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } - else - UI()->DoLabel(&Item.m_Rect, r.front().m_Name, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } } @@ -803,32 +804,30 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) Graphics()->QuadsEnd(); } - Item.m_Rect.y += 2.0f; char aName[128]; - if(r.front().m_Name[0]) - { - if(r.front().m_HasDay && r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); - else if(r.front().m_HasDay && !r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s (day)", r.front().m_Name.cstr()); - else if(!r.front().m_HasDay && r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s (night)", r.front().m_Name.cstr()); - else // generic - str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); - } - else + if(!r.front().m_Name[0]) str_copy(aName, "(none)", sizeof(aName)); + else if(r.front().m_HasDay && r.front().m_HasNight) + str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); + else if(r.front().m_HasDay && !r.front().m_HasNight) + str_format(aName, sizeof(aName), "%s (day)", r.front().m_Name.cstr()); + else if(!r.front().m_HasDay && r.front().m_HasNight) + str_format(aName, sizeof(aName), "%s (night)", r.front().m_Name.cstr()); + else // generic + str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); if(Item.m_Selected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - UI()->DoLabel(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } - else - UI()->DoLabel(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } } @@ -1147,22 +1146,25 @@ 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(); + if(Item.m_Selected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } - else - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); } } @@ -1618,19 +1620,15 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, if(Item.m_Selected) { - TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); - TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, aBuf, Item.m_Rect.h*ms_FontmodHeight*0.8f, - CUI::ALIGN_CENTER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); } - else + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, aBuf, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + if(Item.m_Selected) { - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, aBuf, Item.m_Rect.h*ms_FontmodHeight*0.8f, - CUI::ALIGN_CENTER); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } } diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 120af70c..30b10d38 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -64,8 +64,8 @@ void CNamePlates::RenderNameplate( TextRender()->TextEx(&Cursor, aName, -1); } - TextRender()->TextColor(1,1,1,1); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 32568cab..1a2dc40b 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -650,8 +650,8 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c y += LineHeight; } } - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); return HeadlineHeight+LineHeight*(PlayerLines+1); } diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index f07113b0..2b01a25a 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -11,6 +11,11 @@ UI *********************************************************/ +const vec4 CUI::ms_DefaultTextColor(1.0f, 1.0f, 1.0f, 1.0f); +const vec4 CUI::ms_DefaultTextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); +const vec4 CUI::ms_HighlightTextColor(0.0f, 0.0f, 0.0f, 1.0f); +const vec4 CUI::ms_HighlightTextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + CUI::CUI() { m_pHotItem = 0; diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 382881d5..997d71f5 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -48,6 +48,11 @@ class CUI class ITextRender *m_pTextRender; public: + static const vec4 ms_DefaultTextColor; + static const vec4 ms_DefaultTextOutlineColor; + static const vec4 ms_HighlightTextColor; + static const vec4 ms_HighlightTextOutlineColor; + // TODO: Refactor: Fill this in void Init(class CConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } class CConfig *Config() const { return m_pConfig; } From 6ce1c439cbc4f9b0f1658907ecaf87921c624b9c Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 7 Jun 2020 11:57:48 +0200 Subject: [PATCH 327/479] Fix OOB write in snapshot code reported by mmmds Fix #2642. --- src/engine/shared/snapshot.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index 578a56e0..c4838d9f 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -602,11 +602,17 @@ int CSnapshotBuilder::Finish(void *pSnapdata) // get full item sizes int aItemSizes[CSnapshotBuilder::MAX_ITEMS]; - for(int i = 0; i < NumItems-1; i++) + for(int i = 0; i < NumItems; i++) { - aItemSizes[i] = m_aOffsets[i+1] - m_aOffsets[i]; + if(i < NumItems - 1) + { + aItemSizes[i] = m_aOffsets[i+1] - m_aOffsets[i]; + } + else + { + aItemSizes[i] = m_DataSize - m_aOffsets[i]; + } } - aItemSizes[NumItems-1] = m_DataSize - m_aOffsets[NumItems-1]; // bubble sort by keys bool Sorting = true; From 3d96af6d84617f4cae6b4c69a1e668a72d762048 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 7 Jun 2020 12:01:03 +0200 Subject: [PATCH 328/479] Fix OOB read in snapshot code reported by mmmds Fix #2643. --- src/engine/shared/snapshot.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index c4838d9f..e1ec7e86 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -314,6 +314,10 @@ int CSnapshotDelta::UnpackDelta(const CSnapshot *pFrom, CSnapshot *pTo, const vo // unpack deleted stuff pDeleted = pData; + if(pDelta->m_NumDeletedItems < 0) + { + return -1; + } pData += pDelta->m_NumDeletedItems; if(pData > pEnd) return -1; From 672c149ecb5bf198daae1d64c4a1da78e6a40fc4 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 7 Jun 2020 12:04:36 +0200 Subject: [PATCH 329/479] Fix string buffer being used out of scope Fix #2644. --- src/game/client/components/menus.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 44c9b500..bc5e1731 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1697,6 +1697,7 @@ int CMenus::Render() else { // render full screen popup + char aTitleBuf[128]; const char *pTitle = ""; const char *pExtraText = ""; int NumOptions = 4; @@ -1711,9 +1712,8 @@ int CMenus::Render() pTitle = Localize("Connecting to"); if(Client()->MapDownloadTotalsize() > 0) { - char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Downloading map"), Client()->MapDownloadName()); - pTitle = aBuf; + str_format(aTitleBuf, sizeof(aTitleBuf), "%s: %s", Localize("Downloading map"), Client()->MapDownloadName()); + pTitle = aTitleBuf; pExtraText = ""; NumOptions = 5; } From a97f8a22dee3298c7c0ea7df9bc1733c2dd27a53 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 7 Jun 2020 12:26:12 +0200 Subject: [PATCH 330/479] Fix client use-after-free reported by mmmds Fix #2645. The `Sv_ReadyToEnter` net message is only valid while we're still loading stuff, it is used to signal that we can send the `ENTERGAME` system message. Simply ignoring the server message while we're in the wrong part of the state machine works. --- src/engine/client/client.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index df3cc1aa..827c8e77 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -488,6 +488,12 @@ void CClient::EnterGame() if(State() == IClient::STATE_DEMOPLAYBACK) return; + if(State() == IClient::STATE_ONLINE) + { + // Don't reset everything while already in game. + return; + } + // now we will wait for two snapshots // to finish the connection SendEnterGame(); From 6ed74bcf87add0c699654f8d0cc94fa73e0f4503 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sat, 6 Jun 2020 12:35:32 +0200 Subject: [PATCH 331/479] Cleanup hpp guards Finishes leftovers from https://github.com/teeworlds/teeworlds/commit/e6f0318bdfa49bde503742c856c8415f9b2c8018 --- src/base/tl/algorithm.h | 2 +- src/base/tl/allocator.h | 2 +- src/base/tl/array.h | 2 +- src/base/tl/range.h | 2 +- src/base/tl/sorted_array.h | 2 +- src/base/tl/string.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/base/tl/algorithm.h b/src/base/tl/algorithm.h index e6c1e616..3ea6ba23 100644 --- a/src/base/tl/algorithm.h +++ b/src/base/tl/algorithm.h @@ -135,4 +135,4 @@ bool sort_verify(R range) return true; } -#endif // TL_FILE_ALGORITHMS_HPP +#endif // BASE_TL_ALGORITHM_H diff --git a/src/base/tl/allocator.h b/src/base/tl/allocator.h index d12347e3..01fc9c6c 100644 --- a/src/base/tl/allocator.h +++ b/src/base/tl/allocator.h @@ -14,4 +14,4 @@ class allocator_default static void free_array(T *p) { delete [] p; } }; -#endif // TL_FILE_ALLOCATOR_HPP +#endif // BASE_TL_ALLOCATOR_H diff --git a/src/base/tl/array.h b/src/base/tl/array.h index 2040be22..c5d2a87a 100644 --- a/src/base/tl/array.h +++ b/src/base/tl/array.h @@ -341,4 +341,4 @@ class array : private ALLOCATOR int num_elements; }; -#endif // TL_FILE_ARRAY_HPP +#endif // BASE_TL_ARRAY_H diff --git a/src/base/tl/range.h b/src/base/tl/range.h index ff89b466..0ed719cb 100644 --- a/src/base/tl/range.h +++ b/src/base/tl/range.h @@ -221,4 +221,4 @@ template R reverse(reverse_range range) { return range.range; } -#endif // TL_FILE_RANGE_HPP +#endif // BASE_TL_RANGE_H diff --git a/src/base/tl/sorted_array.h b/src/base/tl/sorted_array.h index bd56a8b7..ca3a8147 100644 --- a/src/base/tl/sorted_array.h +++ b/src/base/tl/sorted_array.h @@ -41,4 +41,4 @@ class sorted_array : public array range all() const { return range(parent::list, parent::list+parent::num_elements); } }; -#endif // TL_FILE_SORTED_ARRAY_HPP +#endif // BASE_TL_SORTED_ARRAY_H diff --git a/src/base/tl/string.h b/src/base/tl/string.h index e0b891ad..675251bd 100644 --- a/src/base/tl/string.h +++ b/src/base/tl/string.h @@ -67,4 +67,4 @@ class string_base : private ALLOCATOR /* normal allocated string */ typedef string_base > string; -#endif // TL_FILE_STRING_HPP +#endif // BASE_TL_STRING_H From 0d17380788d7062785028fc16c8a7b98b7fb6114 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 16:21:25 -0400 Subject: [PATCH 332/479] Start implementing prediction for other players - Currently players render at their predicted positions. However, nameplates, hooks, and other things need to be adjusted to use the predicted positions. --- src/game/client/components/players.cpp | 51 +++++++--- src/game/client/gameclient.cpp | 135 +++++++++++++------------ src/game/client/gameclient.h | 15 ++- src/game/variables.h | 1 + 4 files changed, 121 insertions(+), 81 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 94bf9512..7827cba3 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -68,8 +68,8 @@ void CPlayers::RenderHook( else { // apply predicted results - m_pClient->m_PredictedChar.Write(&Player); - m_pClient->m_PredictedPrevChar.Write(&Prev); + m_pClient->PredictedLocalChar()->Write(&Player); + m_pClient->PredictedLocalPrevChar()->Write(&Prev); IntraTick = Client()->PredIntraGameTick(); } } @@ -93,8 +93,17 @@ void CPlayers::RenderHook( if(Client()->State() == IClient::STATE_DEMOPLAYBACK) // only use prediction if needed HookPos = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y); else - HookPos = mix(vec2(m_pClient->m_PredictedPrevChar.m_Pos.x, m_pClient->m_PredictedPrevChar.m_Pos.y), - vec2(m_pClient->m_PredictedChar.m_Pos.x, m_pClient->m_PredictedChar.m_Pos.y), Client()->PredIntraGameTick()); + HookPos = mix( + vec2( + m_pClient->PredictedLocalPrevChar()->m_Pos.x, + m_pClient->PredictedLocalPrevChar()->m_Pos.y + ), + vec2( + m_pClient->PredictedLocalChar()->m_Pos.x, + m_pClient->PredictedLocalChar()->m_Pos.y + ), + Client()->PredIntraGameTick() + ); } else if(m_pClient->m_LocalClientID == ClientID) { @@ -196,17 +205,31 @@ void CPlayers::RenderPlayer( } // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - if(!m_pClient->m_Snap.m_pLocalCharacter || - (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) - { - } - else - { + if (Client()->State() != IClient::STATE_DEMOPLAYBACK && + !( + m_pClient->m_Snap.m_pGameData && + m_pClient->m_Snap.m_pGameData->m_GameStateFlags & ( + GAMESTATEFLAG_PAUSED | + GAMESTATEFLAG_ROUNDOVER | + GAMESTATEFLAG_GAMEOVER + ) + ) + ) { + if (m_pClient->m_LocalClientID == ClientID && + Config()->m_ClPredict && + m_pClient->m_Snap.m_pLocalCharacter + ) { + // apply predicted results + m_pClient->PredictedLocalChar()->Write(&Player); + m_pClient->PredictedLocalPrevChar()->Write(&Prev); + IntraTick = Client()->PredIntraGameTick(); + } else if ( + m_pClient->m_LocalClientID != ClientID && + Config()->m_ClPredictPlayers + ) { // apply predicted results - m_pClient->m_PredictedChar.Write(&Player); - m_pClient->m_PredictedPrevChar.Write(&Prev); + m_pClient->m_aPredictedChars[ClientID].Write(&Player); + m_pClient->m_aPredictedPrevChars[ClientID].Write(&Prev); IntraTick = Client()->PredIntraGameTick(); } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1bb5889f..55407eef 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -500,13 +500,24 @@ void CGameClient::UpdatePositions() // local character position if(Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_Snap.m_pLocalCharacter || - (m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) - { + if (!m_Snap.m_pLocalCharacter || + ( + m_Snap.m_pGameData && + m_Snap.m_pGameData->m_GameStateFlags & ( + GAMESTATEFLAG_PAUSED | + GAMESTATEFLAG_ROUNDOVER | + GAMESTATEFLAG_GAMEOVER + ) + ) + ) { // don't use predicted + } else { + m_LocalCharacterPos = mix( + PredictedLocalPrevChar()->m_Pos, + PredictedLocalChar()->m_Pos, + Client()->PredIntraGameTick() + ); } - else - m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick()); } else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { @@ -1507,21 +1518,22 @@ void CGameClient::OnDemoRecSnap() void CGameClient::OnPredict() { - // store the previous values so we can detect prediction errors - CCharacterCore BeforePrevChar = m_PredictedPrevChar; - CCharacterCore BeforeChar = m_PredictedChar; + // don't predict anything if we are paused or round/game is over + if (m_Snap.m_pGameData && + m_Snap.m_pGameData->m_GameStateFlags & ( + GAMESTATEFLAG_PAUSED | + GAMESTATEFLAG_ROUNDOVER | + GAMESTATEFLAG_GAMEOVER + ) + ) { + for (int i = 0; i < MAX_CLIENTS; i++) { + if (!m_Snap.m_aCharacters[i].m_Active) + continue; - // we can't predict without our own id or own character - if(m_LocalClientID == -1 || !m_Snap.m_aCharacters[m_LocalClientID].m_Active) - return; + m_aPredictedPrevChars[i].Read(&m_Snap.m_aCharacters[i].m_Prev); + m_aPredictedChars[i].Read(&m_Snap.m_aCharacters[i].m_Cur); + } - // don't predict anything if we are paused or round/game is over - if(m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) - { - if(m_Snap.m_pLocalCharacter) - m_PredictedChar.Read(m_Snap.m_pLocalCharacter); - if(m_Snap.m_pLocalPrevCharacter) - m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter); return; } @@ -1530,9 +1542,8 @@ void CGameClient::OnPredict() World.m_Tuning = m_Tuning; // search for players - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(!m_Snap.m_aCharacters[i].m_Active) + for (int i = 0; i < MAX_CLIENTS; i++) { + if (!m_Snap.m_aCharacters[i].m_Active) continue; m_aClients[i].m_Predicted.Init(&World, Collision()); @@ -1541,36 +1552,40 @@ void CGameClient::OnPredict() } // predict - for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++) - { - // fetch the local - if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_LocalClientID]) - m_PredictedPrevChar = *World.m_apCharacters[m_LocalClientID]; - + for (int Tick = Client()->GameTick() + 1; + Tick <= Client()->PredGameTick(); + Tick++ + ) { // first calculate where everyone should move - for(int c = 0; c < MAX_CLIENTS; c++) - { + for(int c = 0; c < MAX_CLIENTS; c++) { if(!World.m_apCharacters[c]) continue; - mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input)); - if(m_LocalClientID == c) - { + if (Tick == Client()->PredGameTick()) + m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; + + mem_zero( + &World.m_apCharacters[c]->m_Input, + sizeof(World.m_apCharacters[c]->m_Input) + ); + + if (m_LocalClientID == c) { // apply player input const int *pInput = Client()->GetInput(Tick); - if(pInput) - World.m_apCharacters[c]->m_Input = *((const CNetObj_PlayerInput*)pInput); + if (pInput) + World.m_apCharacters[c]->m_Input = *( + (const CNetObj_PlayerInput*)pInput + ); + World.m_apCharacters[c]->Tick(true); - } - else + } else { World.m_apCharacters[c]->Tick(false); - + } } // move all players and quantize their data - for(int c = 0; c < MAX_CLIENTS; c++) - { - if(!World.m_apCharacters[c]) + for (int c = 0; c < MAX_CLIENTS; c++) { + if (!World.m_apCharacters[c]) continue; World.m_apCharacters[c]->Move(); @@ -1578,36 +1593,26 @@ void CGameClient::OnPredict() } // check if we want to trigger effects - if(Tick > m_LastNewPredictedTick) + if (Tick > m_LastNewPredictedTick) { m_LastNewPredictedTick = Tick; - if(m_LocalClientID != -1 && World.m_apCharacters[m_LocalClientID]) - ProcessTriggeredEvents(World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, World.m_apCharacters[m_LocalClientID]->m_Pos); - } - - if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_LocalClientID]) - m_PredictedChar = *World.m_apCharacters[m_LocalClientID]; - } + if (m_LocalClientID != -1 && + World.m_apCharacters[m_LocalClientID] + ) + ProcessTriggeredEvents( + World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, + World.m_apCharacters[m_LocalClientID]->m_Pos + ); - if(Config()->m_Debug && Config()->m_ClPredict && m_PredictedTick == Client()->PredGameTick()) - { - CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; - BeforeChar.Write(&Before); - BeforePrevChar.Write(&BeforePrev); - m_PredictedChar.Write(&Now); - m_PredictedPrevChar.Write(&NowPrev); + // TODO: `ProcessTriggeredEvents` for other players + } - if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0) - { - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "prediction error"); - for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++) - if(((int *)&Before)[i] != ((int *)&Now)[i]) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), " %d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]); - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); - } + if (Tick == Client()->PredGameTick()) { + for (int c = 0; c < MAX_CLIENTS; c++) { + if (World.m_apCharacters[c]) + m_aPredictedChars[c] = *World.m_apCharacters[c]; + } } } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 74db48a3..e856e4bb 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -117,8 +117,19 @@ class CGameClient : public IGameClient vec2 m_LocalCharacterPos; // predicted players - CCharacterCore m_PredictedPrevChar; - CCharacterCore m_PredictedChar; + + CCharacterCore m_aPredictedPrevChars[MAX_CLIENTS]; + CCharacterCore m_aPredictedChars[MAX_CLIENTS]; + + CCharacterCore* PredictedLocalPrevChar() { + return &m_aPredictedPrevChars[m_LocalClientID]; + } + + CCharacterCore* PredictedLocalChar() { + return &m_aPredictedChars[m_LocalClientID]; + } + + // --- struct CPlayerInfoItem { diff --git a/src/game/variables.h b/src/game/variables.h index 2becd0d4..b473bd52 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -7,6 +7,7 @@ // client MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") +MACRO_CONFIG_INT(ClPredictPlayers, cl_predict_players, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict movements of other players") MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show name plates") MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show name plates disregarding of distance") MACRO_CONFIG_INT(ClNameplatesTeamcolors, cl_nameplates_teamcolors, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use team colors for name plates") From da3708cd2d084ad576d4c4178834987a11343203 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 20:58:24 -0400 Subject: [PATCH 333/479] Add some prediction helper methods --- src/game/client/components/players.cpp | 51 ++-------- src/game/client/gameclient.cpp | 134 ++++++++++++++++++------- src/game/client/gameclient.h | 27 +++++ 3 files changed, 131 insertions(+), 81 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 7827cba3..93d72bb0 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -57,21 +57,10 @@ void CPlayers::RenderHook( // set size RenderInfo.m_Size = 64.0f; - - // use preditect players if needed - if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - if(!m_pClient->m_Snap.m_pLocalCharacter || - (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) - { - } - else - { - // apply predicted results - m_pClient->PredictedLocalChar()->Write(&Player); - m_pClient->PredictedLocalPrevChar()->Write(&Prev); - IntraTick = Client()->PredIntraGameTick(); - } + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID) + ) { + m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); @@ -204,34 +193,12 @@ void CPlayers::RenderPlayer( g_GameClient.m_aClients[info.cid].angle = angle;*/ } - // use preditect players if needed - if (Client()->State() != IClient::STATE_DEMOPLAYBACK && - !( - m_pClient->m_Snap.m_pGameData && - m_pClient->m_Snap.m_pGameData->m_GameStateFlags & ( - GAMESTATEFLAG_PAUSED | - GAMESTATEFLAG_ROUNDOVER | - GAMESTATEFLAG_GAMEOVER - ) - ) + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID) ) { - if (m_pClient->m_LocalClientID == ClientID && - Config()->m_ClPredict && - m_pClient->m_Snap.m_pLocalCharacter - ) { - // apply predicted results - m_pClient->PredictedLocalChar()->Write(&Player); - m_pClient->PredictedLocalPrevChar()->Write(&Prev); - IntraTick = Client()->PredIntraGameTick(); - } else if ( - m_pClient->m_LocalClientID != ClientID && - Config()->m_ClPredictPlayers - ) { - // apply predicted results - m_pClient->m_aPredictedChars[ClientID].Write(&Player); - m_pClient->m_aPredictedPrevChars[ClientID].Write(&Prev); - IntraTick = Client()->PredIntraGameTick(); - } + m_pClient->m_aPredictedChars[ClientID].Write(&Player); + m_pClient->m_aPredictedPrevChars[ClientID].Write(&Prev); + IntraTick = Client()->PredIntraGameTick(); } vec2 Direction = direction(Angle); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 55407eef..6e5bbd96 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -497,56 +497,71 @@ void CGameClient::OnReset() void CGameClient::UpdatePositions() { - // local character position - if(Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - if (!m_Snap.m_pLocalCharacter || - ( - m_Snap.m_pGameData && - m_Snap.m_pGameData->m_GameStateFlags & ( - GAMESTATEFLAG_PAUSED | - GAMESTATEFLAG_ROUNDOVER | - GAMESTATEFLAG_GAMEOVER - ) - ) - ) { - // don't use predicted - } else { - m_LocalCharacterPos = mix( - PredictedLocalPrevChar()->m_Pos, - PredictedLocalChar()->m_Pos, - Client()->PredIntraGameTick() - ); - } - } - else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) - { + if (ShouldUsePredicted() && ShouldUsePredictedLocalChar()) { + m_LocalCharacterPos = mix( + PredictedLocalPrevChar()->m_Pos, + PredictedLocalChar()->m_Pos, + Client()->PredIntraGameTick() + ); + } else if (m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { m_LocalCharacterPos = mix( vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y), - vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick()); + vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), + Client()->IntraGameTick() + ); } // spectator position - if(m_Snap.m_SpecInfo.m_Active) + if (m_Snap.m_SpecInfo.m_Active) { - if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && - m_Snap.m_SpecInfo.m_SpectatorID != -1) - { + if (Client()->State() == IClient::STATE_DEMOPLAYBACK && + DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && + m_Snap.m_SpecInfo.m_SpectatorID != -1 + ) { m_Snap.m_SpecInfo.m_Position = mix( - vec2(m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_X, m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_Y), - vec2(m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_X, m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_Y), - Client()->IntraGameTick()); + vec2( + m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_X, + m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_Y + ), + vec2( + m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_X, + m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_Y + ), + Client()->IntraGameTick() + ); m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; m_Snap.m_SpecInfo.m_UsePosition = true; } - else if(m_Snap.m_pSpectatorInfo && (Client()->State() == IClient::STATE_DEMOPLAYBACK || m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW || - (m_Snap.m_pLocalInfo && (m_Snap.m_pLocalInfo->m_PlayerFlags&PLAYERFLAG_DEAD) && m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW))) - { - if(m_Snap.m_pPrevSpectatorInfo) - m_Snap.m_SpecInfo.m_Position = mix(vec2(m_Snap.m_pPrevSpectatorInfo->m_X, m_Snap.m_pPrevSpectatorInfo->m_Y), - vec2(m_Snap.m_pSpectatorInfo->m_X, m_Snap.m_pSpectatorInfo->m_Y), Client()->IntraGameTick()); + else if ( + m_Snap.m_pSpectatorInfo && + ( + Client()->State() == IClient::STATE_DEMOPLAYBACK || + m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW || + ( + m_Snap.m_pLocalInfo && + (m_Snap.m_pLocalInfo->m_PlayerFlags & PLAYERFLAG_DEAD) && + m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW + ) + ) + ) { + if (m_Snap.m_pPrevSpectatorInfo) + m_Snap.m_SpecInfo.m_Position = mix( + vec2( + m_Snap.m_pPrevSpectatorInfo->m_X, + m_Snap.m_pPrevSpectatorInfo->m_Y + ), + vec2( + m_Snap.m_pSpectatorInfo->m_X, + m_Snap.m_pSpectatorInfo->m_Y + ), + Client()->IntraGameTick() + ); else - m_Snap.m_SpecInfo.m_Position = vec2(m_Snap.m_pSpectatorInfo->m_X, m_Snap.m_pSpectatorInfo->m_Y); + m_Snap.m_SpecInfo.m_Position = vec2( + m_Snap.m_pSpectatorInfo->m_X, + m_Snap.m_pSpectatorInfo->m_Y + ); + m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; m_Snap.m_SpecInfo.m_UsePosition = true; } @@ -1619,6 +1634,47 @@ void CGameClient::OnPredict() m_PredictedTick = Client()->PredGameTick(); } + +bool CGameClient::ShouldUsePredicted() { + return + Client()->State() != IClient::STATE_DEMOPLAYBACK && + !( + m_Snap.m_pGameData && + m_Snap.m_pGameData->m_GameStateFlags & ( + GAMESTATEFLAG_PAUSED | + GAMESTATEFLAG_ROUNDOVER | + GAMESTATEFLAG_GAMEOVER + ) + ); +} + +bool CGameClient::ShouldUsePredictedLocalChar() { + return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; +} + +bool CGameClient::ShouldUsePredictedNonLocalChars() { + return Config()->m_ClPredictPlayers; +} + +bool CGameClient::ShouldUsePredictedChar(int ClientID) { + if (ClientID == m_LocalClientID) { + return ShouldUsePredictedLocalChar(); + } else { + return ShouldUsePredictedNonLocalChars(); + } +} + +void CGameClient::UsePredictedChar( + CNetObj_Character *pPrevChar, + CNetObj_Character *pPlayerChar, + float *IntraTick, + int ClientID +) { + m_aPredictedPrevChars[ClientID].Write(pPrevChar); + m_aPredictedChars[ClientID].Write(pPlayerChar); + *IntraTick = Client()->PredIntraGameTick(); +} + void CGameClient::OnActivateEditor() { OnRelease(); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index e856e4bb..afe8786c 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -129,6 +129,33 @@ class CGameClient : public IGameClient return &m_aPredictedChars[m_LocalClientID]; } + bool ShouldUsePredicted(); + // Whether we should use/render predicted entities. Depends on client + // and game state. +private: + bool ShouldUsePredictedLocalChar(); + // Whether we should use/render predicted entities for the local + // character. Depends on config and snap state. Should check + // `ShouldUsePredicted` before checking this. + bool ShouldUsePredictedNonLocalChars(); + // Whether we should use/render predicted entities for non-local + // characters. Depends on config. Should check `ShouldUsePredicted` + // before checking this. +public: + bool ShouldUsePredictedChar(int ClientID); + // Whether we should use/render predictions for a specific `ClientID`. + // Should check `ShouldUsePredicted` before checking this. + + // Replace `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted + // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` + // before using this. + void UsePredictedChar( + CNetObj_Character *pPrevChar, + CNetObj_Character *pPlayerChar, + float *IntraTick, + int ClientID + ); + // --- struct CPlayerInfoItem From 14082d1afce22f008bd95257992df27377700eca Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 22:29:16 -0400 Subject: [PATCH 334/479] Use predicted character positions for hook - Add two helpers: `PredictedCharPos` and `UnpredictedCharPos` --- src/game/client/components/players.cpp | 49 +++++++++--------------- src/game/client/gameclient.cpp | 52 ++++++++++++++++---------- src/game/client/gameclient.h | 9 +++-- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 93d72bb0..ab3101b2 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -63,7 +63,11 @@ void CPlayers::RenderHook( m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } - vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); + vec2 Position = mix( + vec2(Prev.m_X, Prev.m_Y), + vec2(Player.m_X, Player.m_Y), + IntraTick + ); // draw hook if (Prev.m_HookState>0 && Player.m_HookState>0) @@ -75,38 +79,21 @@ void CPlayers::RenderHook( vec2 Pos = Position; vec2 HookPos; - if(pPlayerChar->m_HookedPlayer != -1) - { - if(m_pClient->m_LocalClientID != -1 && pPlayerChar->m_HookedPlayer == m_pClient->m_LocalClientID) - { - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) // only use prediction if needed - HookPos = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y); - else - HookPos = mix( - vec2( - m_pClient->PredictedLocalPrevChar()->m_Pos.x, - m_pClient->PredictedLocalPrevChar()->m_Pos.y - ), - vec2( - m_pClient->PredictedLocalChar()->m_Pos.x, - m_pClient->PredictedLocalChar()->m_Pos.y - ), - Client()->PredIntraGameTick() - ); + if (pPlayerChar->m_HookedPlayer != -1) { + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pPlayerChar->m_HookedPlayer) + ) { + HookPos = m_pClient->PredictedCharPos(pPlayerChar->m_HookedPlayer); + } else { + HookPos = m_pClient->UnpredictedCharPos(pPlayerChar->m_HookedPlayer); } - else if(m_pClient->m_LocalClientID == ClientID) - { - HookPos = mix(vec2(m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Prev.m_X, - m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Prev.m_Y), - vec2(m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Cur.m_X, - m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Cur.m_Y), - Client()->IntraGameTick()); - } - else - HookPos = mix(vec2(pPrevChar->m_HookX, pPrevChar->m_HookY), vec2(pPlayerChar->m_HookX, pPlayerChar->m_HookY), Client()->IntraGameTick()); + } else { + HookPos = mix( + vec2(Prev.m_HookX, Prev.m_HookY), + vec2(Player.m_HookX, Player.m_HookY), + IntraTick + ); } - else - HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick); float d = distance(Pos, HookPos); vec2 Dir = normalize(Pos-HookPos); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 6e5bbd96..deb4cb17 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -498,17 +498,9 @@ void CGameClient::OnReset() void CGameClient::UpdatePositions() { if (ShouldUsePredicted() && ShouldUsePredictedLocalChar()) { - m_LocalCharacterPos = mix( - PredictedLocalPrevChar()->m_Pos, - PredictedLocalChar()->m_Pos, - Client()->PredIntraGameTick() - ); + m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); } else if (m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { - m_LocalCharacterPos = mix( - vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y), - vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), - Client()->IntraGameTick() - ); + m_LocalCharacterPos = UnpredictedCharPos(m_LocalClientID); } // spectator position @@ -518,16 +510,8 @@ void CGameClient::UpdatePositions() DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && m_Snap.m_SpecInfo.m_SpectatorID != -1 ) { - m_Snap.m_SpecInfo.m_Position = mix( - vec2( - m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_X, - m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_Y - ), - vec2( - m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_X, - m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_Y - ), - Client()->IntraGameTick() + m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos( + m_Snap.m_SpecInfo.m_SpectatorID ); m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; m_Snap.m_SpecInfo.m_UsePosition = true; @@ -1675,6 +1659,34 @@ void CGameClient::UsePredictedChar( *IntraTick = Client()->PredIntraGameTick(); } +vec2 CGameClient::PredictedCharPos(int ClientID) { + return mix( + vec2( + m_aPredictedPrevChars[ClientID].m_Pos.x, + m_aPredictedPrevChars[ClientID].m_Pos.y + ), + vec2( + m_aPredictedChars[ClientID].m_Pos.x, + m_aPredictedChars[ClientID].m_Pos.y + ), + Client()->PredIntraGameTick() + ); +} + +vec2 CGameClient::UnpredictedCharPos(int ClientID) { + return mix( + vec2( + m_Snap.m_aCharacters[ClientID].m_Prev.m_X, + m_Snap.m_aCharacters[ClientID].m_Prev.m_Y + ), + vec2( + m_Snap.m_aCharacters[ClientID].m_Cur.m_X, + m_Snap.m_aCharacters[ClientID].m_Cur.m_Y + ), + Client()->IntraGameTick() + ); +} + void CGameClient::OnActivateEditor() { OnRelease(); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index afe8786c..07037c3c 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -146,15 +146,18 @@ class CGameClient : public IGameClient // Whether we should use/render predictions for a specific `ClientID`. // Should check `ShouldUsePredicted` before checking this. - // Replace `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted - // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` - // before using this. void UsePredictedChar( CNetObj_Character *pPrevChar, CNetObj_Character *pPlayerChar, float *IntraTick, int ClientID ); + // Replace `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted + // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` + // before using this. + + vec2 PredictedCharPos(int ClientID); + vec2 UnpredictedCharPos(int ClientID); // --- From 8becd7e6be0041b3ef61f2aeb8f9c17089f6cf46 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 22:35:59 -0400 Subject: [PATCH 335/479] Don't use prediction when spectating --- src/game/client/gameclient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index deb4cb17..03be009c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1629,7 +1629,8 @@ bool CGameClient::ShouldUsePredicted() { GAMESTATEFLAG_ROUNDOVER | GAMESTATEFLAG_GAMEOVER ) - ); + ) && + !(m_Snap.m_SpecInfo.m_Active); } bool CGameClient::ShouldUsePredictedLocalChar() { From 1e82d8dd02b145176e51b2718270ec6c46d64ef8 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 22:46:15 -0400 Subject: [PATCH 336/479] Use predicted position for nameplates --- src/game/client/components/nameplates.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 120af70c..69d3bc9e 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -17,10 +17,14 @@ void CNamePlates::RenderNameplate( int ClientID ) { - float IntraTick = Client()->IntraGameTick(); - - vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick); - + vec2 Position; + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID) + ) { + Position = m_pClient->PredictedCharPos(ClientID); + } else { + Position = m_pClient->UnpredictedCharPos(ClientID); + } float FontSize = 18.0f + 20.0f * Config()->m_ClNameplatesSize / 100.0f; // render name plate From 954b3a0cec7db0a2ca6fbb144a244363d9c71727 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 23:17:38 -0400 Subject: [PATCH 337/479] Use predicted carrier position for flags --- src/game/client/components/items.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index e6560f5e..0c9220a1 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -189,11 +189,29 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, (pCurrent->m_Team == TEAM_BLUE && pPrevGameDataFlag->m_FlagCarrierBlue != pCurGameDataFlag->m_FlagCarrierBlue))) Pos = vec2(pCurrent->m_X, pCurrent->m_Y); - // make sure to use predicted position if we are the carrier - if(m_pClient->m_LocalClientID != -1 && - ((pCurrent->m_Team == TEAM_RED && pCurGameDataFlag->m_FlagCarrierRed == m_pClient->m_LocalClientID) || - (pCurrent->m_Team == TEAM_BLUE && pCurGameDataFlag->m_FlagCarrierBlue == m_pClient->m_LocalClientID))) - Pos = m_pClient->m_LocalCharacterPos; + // use predicted carrier position if possible + + if (pCurrent->m_Team == TEAM_RED) { + if (pCurGameDataFlag->m_FlagCarrierRed >= 0) { + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierRed) + ) { + Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); + } else { + Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); + } + } + } else if (pCurrent->m_Team == TEAM_BLUE) { + if (pCurGameDataFlag->m_FlagCarrierBlue >= 0) { + if (m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierBlue) + ) { + Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); + } else { + Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); + } + } + } } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y-Size*0.75f, Size, Size*2); From 642dc67e13c78350820ab91130b6ddfcce258ec7 Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 23:45:59 -0400 Subject: [PATCH 338/479] Remove TODO comment - We won't use `ProcessTriggeredEvents` for other players because we will never predict that other players will trigger any of those events (e.g. jump, launch hook) --- src/game/client/gameclient.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 03be009c..4f30724e 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1603,8 +1603,6 @@ void CGameClient::OnPredict() World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, World.m_apCharacters[m_LocalClientID]->m_Pos ); - - // TODO: `ProcessTriggeredEvents` for other players } if (Tick == Client()->PredGameTick()) { From 1eba485335536bba79eb32f9c04650679d00154f Mon Sep 17 00:00:00 2001 From: Piepow Date: Mon, 8 Jun 2020 23:46:36 -0400 Subject: [PATCH 339/479] Turn `cl_predict_players` off by default --- src/game/variables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/variables.h b/src/game/variables.h index b473bd52..a94bca60 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -7,7 +7,7 @@ // client MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") -MACRO_CONFIG_INT(ClPredictPlayers, cl_predict_players, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict movements of other players") +MACRO_CONFIG_INT(ClPredictPlayers, cl_predict_players, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict movements of other players") MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show name plates") MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show name plates disregarding of distance") MACRO_CONFIG_INT(ClNameplatesTeamcolors, cl_nameplates_teamcolors, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use team colors for name plates") From 92b6c99a71c18ba65bf568499b6a086aa4a588e8 Mon Sep 17 00:00:00 2001 From: Piepow Date: Tue, 9 Jun 2020 00:13:35 -0400 Subject: [PATCH 340/479] Forgot to use `UsePredictedChar` helper --- src/game/client/components/players.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index ab3101b2..7eb36b8e 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -183,9 +183,7 @@ void CPlayers::RenderPlayer( if (m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(ClientID) ) { - m_pClient->m_aPredictedChars[ClientID].Write(&Player); - m_pClient->m_aPredictedPrevChars[ClientID].Write(&Prev); - IntraTick = Client()->PredIntraGameTick(); + m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } vec2 Direction = direction(Angle); From c83fbea766d6e452b5fd1edbe015eef5f5ae41c0 Mon Sep 17 00:00:00 2001 From: Piepow Date: Tue, 9 Jun 2020 00:41:28 -0400 Subject: [PATCH 341/479] Add comments for prediction code --- src/game/client/components/items.cpp | 2 ++ src/game/client/components/players.cpp | 2 ++ src/game/client/gameclient.cpp | 39 ++++++++++++++++++++++++-- src/game/client/gameclient.h | 10 ++++--- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 0c9220a1..a5e6dc6b 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -193,6 +193,7 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, if (pCurrent->m_Team == TEAM_RED) { if (pCurGameDataFlag->m_FlagCarrierRed >= 0) { + // `FlagCarrier >= 0` means that there is a character carrying the flag if (m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierRed) ) { @@ -203,6 +204,7 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, } } else if (pCurrent->m_Team == TEAM_BLUE) { if (pCurGameDataFlag->m_FlagCarrierBlue >= 0) { + // `FlagCarrier >= 0` means that there is a character carrying the flag if (m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierBlue) ) { diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 7eb36b8e..40b77b71 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -80,6 +80,7 @@ void CPlayers::RenderHook( vec2 HookPos; if (pPlayerChar->m_HookedPlayer != -1) { + // `HookedPlayer != -1` means that a player is being hooked if (m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(pPlayerChar->m_HookedPlayer) ) { @@ -88,6 +89,7 @@ void CPlayers::RenderHook( HookPos = m_pClient->UnpredictedCharPos(pPlayerChar->m_HookedPlayer); } } else { + // The hook is in the air or on a hookable tile HookPos = mix( vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 4f30724e..5c1b840b 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -497,6 +497,8 @@ void CGameClient::OnReset() void CGameClient::UpdatePositions() { + // `m_LocalCharacterPos` is used for many things besides rendering the + // player (e.g. camera position, mouse input), which is why we set it here. if (ShouldUsePredicted() && ShouldUsePredictedLocalChar()) { m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); } else if (m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { @@ -1517,6 +1519,12 @@ void CGameClient::OnDemoRecSnap() void CGameClient::OnPredict() { + // Here we predict player movements. For the local player, we also predict + // the result of the local input to make the game appear responsive even at + // high latencies. For non-local players, we predict what will happen if + // they don't apply any inputs. In both cases we are extrapolating + // (predicting) what will happen between `GameTick` and `PredGameTick`. + // don't predict anything if we are paused or round/game is over if (m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags & ( @@ -1529,6 +1537,8 @@ void CGameClient::OnPredict() if (!m_Snap.m_aCharacters[i].m_Active) continue; + // instead of predicting into the future, just use the current and + // previous snapshots that we already have m_aPredictedPrevChars[i].Read(&m_Snap.m_aCharacters[i].m_Prev); m_aPredictedChars[i].Read(&m_Snap.m_aCharacters[i].m_Cur); } @@ -1556,10 +1566,13 @@ void CGameClient::OnPredict() Tick++ ) { // first calculate where everyone should move - for(int c = 0; c < MAX_CLIENTS; c++) { - if(!World.m_apCharacters[c]) + for (int c = 0; c < MAX_CLIENTS; c++) { + if (!World.m_apCharacters[c]) continue; + // Before running the last iteration, store our predictions. We use + // `Prev` because we haven't run the last iteration yet, so our + // data is from the previous tick. if (Tick == Client()->PredGameTick()) m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; @@ -1578,6 +1591,7 @@ void CGameClient::OnPredict() World.m_apCharacters[c]->Tick(true); } else { + // don't apply inputs for non-local players World.m_apCharacters[c]->Tick(false); } } @@ -1596,6 +1610,12 @@ void CGameClient::OnPredict() { m_LastNewPredictedTick = Tick; + // Only trigger effects for the local character here. Effects for + // non-local characters are triggered in `OnNewSnapshot`. Since we + // don't apply any inputs to non-local characters, it's not + // necessary to trigger events for them here. Also, our predictions + // for other players will often be wrong, so it's safer not to + // trigger events here. if (m_LocalClientID != -1 && World.m_apCharacters[m_LocalClientID] ) @@ -1605,6 +1625,12 @@ void CGameClient::OnPredict() ); } + // After running the last iteration, store our final prediction. We should + // now have the following predictions: + // - `m_aPredictedPrevChars` stores character predictions at time + // `PredGameTick - 1` + // - `m_aPredictedChars` stores character predictions at time + // `PredGameTick` if (Tick == Client()->PredGameTick()) { for (int c = 0; c < MAX_CLIENTS; c++) { if (World.m_apCharacters[c]) @@ -1618,6 +1644,10 @@ void CGameClient::OnPredict() bool CGameClient::ShouldUsePredicted() { + // We don't use predictions when: + // - Viewing a demo + // - When the game is paused or waiting + // - When we are spectating return Client()->State() != IClient::STATE_DEMOPLAYBACK && !( @@ -1632,6 +1662,8 @@ bool CGameClient::ShouldUsePredicted() { } bool CGameClient::ShouldUsePredictedLocalChar() { + // Not sure if `m_Snap.m_pLocalCharacter` is necessary, but the old code + // checked it so I will too. return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; } @@ -1643,6 +1675,9 @@ bool CGameClient::ShouldUsePredictedChar(int ClientID) { if (ClientID == m_LocalClientID) { return ShouldUsePredictedLocalChar(); } else { + // Might want to check if `ClientID` exists in `m_Snap.m_aCharacters`, + // similar to how we check if `m_pLocalCharacter` is not null in + // `ShouldUsePredictedLocalChar` return ShouldUsePredictedNonLocalChars(); } } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 07037c3c..5153dee8 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -134,9 +134,9 @@ class CGameClient : public IGameClient // and game state. private: bool ShouldUsePredictedLocalChar(); - // Whether we should use/render predicted entities for the local - // character. Depends on config and snap state. Should check - // `ShouldUsePredicted` before checking this. + // Whether we should use/render the predicted local character. Depends + // on config and snap state. Should check `ShouldUsePredicted` before + // checking this. bool ShouldUsePredictedNonLocalChars(); // Whether we should use/render predicted entities for non-local // characters. Depends on config. Should check `ShouldUsePredicted` @@ -152,12 +152,14 @@ class CGameClient : public IGameClient float *IntraTick, int ClientID ); - // Replace `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted + // Replaces `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` // before using this. vec2 PredictedCharPos(int ClientID); + // Return the interpolated, predicted position for `ClientID` vec2 UnpredictedCharPos(int ClientID); + // Return the interpolated, unpredicted position for `ClientID` // --- From f87bfb5510de700f12613d3931e6833333d5bafb Mon Sep 17 00:00:00 2001 From: Piepow Date: Tue, 9 Jun 2020 14:40:17 -0400 Subject: [PATCH 342/479] Change prediction code to Teeworlds style code - Remove unused helpers: `PredictedLocalChar()` and `PredictedLocalPrevChar` --- src/game/client/components/items.cpp | 36 ++++--- src/game/client/components/nameplates.cpp | 12 ++- src/game/client/components/players.cpp | 31 +++--- src/game/client/gameclient.cpp | 109 +++++++++++++--------- src/game/client/gameclient.h | 8 -- 5 files changed, 110 insertions(+), 86 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index a5e6dc6b..466304e9 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -190,26 +190,34 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, Pos = vec2(pCurrent->m_X, pCurrent->m_Y); // use predicted carrier position if possible - - if (pCurrent->m_Team == TEAM_RED) { - if (pCurGameDataFlag->m_FlagCarrierRed >= 0) { + if(pCurrent->m_Team == TEAM_RED) + { + if(pCurGameDataFlag->m_FlagCarrierRed >= 0) + { // `FlagCarrier >= 0` means that there is a character carrying the flag - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierRed) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierRed)) + { Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); - } else { + } + else + { Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); } } - } else if (pCurrent->m_Team == TEAM_BLUE) { - if (pCurGameDataFlag->m_FlagCarrierBlue >= 0) { + } + else if(pCurrent->m_Team == TEAM_BLUE) + { + if(pCurGameDataFlag->m_FlagCarrierBlue >= 0) + { // `FlagCarrier >= 0` means that there is a character carrying the flag - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierBlue) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierBlue)) + { Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); - } else { + } + else + { Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); } } @@ -326,7 +334,7 @@ void CItems::OnRender() if(Item.m_Type == NETOBJTYPE_FLAG) { const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID); - if (pPrev) + if(pPrev) { const void *pPrevGameDataFlag = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_GAMEDATAFLAG, m_pClient->m_Snap.m_GameDataFlagSnapID); RenderFlag(static_cast(pPrev), static_cast(pData), diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 69d3bc9e..cf09b319 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -18,11 +18,13 @@ void CNamePlates::RenderNameplate( ) { vec2 Position; - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID)) + { Position = m_pClient->PredictedCharPos(ClientID); - } else { + } + else + { Position = m_pClient->UnpredictedCharPos(ClientID); } @@ -75,7 +77,7 @@ void CNamePlates::RenderNameplate( void CNamePlates::OnRender() { - if (!Config()->m_ClNameplates || Client()->State() < IClient::STATE_ONLINE) + if(!Config()->m_ClNameplates || Client()->State() < IClient::STATE_ONLINE) return; for(int i = 0; i < MAX_CLIENTS; i++) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 40b77b71..df64319c 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -57,9 +57,9 @@ void CPlayers::RenderHook( // set size RenderInfo.m_Size = 64.0f; - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID)) + { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } @@ -70,7 +70,7 @@ void CPlayers::RenderHook( ); // draw hook - if (Prev.m_HookState>0 && Player.m_HookState>0) + if(Prev.m_HookState>0 && Player.m_HookState>0) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); @@ -79,16 +79,21 @@ void CPlayers::RenderHook( vec2 Pos = Position; vec2 HookPos; - if (pPlayerChar->m_HookedPlayer != -1) { + if(pPlayerChar->m_HookedPlayer != -1) + { // `HookedPlayer != -1` means that a player is being hooked - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pPlayerChar->m_HookedPlayer) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(pPlayerChar->m_HookedPlayer)) + { HookPos = m_pClient->PredictedCharPos(pPlayerChar->m_HookedPlayer); - } else { + } + else + { HookPos = m_pClient->UnpredictedCharPos(pPlayerChar->m_HookedPlayer); } - } else { + } + else + { // The hook is in the air or on a hookable tile HookPos = mix( vec2(Prev.m_HookX, Prev.m_HookY), @@ -182,9 +187,9 @@ void CPlayers::RenderPlayer( g_GameClient.m_aClients[info.cid].angle = angle;*/ } - if (m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID) - ) { + if(m_pClient->ShouldUsePredicted() && + m_pClient->ShouldUsePredictedChar(ClientID)) + { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 5c1b840b..06be4cee 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -499,26 +499,27 @@ void CGameClient::UpdatePositions() { // `m_LocalCharacterPos` is used for many things besides rendering the // player (e.g. camera position, mouse input), which is why we set it here. - if (ShouldUsePredicted() && ShouldUsePredictedLocalChar()) { + if(ShouldUsePredicted() && ShouldUsePredictedLocalChar()) + { m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); - } else if (m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { + } + else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) + { m_LocalCharacterPos = UnpredictedCharPos(m_LocalClientID); } // spectator position - if (m_Snap.m_SpecInfo.m_Active) + if(m_Snap.m_SpecInfo.m_Active) { - if (Client()->State() == IClient::STATE_DEMOPLAYBACK && + if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && - m_Snap.m_SpecInfo.m_SpectatorID != -1 - ) { - m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos( - m_Snap.m_SpecInfo.m_SpectatorID - ); + m_Snap.m_SpecInfo.m_SpectatorID != -1) + { + m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos(m_Snap.m_SpecInfo.m_SpectatorID); m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; m_Snap.m_SpecInfo.m_UsePosition = true; } - else if ( + else if( m_Snap.m_pSpectatorInfo && ( Client()->State() == IClient::STATE_DEMOPLAYBACK || @@ -528,9 +529,9 @@ void CGameClient::UpdatePositions() (m_Snap.m_pLocalInfo->m_PlayerFlags & PLAYERFLAG_DEAD) && m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW ) - ) - ) { - if (m_Snap.m_pPrevSpectatorInfo) + )) + { + if(m_Snap.m_pPrevSpectatorInfo) m_Snap.m_SpecInfo.m_Position = mix( vec2( m_Snap.m_pPrevSpectatorInfo->m_X, @@ -1526,15 +1527,16 @@ void CGameClient::OnPredict() // (predicting) what will happen between `GameTick` and `PredGameTick`. // don't predict anything if we are paused or round/game is over - if (m_Snap.m_pGameData && + if(m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags & ( GAMESTATEFLAG_PAUSED | GAMESTATEFLAG_ROUNDOVER | GAMESTATEFLAG_GAMEOVER - ) - ) { - for (int i = 0; i < MAX_CLIENTS; i++) { - if (!m_Snap.m_aCharacters[i].m_Active) + )) + { + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_Snap.m_aCharacters[i].m_Active) continue; // instead of predicting into the future, just use the current and @@ -1551,8 +1553,9 @@ void CGameClient::OnPredict() World.m_Tuning = m_Tuning; // search for players - for (int i = 0; i < MAX_CLIENTS; i++) { - if (!m_Snap.m_aCharacters[i].m_Active) + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_Snap.m_aCharacters[i].m_Active) continue; m_aClients[i].m_Predicted.Init(&World, Collision()); @@ -1561,19 +1564,20 @@ void CGameClient::OnPredict() } // predict - for (int Tick = Client()->GameTick() + 1; + for(int Tick = Client()->GameTick() + 1; Tick <= Client()->PredGameTick(); - Tick++ - ) { + Tick++) + { // first calculate where everyone should move - for (int c = 0; c < MAX_CLIENTS; c++) { - if (!World.m_apCharacters[c]) + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(!World.m_apCharacters[c]) continue; // Before running the last iteration, store our predictions. We use // `Prev` because we haven't run the last iteration yet, so our // data is from the previous tick. - if (Tick == Client()->PredGameTick()) + if(Tick == Client()->PredGameTick()) m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; mem_zero( @@ -1581,7 +1585,8 @@ void CGameClient::OnPredict() sizeof(World.m_apCharacters[c]->m_Input) ); - if (m_LocalClientID == c) { + if(m_LocalClientID == c) + { // apply player input const int *pInput = Client()->GetInput(Tick); if (pInput) @@ -1590,14 +1595,17 @@ void CGameClient::OnPredict() ); World.m_apCharacters[c]->Tick(true); - } else { + } + else + { // don't apply inputs for non-local players World.m_apCharacters[c]->Tick(false); } } // move all players and quantize their data - for (int c = 0; c < MAX_CLIENTS; c++) { + for(int c = 0; c < MAX_CLIENTS; c++) + { if (!World.m_apCharacters[c]) continue; @@ -1606,7 +1614,7 @@ void CGameClient::OnPredict() } // check if we want to trigger effects - if (Tick > m_LastNewPredictedTick) + if(Tick > m_LastNewPredictedTick) { m_LastNewPredictedTick = Tick; @@ -1616,13 +1624,14 @@ void CGameClient::OnPredict() // necessary to trigger events for them here. Also, our predictions // for other players will often be wrong, so it's safer not to // trigger events here. - if (m_LocalClientID != -1 && - World.m_apCharacters[m_LocalClientID] - ) + if(m_LocalClientID != -1 && + World.m_apCharacters[m_LocalClientID]) + { ProcessTriggeredEvents( World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, World.m_apCharacters[m_LocalClientID]->m_Pos ); + } } // After running the last iteration, store our final prediction. We should @@ -1631,9 +1640,11 @@ void CGameClient::OnPredict() // `PredGameTick - 1` // - `m_aPredictedChars` stores character predictions at time // `PredGameTick` - if (Tick == Client()->PredGameTick()) { - for (int c = 0; c < MAX_CLIENTS; c++) { - if (World.m_apCharacters[c]) + if(Tick == Client()->PredGameTick()) + { + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(World.m_apCharacters[c]) m_aPredictedChars[c] = *World.m_apCharacters[c]; } } @@ -1643,7 +1654,8 @@ void CGameClient::OnPredict() } -bool CGameClient::ShouldUsePredicted() { +bool CGameClient::ShouldUsePredicted() +{ // We don't use predictions when: // - Viewing a demo // - When the game is paused or waiting @@ -1661,25 +1673,27 @@ bool CGameClient::ShouldUsePredicted() { !(m_Snap.m_SpecInfo.m_Active); } -bool CGameClient::ShouldUsePredictedLocalChar() { +bool CGameClient::ShouldUsePredictedLocalChar() +{ // Not sure if `m_Snap.m_pLocalCharacter` is necessary, but the old code // checked it so I will too. return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; } -bool CGameClient::ShouldUsePredictedNonLocalChars() { +bool CGameClient::ShouldUsePredictedNonLocalChars() +{ return Config()->m_ClPredictPlayers; } -bool CGameClient::ShouldUsePredictedChar(int ClientID) { - if (ClientID == m_LocalClientID) { +bool CGameClient::ShouldUsePredictedChar(int ClientID) +{ + if(ClientID == m_LocalClientID) return ShouldUsePredictedLocalChar(); - } else { + else // Might want to check if `ClientID` exists in `m_Snap.m_aCharacters`, // similar to how we check if `m_pLocalCharacter` is not null in // `ShouldUsePredictedLocalChar` return ShouldUsePredictedNonLocalChars(); - } } void CGameClient::UsePredictedChar( @@ -1687,13 +1701,15 @@ void CGameClient::UsePredictedChar( CNetObj_Character *pPlayerChar, float *IntraTick, int ClientID -) { + ) +{ m_aPredictedPrevChars[ClientID].Write(pPrevChar); m_aPredictedChars[ClientID].Write(pPlayerChar); *IntraTick = Client()->PredIntraGameTick(); } -vec2 CGameClient::PredictedCharPos(int ClientID) { +vec2 CGameClient::PredictedCharPos(int ClientID) +{ return mix( vec2( m_aPredictedPrevChars[ClientID].m_Pos.x, @@ -1707,7 +1723,8 @@ vec2 CGameClient::PredictedCharPos(int ClientID) { ); } -vec2 CGameClient::UnpredictedCharPos(int ClientID) { +vec2 CGameClient::UnpredictedCharPos(int ClientID) +{ return mix( vec2( m_Snap.m_aCharacters[ClientID].m_Prev.m_X, diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 5153dee8..36741930 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -121,14 +121,6 @@ class CGameClient : public IGameClient CCharacterCore m_aPredictedPrevChars[MAX_CLIENTS]; CCharacterCore m_aPredictedChars[MAX_CLIENTS]; - CCharacterCore* PredictedLocalPrevChar() { - return &m_aPredictedPrevChars[m_LocalClientID]; - } - - CCharacterCore* PredictedLocalChar() { - return &m_aPredictedChars[m_LocalClientID]; - } - bool ShouldUsePredicted(); // Whether we should use/render predicted entities. Depends on client // and game state. From fbb66cb5be3d761331f5f90d54e4a8f8cb277327 Mon Sep 17 00:00:00 2001 From: Piepow Date: Tue, 9 Jun 2020 23:28:38 -0400 Subject: [PATCH 343/479] Revert "fixed sprite rendering. Closes #44" This reverts commit 8eaa040e3ed2a7a40fdb21eec284d85c2540505e. --- src/game/client/render.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 7b777cf3..6a3ad33a 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -37,9 +37,9 @@ void CRenderTools::SelectSprite(CDataSprite *pSpr, int Flags, int sx, int sy) gs_SpriteHScale = h/f; float x1 = x/(float)cx; - float x2 = (x+w-1/32.0f)/(float)cx; + float x2 = (x+w)/(float)cx; float y1 = y/(float)cy; - float y2 = (y+h-1/32.0f)/(float)cy; + float y2 = (y+h)/(float)cy; float Temp = 0; if(Flags&SPRITE_FLAG_FLIP_Y) From a2418969a33d3c1c29e383ffb08cf6ce1ddabbc5 Mon Sep 17 00:00:00 2001 From: Piepow Date: Thu, 11 Jun 2020 00:47:26 -0400 Subject: [PATCH 344/479] Shrink sprite texture coordinates - Fixes bug where pixels from outside the sprite border are rendered - Code by Jupeyy --- src/game/client/render.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 6a3ad33a..f5b145db 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -36,10 +36,11 @@ void CRenderTools::SelectSprite(CDataSprite *pSpr, int Flags, int sx, int sy) gs_SpriteWScale = w/f; gs_SpriteHScale = h/f; - float x1 = x/(float)cx; - float x2 = (x+w)/(float)cx; - float y1 = y/(float)cy; - float y2 = (y+h)/(float)cy; + float x1 = x/(float)cx + 0.5f/(float)(cx*32); + float x2 = (x+w)/(float)cx - 0.5f/(float)(cx*32); + float y1 = y/(float)cy + 0.5f/(float)(cy*32); + float y2 = (y+h)/(float)cy - 0.5f/(float)(cy*32); + float Temp = 0; if(Flags&SPRITE_FLAG_FLIP_Y) From 7abdd9fa8e14d89c1d0a3d8b936d6c33d8410e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 14 Jun 2020 11:10:26 +0200 Subject: [PATCH 345/479] make menu sense dependent on mouse sens again, breaking joystick --- src/game/client/ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 3fbc23f1..72d8b09f 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -63,7 +63,7 @@ bool CUI::MouseInsideClip() const void CUI::ConvertMouseMove(float *x, float *y) const { - float Fac = m_pConfig->m_UiMousesens/100.0f; + const float Fac = m_pConfig->m_UiMousesens/float(m_pConfig->m_InpMousesens); *x = *x * Fac; *y = *y * Fac; } From 5c11e801fd9edad362fda8b4e2bf6001725de156 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 17 Jun 2020 11:39:32 +0200 Subject: [PATCH 346/479] Add more information on map load error --- src/engine/client/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 1eb9fe11..ba4fbaf5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -818,7 +818,7 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, const SHA char aWantedSha256[SHA256_MAXSTRSIZE]; sha256_str(m_pMap->Sha256(), aSha256, sizeof(aSha256)); sha256_str(*pWantedSha256, aWantedSha256, sizeof(aWantedSha256)); - str_format(aErrorMsg, sizeof(aErrorMsg), "map differs from the server. %s != %s", aSha256, aWantedSha256); + str_format(aErrorMsg, sizeof(aErrorMsg), "map differs from the server. found = %s wanted = %s", aSha256, aWantedSha256); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aErrorMsg); m_pMap->Unload(); return aErrorMsg; @@ -827,7 +827,7 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, const SHA // get the crc of the map if(m_pMap->Crc() != WantedCrc) { - str_format(aErrorMsg, sizeof(aErrorMsg), "map differs from the server. %08x != %08x", m_pMap->Crc(), WantedCrc); + str_format(aErrorMsg, sizeof(aErrorMsg), "map differs from the server. found = %08x wanted = %08x", m_pMap->Crc(), WantedCrc); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aErrorMsg); m_pMap->Unload(); return aErrorMsg; From cd74f9b4170cbc00646b3d6d0ab25ad7b7fdd0be Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 17 Jun 2020 16:04:41 +0200 Subject: [PATCH 347/479] Fix gametype filter UI corner --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b6e6c25b..f67e94c2 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1913,7 +1913,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) static char s_aGametype[16] = { 0 }; static float s_OffsetGametype = 0.0f; Button.VSplitRight(Button.h, &Label, &Button); - DoEditBox(&s_OffsetGametype, &Label, s_aGametype, sizeof(s_aGametype), FontSize, &s_OffsetGametype); + DoEditBox(&s_OffsetGametype, &Label, s_aGametype, sizeof(s_aGametype), FontSize, &s_OffsetGametype, false, CUI::CORNER_L); RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_R, 5.0f); DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Button); static CButtonContainer s_AddGametype; From 1608e4cc7bb16baf41ea6302e971803763742cd3 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 13 May 2020 12:41:31 +0200 Subject: [PATCH 348/479] Add demo sorting by name and date (#1739) Ported from ddnet client. Demo sorting implemented by @east https://github.com/ddnet/ddnet/pull/308 Based on work by @def- https://github.com/ddnet/ddnet/commit/08ac551e0e6491d0795c90e0cbc46a1af0be1567 Thanks to @heinrich5991 for helping with the CDemoComparator --- src/base/system.c | 63 +++++++++++++++++++ src/base/system.h | 10 +++ src/base/tl/algorithm.h | 6 +- src/base/tl/sorted_array.h | 5 ++ src/engine/shared/config_variables.h | 3 + src/engine/shared/storage.cpp | 16 +++++ src/engine/storage.h | 1 + src/game/client/components/menus.h | 48 +++++++++++++- src/game/client/components/menus_demo.cpp | 77 +++++++++++++++++++++-- 9 files changed, 223 insertions(+), 6 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 860e1f3c..7314af5d 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1471,6 +1471,60 @@ int net_init() return 0; } + +int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user) +{ +#if defined(CONF_FAMILY_WINDOWS) + WIN32_FIND_DATA finddata; + HANDLE handle; + char buffer[1024*2]; + int length; + str_format(buffer, sizeof(buffer), "%s/*", dir); + + handle = FindFirstFileA(buffer, &finddata); + + if(handle == INVALID_HANDLE_VALUE) + return 0; + + str_format(buffer, sizeof(buffer), "%s/", dir); + length = str_length(buffer); + + /* add all the entries */ + do + { + str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); + if(cb(finddata.cFileName, fs_getmtime(buffer), fs_is_dir(buffer), type, user)) + break; + } + while (FindNextFileA(handle, &finddata)); + + FindClose(handle); + return 0; +#else + struct dirent *entry; + char buffer[1024*2]; + int length; + DIR *d = opendir(dir); + + if(!d) + return 0; + + str_format(buffer, sizeof(buffer), "%s/", dir); + length = str_length(buffer); + + while((entry = readdir(d)) != NULL) + { + str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); + if(cb(entry->d_name, fs_getmtime(buffer), fs_is_dir(buffer), type, user)) + break; + } + + /* close the directory and return */ + closedir(d); + return 0; +#endif +} + void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) { #if defined(CONF_FAMILY_WINDOWS) @@ -1647,6 +1701,15 @@ int fs_is_dir(const char *path) #endif } +time_t fs_getmtime(const char *path) +{ + struct stat sb; + if(stat(path, &sb) == -1) + return 0; + + return sb.st_mtime; +} + int fs_chdir(const char *path) { if(fs_is_dir(path)) diff --git a/src/base/system.h b/src/base/system.h index f08a9e37..82511411 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1314,6 +1314,10 @@ int str_span(const char *str, const char *set); typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, void *user); void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user); + +typedef int (*FS_LISTDIR_INFO_CALLBACK)(const char *name, time_t date, int is_dir, int dir_type, void *user); +int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user); + /* Function: fs_makedir Creates a directory @@ -1366,6 +1370,12 @@ int fs_storage_path(const char *appname, char *path, int max); */ int fs_is_dir(const char *path); +/* + Function: fs_getmtime + Gets the modification time of a file +*/ +time_t fs_getmtime(const char *path); + /* Function: fs_chdir Changes current working directory diff --git a/src/base/tl/algorithm.h b/src/base/tl/algorithm.h index 3ea6ba23..22c27810 100644 --- a/src/base/tl/algorithm.h +++ b/src/base/tl/algorithm.h @@ -107,6 +107,11 @@ void sort_quick(R range) concept_index::check(range); }*/ +template +void sort(R range, Cmp cmp) +{ + std::stable_sort(&range.front(), &range.back()+1, cmp); +} template void sort(R range) @@ -114,7 +119,6 @@ void sort(R range) std::stable_sort(&range.front(), &range.back()+1); } - template bool sort_verify(R range) { diff --git a/src/base/tl/sorted_array.h b/src/base/tl/sorted_array.h index ca3a8147..d4beb6ad 100644 --- a/src/base/tl/sorted_array.h +++ b/src/base/tl/sorted_array.h @@ -33,6 +33,11 @@ class sorted_array : public array sort(all()); } + template + void sort_range_by(R cmp) + { + sort(all(), cmp); + } /* Function: all diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 7a5211e5..5fe757f5 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -38,6 +38,9 @@ MACRO_CONFIG_INT(BrSort, br_sort, 4, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sort MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sort order in the server browser") MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 25, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser") +MACRO_CONFIG_INT(BrDemoSort, br_demo_sort, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") +MACRO_CONFIG_INT(BrDemoSortOrder, br_demo_sort_order, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") + MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 128, 32768, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size") MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate") MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable sounds") diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index f646f3e7..0e437d85 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -307,6 +307,22 @@ class CStorage : public IStorage } } + virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser) + { + char aBuffer[IO_MAX_PATH_LENGTH]; + if(Type == TYPE_ALL) + { + // list all available directories + for(int i = 0; i < m_NumPaths; ++i) + fs_listdir_info(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser); + } + else if(Type >= 0 && Type < m_NumPaths) + { + // list wanted directory + fs_listdir_info(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser); + } + } + const char *GetPath(int Type, const char *pDir, char *pBuffer, unsigned BufferSize) { str_format(pBuffer, BufferSize, "%s%s%s", m_aaStoragePaths[Type], !m_aaStoragePaths[Type][0] ? "" : "/", pDir); diff --git a/src/engine/storage.h b/src/engine/storage.h index 3028616f..6f2baf14 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -23,6 +23,7 @@ class IStorage : public IInterface typedef bool(*FCheckCallback)(IOHANDLE Handle, const void *pUserData); virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0; + virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser) = 0; virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0, FCheckCallback pfnCheckCB = 0, const void *pCheckCBData = 0) = 0; virtual bool ReadFile(const char *pFilename, int Type, void **ppResult, unsigned *pResultLen) = 0; virtual char *ReadFileStr(const char *pFilename, int Type) = 0; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index ad0a3c8f..72261d5f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -459,12 +459,19 @@ class CMenus : public CComponent int *m_pActiveDropdown; // demo + enum + { + SORT_DEMONAME=0, + SORT_DATE, + }; + struct CDemoItem { char m_aFilename[128]; char m_aName[128]; bool m_IsDir; int m_StorageType; + time_t m_Date; bool m_InfosLoaded; bool m_Valid; @@ -490,6 +497,39 @@ class CMenus : public CComponent } }; + class CDemoComparator + { + int m_Type; + int m_Order; + public: + CDemoComparator(int Type, int Order) + { + m_Type = Type; + m_Order = Order; + } + + bool operator()(const CDemoItem &Self, const CDemoItem &Other) + { + if(!str_comp(Self.m_aFilename, "..")) + return true; + if(!str_comp(Other.m_aFilename, "..")) + return false; + if(Self.m_IsDir && !Other.m_IsDir) + return true; + if(!Self.m_IsDir && Other.m_IsDir) + return false; + + const CDemoItem &Left = m_Order ? Other : Self; + const CDemoItem &Right = m_Order ? Self : Other; + + if(m_Type == SORT_DEMONAME) + return str_comp_nocase(Left.m_aFilename, Right.m_aFilename) < 0; + else if(m_Type == SORT_DATE) + return Left.m_Date < Right.m_Date; + return false; + } + }; + sorted_array m_lDemos; char m_aCurrentDemoFolder[IO_MAX_PATH_LENGTH]; char m_aCurrentDemoFile[IO_MAX_PATH_LENGTH]; @@ -501,7 +541,7 @@ class CMenus : public CComponent void DemolistOnUpdate(bool Reset); void DemolistPopulate(); - static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser); + static int DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser); // friends class CFriendItem @@ -641,6 +681,11 @@ class CMenus : public CComponent COL_BROWSER_PING, NUM_BROWSER_COLS, + COL_DEMO_ICON=0, + COL_DEMO_NAME, + COL_DEMO_DATE, + NUM_DEMO_COLS, + SIDEBAR_TAB_INFO = 0, SIDEBAR_TAB_FILTER, SIDEBAR_TAB_FRIEND, @@ -659,6 +704,7 @@ class CMenus : public CComponent int m_aSelectedServers[IServerBrowser::NUM_TYPES]; // -1 if none selected int m_AddressSelection; static CColumn ms_aBrowserCols[NUM_BROWSER_COLS]; + static CColumn ms_aDemoCols[NUM_DEMO_COLS]; CBrowserFilter* GetSelectedBrowserFilter() { diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index fc63ce4d..f8e838a2 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -20,7 +20,11 @@ #include "maplayers.h" #include "menus.h" - +CMenus::CColumn CMenus::ms_aDemoCols[] = { + {COL_DEMO_ICON, -1, " ", -1, 4*16.0f+3*2.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_NAME, CMenus::SORT_DEMONAME, "Demo", 0, 200.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_DATE, CMenus::SORT_DATE, "Date", 1, 160.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, +}; void CMenus::RenderDemoPlayer(CUIRect MainView) { @@ -349,7 +353,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } -int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser) +int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(str_comp(pName, ".") == 0 @@ -370,6 +374,7 @@ int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, { str_truncate(Item.m_aName, sizeof(Item.m_aName), pName, str_length(pName) - 5); Item.m_InfosLoaded = false; + Item.m_Date = Date; } Item.m_IsDir = IsDir != 0; Item.m_StorageType = StorageType; @@ -383,8 +388,10 @@ void CMenus::DemolistPopulate() m_lDemos.clear(); if(!str_comp(m_aCurrentDemoFolder, "demos")) m_DemolistStorageType = IStorage::TYPE_ALL; - Storage()->ListDirectory(m_DemolistStorageType, m_aCurrentDemoFolder, DemolistFetchCallback, this); - m_lDemos.sort_range(); + Storage()->ListDirectoryInfo(m_DemolistStorageType, m_aCurrentDemoFolder, DemolistFetchCallback, this); + m_lDemos.sort_range_by(CDemoComparator( + Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder + )); } void CMenus::DemolistOnUpdate(bool Reset) @@ -449,8 +456,70 @@ void CMenus::RenderDemoList(CUIRect MainView) CUIRect ListBox, Button, FileIcon; MainView.HSplitTop(MainView.h - BackgroundHeight - 2 * HMargin, &ListBox, &MainView); + // demo list + + CUIRect Headers; + ListBox.HSplitTop(GetListHeaderHeight(), &Headers, &ListBox); + + RenderTools()->DrawUIRect(&Headers, vec4(0.0f,0,0,0.15f), 0, 0); + + int NumCols = sizeof(ms_aDemoCols)/sizeof(CColumn); + + // do layout + for(int i = 0; i < NumCols; i++) + { + if(ms_aDemoCols[i].m_Direction == -1) + { + Headers.VSplitLeft(ms_aDemoCols[i].m_Width, &ms_aDemoCols[i].m_Rect, &Headers); + + if(i+1 < NumCols) + { + //Cols[i].flags |= SPACER; + Headers.VSplitLeft(2, &ms_aDemoCols[i].m_Spacer, &Headers); + } + } + } + + for(int i = NumCols-1; i >= 0; i--) + { + if(ms_aDemoCols[i].m_Direction == 1) + { + Headers.VSplitRight(ms_aDemoCols[i].m_Width, &Headers, &ms_aDemoCols[i].m_Rect); + Headers.VSplitRight(2, &Headers, &ms_aDemoCols[i].m_Spacer); + } + } + + for(int i = 0; i < NumCols; i++) + { + if(ms_aDemoCols[i].m_Direction == 0) + ms_aDemoCols[i].m_Rect = Headers; + } + + // do headers + for(int i = 0; i < NumCols; i++) + { + if(i == COL_DEMO_ICON) + continue; + + if(DoButton_GridHeader(ms_aDemoCols[i].m_Caption, ms_aDemoCols[i].m_Caption, Config()->m_BrDemoSort == ms_aDemoCols[i].m_Sort, ms_aDemoCols[i].m_Align, &ms_aDemoCols[i].m_Rect)) + { + if(ms_aDemoCols[i].m_Sort != -1) + { + if(Config()->m_BrDemoSort == ms_aDemoCols[i].m_Sort) + Config()->m_BrDemoSortOrder ^= 1; + else + Config()->m_BrDemoSortOrder = 0; + Config()->m_BrDemoSort = ms_aDemoCols[i].m_Sort; + } + + DemolistPopulate(); + DemolistOnUpdate(false); + } + } + static CListBox s_ListBox; s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); + s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { From a626a8f1253690e9ae761f70de999708332a6709 Mon Sep 17 00:00:00 2001 From: Chairn Date: Sat, 22 Aug 2015 21:07:13 +0200 Subject: [PATCH 349/479] Made fs_getmtime works for window. (cherry picked from commit https://github.com/ddnet/ddnet/commit/33c421b42863ba9a2e8d7671829678da40fac571) --- src/base/system.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 7314af5d..ca3dc3c6 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -9,13 +9,14 @@ #include "system.h" +#include +#include + #if defined(CONF_FAMILY_UNIX) #include #include /* unix net includes */ - #include - #include #include #include #include From b64a81727c2b9722eac2efc3847b8834b9806724 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 19 Jun 2020 19:20:25 +0200 Subject: [PATCH 350/479] Show dates in demo browser and localize --- src/game/client/components/menus_demo.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index f8e838a2..d246c027 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -21,9 +21,9 @@ #include "menus.h" CMenus::CColumn CMenus::ms_aDemoCols[] = { - {COL_DEMO_ICON, -1, " ", -1, 4*16.0f+3*2.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, - {COL_DEMO_NAME, CMenus::SORT_DEMONAME, "Demo", 0, 200.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, - {COL_DEMO_DATE, CMenus::SORT_DATE, "Date", 1, 160.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_ICON, -1, " ", -1, 0, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_NAME, CMenus::SORT_DEMONAME, Localize("Name"), 0, 200.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_DATE, CMenus::SORT_DATE, Localize("Date"), 1, 160.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, }; void CMenus::RenderDemoPlayer(CUIRect MainView) @@ -552,10 +552,14 @@ void CMenus::RenderDemoList(CUIRect MainView) TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); } Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + char aDate[64]; + str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); + TextRender()->TextColor(0.7f, 0.7f, 0.7f, 0.7f); + UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); + TextRender()->TextColor(CUI::ms_DefaultTextColor); if(Item.m_Selected) { - TextRender()->TextColor(CUI::ms_DefaultTextColor); TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } From d28782d169f0d7831754ec8d7b5f616d658e8c3b Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 19 Jun 2020 19:51:53 +0200 Subject: [PATCH 351/479] Use consistent text transparency --- src/game/client/components/chat.cpp | 4 ++-- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/scoreboard.cpp | 8 ++++---- src/game/client/ui.cpp | 1 + src/game/client/ui.h | 1 + 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 62e2d1cf..d6b2db49 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -983,7 +983,7 @@ void CChat::OnRender() const CCommandManager::CCommand *pCommand = m_CommandManager.GetCommand(m_SelectedCommand); if(str_length(pCommand->m_aName)+1 > str_length(m_Input.GetString())) { - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); TextRender()->TextEx(&Cursor, pCommand->m_aName + str_length(m_Input.GetString())-1, -1); } } @@ -994,7 +994,7 @@ void CChat::OnRender() CTextCursor InfoCursor; TextRender()->SetCursor(&InfoCursor, 2.0f, y+12.0f, CategoryFontSize*0.75, TEXTFLAG_RENDER); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); TextRender()->TextEx(&InfoCursor, Localize("Press Tab to cycle chat recipients. Whispers aren't encrypted and might be logged by the server."), -1); } } diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index f67e94c2..80c60be9 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -606,7 +606,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn if(Num < 10) Button.x += RenderOffset; if(!Num) - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); UI()->DoLabel(&Button, aTemp, 12.0f, CUI::ALIGN_LEFT); Button.x += TextRender()->TextWidth(0, 12.0f, aTemp, -1, -1.0f); } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index d246c027..1719191e 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -555,7 +555,7 @@ void CMenus::RenderDemoList(CUIRect MainView) UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); char aDate[64]; str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); - TextRender()->TextColor(0.7f, 0.7f, 0.7f, 0.7f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); TextRender()->TextColor(CUI::ms_DefaultTextColor); if(Item.m_Selected) diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 3a5e1378..4f523fbc 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -258,7 +258,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c if(!NoTitle) { str_format(aBuf, sizeof(aBuf), " (%d)", NumPlayers); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); TextRender()->Text(0, x+20.0f+tw, y+5.0f, TitleFontsize, aBuf, -1.0f); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } @@ -270,7 +270,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c { str_format(aBuf, sizeof(aBuf), "(%d) ", NumPlayers); float PlayersTextWidth = TextRender()->TextWidth(0, TitleFontsize, aBuf, -1, -1.0f); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); TextRender()->Text(0, x+w-tw-PlayersTextWidth-20.0f, y+5.0f, TitleFontsize, aBuf, -1.0f); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } @@ -344,7 +344,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c } const char *pPingStr = Localize("Ping"); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); tw = TextRender()->TextWidth(0, HeadlineFontsize, pPingStr, -1, -1.0f); TextRender()->Text(0, PingOffset+PingLength-tw, y+Spacing, HeadlineFontsize, pPingStr, -1.0f); @@ -357,7 +357,7 @@ float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const c if(!Race) { - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f); + TextRender()->TextColor(CUI::ms_TransparentTextColor); tw = TextRender()->TextWidth(0, HeadlineFontsize, "K", -1, -1.0f); TextRender()->Text(0, KillOffset+KillLength/2-tw/2, y+Spacing, HeadlineFontsize, "K", -1.0f); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 654b282f..0b6ca269 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -15,6 +15,7 @@ const vec4 CUI::ms_DefaultTextColor(1.0f, 1.0f, 1.0f, 1.0f); const vec4 CUI::ms_DefaultTextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); const vec4 CUI::ms_HighlightTextColor(0.0f, 0.0f, 0.0f, 1.0f); const vec4 CUI::ms_HighlightTextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); +const vec4 CUI::ms_TransparentTextColor(1.0f, 1.0f, 1.0f, 0.5f); CUI::CUI() { diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 997d71f5..58f908a0 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -52,6 +52,7 @@ class CUI static const vec4 ms_DefaultTextOutlineColor; static const vec4 ms_HighlightTextColor; static const vec4 ms_HighlightTextOutlineColor; + static const vec4 ms_TransparentTextColor; // TODO: Refactor: Fill this in void Init(class CConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } From b18b4dee1042bee038011dcb66ef51581a875cf8 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Mon, 22 Jun 2020 13:09:55 +0200 Subject: [PATCH 352/479] Clamp cl_mouse_max_distance_* values to prevent camera glitches --- src/game/variables.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/variables.h b/src/game/variables.h index 2becd0d4..e9bada7d 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -27,8 +27,8 @@ MACRO_CONFIG_INT(ClWarningTeambalance, cl_warning_teambalance, 1, 0, 1, CFGFLAG_ MACRO_CONFIG_INT(ClDynamicCamera, cl_dynamic_camera, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Switches camera mode. 0=static camera, 1=dynamic camera") MACRO_CONFIG_INT(ClMouseDeadzone, cl_mouse_deadzone, 300, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Zone that doesn't trigger the dynamic camera") MACRO_CONFIG_INT(ClMouseFollowfactor, cl_mouse_followfactor, 60, 0, 200, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Trigger amount for the dynamic camera") -MACRO_CONFIG_INT(ClMouseMaxDistanceDynamic, cl_mouse_max_distance_dynamic, 1000, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Mouse max distance, in dynamic camera mode") -MACRO_CONFIG_INT(ClMouseMaxDistanceStatic, cl_mouse_max_distance_static, 400, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Mouse max distance, in static camera mode") +MACRO_CONFIG_INT(ClMouseMaxDistanceDynamic, cl_mouse_max_distance_dynamic, 1000, 1, 2000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Mouse max distance, in dynamic camera mode") +MACRO_CONFIG_INT(ClMouseMaxDistanceStatic, cl_mouse_max_distance_static, 400, 1, 2000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Mouse max distance, in static camera mode") MACRO_CONFIG_INT(ClCustomizeSkin, cl_customize_skin, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use a customized skin") From a32c2c5012818c3b2346e0e1ad500ab0efa94b47 Mon Sep 17 00:00:00 2001 From: Stiopa866 Date: Wed, 24 Jun 2020 18:02:18 +0200 Subject: [PATCH 353/479] Update hud.cpp --- src/game/client/components/hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index a32ab612..ab7e012b 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -705,7 +705,7 @@ void CHud::RenderSpectatorHud() case SPEC_FLAGRED: case SPEC_FLAGBLUE: char aFlag[64]; - str_format(aFlag, sizeof(aFlag), SpecMode == SPEC_FLAGRED ? Localize("red flag") : Localize("blue flag")); + str_format(aFlag, sizeof(aFlag), SpecMode == SPEC_FLAGRED ? Localize("Red Flag") : Localize("Blue Flag")); if(SpecID != -1) str_format(aBuf, sizeof(aBuf), "%s (%s)", aFlag, aName); From 750288bd6b12856f5d704a9ba0c58af5e90b8c48 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Thu, 25 Jun 2020 14:50:52 +0200 Subject: [PATCH 354/479] Use dark highlight text color for selected demos --- src/game/client/components/menus_demo.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 1719191e..4240f464 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -555,13 +555,12 @@ void CMenus::RenderDemoList(CUIRect MainView) UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); char aDate[64]; str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); - TextRender()->TextColor(CUI::ms_TransparentTextColor); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); TextRender()->TextColor(CUI::ms_DefaultTextColor); if(Item.m_Selected) - { TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); - } } } m_DemolistSelectedIndex = s_ListBox.DoEnd(); From 1f43e00726e57f17ebc396fe9f1df7d9a86a38bb Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Thu, 25 Jun 2020 14:54:33 +0200 Subject: [PATCH 355/479] Github macOS image ships freetype (closed #2664) --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 22a3d7ac..c8c936f5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -57,7 +57,7 @@ jobs: if: contains(matrix.os, 'macOS') run: | brew update - brew install pkg-config freetype sdl2 + brew install pkg-config sdl2 - name: Build in debug mode env: ${{ matrix.env }} @@ -133,7 +133,7 @@ jobs: if: contains(matrix.os, 'macOS') run: | brew update - brew install freetype sdl2 + brew install sdl2 cd bam ./make_unix.sh From a5afae5e38a84c6287eb3813eeb525e71dce58c9 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Thu, 2 Jul 2020 11:51:50 +0200 Subject: [PATCH 356/479] Do not enforce winter theme on new users --- src/engine/client/client.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index ba4fbaf5..b36f6db5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2558,8 +2558,6 @@ void CClient::ConnectOnStart(const char *pAddress) void CClient::DoVersionSpecificActions() { - if(Config()->m_ClLastVersionPlayed <= 0x0703) - str_copy(Config()->m_ClMenuMap, "winter", sizeof(Config()->m_ClMenuMap)); Config()->m_ClLastVersionPlayed = CLIENT_VERSION; } From 726bb67e129be9f4b902ce61d9cbf20f6dc0a2b5 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 3 Jul 2020 08:54:38 +0200 Subject: [PATCH 357/479] added a previous version entry, so it isn't forgotten again when doing a release --- src/game/variables.h | 2 +- src/game/version.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/variables.h b/src/game/variables.h index e9bada7d..ee8e262c 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -101,7 +101,7 @@ MACRO_CONFIG_INT(ClSkipStartMenu, cl_skip_start_menu, 0, 0, 1, CFGFLAG_CLIENT|CF MACRO_CONFIG_INT(ClStatboardInfos, cl_statboard_infos, 1259, 1, 2047, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Mask of info to display on the global statboard") -MACRO_CONFIG_INT(ClLastVersionPlayed, cl_last_version_played, 0x0703, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Last version of the game that was played") +MACRO_CONFIG_INT(ClLastVersionPlayed, cl_last_version_played, PREV_CLIENT_VERSION, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Last version of the game that was played") // server MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, -1, 1000, CFGFLAG_SAVE|CFGFLAG_SERVER, "Number of seconds to do warmup before match starts (0 disables, -1 all players ready)") diff --git a/src/game/version.h b/src/game/version.h index 5070174e..f7ea5015 100644 --- a/src/game/version.h +++ b/src/game/version.h @@ -7,6 +7,7 @@ #define GAME_NETVERSION_HASH_FORCED "802f1be60a05665f" #define GAME_NETVERSION "0.7 " GAME_NETVERSION_HASH_FORCED #define CLIENT_VERSION 0x0705 +#define PREV_CLIENT_VERSION 0x0704 #define SETTINGS_FILENAME "settings07" static const char GAME_RELEASE_VERSION[8] = "0.7.5"; #endif From 1846c74467e8a95a44c1ba972455e4da15083e66 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 4 Jul 2020 12:17:01 +0200 Subject: [PATCH 358/479] don't show date info for folders --- src/game/client/components/menus_demo.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 4240f464..1ef27222 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -474,7 +474,6 @@ void CMenus::RenderDemoList(CUIRect MainView) if(i+1 < NumCols) { - //Cols[i].flags |= SPACER; Headers.VSplitLeft(2, &ms_aDemoCols[i].m_Spacer, &Headers); } } @@ -553,11 +552,14 @@ void CMenus::RenderDemoList(CUIRect MainView) } Item.m_Rect.y += 2.0f; UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - char aDate[64]; - str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); - if(!Item.m_Selected) - TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); + if(!DemoItem.m_IsDir) + { + char aDate[64]; + str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); + } TextRender()->TextColor(CUI::ms_DefaultTextColor); if(Item.m_Selected) TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); From defb2e9709a60a95b9847cb6ba0d3a204d266109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 7 Jul 2020 00:10:37 +0200 Subject: [PATCH 359/479] click on friend to select server, double click to connect, refactoring --- src/game/client/components/menus.h | 8 +- src/game/client/components/menus_browser.cpp | 125 ++++++++++--------- 2 files changed, 69 insertions(+), 64 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 72261d5f..406de659 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -691,10 +691,10 @@ class CMenus : public CComponent SIDEBAR_TAB_FRIEND, NUM_SIDEBAR_TABS, - ADDR_SELECTION_CHANGE = 1, - ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND = 2, - ADDR_SELECTION_REVEAL = 4, - ADDR_SELECTION_UPDATE_ADDRESS = 8, + ADDR_SELECTION_CHANGE = 1, // select the server based on server address input + ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND = 2, // clear selection if ADDR_SELECTION_CHANGE did not match any server + ADDR_SELECTION_REVEAL = 4, // scroll to the selected server + ADDR_SELECTION_UPDATE_ADDRESS = 8, // update address input to the selected server's address }; int m_SidebarTab; bool m_SidebarActive; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 80c60be9..8de99194 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1250,12 +1250,12 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) CBrowserFilter *pFilter = &m_lFilters[FilterIndex]; // filter header - CUIRect Row; - View.HSplitTop(20.0f, &Row, &View); - s_ScrollRegion.AddRect(Row); + CUIRect Header; + View.HSplitTop(20.0f, &Header, &View); + s_ScrollRegion.AddRect(Header); // render header - RenderFilterHeader(Row, FilterIndex); + RenderFilterHeader(Header, FilterIndex); if(pFilter->Extended()) { @@ -1265,7 +1265,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && m_aSelectedServers[BrowserType] == ServerIndex; - if(!(m_AddressSelection&ADDR_SELECTION_UPDATE_ADDRESS) && !str_comp(pItem->m_aAddress, pAddress)) + if(m_AddressSelection&ADDR_SELECTION_CHANGE && !str_comp(pItem->m_aAddress, pAddress)) { if(!IsSelected) { @@ -1282,32 +1282,25 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) { ItemHeight *= 6.0f; } + CUIRect Row; View.HSplitTop(ItemHeight, &Row, &View); - s_ScrollRegion.AddRect(Row); + if(IsSelected && (m_AddressSelection&ADDR_SELECTION_REVEAL)) // new selection (hotkeys or address input) { - s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); + s_ScrollRegion.ScrollHere(); m_AddressSelection &= ~ADDR_SELECTION_REVEAL; } - // make sure that only those in view can be selected - if(!s_ScrollRegion.IsRectClipped(Row)) + if(s_ScrollRegion.IsRectClipped(Row)) { - if(IsSelected) - { - CUIRect r = Row; - RenderTools()->DrawUIRect(&r, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 4.0f); - } + // only those in the view are rendered and can be selected + continue; } - else - { - // reset active item, if not visible - if(UI()->CheckActiveItem(pItem)) - UI()->SetActiveItem(0); - // don't render invisible items - continue; + if(IsSelected) + { + RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f); } if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected)) @@ -1324,16 +1317,19 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } } - if(m_AddressSelection&ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND) + if((m_AddressSelection&ADDR_SELECTION_CHANGE) && (m_AddressSelection&ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND)) { m_aSelectedServers[BrowserType] = -1; - m_AddressSelection &= ~ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND; + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); } } if(FilterIndex < m_lFilters.size()-1) - View.HSplitTop(SpacingH, &Row, &View); - + { + CUIRect Space; + View.HSplitTop(SpacingH, &Space, &View); + s_ScrollRegion.AddRect(Space); + } } if(m_AddressSelection&ADDR_SELECTION_UPDATE_ADDRESS) @@ -1540,15 +1536,18 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) CUIRect BottomArea; const float FontSize = 10.0f; static bool s_ListExtended[NUM_FRIEND_TYPES] = { 1, 1, 0 }; + static vec3 s_ListColor[NUM_FRIEND_TYPES] = { vec3(0.5f, 1.0f, 0.5f), vec3(0.4f, 0.4f, 1.0f), vec3(1.0f, 0.5f, 0.5f) }; + const float HeaderHeight = GetListHeaderHeight(); + const float SpacingH = 2.0f; - View.HSplitBottom(3*GetListHeaderHeight(), &View, &BottomArea); + View.HSplitBottom(3*HeaderHeight+2*SpacingH, &View, &BottomArea); // calculate friends // todo: optimize this m_pDeleteFriend = 0; - m_lFriendList[0].clear(); - m_lFriendList[1].clear(); - m_lFriendList[2].clear(); + m_lFriendList[FRIEND_PLAYER_ON].clear(); + m_lFriendList[FRIEND_CLAN_ON].clear(); + m_lFriendList[FRIEND_OFF].clear(); for(int f = 0; f < m_pClient->Friends()->NumFriends(); ++f) { const CContactInfo *pFriendInfo = m_pClient->Friends()->GetFriend(f); @@ -1558,7 +1557,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) str_copy(FriendItem.m_aClan, pFriendInfo->m_aClan, sizeof(FriendItem.m_aClan)); FriendItem.m_FriendState = pFriendInfo->m_aName[0] ? CContactInfo::CONTACT_PLAYER : CContactInfo::CONTACT_CLAN; FriendItem.m_IsPlayer = false; - m_lFriendList[2].add(FriendItem); + m_lFriendList[FRIEND_OFF].add(FriendItem); } for(int ServerIndex = 0; ServerIndex < ServerBrowser()->NumServers(); ++ServerIndex) @@ -1579,15 +1578,15 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) FriendItem.m_FriendState = pEntry->m_aClients[j].m_FriendState; FriendItem.m_IsPlayer = !(pEntry->m_aClients[j].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC); - if(pEntry->m_aClients[j].m_FriendState == CContactInfo::CONTACT_PLAYER) - m_lFriendList[0].add(FriendItem); - else - m_lFriendList[1].add(FriendItem); + m_lFriendList[pEntry->m_aClients[j].m_FriendState == CContactInfo::CONTACT_PLAYER ? FRIEND_PLAYER_ON : FRIEND_CLAN_ON].add(FriendItem); - for(int f = 0; f < m_lFriendList[2].size(); ++f) + for(int f = 0; f < m_lFriendList[FRIEND_OFF].size(); ++f) { - if((!m_lFriendList[2][f].m_aName[0] || !str_comp(m_lFriendList[2][f].m_aName, pEntry->m_aClients[j].m_aName)) && !str_comp(m_lFriendList[2][f].m_aClan, pEntry->m_aClients[j].m_aClan)) - m_lFriendList[2].remove_index(f--); + if((!m_lFriendList[FRIEND_OFF][f].m_aName[0] || !str_comp(m_lFriendList[FRIEND_OFF][f].m_aName, pEntry->m_aClients[j].m_aName)) + && !str_comp(m_lFriendList[FRIEND_OFF][f].m_aClan, pEntry->m_aClients[j].m_aClan)) + { + m_lFriendList[FRIEND_OFF].remove_index(f--); + } } } } @@ -1606,33 +1605,27 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // show lists // only ~10 buttons will be displayed at once, a sliding window of 20 buttons ought to be enough - static CButtonContainer s_FriendJoinButtons[20]; - const float HeaderHeight = GetListHeaderHeight(); + static CButtonContainer s_FriendButtons[20]; int ButtonId = 0; for(int i = 0; i < NUM_FRIEND_TYPES; ++i) { CUIRect Header; char aBuf[64] = { 0 }; View.HSplitTop(HeaderHeight, &Header, &View); + s_ScrollRegion.AddRect(Header); if(s_ListExtended[i]) { // entries for(int f = 0; f < m_lFriendList[i].size(); ++f, ++ButtonId) { - if(i == FRIEND_OFF) - View.HSplitTop(8.0f + HeaderHeight, &Rect, &View); - else - View.HSplitTop(20.0f + HeaderHeight, &Rect, &View); + View.HSplitTop((i == FRIEND_OFF ? 8.0f : 20.0f) + HeaderHeight, &Rect, &View); s_ScrollRegion.AddRect(Rect); - if(i == FRIEND_PLAYER_ON) - RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 1.0f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); - else if(i == FRIEND_CLAN_ON) - RenderTools()->DrawUIRect(&Rect, vec4(0.5f, 0.5f, 1.5f, 0.30f), CUI::CORNER_ALL, 5.0f); - else - RenderTools()->DrawUIRect(&Rect, vec4(1.0f, 0.5f, 0.5f, 0.30f), CUI::CORNER_ALL, 5.0f); - Rect.VMargin(2.0f, &Rect); - Rect.HMargin(2.0f, &Rect); - Rect.VSplitRight(45.0f, &Rect, &Icon); + const bool Inside = UI()->MouseInside(&Rect); + bool ButtonResult = UI()->DoButtonLogic(&(s_FriendButtons[ButtonId%20]), &Rect); + RenderTools()->DrawUIRect(&Rect, vec4(s_ListColor[i].r, s_ListColor[i].g, s_ListColor[i].b, Inside ? 0.5f : 0.3f), CUI::CORNER_ALL, 5.0f); + Rect.Margin(2.0f, &Rect); + Rect.VSplitRight(50.0f, &Rect, &Icon); + Rect.HSplitTop(20.0f, &Button, 0); // name Rect.HSplitTop(10.0f, &Button, &Rect); @@ -1661,23 +1654,33 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &Icon)) { m_pDeleteFriend = &m_lFriendList[i][f]; + ButtonResult = false; } - // join button - Rect.VSplitRight(15.0f, &Button, 0); - if(m_lFriendList[i][f].m_pServerInfo) + // handle click and double click on item + if(ButtonResult && m_lFriendList[i][f].m_pServerInfo) { - Button.Margin((Button.h - HeaderHeight + 2.0f) / 2, &Button); - if(DoButton_Menu(&(s_FriendJoinButtons[ButtonId%20]), Localize("Join", "Join a server"), 0, &Button) ) + SetServerBrowserAddress(m_lFriendList[i][f].m_pServerInfo->m_aAddress); + m_AddressSelection |= ADDR_SELECTION_CHANGE | ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND | ADDR_SELECTION_REVEAL; + if(Input()->MouseDoubleClick()) { - SetServerBrowserAddress(m_lFriendList[i][f].m_pServerInfo->m_aAddress); Client()->Connect(GetServerBrowserAddress()); } } + if(f < m_lFriendList[i].size()-1) - View.HSplitTop(2.0f, 0, &View); + { + CUIRect Space; + View.HSplitTop(SpacingH, &Space, &View); + s_ScrollRegion.AddRect(Space); + } } } - View.HSplitTop(2.0f, 0, &View); + + { + CUIRect Space; + View.HSplitTop(SpacingH, &Space, &View); + s_ScrollRegion.AddRect(Space); + } // header RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); @@ -1703,6 +1706,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // add friend BottomArea.HSplitTop(HeaderHeight, &Button, &BottomArea); + BottomArea.HSplitTop(SpacingH, 0, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Name"), FontSize, CUI::ALIGN_LEFT); static char s_aName[MAX_NAME_LENGTH] = { 0 }; @@ -1710,6 +1714,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), Button.h*ms_FontmodHeight*0.8f, &s_OffsetName); BottomArea.HSplitTop(HeaderHeight, &Button, &BottomArea); + BottomArea.HSplitTop(SpacingH, 0, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Clan"), FontSize, CUI::ALIGN_LEFT); static char s_aClan[MAX_CLAN_LENGTH] = { 0 }; From 3603712bfef5865ef12303fbddc6c70550115430 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 21 Jul 2020 12:35:55 +0200 Subject: [PATCH 360/479] Demo browser: sort by length (closed #1739) Full credits go to @def- code was taken from this ddnet commit https://github.com/ddnet/ddnet/commit/f9d9fee31448d0d98b35456f63931a387208e6a4 --- src/engine/shared/config_variables.h | 2 +- src/game/client/components/menus.h | 13 +++++ src/game/client/components/menus_demo.cpp | 59 +++++++++++++++-------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 5fe757f5..00467cdc 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -38,7 +38,7 @@ MACRO_CONFIG_INT(BrSort, br_sort, 4, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sort MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sort order in the server browser") MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 25, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser") -MACRO_CONFIG_INT(BrDemoSort, br_demo_sort, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") +MACRO_CONFIG_INT(BrDemoSort, br_demo_sort, 0, 0, 2, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") MACRO_CONFIG_INT(BrDemoSortOrder, br_demo_sort_order, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 128, 32768, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size") diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 72261d5f..9a949ffb 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -462,6 +462,7 @@ class CMenus : public CComponent enum { SORT_DEMONAME=0, + SORT_LENGTH, SORT_DATE, }; @@ -487,6 +488,14 @@ class CMenus : public CComponent (m_Info.m_aNumTimelineMarkers[3]&0xFF); } + int Length() const + { + return ((m_Info.m_aLength[0]<<24)&0xFF000000) | + ((m_Info.m_aLength[1]<<16)&0xFF0000) | + ((m_Info.m_aLength[2]<<8)&0xFF00) | + (m_Info.m_aLength[3]&0xFF); + } + bool operator<(const CDemoItem &Other) const { return !str_comp(m_aFilename, "..") ? true @@ -524,6 +533,8 @@ class CMenus : public CComponent if(m_Type == SORT_DEMONAME) return str_comp_nocase(Left.m_aFilename, Right.m_aFilename) < 0; + else if(m_Type == SORT_LENGTH) + return Left.Length() < Right.Length(); else if(m_Type == SORT_DATE) return Left.m_Date < Right.m_Date; return false; @@ -683,6 +694,7 @@ class CMenus : public CComponent COL_DEMO_ICON=0, COL_DEMO_NAME, + COL_DEMO_LENGTH, COL_DEMO_DATE, NUM_DEMO_COLS, @@ -761,6 +773,7 @@ class CMenus : public CComponent void UpdateMusicState(); // found in menus_demo.cpp + bool FetchHeader(CDemoItem &Item); void RenderDemoPlayer(CUIRect MainView); void RenderDemoList(CUIRect MainView); float RenderDemoDetails(CUIRect View); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 1ef27222..ed76e007 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -22,7 +22,8 @@ CMenus::CColumn CMenus::ms_aDemoCols[] = { {COL_DEMO_ICON, -1, " ", -1, 0, 0, {0}, {0}, CUI::ALIGN_CENTER}, - {COL_DEMO_NAME, CMenus::SORT_DEMONAME, Localize("Name"), 0, 200.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_NAME, CMenus::SORT_DEMONAME, Localize("Name"), 0, 100.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_LENGTH, CMenus::SORT_LENGTH, Localize("Length"), 1, 100.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, {COL_DEMO_DATE, CMenus::SORT_DATE, Localize("Date"), 1, 160.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, }; @@ -401,6 +402,18 @@ void CMenus::DemolistOnUpdate(bool Reset) m_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_lDemos[m_DemolistSelectedIndex].m_IsDir; } +bool CMenus::FetchHeader(CDemoItem &Item) +{ + if(!Item.m_InfosLoaded) + { + char aBuffer[IO_MAX_PATH_LENGTH]; + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item.m_aFilename); + Item.m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item.m_StorageType, &Item.m_Info); + Item.m_InfosLoaded = true; + } + return Item.m_Valid; +} + void CMenus::RenderDemoList(CUIRect MainView) { CUIRect BottomView; @@ -425,25 +438,15 @@ void CMenus::RenderDemoList(CUIRect MainView) char aFooterLabel[128] = {0}; if(m_DemolistSelectedIndex >= 0) { - CDemoItem *Item = &m_lDemos[m_DemolistSelectedIndex]; - if(str_comp(Item->m_aFilename, "..") == 0) + CDemoItem &Item = m_lDemos[m_DemolistSelectedIndex]; + if(str_comp(Item.m_aFilename, "..") == 0) str_copy(aFooterLabel, Localize("Parent Folder"), sizeof(aFooterLabel)); else if(m_DemolistSelectedIsDir) str_copy(aFooterLabel, Localize("Folder"), sizeof(aFooterLabel)); + else if(!FetchHeader(Item)) + str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel)); else - { - if(!Item->m_InfosLoaded) - { - char aBuffer[IO_MAX_PATH_LENGTH]; - str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename); - Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, &Item->m_Info); - Item->m_InfosLoaded = true; - } - if(!Item->m_Valid) - str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel)); - else - str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); - } + str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); } static bool s_DemoDetailsActive = true; @@ -511,7 +514,10 @@ void CMenus::RenderDemoList(CUIRect MainView) Config()->m_BrDemoSort = ms_aDemoCols[i].m_Sort; } - DemolistPopulate(); + // Don't rescan in order to keep fetched headers, just resort + m_lDemos.sort_range_by(CDemoComparator( + Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder + )); DemolistOnUpdate(false); } } @@ -582,7 +588,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } // demo buttons - int NumButtons = m_DemolistSelectedIsDir ? 2 : 4; + int NumButtons = m_DemolistSelectedIsDir ? 3 : 5; float Spacing = 3.0f; float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; float BackgroundWidth = ButtonWidth*(float)NumButtons+(float)(NumButtons-1)*Spacing; @@ -631,6 +637,20 @@ void CMenus::RenderDemoList(CUIRect MainView) } } + BottomView.VSplitLeft(Spacing, 0, &BottomView); + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static CButtonContainer s_FetchButton; + if(DoButton_Menu(&s_FetchButton, Localize("Fetch Info"), 0, &Button)) + { + for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) + { + FetchHeader(r.front()); + } + m_lDemos.sort_range_by(CDemoComparator( + Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder + )); + } + BottomView.VSplitLeft(Spacing, 0, &BottomView); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static CButtonContainer s_PlayButton; @@ -705,8 +725,7 @@ float CMenus::RenderDemoDetails(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | - ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); + int Length = m_lDemos[m_DemolistSelectedIndex].Length(); char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); DoInfoBox(&Button, Localize("Length"), aBuf); From c39dba4d09e3f26479c461c89d313c3b7423abf3 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 21 Jul 2020 12:44:15 +0200 Subject: [PATCH 361/479] Fix warning on fetching demo info --- src/game/client/components/menus_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index ed76e007..bc0428b5 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -644,7 +644,8 @@ void CMenus::RenderDemoList(CUIRect MainView) { for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { - FetchHeader(r.front()); + if(str_comp(r.front().m_aFilename, "..")) + FetchHeader(r.front()); } m_lDemos.sort_range_by(CDemoComparator( Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder From 01b9de850ed09d88a66bcf0ffdc3d73ca6ca0173 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 21 Jul 2020 17:20:33 +0200 Subject: [PATCH 362/479] Fix rand init error message --- src/engine/client/client.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b36f6db5..9695ac04 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2599,11 +2599,7 @@ int main(int argc, const char **argv) // ignore_convention } } - if(secure_random_init() != 0) - { - dbg_msg("secure", "could not initialize secure RNG"); - return -1; - } + bool RandInitFailed = secure_random_init() != 0; CClient *pClient = CreateClient(); IKernel *pKernel = IKernel::Create(); @@ -2622,6 +2618,12 @@ int main(int argc, const char **argv) // ignore_convention IEngineMap *pEngineMap = CreateEngineMap(); IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer(); + if(RandInitFailed) + { + dbg_msg("secure", "could not initialize secure RNG"); + return -1; + } + { bool RegisterFail = false; From 101b7b3c01be20399066c81ef475af60efbb273d Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 2 Aug 2020 17:44:45 +0200 Subject: [PATCH 363/479] fixed line breaks --- src/game/client/gameclient.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1bb5889f..b2210620 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -572,22 +572,22 @@ void CGameClient::StartRendering() } else if(m_pMenus->IsBackgroundNeeded()) { - // render background color - float sw = 300 * Graphics()->ScreenAspect(); - float sh = 300; - Graphics()->MapScreen(0, 0, sw, sh); - Graphics()->TextureClear(); - Graphics()->QuadsBegin(); - vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); - vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); - IGraphics::CColorVertex Array[4] = { - IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), - IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a) }; - Graphics()->SetColorVertex(Array, 4); - IGraphics::CQuadItem QuadItem(0, 0, sw, sh); - Graphics()->QuadsDrawTL(&QuadItem, 1); + // render background color + float sw = 300 * Graphics()->ScreenAspect(); + float sh = 300; + Graphics()->MapScreen(0, 0, sw, sh); + Graphics()->TextureClear(); + Graphics()->QuadsBegin(); + vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); + vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), + IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a) }; + Graphics()->SetColorVertex(Array, 4); + IGraphics::CQuadItem QuadItem(0, 0, sw, sh); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } } From 293209e7227c81e92b99c89890ebfdc264374a4a Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 2 Aug 2020 17:57:29 +0200 Subject: [PATCH 364/479] do a proper bounds check for types when unpacking the snapshot delta. closes #2649 --- src/engine/shared/snapshot.cpp | 4 +++- src/engine/shared/snapshot.h | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index e1ec7e86..ff23809b 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -172,6 +172,8 @@ CSnapshotDelta::CSnapshotDelta() void CSnapshotDelta::SetStaticsize(int ItemType, int Size) { + if(ItemType < 0 || ItemType >= MAX_NETOBJTYPES) + return; m_aItemSizes[ItemType] = Size; } @@ -354,7 +356,7 @@ int CSnapshotDelta::UnpackDelta(const CSnapshot *pFrom, CSnapshot *pTo, const vo return -1; Type = *pData++; - if(Type < 0) + if(Type < 0 || Type >= MAX_NETOBJTYPES) return -1; ID = *pData++; if(m_aItemSizes[Type]) diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index 1fa65b43..7d58704a 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -70,8 +70,11 @@ class CSnapshotDelta }; private: - // TODO: strange arbitrary number - short m_aItemSizes[64]; + enum + { + MAX_NETOBJTYPES=64 + }; + short m_aItemSizes[MAX_NETOBJTYPES]; int m_aSnapshotDataRate[0xffff]; int m_aSnapshotDataUpdates[0xffff]; int m_SnapshotCurrent; From 6460336328236b4bb609c8302f1d70e7d0e199a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 22 Jan 2020 23:59:55 +0100 Subject: [PATCH 365/479] call TickPaused when either game world or game controller are paused (closes #1991) --- src/game/server/gameworld.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 932f6082..24f3de36 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -168,33 +168,33 @@ void CGameWorld::Tick() if(m_ResetRequested) Reset(); - if(!m_Paused) + if(m_Paused || GameServer()->m_pController->IsGamePaused()) { // update all objects for(int i = 0; i < NUM_ENTTYPES; i++) for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) { m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; - pEnt->Tick(); + pEnt->TickPaused(); 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->TickDefered(); + pEnt->Tick(); pEnt = m_pNextTraverseEntity; } - } - else if(GameServer()->m_pController->IsGamePaused()) - { - // 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->TickDefered(); pEnt = m_pNextTraverseEntity; } } From 23ef86c2dc6b6bc150d09ee024bcad00d437afc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 23 Jan 2020 13:05:49 +0100 Subject: [PATCH 366/479] disable projectile/pickup predict on game/round over (world paused) --- src/game/client/components/items.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index e6560f5e..fa9df23c 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -37,7 +37,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) } static float s_LastGameTickTime = Client()->GameTickTime(); - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) s_LastGameTickTime = Client()->GameTickTime(); float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) @@ -72,7 +72,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) } else { - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) s_Time += Client()->LocalTime()-s_LastLocalTime; } @@ -153,7 +153,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu } else { - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) s_Time += Client()->LocalTime()-s_LastLocalTime; } Pos.x += cosf(s_Time*2.0f+Offset)*2.5f; From ffa82bd82908eeab965179e40e312e832f379cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 3 Aug 2020 00:42:01 +0200 Subject: [PATCH 367/479] pause animations, particles etc. on game/round end --- src/game/client/components/controls.cpp | 3 +-- src/game/client/components/damageind.cpp | 2 +- src/game/client/components/items.cpp | 6 +++--- src/game/client/components/maplayers.cpp | 2 +- src/game/client/components/particles.cpp | 4 ++-- src/game/client/components/players.cpp | 15 +++++++-------- src/game/client/gameclient.cpp | 5 ++--- src/game/client/gameclient.h | 5 +++-- 8 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 041832f4..60046c3e 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -209,8 +209,7 @@ void CControls::OnRender() bool CControls::OnMouseMove(float x, float y) { - if((m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) || - (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) + if(m_pClient->IsWorldPaused() || (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) return false; m_MousePos += vec2(x, y); // TODO: ugly diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index f0230f21..19151833 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -60,7 +60,7 @@ void CDamageInd::OnRender() } else { - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + if(m_pClient->IsWorldPaused()) m_aItems[i].m_StartTime += Client()->LocalTime()-s_LastLocalTime; } diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index fa9df23c..58ba1db2 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -37,7 +37,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) } static float s_LastGameTickTime = Client()->GameTickTime(); - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_pClient->IsWorldPaused()) s_LastGameTickTime = Client()->GameTickTime(); float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) @@ -72,7 +72,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) } else { - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_pClient->IsWorldPaused()) s_Time += Client()->LocalTime()-s_LastLocalTime; } @@ -153,7 +153,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu } else { - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_pClient->IsWorldPaused()) s_Time += Client()->LocalTime()-s_LastLocalTime; } Pos.x += cosf(s_Time*2.0f+Offset)*2.5f; diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 35255c39..583bafd8 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -333,7 +333,7 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void } else if(pThis->Client()->State() != IClient::STATE_OFFLINE) { - if(pThis->m_pClient->m_Snap.m_pGameData && !(pThis->m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(pThis->m_pClient->m_Snap.m_pGameData && !pThis->m_pClient->IsWorldPaused()) { if(pItem->m_Version < 2 || pItem->m_Synchronized) { diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index c9af6343..2c2e2450 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -45,7 +45,7 @@ void CParticles::Add(int Group, CParticle *pPart) } else { - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + if(m_pClient->IsWorldPaused()) return; } @@ -148,7 +148,7 @@ void CParticles::OnRender() } else { - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(!m_pClient->IsWorldPaused()) Update((float)((Now-s_LastTime)/(double)time_freq())); } diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 94bf9512..54214cec 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -61,8 +61,7 @@ void CPlayers::RenderHook( // use preditect players if needed if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || - (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_pClient->m_Snap.m_pLocalCharacter || m_pClient->IsWorldPaused()) { } else @@ -195,11 +194,11 @@ void CPlayers::RenderPlayer( g_GameClient.m_aClients[info.cid].angle = angle;*/ } + const bool WorldPaused = m_pClient->IsWorldPaused(); // use preditect players if needed if(m_pClient->m_LocalClientID == ClientID && Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || - (m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_pClient->m_Snap.m_pLocalCharacter || WorldPaused) { } else @@ -241,7 +240,7 @@ void CPlayers::RenderPlayer( State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f); static float s_LastGameTickTime = Client()->GameTickTime(); - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(!WorldPaused) s_LastGameTickTime = Client()->GameTickTime(); if (Player.m_Weapon == WEAPON_HAMMER) { @@ -333,7 +332,7 @@ void CPlayers::RenderPlayer( } else { - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + if(WorldPaused) IteX = s_LastIteX; else s_LastIteX = IteX; @@ -359,7 +358,7 @@ void CPlayers::RenderPlayer( // TODO: should be an animation Recoil = 0; static float s_LastIntraTick = IntraTick; - if(m_pClient->m_Snap.m_pGameData && !(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + if(!WorldPaused) s_LastIntraTick = IntraTick; float a = (Client()->GameTick()-Player.m_AttackTick+s_LastIntraTick)/5.0f; @@ -395,7 +394,7 @@ void CPlayers::RenderPlayer( } else { - if(m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + if(WorldPaused) IteX = s_LastIteX; else s_LastIteX = IteX; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 95a40139..99d9d751 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -500,8 +500,7 @@ void CGameClient::UpdatePositions() // local character position if(Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_Snap.m_pLocalCharacter || - (m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + if(!m_Snap.m_pLocalCharacter || IsWorldPaused()) { // don't use predicted } @@ -1516,7 +1515,7 @@ void CGameClient::OnPredict() return; // don't predict anything if we are paused or round/game is over - if(m_Snap.m_pGameData && m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) + if(IsWorldPaused()) { if(m_Snap.m_pLocalCharacter) m_PredictedChar.Read(m_Snap.m_pLocalCharacter); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 74db48a3..4e53037d 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -269,11 +269,12 @@ class CGameClient : public IGameClient virtual const char *NetVersionHashReal() const; virtual int ClientVersion() const; void GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName); - bool IsXmas() const; - bool IsEaster() const; void StartRendering(); + bool IsXmas() const; + bool IsEaster() const; int RacePrecision() const { return m_Snap.m_pGameDataRace ? m_Snap.m_pGameDataRace->m_Precision : 3; } + bool IsWorldPaused() const { return m_Snap.m_pGameData && (m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)); } // void DoEnterMessage(const char *pName, int ClientID, int Team); From de98c14096dc90f7ed084fbc9cf9d5504b568469 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 4 Aug 2020 11:36:12 +0200 Subject: [PATCH 368/479] Pass by pointer https://github.com/teeworlds/documentation/blob/master/nomenclature.md#passing-variables --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_demo.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 9a949ffb..a83fc20f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -773,7 +773,7 @@ class CMenus : public CComponent void UpdateMusicState(); // found in menus_demo.cpp - bool FetchHeader(CDemoItem &Item); + bool FetchHeader(CDemoItem *pItem); void RenderDemoPlayer(CUIRect MainView); void RenderDemoList(CUIRect MainView); float RenderDemoDetails(CUIRect View); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index bc0428b5..ae438976 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -402,16 +402,16 @@ void CMenus::DemolistOnUpdate(bool Reset) m_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_lDemos[m_DemolistSelectedIndex].m_IsDir; } -bool CMenus::FetchHeader(CDemoItem &Item) +bool CMenus::FetchHeader(CDemoItem *pItem) { - if(!Item.m_InfosLoaded) + if(!pItem->m_InfosLoaded) { char aBuffer[IO_MAX_PATH_LENGTH]; - str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item.m_aFilename); - Item.m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item.m_StorageType, &Item.m_Info); - Item.m_InfosLoaded = true; + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, pItem->m_aFilename); + pItem->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, pItem->m_StorageType, &pItem->m_Info); + pItem->m_InfosLoaded = true; } - return Item.m_Valid; + return pItem->m_Valid; } void CMenus::RenderDemoList(CUIRect MainView) @@ -438,12 +438,12 @@ void CMenus::RenderDemoList(CUIRect MainView) char aFooterLabel[128] = {0}; if(m_DemolistSelectedIndex >= 0) { - CDemoItem &Item = m_lDemos[m_DemolistSelectedIndex]; - if(str_comp(Item.m_aFilename, "..") == 0) + CDemoItem *pItem = &m_lDemos[m_DemolistSelectedIndex]; + if(str_comp(pItem->m_aFilename, "..") == 0) str_copy(aFooterLabel, Localize("Parent Folder"), sizeof(aFooterLabel)); else if(m_DemolistSelectedIsDir) str_copy(aFooterLabel, Localize("Folder"), sizeof(aFooterLabel)); - else if(!FetchHeader(Item)) + else if(!FetchHeader(pItem)) str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel)); else str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); @@ -645,7 +645,7 @@ void CMenus::RenderDemoList(CUIRect MainView) for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { if(str_comp(r.front().m_aFilename, "..")) - FetchHeader(r.front()); + FetchHeader(&r.front()); } m_lDemos.sort_range_by(CDemoComparator( Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder From 8554c1e7002acd3906f2ddb36793ee8d46b3e65e Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 4 Aug 2020 12:33:35 +0200 Subject: [PATCH 369/479] Show length in demo list Thanks to @east code is heavily inspired by this commit: https://github.com/ddnet/ddnet/commit/da17b795c5b7460be130084e88cb28eefe051cbe --- src/game/client/components/menus_demo.cpp | 58 ++++++++++++++++------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index ae438976..e3598aa0 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -551,24 +551,50 @@ void CMenus::RenderDemoList(CUIRect MainView) DoIconColor(IMAGE_FILEICONS, DemoItem.m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); - if(Item.m_Selected) + for(int c = 0; c < NumCols; c++) { - TextRender()->TextColor(CUI::ms_HighlightTextColor); - TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); - } - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - if(!DemoItem.m_IsDir) - { - char aDate[64]; - str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); - if(!Item.m_Selected) - TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Item.m_Rect, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); + CUIRect Button; + Button.x = ms_aDemoCols[c].m_Rect.x + FileIcon.w + 10.0f; + Button.y = FileIcon.y; + Button.h = ms_aDemoCols[c].m_Rect.h; + Button.w = ms_aDemoCols[c].m_Rect.w; + + int ID = ms_aDemoCols[c].m_ID; + + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + if(ID == COL_DEMO_NAME) + { + UI()->DoLabel(&Button, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + } + else if(ID == COL_DEMO_LENGTH && !r.front().m_IsDir && r.front().m_InfosLoaded) + { + int Length = r.front().Length(); + char aLength[32]; + str_format(aLength, sizeof(aLength), "%d:%02d", Length/60, Length%60); + Button.VMargin(4.0f, &Button); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Button, aLength, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + } + else if(ID == COL_DEMO_DATE) + { + if(!DemoItem.m_IsDir) + { + char aDate[64]; + str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Button, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + } + } + TextRender()->TextColor(CUI::ms_DefaultTextColor); + if(Item.m_Selected) + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } - TextRender()->TextColor(CUI::ms_DefaultTextColor); - if(Item.m_Selected) - TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } m_DemolistSelectedIndex = s_ListBox.DoEnd(); From 76262c699bd2eb77ebf39aaaa28566a595078650 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Wed, 5 Aug 2020 10:44:52 +0200 Subject: [PATCH 370/479] Fix button order in demo browser (closed #2679) Do not move the refresh button when switching from demofile to directory --- src/game/client/components/menus_demo.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index e3598aa0..dc8b1edc 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -623,17 +623,8 @@ void CMenus::RenderDemoList(CUIRect MainView) RenderBackgroundShadow(&BottomView, true); BottomView.HSplitTop(25.0f, &BottomView, 0); - BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); - static CButtonContainer s_RefreshButton; - if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) - { - DemolistPopulate(); - DemolistOnUpdate(false); - } - if(!m_DemolistSelectedIsDir) { - BottomView.VSplitLeft(Spacing, 0, &BottomView); BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static CButtonContainer s_DeleteButton; if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &Button) || m_DeletePressed) @@ -661,6 +652,15 @@ void CMenus::RenderDemoList(CUIRect MainView) return; } } + BottomView.VSplitLeft(Spacing, 0, &BottomView); + } + + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static CButtonContainer s_RefreshButton; + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) + { + DemolistPopulate(); + DemolistOnUpdate(false); } BottomView.VSplitLeft(Spacing, 0, &BottomView); From 757b0aa58fdc8414ec91b8c10def22ca21f850bb Mon Sep 17 00:00:00 2001 From: Redix Date: Thu, 30 Jul 2020 20:39:17 +0200 Subject: [PATCH 371/479] Fix 'net_addr_comp' so it does not use uninitialized memory --- src/base/system.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index ca3dc3c6..91985b5c 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -764,7 +764,9 @@ static void sockaddr_to_netaddr(const struct sockaddr *src, NETADDR *dst) int net_addr_comp(const NETADDR *a, const NETADDR *b) { - return mem_comp(a, b, sizeof(NETADDR)); + if(mem_comp(a->ip, b->ip, sizeof(a->ip)) == 0 && a->port == b->port && a->type == b->type) + return 0; + return -1; } void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port) From 31169b63a1e555644ee9518019fd7fa79d88f60d Mon Sep 17 00:00:00 2001 From: Redix Date: Fri, 31 Jul 2020 15:16:02 +0200 Subject: [PATCH 372/479] Do not use uninitialized memory to generate network tokens --- src/engine/shared/network_token.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index ca71bd71..43183051 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -95,8 +95,10 @@ TOKEN CNetTokenManager::GenerateToken(const NETADDR *pAddr, int64 Seed) if(pAddr->type & NETTYPE_LINK_BROADCAST) return GenerateToken(&NullAddr, Seed); - Addr = *pAddr; - Addr.port = 0; + mem_zero(&Addr, sizeof(NETADDR)); + mem_copy(Addr.ip, pAddr->ip, sizeof(Addr.ip)); + Addr.type = pAddr->type; + mem_copy(aBuf, &Addr, sizeof(NETADDR)); mem_copy(aBuf + sizeof(NETADDR), &Seed, sizeof(int64)); From 412db166c6ec3c39b15dcabef5c2ecb9e76c54f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Aug 2020 16:21:44 +0200 Subject: [PATCH 373/479] fix scrolling to reveal server not working in some cases --- src/game/client/components/menus_browser.cpp | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 8de99194..88608055 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1265,16 +1265,23 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // select server if address changed and match found bool IsSelected = m_aSelectedFilters[BrowserType] == FilterIndex && m_aSelectedServers[BrowserType] == ServerIndex; - if(m_AddressSelection&ADDR_SELECTION_CHANGE && !str_comp(pItem->m_aAddress, pAddress)) + if(m_AddressSelection&ADDR_SELECTION_CHANGE) { - if(!IsSelected) + if (!str_comp(pItem->m_aAddress, pAddress)) { - m_ShowServerDetails = true; - m_aSelectedFilters[BrowserType] = FilterIndex; - m_aSelectedServers[BrowserType] = ServerIndex; - IsSelected = true; + if(!IsSelected) + { + m_ShowServerDetails = true; + m_aSelectedFilters[BrowserType] = FilterIndex; + m_aSelectedServers[BrowserType] = ServerIndex; + IsSelected = true; + } + m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); + } + else + { + IsSelected = false; } - m_AddressSelection &= ~(ADDR_SELECTION_CHANGE|ADDR_SELECTION_RESET_SERVER_IF_NOT_FOUND); } float ItemHeight = HeaderHeight; From c52b77ab40275373e760cc229f040abb044fbb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 6 Aug 2020 16:34:41 +0200 Subject: [PATCH 374/479] make warmup abortable with 'restart -1' --- src/game/server/gamecontext.cpp | 9 +++++---- src/game/server/gamecontroller.h | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index b15a2649..f767d467 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1217,10 +1217,11 @@ void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConRestart(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; - if(pResult->NumArguments()) - pSelf->m_pController->DoWarmup(clamp(pResult->GetInteger(0), -1, 1000)); + int Seconds = pResult->NumArguments() ? clamp(pResult->GetInteger(0), -1, 1000) : 0; + if(Seconds < 0) + pSelf->m_pController->AbortWarmup(); else - pSelf->m_pController->DoWarmup(0); + pSelf->m_pController->DoWarmup(Seconds); } void CGameContext::ConSay(IConsole::IResult *pResult, void *pUserData) @@ -1521,7 +1522,7 @@ void CGameContext::OnConsoleInit() Console()->Register("pause", "?i[seconds]", CFGFLAG_SERVER|CFGFLAG_STORE, ConPause, this, "Pause/unpause game"); Console()->Register("change_map", "?r[map]", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map"); - Console()->Register("restart", "?i[seconds]", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)"); + Console()->Register("restart", "?i[seconds]", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (-1 = abort)"); Console()->Register("say", "r[text]", CFGFLAG_SERVER, ConSay, this, "Say in chat"); Console()->Register("broadcast", "r[text]", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message"); Console()->Register("set_team", "i[id] i[team] ?i[delay]", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team"); diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index ca467b30..5eb111f0 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -185,6 +185,14 @@ class IGameController { SetGameState(IGS_WARMUP_USER, Seconds); } + void AbortWarmup() + { + if((m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER) + && m_GameStateTimer != TIMER_INFINITE) + { + SetGameState(IGS_GAME_RUNNING); + } + } void SwapTeamscore(); // general From c87a7b438f08f83385f4e21d1c23a498a6fb4c55 Mon Sep 17 00:00:00 2001 From: Redix Date: Fri, 7 Aug 2020 16:01:48 +0200 Subject: [PATCH 375/479] Allow snap items with type >= 64 --- src/engine/shared/snapshot.cpp | 14 ++++++++------ src/engine/shared/snapshot.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index ff23809b..54f59e11 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -172,7 +172,7 @@ CSnapshotDelta::CSnapshotDelta() void CSnapshotDelta::SetStaticsize(int ItemType, int Size) { - if(ItemType < 0 || ItemType >= MAX_NETOBJTYPES) + if(ItemType < 0 || ItemType >= MAX_NETOBJSIZES) return; m_aItemSizes[ItemType] = Size; } @@ -232,13 +232,15 @@ int CSnapshotDelta::CreateDelta(const CSnapshot *pFrom, CSnapshot *pTo, void *pD pCurItem = pTo->GetItem(i); // O(1) .. O(n) PastIndex = aPastIndecies[i]; + bool IncludeSize = pCurItem->Type() >= MAX_NETOBJSIZES || !m_aItemSizes[pCurItem->Type()]; + if(PastIndex != -1) { int *pItemDataDst = pData+3; pPastItem = pFrom->GetItem(PastIndex); - if(m_aItemSizes[pCurItem->Type()]) + if(!IncludeSize) pItemDataDst = pData+2; if(DiffItem(pPastItem->Data(), (int*)pCurItem->Data(), pItemDataDst, ItemSize/4)) @@ -246,7 +248,7 @@ int CSnapshotDelta::CreateDelta(const CSnapshot *pFrom, CSnapshot *pTo, void *pD *pData++ = pCurItem->Type(); *pData++ = pCurItem->ID(); - if(!m_aItemSizes[pCurItem->Type()]) + if(IncludeSize) *pData++ = ItemSize/4; pData += ItemSize/4; pDelta->m_NumUpdateItems++; @@ -256,7 +258,7 @@ int CSnapshotDelta::CreateDelta(const CSnapshot *pFrom, CSnapshot *pTo, void *pD { *pData++ = pCurItem->Type(); *pData++ = pCurItem->ID(); - if(!m_aItemSizes[pCurItem->Type()]) + if(IncludeSize) *pData++ = ItemSize/4; mem_copy(pData, pCurItem->Data(), ItemSize); @@ -356,10 +358,10 @@ int CSnapshotDelta::UnpackDelta(const CSnapshot *pFrom, CSnapshot *pTo, const vo return -1; Type = *pData++; - if(Type < 0 || Type >= MAX_NETOBJTYPES) + if(Type < 0) return -1; ID = *pData++; - if(m_aItemSizes[Type]) + if(Type < MAX_NETOBJSIZES && m_aItemSizes[Type]) ItemSize = m_aItemSizes[Type]; else { diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index 7d58704a..aba0dd91 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -72,9 +72,9 @@ class CSnapshotDelta private: enum { - MAX_NETOBJTYPES=64 + MAX_NETOBJSIZES=64 }; - short m_aItemSizes[MAX_NETOBJTYPES]; + short m_aItemSizes[MAX_NETOBJSIZES]; int m_aSnapshotDataRate[0xffff]; int m_aSnapshotDataUpdates[0xffff]; int m_SnapshotCurrent; From 38aabdc411eec88b50b9af40d966af3124cd2972 Mon Sep 17 00:00:00 2001 From: Redix Date: Thu, 23 Apr 2020 20:17:10 +0200 Subject: [PATCH 376/479] Move video mode query to the main thread --- src/engine/client/backend_sdl.cpp | 81 ++++++++++++++----------- src/engine/client/backend_sdl.h | 2 +- src/engine/client/graphics_threaded.cpp | 23 +------ src/engine/client/graphics_threaded.h | 12 +--- 4 files changed, 49 insertions(+), 69 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 6f82aa19..ebe528fa 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -565,42 +565,6 @@ void CCommandProcessorFragment_SDL::Cmd_VSync(const CCommandBuffer::CVSyncComman *pCommand->m_pRetOk = SDL_GL_SetSwapInterval(pCommand->m_VSync) == 0; } -void CCommandProcessorFragment_SDL::Cmd_VideoModes(const CCommandBuffer::CVideoModesCommand *pCommand) -{ - SDL_DisplayMode mode; - int maxModes = SDL_GetNumDisplayModes(pCommand->m_Screen), - numModes = 0; - - for(int i = 0; i < maxModes; i++) - { - if(SDL_GetDisplayMode(pCommand->m_Screen, i, &mode) < 0) - { - dbg_msg("gfx", "unable to get display mode: %s", SDL_GetError()); - continue; - } - - bool alreadyFound = false; - for(int j = 0; j < numModes; j++) - { - if(pCommand->m_pModes[j].m_Width == mode.w && pCommand->m_pModes[j].m_Height == mode.h) - { - alreadyFound = true; - break; - } - } - if(alreadyFound) - continue; - - pCommand->m_pModes[numModes].m_Width = mode.w; - pCommand->m_pModes[numModes].m_Height = mode.h; - pCommand->m_pModes[numModes].m_Red = 8; - pCommand->m_pModes[numModes].m_Green = 8; - pCommand->m_pModes[numModes].m_Blue = 8; - numModes++; - } - *pCommand->m_pNumModes = numModes; -} - CCommandProcessorFragment_SDL::CCommandProcessorFragment_SDL() { } @@ -611,7 +575,6 @@ bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::CCommand *p { case CCommandBuffer::CMD_SWAP: Cmd_Swap(static_cast(pBaseCommand)); break; case CCommandBuffer::CMD_VSYNC: Cmd_VSync(static_cast(pBaseCommand)); break; - case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast(pBaseCommand)); break; case CMD_INIT: Cmd_Init(static_cast(pBaseCommand)); break; case CMD_SHUTDOWN: Cmd_Shutdown(static_cast(pBaseCommand)); break; default: return false; @@ -864,6 +827,50 @@ int CGraphicsBackend_SDL_OpenGL::GetWindowScreen() return SDL_GetWindowDisplayIndex(m_pWindow); } +int CGraphicsBackend_SDL_OpenGL::GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) +{ + int NumModes = SDL_GetNumDisplayModes(Screen); + if(NumModes < 0) + { + dbg_msg("gfx", "unable to get the number of display modes: %s", SDL_GetError()); + return 0; + } + + if(NumModes > MaxModes) + NumModes = MaxModes; + + int ModesCount = 0; + for(int i = 0; i < NumModes; i++) + { + SDL_DisplayMode Mode; + if(SDL_GetDisplayMode(Screen, i, &Mode) < 0) + { + dbg_msg("gfx", "unable to get display mode: %s", SDL_GetError()); + continue; + } + + bool AlreadyFound = false; + for(int j = 0; j < ModesCount; j++) + { + if(pModes[j].m_Width == Mode.w && pModes[j].m_Height == Mode.h) + { + AlreadyFound = true; + break; + } + } + if(AlreadyFound) + continue; + + pModes[ModesCount].m_Width = Mode.w; + pModes[ModesCount].m_Height = Mode.h; + pModes[ModesCount].m_Red = 8; + pModes[ModesCount].m_Green = 8; + pModes[ModesCount].m_Blue = 8; + ModesCount++; + } + return ModesCount; +} + bool CGraphicsBackend_SDL_OpenGL::GetDesktopResolution(int Index, int *pDesktopWidth, int* pDesktopHeight) { SDL_DisplayMode DisplayMode; diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h index 16fa049d..2826e918 100644 --- a/src/engine/client/backend_sdl.h +++ b/src/engine/client/backend_sdl.h @@ -171,7 +171,6 @@ class CCommandProcessorFragment_SDL void Cmd_Shutdown(const CShutdownCommand *pCommand); void Cmd_Swap(const CCommandBuffer::CSwapCommand *pCommand); void Cmd_VSync(const CCommandBuffer::CVSyncCommand *pCommand); - void Cmd_VideoModes(const CCommandBuffer::CVideoModesCommand *pCommand); public: CCommandProcessorFragment_SDL(); @@ -212,6 +211,7 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded virtual void SetWindowBordered(bool State); // on=true/off=false virtual bool SetWindowScreen(int Index); virtual int GetWindowScreen(); + virtual int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen); virtual bool GetDesktopResolution(int Index, int *pDesktopWidth, int* pDesktopHeight); virtual int WindowActive(); virtual int WindowOpen(); diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index e450b9ec..fe10aa5f 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -1004,29 +1004,12 @@ int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Scre { if(m_pConfig->m_GfxDisplayAllModes) { - int Count = sizeof(g_aFakeModes)/sizeof(CVideoMode); - mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes)); - if(MaxModes < Count) - Count = MaxModes; + int Count = min((int)(sizeof(g_aFakeModes)/sizeof(CVideoMode)), MaxModes); + mem_copy(pModes, g_aFakeModes, sizeof(CVideoMode) * Count); return Count; } - // add videomodes command - CImageInfo Image; - mem_zero(&Image, sizeof(Image)); - - int NumModes = 0; - CCommandBuffer::CVideoModesCommand Cmd; - Cmd.m_pModes = pModes; - Cmd.m_MaxModes = MaxModes; - Cmd.m_pNumModes = &NumModes; - Cmd.m_Screen = Screen; - m_pCommandBuffer->AddCommand(Cmd); - - // kick the buffer and wait for the result and return it - KickCommandBuffer(); - WaitForIdle(); - return NumModes; + return m_pBackend->GetVideoModes(pModes, MaxModes, Screen); } extern IEngineGraphics *CreateEngineGraphicsThreaded() { return new CGraphics_Threaded(); } diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index ce92dede..91d1202d 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -84,7 +84,6 @@ class CCommandBuffer // misc CMD_VSYNC, CMD_SCREENSHOT, - CMD_VIDEOMODES, }; @@ -190,16 +189,6 @@ class CCommandBuffer CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well }; - struct CVideoModesCommand : public CCommand - { - CVideoModesCommand() : CCommand(CMD_VIDEOMODES) {} - - CVideoMode *m_pModes; // processor will fill this in - int m_MaxModes; // maximum of modes the processor can write to the m_pModes - int *m_pNumModes; // processor will write to this pointer - int m_Screen; - }; - struct CSwapCommand : public CCommand { CSwapCommand() : CCommand(CMD_SWAP) {} @@ -328,6 +317,7 @@ class IGraphicsBackend virtual bool Fullscreen(bool State) = 0; virtual void SetWindowBordered(bool State) = 0; virtual bool SetWindowScreen(int Index) = 0; + virtual int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) = 0; virtual bool GetDesktopResolution(int Index, int *pDesktopWidth, int* pDesktopHeight) = 0; virtual int GetWindowScreen() = 0; virtual int WindowActive() = 0; From 510bbb4e92b45af2536886502b40bf84e6230e60 Mon Sep 17 00:00:00 2001 From: Redix Date: Thu, 23 Apr 2020 20:08:43 +0200 Subject: [PATCH 377/479] Move OpenGL configuration to OpenGL command processor --- src/engine/client/backend_sdl.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index ebe528fa..f077c648 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -246,6 +246,17 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::CState &St void CCommandProcessorFragment_OpenGL::Cmd_Init(const CInitCommand *pCommand) { + // 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); + m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage; *m_pTextureMemoryUsage = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize); @@ -534,17 +545,6 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const CInitCommand *pCommand) m_GLContext = pCommand->m_GLContext; m_pWindow = pCommand->m_pWindow; SDL_GL_MakeCurrent(m_pWindow, m_GLContext); - - // 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); } void CCommandProcessorFragment_SDL::Cmd_Shutdown(const CShutdownCommand *pCommand) From 89dde821e2280ac31e4265551711db6da61d57ed Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 18:53:46 +0200 Subject: [PATCH 378/479] Use consistent line endings in json files --- src/engine/shared/jsonwriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shared/jsonwriter.cpp b/src/engine/shared/jsonwriter.cpp index 0af0a140..ae1936c9 100644 --- a/src/engine/shared/jsonwriter.cpp +++ b/src/engine/shared/jsonwriter.cpp @@ -27,7 +27,7 @@ CJsonWriter::CJsonWriter(IOHANDLE IO) CJsonWriter::~CJsonWriter() { - WriteInternal("\n"); + io_write_newline(m_IO); io_close(m_IO); } From c89fe78aeea78f90b07ab146d1403e4545333d62 Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 18:54:13 +0200 Subject: [PATCH 379/479] Fix json tests on windows --- src/test/jsonwriter.cpp | 42 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/test/jsonwriter.cpp b/src/test/jsonwriter.cpp index eae56666..dca598e2 100644 --- a/src/test/jsonwriter.cpp +++ b/src/test/jsonwriter.cpp @@ -4,6 +4,12 @@ #include #include +#if defined(CONF_FAMILY_WINDOWS) + #define LINE_ENDING "\r\n" +#else + #define LINE_ENDING "\n" +#endif + class JsonWriter : public ::testing::Test { protected: @@ -54,14 +60,14 @@ TEST_F(JsonWriter, EmptyObject) { m_pJson->BeginObject(); m_pJson->EndObject(); - Expect("{\n}\n"); + Expect("{" LINE_ENDING "}" LINE_ENDING); } TEST_F(JsonWriter, EmptyArray) { m_pJson->BeginArray(); m_pJson->EndArray(); - Expect("[\n]\n"); + Expect("[" LINE_ENDING "]" LINE_ENDING); } TEST_F(JsonWriter, SpecialCharacters) @@ -73,32 +79,32 @@ TEST_F(JsonWriter, SpecialCharacters) m_pJson->EndArray(); m_pJson->EndObject(); Expect( - "{\n" - "\t\"\\u0001\\\"'\\r\\n\\t\": [\n" - "\t\t\" \\\"'abc\\u0001\\n\"\n" - "\t]\n" - "}\n" + "{" LINE_ENDING + "\t\"\\u0001\\\"'\\r\\n\\t\": [" LINE_ENDING + "\t\t\" \\\"'abc\\u0001\\n\"" LINE_ENDING + "\t]" LINE_ENDING + "}" LINE_ENDING ); } TEST_F(JsonWriter, HelloWorld) { m_pJson->WriteStrValue("hello world"); - Expect("\"hello world\"\n"); + Expect("\"hello world\"" LINE_ENDING); } TEST_F(JsonWriter, Unicode) { m_pJson->WriteStrValue("Heizölrückstoßabdämpfung"); - Expect("\"Heizölrückstoßabdämpfung\"\n"); + Expect("\"Heizölrückstoßabdämpfung\"" LINE_ENDING); } -TEST_F(JsonWriter, True) { m_pJson->WriteBoolValue(true); Expect("true\n"); } -TEST_F(JsonWriter, False) { m_pJson->WriteBoolValue(false); Expect("false\n"); } -TEST_F(JsonWriter, Null) { m_pJson->WriteNullValue(); Expect("null\n"); } -TEST_F(JsonWriter, EmptyString) { m_pJson->WriteStrValue(""); Expect("\"\"\n"); } -TEST_F(JsonWriter, Zero) { m_pJson->WriteIntValue(0); Expect("0\n"); } -TEST_F(JsonWriter, One) { m_pJson->WriteIntValue(1); Expect("1\n"); } -TEST_F(JsonWriter, MinusOne) { m_pJson->WriteIntValue(-1); Expect("-1\n"); } -TEST_F(JsonWriter, Large) { m_pJson->WriteIntValue(INT_MAX); Expect("2147483647\n"); } -TEST_F(JsonWriter, Small) { m_pJson->WriteIntValue(INT_MIN); Expect("-2147483648\n"); } +TEST_F(JsonWriter, True) { m_pJson->WriteBoolValue(true); Expect("true" LINE_ENDING); } +TEST_F(JsonWriter, False) { m_pJson->WriteBoolValue(false); Expect("false" LINE_ENDING); } +TEST_F(JsonWriter, Null) { m_pJson->WriteNullValue(); Expect("null" LINE_ENDING); } +TEST_F(JsonWriter, EmptyString) { m_pJson->WriteStrValue(""); Expect("\"\"" LINE_ENDING); } +TEST_F(JsonWriter, Zero) { m_pJson->WriteIntValue(0); Expect("0" LINE_ENDING); } +TEST_F(JsonWriter, One) { m_pJson->WriteIntValue(1); Expect("1" LINE_ENDING); } +TEST_F(JsonWriter, MinusOne) { m_pJson->WriteIntValue(-1); Expect("-1" LINE_ENDING); } +TEST_F(JsonWriter, Large) { m_pJson->WriteIntValue(INT_MAX); Expect("2147483647" LINE_ENDING); } +TEST_F(JsonWriter, Small) { m_pJson->WriteIntValue(INT_MIN); Expect("-2147483648" LINE_ENDING); } From fdf78b0cdf93eef6e996191a5b2920a6afa58d53 Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 22:47:40 +0200 Subject: [PATCH 380/479] Validate variables of the snap-item base class --- datasrc/compile.py | 5 ++++- datasrc/datatypes.py | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/datasrc/compile.py b/datasrc/compile.py index d669f489..9ef5eaf7 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -269,7 +269,10 @@ class CNetObjHandler lines += ['\t{'] for item in network.Objects: - for line in item.emit_validate(): + base_item = None + if item.base: + base_item = next(i for i in network.Objects if i.name == item.base) + for line in item.emit_validate(base_item): lines += ["\t" + line] lines += ['\t'] lines += ['\t}'] diff --git a/datasrc/datatypes.py b/datasrc/datatypes.py index 4fd88420..da47ef40 100644 --- a/datasrc/datatypes.py +++ b/datasrc/datatypes.py @@ -229,12 +229,15 @@ def emit_declaration(self): lines += ["\t"+line for line in v.emit_declaration()] lines += ["};"] return lines - def emit_validate(self): + def emit_validate(self, base_item): lines = ["case %s:" % self.enum_name] lines += ["{"] - lines += ["\t%s *pObj = (%s *)pData;"%(self.struct_name, self.struct_name)] + lines += ["\tconst %s *pObj = (const %s *)pData;"%(self.struct_name, self.struct_name)] lines += ["\tif(sizeof(*pObj) != Size) return -1;"] - for v in self.variables: + variables = self.variables + if base_item: + variables += base_item.variables + for v in variables: lines += ["\t"+line for line in v.emit_validate()] lines += ["\treturn 0;"] lines += ["}"] From 204ce4e959d4341310e25494c3b765596497ef44 Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 22:49:16 +0200 Subject: [PATCH 381/479] Fix validation range of m_HookedPlayer in character snap items --- datasrc/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datasrc/network.py b/datasrc/network.py index 315f976f..368fbd3a 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -159,7 +159,7 @@ NetIntRange("m_Direction", -1, 1), NetIntRange("m_Jumped", 0, 3), - NetIntRange("m_HookedPlayer", 0, 'MAX_CLIENTS-1'), + NetIntRange("m_HookedPlayer", -1, 'MAX_CLIENTS-1'), NetIntRange("m_HookState", -1, 5), NetTick("m_HookTick"), From 5a6900b8ece4973c8da07f59b6b87aae31a73db9 Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 23:12:19 +0200 Subject: [PATCH 382/479] Add client-side dead reckoning limit --- src/game/client/gameclient.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 99d9d751..55df9510 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1276,26 +1276,34 @@ void CGameClient::OnNewSnapshot() { if(Item.m_ID < MAX_CLIENTS) { + CSnapState::CCharacterInfo *pCharInfo = &m_Snap.m_aCharacters[Item.m_ID]; const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID); - m_Snap.m_aCharacters[Item.m_ID].m_Cur = *((const CNetObj_Character *)pData); + pCharInfo->m_Cur = *((const CNetObj_Character *)pData); // clamp ammo count for non ninja weapon - if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Weapon != WEAPON_NINJA) - m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount = clamp(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount, 0, 10); + if(pCharInfo->m_Cur.m_Weapon != WEAPON_NINJA) + pCharInfo->m_Cur.m_AmmoCount = clamp(pCharInfo->m_Cur.m_AmmoCount, 0, 10); if(pOld) { - m_Snap.m_aCharacters[Item.m_ID].m_Active = true; - m_Snap.m_aCharacters[Item.m_ID].m_Prev = *((const CNetObj_Character *)pOld); + pCharInfo->m_Active = true; + pCharInfo->m_Prev = *((const CNetObj_Character *)pOld); - if(m_Snap.m_aCharacters[Item.m_ID].m_Prev.m_Tick) - EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick()); - if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Tick) - EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick()); + if(pCharInfo->m_Prev.m_Tick) + { + // limit evolving to 3 seconds + int EvolveTick = min(pCharInfo->m_Prev.m_Tick + Client()->GameTickSpeed()*3, Client()->PrevGameTick()); + EvolveCharacter(&pCharInfo->m_Prev, EvolveTick); + } + if(pCharInfo->m_Cur.m_Tick) + { + int EvolveTick = min(pCharInfo->m_Cur.m_Tick + Client()->GameTickSpeed()*3, Client()->GameTick()); + EvolveCharacter(&pCharInfo->m_Cur, EvolveTick); + } } if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK) - ProcessTriggeredEvents(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_TriggeredEvents, vec2(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_X, m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Y)); + ProcessTriggeredEvents(pCharInfo->m_Cur.m_TriggeredEvents, vec2(pCharInfo->m_Cur.m_X, pCharInfo->m_Cur.m_Y)); } } else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO) From b24402747d09e26dcf6c55004599523a7199d607 Mon Sep 17 00:00:00 2001 From: Redix Date: Wed, 12 Aug 2020 16:17:07 +0200 Subject: [PATCH 383/479] Reuse the evolved character --- src/game/client/gameclient.cpp | 24 ++++++++++++++++-------- src/game/client/gameclient.h | 2 ++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 55df9510..51b4fcbe 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1289,17 +1289,24 @@ void CGameClient::OnNewSnapshot() pCharInfo->m_Active = true; pCharInfo->m_Prev = *((const CNetObj_Character *)pOld); - if(pCharInfo->m_Prev.m_Tick) + // limit evolving to 3 seconds + int EvolvePrevTick = min(pCharInfo->m_Prev.m_Tick + Client()->GameTickSpeed()*3, Client()->PrevGameTick()); + int EvolveCurTick = min(pCharInfo->m_Cur.m_Tick + Client()->GameTickSpeed()*3, Client()->GameTick()); + + // reuse the evolved char + if(m_aClients[Item.m_ID].m_Evolved.m_Tick == EvolvePrevTick) { - // limit evolving to 3 seconds - int EvolveTick = min(pCharInfo->m_Prev.m_Tick + Client()->GameTickSpeed()*3, Client()->PrevGameTick()); - EvolveCharacter(&pCharInfo->m_Prev, EvolveTick); + pCharInfo->m_Prev = m_aClients[Item.m_ID].m_Evolved; + if(mem_comp(pData, pOld, sizeof(CNetObj_Character)) == 0) + pCharInfo->m_Cur = m_aClients[Item.m_ID].m_Evolved; } + + if(pCharInfo->m_Prev.m_Tick) + EvolveCharacter(&pCharInfo->m_Prev, EvolvePrevTick); if(pCharInfo->m_Cur.m_Tick) - { - int EvolveTick = min(pCharInfo->m_Cur.m_Tick + Client()->GameTickSpeed()*3, Client()->GameTick()); - EvolveCharacter(&pCharInfo->m_Cur, EvolveTick); - } + EvolveCharacter(&pCharInfo->m_Cur, EvolveCurTick); + + m_aClients[Item.m_ID].m_Evolved = m_Snap.m_aCharacters[Item.m_ID].m_Cur; } if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK) @@ -1748,6 +1755,7 @@ void CGameClient::CClientData::Reset(CGameClient *pGameClient, int ClientID) m_Active = false; m_ChatIgnore = false; m_Friend = false; + m_Evolved.m_Tick = -1; for(int p = 0; p < NUM_SKINPARTS; p++) { m_SkinPartIDs[p] = 0; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 4e53037d..b3e52b94 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -194,6 +194,8 @@ class CGameClient : public IGameClient CTeeRenderInfo m_SkinInfo; // this is what the server reports CTeeRenderInfo m_RenderInfo; // this is what we use + CNetObj_Character m_Evolved; + float m_Angle; bool m_Active; bool m_ChatIgnore; From 7b94d8de455046dc9408ef52b9e2a12edfeeb6a2 Mon Sep 17 00:00:00 2001 From: Redix Date: Wed, 12 Aug 2020 19:20:02 +0200 Subject: [PATCH 384/479] Use rounding for all snap values --- src/game/server/entities/flag.cpp | 4 ++-- src/game/server/entities/laser.cpp | 8 ++++---- src/game/server/entities/pickup.cpp | 4 ++-- src/game/server/entities/projectile.cpp | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/game/server/entities/flag.cpp b/src/game/server/entities/flag.cpp index 4d06ad97..99bf05da 100644 --- a/src/game/server/entities/flag.cpp +++ b/src/game/server/entities/flag.cpp @@ -90,7 +90,7 @@ void CFlag::Snap(int SnappingClient) if(!pFlag) return; - pFlag->m_X = (int)m_Pos.x; - pFlag->m_Y = (int)m_Pos.y; + pFlag->m_X = round_to_int(m_Pos.x); + pFlag->m_Y = round_to_int(m_Pos.y); pFlag->m_Team = m_Team; } diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index ecc06149..8bc9194c 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -106,9 +106,9 @@ void CLaser::Snap(int SnappingClient) if(!pObj) return; - pObj->m_X = (int)m_Pos.x; - pObj->m_Y = (int)m_Pos.y; - pObj->m_FromX = (int)m_From.x; - pObj->m_FromY = (int)m_From.y; + pObj->m_X = round_to_int(m_Pos.x); + pObj->m_Y = round_to_int(m_Pos.y); + pObj->m_FromX = round_to_int(m_From.x); + pObj->m_FromY = round_to_int(m_From.y); pObj->m_StartTick = m_EvalTick; } diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index 01ee70b7..c11fc5c3 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -143,7 +143,7 @@ void CPickup::Snap(int SnappingClient) if(!pP) return; - pP->m_X = (int)m_Pos.x; - pP->m_Y = (int)m_Pos.y; + pP->m_X = round_to_int(m_Pos.x); + pP->m_Y = round_to_int(m_Pos.y); pP->m_Type = m_Type; } diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index fa8caa7f..8bf7e6ff 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -99,10 +99,10 @@ void CProjectile::TickPaused() void CProjectile::FillInfo(CNetObj_Projectile *pProj) { - pProj->m_X = (int)m_Pos.x; - pProj->m_Y = (int)m_Pos.y; - pProj->m_VelX = (int)(m_Direction.x*100.0f); - pProj->m_VelY = (int)(m_Direction.y*100.0f); + pProj->m_X = round_to_int(m_Pos.x); + pProj->m_Y = round_to_int(m_Pos.y); + pProj->m_VelX = round_to_int(m_Direction.x*100.0f); + pProj->m_VelY = round_to_int(m_Direction.y*100.0f); pProj->m_StartTick = m_StartTick; pProj->m_Type = m_Type; } From 6ba87577ae9e2b62e4fa50ef1fcfb01a346f39a3 Mon Sep 17 00:00:00 2001 From: Redix Date: Wed, 12 Aug 2020 19:22:09 +0200 Subject: [PATCH 385/479] Quantize the projectiles on the server side to match the client --- src/game/server/entities/projectile.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 8bf7e6ff..0c4d37b4 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -8,10 +8,11 @@ CProjectile::CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span, int Damage, bool Explosive, float Force, int SoundImpact, int Weapon) -: CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE, Pos) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE, vec2(round_to_int(Pos.x), round_to_int(Pos.y))) { m_Type = Type; - m_Direction = Dir; + m_Direction.x = round_to_int(Dir.x*100.0f) / 100.0f; + m_Direction.y = round_to_int(Dir.y*100.0f) / 100.0f; m_LifeSpan = Span; m_Owner = Owner; m_OwnerTeam = GameServer()->m_apPlayers[Owner]->GetTeam(); From 1e8373eed921d4ed392de776cb08bb581cae93f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 14 Aug 2020 19:50:34 +0200 Subject: [PATCH 386/479] separate mouse/joystick cursor movement, add joystick ui sens --- src/engine/client/input.cpp | 34 ++++++++++++------- src/engine/client/input.h | 17 +++++----- src/engine/input.h | 19 +++++++++-- src/game/client/component.h | 2 +- src/game/client/components/controls.cpp | 14 ++++++-- src/game/client/components/controls.h | 2 +- src/game/client/components/emoticon.cpp | 6 ++-- src/game/client/components/emoticon.h | 2 +- src/game/client/components/menus.cpp | 4 +-- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_callback.cpp | 14 +++++--- src/game/client/components/spectator.cpp | 6 ++-- src/game/client/components/spectator.h | 2 +- src/game/client/gameclient.cpp | 8 ++--- src/game/client/ui.cpp | 18 +++++++--- src/game/client/ui.h | 2 +- src/game/editor/editor.cpp | 11 +++--- src/game/variables.h | 1 + 18 files changed, 108 insertions(+), 56 deletions(-) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 762df987..2ae03469 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -201,31 +201,41 @@ int CInput::GetJoystickNumAxes() return SDL_JoystickNumAxes(pJoystick); } -void CInput::MouseRelative(float *x, float *y) +bool CInput::JoystickRelative(float *pX, float *pY) { if(!m_MouseInputRelative) - return; + return false; - int MouseX = 0, MouseY = 0; - SDL_GetRelativeMouseState(&MouseX, &MouseY); - - vec2 JoystickPos = vec2(0.0f, 0.0f); if(m_pConfig->m_JoystickEnable && GetActiveJoystick()) { const vec2 RawJoystickPos = vec2(GetJoystickAxisValue(m_pConfig->m_JoystickX), GetJoystickAxisValue(m_pConfig->m_JoystickY)); const float Len = length(RawJoystickPos); const float DeadZone = m_pConfig->m_JoystickTolerance/50.0f; - const float JoystickSens = m_pConfig->m_JoystickSens/100.0f; - if(Len >= DeadZone) // >= to allow max tolerance value + if(Len > DeadZone) { - JoystickPos = RawJoystickPos * (JoystickSens * max(Len - DeadZone, 0.001f) / Len); + const float Factor = 0.1f * max((Len - DeadZone) / (1 - DeadZone), 0.001f) / Len; + *pX = RawJoystickPos.x * Factor; + *pY = RawJoystickPos.y * Factor; + return true; } } + return false; +} - const float MouseSens = m_pConfig->m_InpMousesens/100.0f; +bool CInput::MouseRelative(float *pX, float *pY) +{ + if(!m_MouseInputRelative) + return false; - *x = MouseX * MouseSens + JoystickPos.x; - *y = MouseY * MouseSens + JoystickPos.y; + int MouseX = 0, MouseY = 0; + SDL_GetRelativeMouseState(&MouseX, &MouseY); + if (MouseX || MouseY) + { + *pX = MouseX; + *pY = MouseY; + return true; + } + return false; } void CInput::MouseModeAbsolute() diff --git a/src/engine/client/input.h b/src/engine/client/input.h index b6d0dbc8..929d53aa 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -43,7 +43,8 @@ class CInput : public IEngineInput CInput(); ~CInput(); - virtual void Init(); + void Init(); + int Update(); bool KeyIsPressed(int Key) const { return KeyState(Key); } bool KeyPress(int Key, bool CheckCounter) const { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; } @@ -54,15 +55,15 @@ class CInput : public IEngineInput const char* GetJoystickName(); int GetJoystickNumAxes(); float GetJoystickAxisValue(int Axis); + bool JoystickRelative(float *pX, float *pY); - virtual void MouseRelative(float *x, float *y); - virtual void MouseModeAbsolute(); - virtual void MouseModeRelative(); - virtual int MouseDoubleClick(); - virtual const char *GetClipboardText(); - virtual void SetClipboardText(const char *pText); + void MouseModeRelative(); + void MouseModeAbsolute(); + int MouseDoubleClick(); + bool MouseRelative(float *pX, float *pY); - virtual int Update(); + const char *GetClipboardText(); + void SetClipboardText(const char *pText); }; #endif diff --git a/src/engine/input.h b/src/engine/input.h index 118073c5..bfa9bdb2 100644 --- a/src/engine/input.h +++ b/src/engine/input.h @@ -39,6 +39,10 @@ class IInput : public IInterface FLAG_RELEASE=2, FLAG_REPEAT=4, FLAG_TEXT=8, + + CURSOR_NONE = 0, + CURSOR_MOUSE, + CURSOR_JOYSTICK }; // events @@ -53,12 +57,12 @@ class IInput : public IInterface } return m_aInputEvents[Index]; } + virtual void Clear() = 0; // keys virtual bool KeyIsPressed(int Key) const = 0; virtual bool KeyPress(int Key, bool CheckCounter=false) const = 0; const char *KeyName(int Key) const { return (Key >= 0 && Key < g_MaxKeys) ? g_aaKeyStrings[Key] : g_aaKeyStrings[0]; } - virtual void Clear() = 0; // joystick virtual int NumJoysticks() const = 0; @@ -67,15 +71,26 @@ class IInput : public IInterface virtual const char* GetJoystickName() = 0; virtual int GetJoystickNumAxes() = 0; virtual float GetJoystickAxisValue(int Axis) = 0; + virtual bool JoystickRelative(float *pX, float *pY) = 0; // mouse virtual void MouseModeRelative() = 0; virtual void MouseModeAbsolute() = 0; virtual int MouseDoubleClick() = 0; + virtual bool MouseRelative(float *pX, float *pY) = 0; + + // clipboard virtual const char* GetClipboardText() = 0; virtual void SetClipboardText(const char *pText) = 0; - virtual void MouseRelative(float *x, float *y) = 0; + int CursorRelative(float *pX, float *pY) + { + if (MouseRelative(pX, pY)) + return CURSOR_MOUSE; + if (JoystickRelative(pX, pY)) + return CURSOR_JOYSTICK; + return CURSOR_NONE; + } }; diff --git a/src/game/client/component.h b/src/game/client/component.h index c8349314..6ac9817c 100644 --- a/src/game/client/component.h +++ b/src/game/client/component.h @@ -43,7 +43,7 @@ class CComponent virtual void OnRelease() {}; virtual void OnMapLoad() {}; virtual void OnMessage(int Msg, void *pRawMsg) {} - virtual bool OnMouseMove(float x, float y) { return false; } + virtual bool OnCursorMove(float x, float y, int CursorType) { return false; } virtual bool OnInput(IInput::CEvent e) { return false; } }; diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 60046c3e..02644816 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -207,13 +207,23 @@ void CControls::OnRender() m_TargetPos = m_MousePos; } -bool CControls::OnMouseMove(float x, float y) +bool CControls::OnCursorMove(float x, float y, int CursorType) { if(m_pClient->IsWorldPaused() || (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) return false; - m_MousePos += vec2(x, y); // TODO: ugly + float Factor = 1.0f; + switch(CursorType) + { + case IInput::CURSOR_MOUSE: + Factor = Config()->m_InpMousesens/100.0f; + break; + case IInput::CURSOR_JOYSTICK: + Factor = Config()->m_JoystickSens/100.0f; + break; + } + m_MousePos += vec2(x, y) * Factor; return true; } diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h index aefc850c..172403b2 100644 --- a/src/game/client/components/controls.h +++ b/src/game/client/components/controls.h @@ -22,7 +22,7 @@ class CControls : public CComponent virtual void OnRelease(); virtual void OnRender(); virtual void OnMessage(int MsgType, void *pRawMsg); - virtual bool OnMouseMove(float x, float y); + virtual bool OnCursorMove(float x, float y, int CursorType); virtual void OnConsoleInit(); virtual void OnPlayerDeath(); diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index ddff228e..4fbf2081 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -48,13 +48,13 @@ void CEmoticon::OnMessage(int MsgType, void *pRawMsg) { } -bool CEmoticon::OnMouseMove(float x, float y) +bool CEmoticon::OnCursorMove(float x, float y, int CursorType) { if(!m_Active) return false; - UI()->ConvertMouseMove(&x, &y); - m_SelectorMouse += vec2(x,y); + UI()->ConvertCursorMove(&x, &y, CursorType); + m_SelectorMouse += vec2(x, y); return true; } diff --git a/src/game/client/components/emoticon.h b/src/game/client/components/emoticon.h index 37bc8372..913e914e 100644 --- a/src/game/client/components/emoticon.h +++ b/src/game/client/components/emoticon.h @@ -26,7 +26,7 @@ class CEmoticon : public CComponent virtual void OnRender(); virtual void OnRelease(); virtual void OnMessage(int MsgType, void *pRawMsg); - virtual bool OnMouseMove(float x, float y); + virtual bool OnCursorMove(float x, float y, int CursorType); void Emote(int Emoticon); }; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0e3ccbaa..4911fcb0 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -2190,7 +2190,7 @@ void CMenus::OnReset() { } -bool CMenus::OnMouseMove(float x, float y) +bool CMenus::OnCursorMove(float x, float y, int CursorType) { m_LastInput = time_get(); @@ -2200,7 +2200,7 @@ bool CMenus::OnMouseMove(float x, float y) // prev mouse position m_PrevMousePos = m_MousePos; - UI()->ConvertMouseMove(&x, &y); + UI()->ConvertCursorMove(&x, &y, CursorType); m_MousePos.x += x; m_MousePos.y += y; if(m_MousePos.x < 0) m_MousePos.x = 0; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index a83fc20f..f87b1855 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -901,6 +901,6 @@ class CMenus : public CComponent virtual void OnReset(); virtual void OnRender(); virtual bool OnInput(IInput::CEvent Event); - virtual bool OnMouseMove(float x, float y); + virtual bool OnCursorMove(float x, float y, int CursorType); }; #endif diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index a19c3234..b1fb130b 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -168,12 +168,12 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) { NumOptions++; // joystick selection } - NumOptions += 2; // sensitivity & tolerance + NumOptions += 3; // ingame sens, ui sens, tolerance NumOptions += m_pClient->Input()->GetJoystickNumAxes(); // axis selection } - float ButtonHeight = 20.0f; - float Spacing = 2.0f; - float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spacing+Spacing; + const float ButtonHeight = 20.0f; + const float Spacing = 2.0f; + const float BackgroundHeight = NumOptions*(ButtonHeight+Spacing)+Spacing; View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); @@ -206,7 +206,11 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->m_JoystickSens, &Config()->m_JoystickSens, &Button, Localize("Joystick sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_JoystickSens, &Config()->m_JoystickSens, &Button, Localize("Ingame joystick sens."), 1, 500, &LogarithmicScrollbarScale); + + View.HSplitTop(Spacing, 0, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + DoScrollbarOption(&Config()->m_UiJoystickSens, &Config()->m_UiJoystickSens, &Button, Localize("Menu/Editor joystick sens."), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); diff --git a/src/game/client/components/spectator.cpp b/src/game/client/components/spectator.cpp index b90a0fc3..3c1ce10b 100644 --- a/src/game/client/components/spectator.cpp +++ b/src/game/client/components/spectator.cpp @@ -128,13 +128,13 @@ void CSpectator::OnConsoleInit() Console()->Register("spectate_previous", "", CFGFLAG_CLIENT, ConSpectatePrevious, this, "Spectate the previous player"); } -bool CSpectator::OnMouseMove(float x, float y) +bool CSpectator::OnCursorMove(float x, float y, int CursorType) { if(!m_Active) return false; - UI()->ConvertMouseMove(&x, &y); - m_SelectorMouse += vec2(x,y); + UI()->ConvertCursorMove(&x, &y, CursorType); + m_SelectorMouse += vec2(x, y); return true; } diff --git a/src/game/client/components/spectator.h b/src/game/client/components/spectator.h index 763f872e..5aad68a7 100644 --- a/src/game/client/components/spectator.h +++ b/src/game/client/components/spectator.h @@ -32,7 +32,7 @@ class CSpectator : public CComponent CSpectator(); virtual void OnConsoleInit(); - virtual bool OnMouseMove(float x, float y); + virtual bool OnCursorMove(float x, float y, int CursorType); virtual void OnRender(); virtual void OnRelease(); virtual void OnReset(); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 99d9d751..81547b48 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -420,14 +420,14 @@ void CGameClient::OnInit() void CGameClient::OnUpdate() { - // handle mouse movement + // handle mouse and joystick movement, prefer mouse movement float x = 0.0f, y = 0.0f; - Input()->MouseRelative(&x, &y); - if(x != 0.0f || y != 0.0f) + int CursorType = Input()->CursorRelative(&x, &y); + if(CursorType != IInput::CURSOR_NONE) { for(int h = 0; h < m_Input.m_Num; h++) { - if(m_Input.m_paComponents[h]->OnMouseMove(x, y)) + if(m_Input.m_paComponents[h]->OnCursorMove(x, y, CursorType)) break; } } diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 0b6ca269..1a164859 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "ui.h" /******************************************************** @@ -67,11 +68,20 @@ bool CUI::MouseInsideClip() const return !IsClipped() || MouseInside(ClipArea()); } -void CUI::ConvertMouseMove(float *x, float *y) const +void CUI::ConvertCursorMove(float *pX, float *pY, int CursorType) const { - const float Fac = m_pConfig->m_UiMousesens/float(m_pConfig->m_InpMousesens); - *x = *x * Fac; - *y = *y * Fac; + float Factor = 1.0f; + switch(CursorType) + { + case IInput::CURSOR_MOUSE: + Factor = Config()->m_UiMousesens/100.0f; + break; + case IInput::CURSOR_JOYSTICK: + Factor = Config()->m_UiJoystickSens/100.0f; + break; + } + *pX *= Factor; + *pY *= Factor; } CUIRect *CUI::Screen() diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 58f908a0..1ae68706 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -117,7 +117,7 @@ class CUI bool MouseInside(const CUIRect *pRect) const; bool MouseInsideClip() const; - void ConvertMouseMove(float *x, float *y) const; + void ConvertCursorMove(float *pX, float *pY, int CursorType) const; CUIRect *Screen(); float PixelSize(); diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 7ade6bad..61fc1c6d 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4641,12 +4641,13 @@ void CEditor::UpdateAndRender() ms_pUiGotContext = 0; UI()->StartCheck(); - // handle mouse movement - float mx, my, Mwx, Mwy, Mdx, Mdy; - float rx = 0.0f, ry = 0.0f; + // handle cursor movement { - Input()->MouseRelative(&rx, &ry); - UI()->ConvertMouseMove(&rx, &ry); + float mx, my, Mwx, Mwy, Mdx, Mdy; + float rx = 0.0f, ry = 0.0f; + int CursorType = Input()->CursorRelative(&rx, &ry); + UI()->ConvertCursorMove(&rx, &ry, CursorType); + m_MouseDeltaX = rx; m_MouseDeltaY = ry; diff --git a/src/game/variables.h b/src/game/variables.h index ee8e262c..b45d1b15 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -84,6 +84,7 @@ MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 5, CFGFLAG_CLIENT|CFGFL MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (Internet page)") MACRO_CONFIG_STR(UiServerAddressLan, ui_server_address_lan, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address (LAN page)") MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor") +MACRO_CONFIG_INT(UiJoystickSens, ui_joystick_sens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick sensitivity for menus/editor") MACRO_CONFIG_INT(UiAutoswitchInfotab, ui_autoswitch_infotab, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Switch to the info tab when clicking on a server") MACRO_CONFIG_INT(UiWideview, ui_wideview, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Extended menus GUI") From 2a9bc5f4cc4a81f7c6e6e8d696a82232814b48ad Mon Sep 17 00:00:00 2001 From: Sonix- Date: Sat, 15 Aug 2020 12:13:59 +0200 Subject: [PATCH 387/479] Add original light eyes to bluekitty and limekitty also fix limedog eyes --- datasrc/skins/bluekitty.json | 73 ++++++++++++++++++---------------- datasrc/skins/limedog.json | 76 ++++++++++++++++++------------------ datasrc/skins/limekitty.json | 73 ++++++++++++++++++---------------- 3 files changed, 117 insertions(+), 105 deletions(-) diff --git a/datasrc/skins/bluekitty.json b/datasrc/skins/bluekitty.json index 9d9bf9a3..6951315b 100644 --- a/datasrc/skins/bluekitty.json +++ b/datasrc/skins/bluekitty.json @@ -1,35 +1,40 @@ -{"skin": { - "body": { - "filename": "kitty", - "custom_colors": "true", - "hue": 132, - "sat": 118, - "lgt": 184 - }, - "marking": { - "filename": "whisker", - "custom_colors": "true", - "hue": 130, - "sat": 109, - "lgt": 219, - "alp": 255 - }, - "hands": { - "filename": "standard", - "custom_colors": "true", - "hue": 120, - "sat": 82, - "lgt": 235 - }, - "feet": { - "filename": "standard", - "custom_colors": "true", - "hue": 120, - "sat": 82, - "lgt": 235 - }, - "eyes": { - "filename": "standard", - "custom_colors": "false" - }} +{ + "skin": { + "body": { + "filename": "kitty", + "custom_colors": true, + "hue": 132, + "sat": 118, + "lgt": 184 + }, + "marking": { + "filename": "whisker", + "custom_colors": true, + "hue": 130, + "sat": 109, + "lgt": 219, + "alp": 255 + }, + "hands": { + "filename": "standard", + "custom_colors": true, + "hue": 120, + "sat": 82, + "lgt": 235 + }, + "feet": { + "filename": "standard", + "custom_colors": true, + "hue": 135, + "sat": 82, + "lgt": 233 + }, + "eyes": { + "filename": "negative", + "custom_colors": true, + "hue": 137, + "sat": 255, + "lgt": 0 + } + } } diff --git a/datasrc/skins/limedog.json b/datasrc/skins/limedog.json index b3cc9f89..e9e77279 100644 --- a/datasrc/skins/limedog.json +++ b/datasrc/skins/limedog.json @@ -1,38 +1,40 @@ -{"skin": { - "body": { - "filename": "dog", - "custom_colors": "true", - "hue": 36, - "sat": 185, - "lgt": 169 - }, - "marking": { - "filename": "whisker", - "custom_colors": "true", - "hue": 0, - "sat": 153, - "lgt": 255, - "alp": 255 - }, - "hands": { - "filename": "standard", - "custom_colors": "true", - "hue": 12, - "sat": 178, - "lgt": 136 - }, - "feet": { - "filename": "standard", - "custom_colors": "true", - "hue": 14, - "sat": 205, - "lgt": 112 - }, - "eyes": { - "filename": "negative", - "custom_colors": "true", - "hue": 19, - "sat": 255, - "lgt": 25 - }} +{ + "skin": { + "body": { + "filename": "dog", + "custom_colors": true, + "hue": 36, + "sat": 185, + "lgt": 169 + }, + "marking": { + "filename": "whisker", + "custom_colors": true, + "hue": 0, + "sat": 153, + "lgt": 255, + "alp": 255 + }, + "hands": { + "filename": "standard", + "custom_colors": true, + "hue": 12, + "sat": 178, + "lgt": 136 + }, + "feet": { + "filename": "standard", + "custom_colors": true, + "hue": 14, + "sat": 205, + "lgt": 112 + }, + "eyes": { + "filename": "negative", + "custom_colors": true, + "hue": 18, + "sat": 180, + "lgt": 118 + } + } } diff --git a/datasrc/skins/limekitty.json b/datasrc/skins/limekitty.json index c658fd1c..ae66e4ff 100644 --- a/datasrc/skins/limekitty.json +++ b/datasrc/skins/limekitty.json @@ -1,35 +1,40 @@ -{"skin": { - "body": { - "filename": "kitty", - "custom_colors": "true", - "hue": 70, - "sat": 98, - "lgt": 195 - }, - "marking": { - "filename": "whisker", - "custom_colors": "true", - "hue": 69, - "sat": 98, - "lgt": 224, - "alp": 255 - }, - "hands": { - "filename": "standard", - "custom_colors": "true", - "hue": 58, - "sat": 104, - "lgt": 239 - }, - "feet": { - "filename": "standard", - "custom_colors": "true", - "hue": 58, - "sat": 104, - "lgt": 239 - }, - "eyes": { - "filename": "standard", - "custom_colors": "false" - }} +{ + "skin": { + "body": { + "filename": "kitty", + "custom_colors": true, + "hue": 70, + "sat": 98, + "lgt": 195 + }, + "marking": { + "filename": "whisker", + "custom_colors": true, + "hue": 69, + "sat": 98, + "lgt": 224, + "alp": 255 + }, + "hands": { + "filename": "standard", + "custom_colors": true, + "hue": 58, + "sat": 104, + "lgt": 239 + }, + "feet": { + "filename": "standard", + "custom_colors": true, + "hue": 58, + "sat": 104, + "lgt": 239 + }, + "eyes": { + "filename": "negative", + "custom_colors": true, + "hue": 125, + "sat": 250, + "lgt": 0 + } + } } From 4418ba055085e1f480d5e916956d282757b90eaa Mon Sep 17 00:00:00 2001 From: Redix Date: Fri, 21 Aug 2020 18:12:29 +0200 Subject: [PATCH 388/479] Do not render invisible elements in scrollregions --- src/game/client/components/menus_browser.cpp | 19 ++++++++++++------- src/game/client/components/menus_ingame.cpp | 3 +++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 88608055..ad72b53b 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1627,6 +1627,15 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) { View.HSplitTop((i == FRIEND_OFF ? 8.0f : 20.0f) + HeaderHeight, &Rect, &View); s_ScrollRegion.AddRect(Rect); + if(f < m_lFriendList[i].size()-1) + { + CUIRect Space; + View.HSplitTop(SpacingH, &Space, &View); + s_ScrollRegion.AddRect(Space); + } + if(s_ScrollRegion.IsRectClipped(Rect)) + continue; + const bool Inside = UI()->MouseInside(&Rect); bool ButtonResult = UI()->DoButtonLogic(&(s_FriendButtons[ButtonId%20]), &Rect); RenderTools()->DrawUIRect(&Rect, vec4(s_ListColor[i].r, s_ListColor[i].g, s_ListColor[i].b, Inside ? 0.5f : 0.3f), CUI::CORNER_ALL, 5.0f); @@ -1673,13 +1682,6 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) Client()->Connect(GetServerBrowserAddress()); } } - - if(f < m_lFriendList[i].size()-1) - { - CUIRect Space; - View.HSplitTop(SpacingH, &Space, &View); - s_ScrollRegion.AddRect(Space); - } } } @@ -2208,6 +2210,9 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); } + if(s_ScrollRegion.IsRectClipped(Name)) + continue; + RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); // friend diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index dc9080f4..8f2c62cf 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -281,6 +281,9 @@ void CMenus::RenderPlayers(CUIRect MainView) MainView.HSplitTop(ButtonHeight, &Row, &MainView); s_ScrollRegion.AddRect(Row); + if(s_ScrollRegion.IsRectClipped(Row)) + continue; + if(Count++ % 2 == 0) RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); From d0b1dd8e7d6fa61d51d918697ad2f383a1ac4d15 Mon Sep 17 00:00:00 2001 From: patiga Date: Tue, 19 May 2020 11:29:35 +0200 Subject: [PATCH 389/479] boundary check on curve type label in editor, avoids client crash --- src/game/editor/editor.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 7ade6bad..92550e29 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3755,8 +3755,11 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) const char *paTypeName[] = { "N", "L", "S", "F", "M", "B" }; - - if(DoButton_Editor(pID, paTypeName[pEnvelope->m_lPoints[i].m_Curvetype], 0, &v, 0, "Switch curve type")) + const char *pTypeName = "Invalid"; + if(0 <= pEnvelope->m_lPoints[i].m_Curvetype + && pEnvelope->m_lPoints[i].m_Curvetype < (int)(sizeof(paTypeName)/sizeof(const char *))) + pTypeName = paTypeName[pEnvelope->m_lPoints[i].m_Curvetype]; + if(DoButton_Editor(pID, pTypeName, 0, &v, 0, "Switch curve type")) pEnvelope->m_lPoints[i].m_Curvetype = (pEnvelope->m_lPoints[i].m_Curvetype+1)%NUM_CURVETYPES; } } From dd027d665f2fca7fad19f1341e888b854e064dab Mon Sep 17 00:00:00 2001 From: patiga Date: Sat, 22 Aug 2020 14:47:19 +0200 Subject: [PATCH 390/479] replace error tag --- src/game/editor/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 92550e29..fada1ad6 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3755,7 +3755,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) const char *paTypeName[] = { "N", "L", "S", "F", "M", "B" }; - const char *pTypeName = "Invalid"; + const char *pTypeName = "!?"; if(0 <= pEnvelope->m_lPoints[i].m_Curvetype && pEnvelope->m_lPoints[i].m_Curvetype < (int)(sizeof(paTypeName)/sizeof(const char *))) pTypeName = paTypeName[pEnvelope->m_lPoints[i].m_Curvetype]; From ad7bac06b4ef7590a3a2b6965cf281923b7fdb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 22 Aug 2020 22:31:47 +0200 Subject: [PATCH 391/479] add 'auto' theme based on season --- src/base/system.c | 30 +++ src/base/system.h | 20 +- src/game/client/components/maplayers.cpp | 247 ++++++++++-------- src/game/client/components/maplayers.h | 2 + src/game/client/components/menus_settings.cpp | 118 +++++---- src/game/variables.h | 2 +- 6 files changed, 249 insertions(+), 170 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 91985b5c..71d0f4fc 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1871,6 +1871,36 @@ int time_houroftheday() return time_info->tm_hour; } +int time_season() +{ + time_t time_data; + struct tm *time_info; + + time(&time_data); + time_info = localtime(&time_data); + + switch(time_info->tm_mon) + { + case 11: + case 0: + case 1: + return SEASON_WINTER; + case 2: + case 3: + case 4: + return SEASON_SPRING; + case 5: + case 6: + case 7: + return SEASON_SUMMER; + case 8: + case 9: + case 10: + return SEASON_AUTUMN; + } + return SEASON_SPRING; // should never happen +} + int time_isxmasday() { time_t time_data; diff --git a/src/base/system.h b/src/base/system.h index 82511411..49f1fd62 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -539,13 +539,31 @@ int time_timestamp(); /* Function: time_houroftheday - Retrives the hours since midnight (0..23) + Retrieves the hours since midnight (0..23) Returns: The current hour of the day */ int time_houroftheday(); + +enum +{ + SEASON_SPRING = 0, + SEASON_SUMMER, + SEASON_AUTUMN, + SEASON_WINTER +}; + +/* + Function: time_season + Retrieves the current season of the year. + + Returns: + one of the SEASON_* enum literals +*/ +int time_season(); + /* Function: time_isxmasday Checks if it's xmas diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 583bafd8..24a8a4c3 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -19,9 +19,9 @@ #include "menus.h" #include "maplayers.h" -CMapLayers::CMapLayers(int t) +CMapLayers::CMapLayers(int Type) { - m_Type = t; + m_Type = Type; m_CurrentLocalTick = 0; m_LastLocalTick = 0; m_EnvelopeUpdate = false; @@ -38,28 +38,50 @@ void CMapLayers::OnStateChange(int NewState, int OldState) void CMapLayers::LoadBackgroundMap() { - int HourOfTheDay = time_houroftheday(); + const char *pMenuMap = Config()->m_ClMenuMap; + if(str_comp(pMenuMap, "auto") == 0) + { + switch(time_season()) + { + case SEASON_SPRING: + pMenuMap = "heavens"; + break; + case SEASON_SUMMER: + pMenuMap = "jungle"; + break; + case SEASON_AUTUMN: + pMenuMap = "autumn"; + break; + case SEASON_WINTER: + pMenuMap = "winter"; + break; + } + } + + const int HourOfTheDay = time_houroftheday(); + const bool IsDaytime = HourOfTheDay >= 6 && HourOfTheDay < 18; + char aBuf[128]; // check for the appropriate day/night map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", pMenuMap, IsDaytime ? "day" : "night"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on generic map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", Config()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", pMenuMap); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { // fall back on day/night alternative map - str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", Config()->m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day"); + str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", pMenuMap, IsDaytime ? "night" : "day"); if(!m_pMenuMap->Load(aBuf, m_pClient->Storage())) { - str_format(aBuf, sizeof(aBuf), "map '%s' not found", Config()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "map '%s' not found", pMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); return; } } } - str_format(aBuf, sizeof(aBuf), "loaded map '%s'", Config()->m_ClMenuMap); + str_format(aBuf, sizeof(aBuf), "loaded map '%s'", pMenuMap); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); m_pMenuLayers->Init(Kernel(), m_pMenuMap); @@ -91,113 +113,15 @@ void CMapLayers::OnInit() m_pEggTiles = 0; } -static void PlaceEggDoodads(int LayerWidth, int LayerHeight, CTile* aOutTiles, CTile* aGameLayerTiles, int ItemWidth, int ItemHeight, const int* aImageTileID, int ImageTileIDCount, int Freq) -{ - for(int y = 0; y < LayerHeight-ItemHeight; y++) - { - for(int x = 0; x < LayerWidth-ItemWidth; x++) - { - bool Overlap = false; - bool ObstructedByWall = false; - bool HasGround = true; - - for(int iy = 0; iy < ItemHeight; iy++) - { - for(int ix = 0; ix < ItemWidth; ix++) - { - int Tid = (y+iy) * LayerWidth + (x+ix); - int DownTid = (y+iy+1) * LayerWidth + (x+ix); - - if(aOutTiles[Tid].m_Index != 0) - { - Overlap = true; - break; - } - - if(aGameLayerTiles[Tid].m_Index == 1) - { - ObstructedByWall = true; - break; - } - - if(iy == ItemHeight-1 && aGameLayerTiles[DownTid].m_Index != 1) - { - HasGround = false; - break; - } - } - } - - if(!Overlap && !ObstructedByWall && HasGround && random_int()%Freq == 0) - { - const int BaskerStartID = aImageTileID[random_int()%ImageTileIDCount]; - - for(int iy = 0; iy < ItemHeight; iy++) - { - for(int ix = 0; ix < ItemWidth; ix++) - { - int Tid = (y+iy) * LayerWidth + (x+ix); - aOutTiles[Tid].m_Index = BaskerStartID + iy * 16 + ix; - } - } - } - } - } -} - void CMapLayers::OnMapLoad() { if(Layers()) + { LoadEnvPoints(Layers(), m_lEnvPoints); - // easter time, place eggs - if(m_pClient->IsEaster()) - { - CMapItemLayerTilemap* pGameLayer = Layers()->GameLayer(); - if(m_pEggTiles) - mem_free(m_pEggTiles); - - m_EggLayerWidth = pGameLayer->m_Width; - m_EggLayerHeight = pGameLayer->m_Height; - m_pEggTiles = (CTile*)mem_alloc(sizeof(CTile) * m_EggLayerWidth * m_EggLayerHeight,1); - mem_zero(m_pEggTiles, sizeof(CTile) * m_EggLayerWidth * m_EggLayerHeight); - CTile* aGameLayerTiles = (CTile*)Layers()->Map()->GetData(pGameLayer->m_Data); - - // first pass: baskets - static const int s_aBasketIDs[] = { - 38, - 86 - }; - - static const int s_BasketCount = sizeof(s_aBasketIDs)/sizeof(s_aBasketIDs[0]); - PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 3, 2, s_aBasketIDs, s_BasketCount, 250); - - // second pass: double eggs - static const int s_aDoubleEggIDs[] = { - 9, - 25, - 41, - 57, - 73, - 89 - }; - - static const int s_DoubleEggCount = sizeof(s_aDoubleEggIDs)/sizeof(s_aDoubleEggIDs[0]); - PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 2, 1, s_aDoubleEggIDs, s_DoubleEggCount, 100); - - // third pass: eggs - static const int s_aEggIDs[] = { - 1, 2, 3, 4, 5, - 17, 18, 19, 20, - 33, 34, 35, 36, - 49, 50, 52, - 65, 66, - 82, - 98 - }; - - static const int s_EggCount = sizeof(s_aEggIDs)/sizeof(s_aEggIDs[0]); - PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 1, 1, s_aEggIDs, s_EggCount, 30); + // easter time, place eggs + if(m_pClient->IsEaster()) + PlaceEasterEggs(Layers()); } } @@ -535,3 +459,106 @@ void CMapLayers::BackgroundMapUpdate() LoadBackgroundMap(); } } + +static void PlaceEggDoodads(int LayerWidth, int LayerHeight, CTile* aOutTiles, CTile* aGameLayerTiles, int ItemWidth, int ItemHeight, const int* aImageTileID, int ImageTileIDCount, int Freq) +{ + for(int y = 0; y < LayerHeight-ItemHeight; y++) + { + for(int x = 0; x < LayerWidth-ItemWidth; x++) + { + bool Overlap = false; + bool ObstructedByWall = false; + bool HasGround = true; + + for(int iy = 0; iy < ItemHeight; iy++) + { + for(int ix = 0; ix < ItemWidth; ix++) + { + int Tid = (y+iy) * LayerWidth + (x+ix); + int DownTid = (y+iy+1) * LayerWidth + (x+ix); + + if(aOutTiles[Tid].m_Index != 0) + { + Overlap = true; + break; + } + + if(aGameLayerTiles[Tid].m_Index == 1) + { + ObstructedByWall = true; + break; + } + + if(iy == ItemHeight-1 && aGameLayerTiles[DownTid].m_Index != 1) + { + HasGround = false; + break; + } + } + } + + if(!Overlap && !ObstructedByWall && HasGround && random_int()%Freq == 0) + { + const int BaskerStartID = aImageTileID[random_int()%ImageTileIDCount]; + + for(int iy = 0; iy < ItemHeight; iy++) + { + for(int ix = 0; ix < ItemWidth; ix++) + { + int Tid = (y+iy) * LayerWidth + (x+ix); + aOutTiles[Tid].m_Index = BaskerStartID + iy * 16 + ix; + } + } + } + } + } +} + +void CMapLayers::PlaceEasterEggs(const CLayers *pLayers) +{ + CMapItemLayerTilemap* pGameLayer = pLayers->GameLayer(); + if(m_pEggTiles) + mem_free(m_pEggTiles); + + m_EggLayerWidth = pGameLayer->m_Width; + m_EggLayerHeight = pGameLayer->m_Height; + m_pEggTiles = (CTile*)mem_alloc(sizeof(CTile) * m_EggLayerWidth * m_EggLayerHeight,1); + mem_zero(m_pEggTiles, sizeof(CTile) * m_EggLayerWidth * m_EggLayerHeight); + CTile* aGameLayerTiles = (CTile*)pLayers->Map()->GetData(pGameLayer->m_Data); + + // first pass: baskets + static const int s_aBasketIDs[] = { + 38, + 86 + }; + + static const int s_BasketCount = sizeof(s_aBasketIDs)/sizeof(s_aBasketIDs[0]); + PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 3, 2, s_aBasketIDs, s_BasketCount, 250); + + // second pass: double eggs + static const int s_aDoubleEggIDs[] = { + 9, + 25, + 41, + 57, + 73, + 89 + }; + + static const int s_DoubleEggCount = sizeof(s_aDoubleEggIDs)/sizeof(s_aDoubleEggIDs[0]); + PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 2, 1, s_aDoubleEggIDs, s_DoubleEggCount, 100); + + // third pass: eggs + static const int s_aEggIDs[] = { + 1, 2, 3, 4, 5, + 17, 18, 19, 20, + 33, 34, 35, 36, + 49, 50, 52, + 65, 66, + 82, + 98 + }; + + static const int s_EggCount = sizeof(s_aEggIDs)/sizeof(s_aEggIDs[0]); + PlaceEggDoodads(m_EggLayerWidth, m_EggLayerHeight, m_pEggTiles, aGameLayerTiles, 1, 1, s_aEggIDs, s_EggCount, 30); +} diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 9bee0fc3..46f94f83 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -28,6 +28,8 @@ class CMapLayers : public CComponent void LoadEnvPoints(const CLayers *pLayers, array& lEnvPoints); void LoadBackgroundMap(); + void PlaceEasterEggs(const CLayers *pLayers); + public: enum { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index bb3fe51d..4585027d 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -583,7 +583,8 @@ int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser) else str_copy(aThemeName, aFullName, sizeof(aThemeName)); - if(str_comp(aThemeName, "none") == 0) // "none" is reserved, disallowed for maps + // "none" and "auto" are reserved, disallowed for maps + if(str_comp(aThemeName, "none") == 0 || str_comp(aThemeName, "auto") == 0) return 0; // try to edit an existing theme @@ -754,7 +755,6 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) { - static int s_SelectedTheme = -1; static CListBox s_ListBox; if(m_lThemes.size() == 0) // not loaded yet @@ -762,85 +762,87 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) if(!Config()->m_ClShowMenuMap) str_copy(Config()->m_ClMenuMap, "", sizeof(Config()->m_ClMenuMap)); // cl_menu_map otherwise resets to default on loading m_lThemes.add(CTheme("", false, false)); // no theme + m_lThemes.add(CTheme("auto", false, false)); // auto theme Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeScan, (CMenus*)this); Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeIconScan, (CMenus*)this); - for(int i = 0; i < m_lThemes.size(); i++) - if(str_comp(m_lThemes[i].m_Name, Config()->m_ClMenuMap) == 0) - { - s_SelectedTheme = i; - break; - } } - int OldSelected = s_SelectedTheme; + int SelectedTheme = -1; + for(int i = 0; i < m_lThemes.size(); i++) + if(str_comp(m_lThemes[i].m_Name, Config()->m_ClMenuMap) == 0) + { + SelectedTheme = i; + break; + } + const int OldSelected = SelectedTheme; if(Header) s_ListBox.DoHeader(&MainView, Localize("Theme"), GetListHeaderHeight()); + bool IsActive = m_ActiveListBox == ACTLB_THEME; - s_ListBox.DoStart(20.0f, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header, &IsActive); + s_ListBox.DoStart(20.0f, m_lThemes.size(), 1, SelectedTheme, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = m_lThemes.all(); !r.empty(); r.pop_front()) { - CListboxItem Item = s_ListBox.DoNextItem(&r.front(), s_SelectedTheme != -1 && !str_comp(m_lThemes[s_SelectedTheme].m_Name, r.front().m_Name), &IsActive); + const CTheme& Theme = r.front(); + CListboxItem Item = s_ListBox.DoNextItem(&Theme, SelectedTheme == (&Theme-m_lThemes.base_ptr()), &IsActive); if(IsActive) m_ActiveListBox = ACTLB_THEME; - if(Item.m_Visible) - { - CUIRect Rect; - Item.m_Rect.VSplitLeft(Item.m_Rect.h*2.0f, &Rect, &Item.m_Rect); - Rect.VMargin(6.0f, &Rect); - Rect.HMargin(3.0f, &Rect); - vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); + if(!Item.m_Visible) + continue; - // draw icon if it exists - if(r.front().m_IconTexture.IsValid()) - { - Graphics()->TextureSet(r.front().m_IconTexture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - } + CUIRect Icon; + Item.m_Rect.VSplitLeft(Item.m_Rect.h*2.0f, &Icon, &Item.m_Rect); - char aName[128]; - if(!r.front().m_Name[0]) - str_copy(aName, "(none)", sizeof(aName)); - else if(r.front().m_HasDay && r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); - else if(r.front().m_HasDay && !r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s (day)", r.front().m_Name.cstr()); - else if(!r.front().m_HasDay && r.front().m_HasNight) - str_format(aName, sizeof(aName), "%s (night)", r.front().m_Name.cstr()); - else // generic - str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr()); + // draw icon if it exists + if(Theme.m_IconTexture.IsValid()) + { + Icon.VMargin(6.0f, &Icon); + Icon.HMargin(3.0f, &Icon); + Graphics()->TextureSet(Theme.m_IconTexture); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + IGraphics::CQuadItem QuadItem(Icon.x, Icon.y, Icon.w, Icon.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } - if(Item.m_Selected) - { - TextRender()->TextColor(CUI::ms_HighlightTextColor); - TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); - } - Item.m_Rect.y += 2.0f; - UI()->DoLabel(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - if(Item.m_Selected) - { - TextRender()->TextColor(CUI::ms_DefaultTextColor); - TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); - } + char aName[128]; + if(!Theme.m_Name[0]) + str_copy(aName, "(none)", sizeof(aName)); + else if(str_comp(Theme.m_Name, "auto") == 0) + str_copy(aName, "(automatic)", sizeof(aName)); + else if(Theme.m_HasDay && Theme.m_HasNight) + str_format(aName, sizeof(aName), "%s", Theme.m_Name.cstr()); + else if(Theme.m_HasDay && !Theme.m_HasNight) + str_format(aName, sizeof(aName), "%s (day)", Theme.m_Name.cstr()); + else if(!Theme.m_HasDay && Theme.m_HasNight) + str_format(aName, sizeof(aName), "%s (night)", Theme.m_Name.cstr()); + else // generic + str_format(aName, sizeof(aName), "%s", Theme.m_Name.cstr()); + + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } } - s_SelectedTheme = s_ListBox.DoEnd(); + SelectedTheme = s_ListBox.DoEnd(); - if(OldSelected != s_SelectedTheme) + if(OldSelected != SelectedTheme) { m_ActiveListBox = ACTLB_THEME; - str_copy(Config()->m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(Config()->m_ClMenuMap)); - if(m_lThemes[s_SelectedTheme].m_Name[0]) - Config()->m_ClShowMenuMap = 1; - else - Config()->m_ClShowMenuMap = 0; + str_copy(Config()->m_ClMenuMap, m_lThemes[SelectedTheme].m_Name, sizeof(Config()->m_ClMenuMap)); + Config()->m_ClShowMenuMap = m_lThemes[SelectedTheme].m_Name[0] ? 1 : 0; m_pClient->m_pMapLayersBackGround->BackgroundMapUpdate(); } } diff --git a/src/game/variables.h b/src/game/variables.h index b45d1b15..6c6e36d1 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -90,7 +90,7 @@ MACRO_CONFIG_INT(UiWideview, ui_wideview, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping") -MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 64, "heavens", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Background map in the menu") +MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 64, "auto", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Background map in the menu, auto = automatic based on season") MACRO_CONFIG_INT(ClShowMenuMap, cl_show_menu_map, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Display background map in the menu") MACRO_CONFIG_INT(ClMenuAlpha, cl_menu_alpha, 25, 0, 75, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Transparency of the menu background") MACRO_CONFIG_INT(ClRotationRadius, cl_rotation_radius, 30, 1, 500, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Menu camera rotation radius") From e5d592eb3228177a0ce65d9b89dc4f50c42e1aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 8 May 2020 11:11:11 +0200 Subject: [PATCH 392/479] add gametype exclusion filter by using '-' as prefix --- src/engine/client/serverbrowser_filter.cpp | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/engine/client/serverbrowser_filter.cpp b/src/engine/client/serverbrowser_filter.cpp index 1f1e69d1..b816f5f7 100644 --- a/src/engine/client/serverbrowser_filter.cpp +++ b/src/engine/client/serverbrowser_filter.cpp @@ -130,20 +130,33 @@ void CServerBrowserFilter::CServerFilter::Filter() { if(m_FilterInfo.m_aGametype[0][0]) { - Filtered = 1; + bool Excluded = false, DoInclude = false, Included = false; for(int Index = 0; Index < CServerFilterInfo::MAX_GAMETYPES; ++Index) { if(!m_FilterInfo.m_aGametype[Index][0]) break; - if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index])) + if(m_FilterInfo.m_aGametype[Index][0] == '-' && m_FilterInfo.m_aGametype[Index][1]) { - Filtered = 0; - break; + if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index]+1)) + { + Excluded = true; + break; + } + } + else + { + DoInclude = true; + if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index])) + { + Included = true; + break; + } } } + Filtered = Excluded || (DoInclude && !Included); } - if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) + if(!Filtered && m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) { Filtered = 1; // match against player country From 0b15ac8c054245c2a6abcc98f1e67b4dd748ce64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 10 May 2020 12:19:17 +0200 Subject: [PATCH 393/479] add red background color for exclusive filter, add padding --- src/game/client/components/menus_browser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index ad72b53b..1881d922 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1888,9 +1888,11 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) { if(FilterInfo.m_aGametype[i][0]) { + const bool IsExclusive = FilterInfo.m_aGametype[i][0] == '-' && FilterInfo.m_aGametype[i][1]; float CurLength = TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + 12.0f; Button.VSplitLeft(CurLength, &Icon, &Button); - RenderTools()->DrawUIRect(&Icon, vec4(0.75, 0.75, 0.75, 0.25f), CUI::CORNER_ALL, 3.0f); + RenderTools()->DrawUIRect(&Icon, IsExclusive ? vec4(0.75f, 0.25f, 0.25f, 0.25f) : vec4(0.75f, 0.75f, 0.75f, 0.25f), CUI::CORNER_ALL, 3.0f); + Icon.VSplitLeft(2.0f, 0, &Icon); UI()->DoLabel(&Icon, FilterInfo.m_aGametype[i], FontSize, CUI::ALIGN_LEFT); Icon.VSplitRight(10.0f, 0, &Icon); if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &Icon)) From 491782e99756f94916429bddc5c161d9b66b5a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 10 May 2020 14:08:56 +0200 Subject: [PATCH 394/479] store gametype exclusion flag separately, plus/minus buttons, refactoring --- src/engine/client/serverbrowser_filter.cpp | 22 ++- src/engine/serverbrowser.h | 1 + src/game/client/components/menus_browser.cpp | 192 ++++++++++++------- 3 files changed, 144 insertions(+), 71 deletions(-) diff --git a/src/engine/client/serverbrowser_filter.cpp b/src/engine/client/serverbrowser_filter.cpp index b816f5f7..b1696709 100644 --- a/src/engine/client/serverbrowser_filter.cpp +++ b/src/engine/client/serverbrowser_filter.cpp @@ -32,7 +32,10 @@ CServerBrowserFilter::CServerFilter::CServerFilter() m_FilterInfo.m_Country = 0; m_FilterInfo.m_ServerLevel = 0; for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { m_FilterInfo.m_aGametype[i][0] = 0; + m_FilterInfo.m_aGametypeExclusive[i] = false; + } m_FilterInfo.m_aAddress[0] = 0; m_NumSortedPlayers = 0; @@ -60,9 +63,15 @@ CServerBrowserFilter::CServerFilter& CServerBrowserFilter::CServerFilter::operat for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) { if(Other.m_FilterInfo.m_aGametype[i][0]) + { str_copy(m_FilterInfo.m_aGametype[i], Other.m_FilterInfo.m_aGametype[i], sizeof(m_FilterInfo.m_aGametype[i])); + m_FilterInfo.m_aGametypeExclusive[i] = Other.m_FilterInfo.m_aGametypeExclusive[i]; + } else + { m_FilterInfo.m_aGametype[i][0] = 0; + m_FilterInfo.m_aGametypeExclusive[i] = false; + } } str_copy(m_FilterInfo.m_aAddress, Other.m_FilterInfo.m_aAddress, sizeof(m_FilterInfo.m_aAddress)); @@ -135,9 +144,9 @@ void CServerBrowserFilter::CServerFilter::Filter() { if(!m_FilterInfo.m_aGametype[Index][0]) break; - if(m_FilterInfo.m_aGametype[Index][0] == '-' && m_FilterInfo.m_aGametype[Index][1]) + if(m_FilterInfo.m_aGametypeExclusive[Index]) { - if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index]+1)) + if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index])) { Excluded = true; break; @@ -386,7 +395,10 @@ int CServerBrowserFilter::AddFilter(const CServerFilterInfo *pFilterInfo) Filter.m_FilterInfo.m_Country = pFilterInfo->m_Country; Filter.m_FilterInfo.m_ServerLevel = pFilterInfo->m_ServerLevel; for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { str_copy(Filter.m_FilterInfo.m_aGametype[i], pFilterInfo->m_aGametype[i], sizeof(Filter.m_FilterInfo.m_aGametype[i])); + Filter.m_FilterInfo.m_aGametypeExclusive[i] = pFilterInfo->m_aGametypeExclusive[i]; + } str_copy(Filter.m_FilterInfo.m_aAddress, pFilterInfo->m_aAddress, sizeof(Filter.m_FilterInfo.m_aAddress)); Filter.m_pSortedServerlist = 0; Filter.m_NumSortedPlayers = 0; @@ -406,7 +418,10 @@ void CServerBrowserFilter::GetFilter(int Index, CServerFilterInfo *pFilterInfo) pFilterInfo->m_Country = pFilter->m_FilterInfo.m_Country; pFilterInfo->m_ServerLevel = pFilter->m_FilterInfo.m_ServerLevel; for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { str_copy(pFilterInfo->m_aGametype[i], pFilter->m_FilterInfo.m_aGametype[i], sizeof(pFilterInfo->m_aGametype[i])); + pFilterInfo->m_aGametypeExclusive[i] = pFilter->m_FilterInfo.m_aGametypeExclusive[i]; + } str_copy(pFilterInfo->m_aAddress, pFilter->m_FilterInfo.m_aAddress, sizeof(pFilterInfo->m_aAddress)); } @@ -418,7 +433,10 @@ void CServerBrowserFilter::SetFilter(int Index, const CServerFilterInfo *pFilter pFilter->m_FilterInfo.m_Country = pFilterInfo->m_Country; pFilter->m_FilterInfo.m_ServerLevel = pFilterInfo->m_ServerLevel; for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { str_copy(pFilter->m_FilterInfo.m_aGametype[i], pFilterInfo->m_aGametype[i], sizeof(pFilter->m_FilterInfo.m_aGametype[i])); + pFilter->m_FilterInfo.m_aGametypeExclusive[i] = pFilterInfo->m_aGametypeExclusive[i]; + } str_copy(pFilter->m_FilterInfo.m_aAddress, pFilterInfo->m_aAddress, sizeof(pFilter->m_FilterInfo.m_aAddress)); pFilter->Sort(); diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index bfe6d81b..3f0c9ebc 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -82,6 +82,7 @@ class CServerFilterInfo int m_Country; int m_ServerLevel; char m_aGametype[MAX_GAMETYPES][16]; + char m_aGametypeExclusive[MAX_GAMETYPES]; char m_aAddress[NETADDR_MAXSTRSIZE]; void ToggleLevel(int Level) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 1881d922..56ff8a68 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -209,12 +209,27 @@ void CMenus::LoadFilters() if(rSubStart["filter_hash"].type == json_integer) FilterInfo.m_SortHash = rSubStart["filter_hash"].u.integer; const json_value &rGametypeEntry = rSubStart["filter_gametype"]; - if(rGametypeEntry.type == json_array) + if(rGametypeEntry.type == json_array) // legacy: all entries are inclusive { for(unsigned j = 0; j < rGametypeEntry.u.array.length && j < CServerFilterInfo::MAX_GAMETYPES; ++j) { if(rGametypeEntry[j].type == json_string) + { str_copy(FilterInfo.m_aGametype[j], rGametypeEntry[j], sizeof(FilterInfo.m_aGametype[j])); + FilterInfo.m_aGametypeExclusive[j] = false; + } + } + } + else if(rGametypeEntry.type == json_object) + { + for(unsigned j = 0; j < rGametypeEntry.u.object.length && j < CServerFilterInfo::MAX_GAMETYPES; ++j) + { + const json_value &rValue = *(rGametypeEntry.u.object.values[j].value); + if(rValue.type == json_boolean) + { + str_copy(FilterInfo.m_aGametype[j], rGametypeEntry.u.object.values[j].name, sizeof(FilterInfo.m_aGametype[j])); + FilterInfo.m_aGametypeExclusive[j] = rValue.u.boolean; + } } } if(rSubStart["filter_ping"].type == json_integer) @@ -294,10 +309,13 @@ void CMenus::SaveFilters() Writer.WriteIntValue(FilterInfo.m_SortHash); Writer.WriteAttribute("filter_gametype"); - Writer.BeginArray(); + Writer.BeginObject(); for(unsigned j = 0; j < CServerFilterInfo::MAX_GAMETYPES && FilterInfo.m_aGametype[j][0]; ++j) - Writer.WriteStrValue(FilterInfo.m_aGametype[j]); - Writer.EndArray(); + { + Writer.WriteAttribute(FilterInfo.m_aGametype[j]); + Writer.WriteBoolValue(FilterInfo.m_aGametypeExclusive[j]); + } + Writer.EndObject(); Writer.WriteAttribute("filter_ping"); Writer.WriteIntValue(FilterInfo.m_Ping); @@ -1864,102 +1882,138 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) UpdateFilter = true; } - ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); + // game types filter + { + ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); - UI()->DoLabel(&Button, Localize("Game types:"), FontSize, CUI::ALIGN_LEFT); - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); - RenderTools()->DrawUIRect(&Button, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 2.0f); - Button.HMargin(2.0f, &Button); - UI()->ClipEnable(&Button); + ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); + UI()->DoLabel(&Button, Localize("Game types:"), FontSize, CUI::ALIGN_LEFT); - float Length = 0.0f; - for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) - { - if(FilterInfo.m_aGametype[i][0]) + ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); + RenderTools()->DrawUIRect(&Button, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 2.0f); + + Button.HMargin(2.0f, &Button); + UI()->ClipEnable(&Button); + + const float Spacing = 2.0f; + const float IconWidth = 10.0f; + + float Length = 0.0f; + for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) { - Length += TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + 14.0f; + if(!FilterInfo.m_aGametype[i][0]) + break; + Length += TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + IconWidth + 2*Spacing; } - } - static float s_ScrollValue = 0.0f; - bool NeedScrollbar = (Button.w - Length) < 0.0f; - Button.x += min(0.0f, Button.w - Length) * s_ScrollValue; - for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) - { - if(FilterInfo.m_aGametype[i][0]) + static float s_ScrollValue = 0.0f; + const bool NeedScrollbar = (Button.w - Length) < 0.0f; + Button.x += min(0.0f, Button.w - Length) * s_ScrollValue; + for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) { - const bool IsExclusive = FilterInfo.m_aGametype[i][0] == '-' && FilterInfo.m_aGametype[i][1]; - float CurLength = TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + 12.0f; - Button.VSplitLeft(CurLength, &Icon, &Button); - RenderTools()->DrawUIRect(&Icon, IsExclusive ? vec4(0.75f, 0.25f, 0.25f, 0.25f) : vec4(0.75f, 0.75f, 0.75f, 0.25f), CUI::CORNER_ALL, 3.0f); - Icon.VSplitLeft(2.0f, 0, &Icon); - UI()->DoLabel(&Icon, FilterInfo.m_aGametype[i], FontSize, CUI::ALIGN_LEFT); - Icon.VSplitRight(10.0f, 0, &Icon); - if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &Icon)) + if(!FilterInfo.m_aGametype[i][0]) + break; + const float ItemLength = TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + IconWidth + Spacing; + CUIRect FilterItem; + Button.VSplitLeft(ItemLength, &FilterItem, &Button); + RenderTools()->DrawUIRect(&FilterItem, FilterInfo.m_aGametypeExclusive[i] ? vec4(0.75f, 0.25f, 0.25f, 0.25f) : vec4(0.75f, 0.75f, 0.75f, 0.25f), CUI::CORNER_ALL, 3.0f); + FilterItem.VSplitLeft(Spacing, 0, &FilterItem); + UI()->DoLabel(&FilterItem, FilterInfo.m_aGametype[i], FontSize, CUI::ALIGN_LEFT); + FilterItem.VSplitRight(IconWidth, 0, &FilterItem); + if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &FilterItem)) { // remove gametype entry if((i == CServerFilterInfo::MAX_GAMETYPES - 1) || !FilterInfo.m_aGametype[i + 1][0]) + { FilterInfo.m_aGametype[i][0] = 0; + FilterInfo.m_aGametypeExclusive[i] = false; + } else { int j = i; for(; j < CServerFilterInfo::MAX_GAMETYPES - 1 && FilterInfo.m_aGametype[j + 1][0]; ++j) + { str_copy(FilterInfo.m_aGametype[j], FilterInfo.m_aGametype[j + 1], sizeof(FilterInfo.m_aGametype[j])); + FilterInfo.m_aGametypeExclusive[j] = FilterInfo.m_aGametypeExclusive[j + 1]; + } FilterInfo.m_aGametype[j][0] = 0; + FilterInfo.m_aGametypeExclusive[j] = false; } UpdateFilter = true; } - Button.VSplitLeft(2.0f, 0, &Button); + Button.VSplitLeft(Spacing, 0, &Button); } - } - UI()->ClipDisable(); + UI()->ClipDisable(); - if(NeedScrollbar) - { - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); - s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Button, s_ScrollValue); - } - else - ServerFilter.HSplitTop(4.f, &Button, &ServerFilter); // Leave some space in between edit boxes - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); + if(NeedScrollbar) + { + ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); + s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Button, s_ScrollValue); + } + else + ServerFilter.HSplitTop(4.f, &Button, &ServerFilter); // Leave some space in between edit boxes - Button.VSplitLeft(60.0f, &Button, &Icon); - ServerFilter.HSplitTop(3.0f, 0, &ServerFilter); - static char s_aGametype[16] = { 0 }; - static float s_OffsetGametype = 0.0f; - Button.VSplitRight(Button.h, &Label, &Button); - DoEditBox(&s_OffsetGametype, &Label, s_aGametype, sizeof(s_aGametype), FontSize, &s_OffsetGametype, false, CUI::CORNER_L); - RenderTools()->DrawUIRect(&Button, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_R, 5.0f); - DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Button); - static CButtonContainer s_AddGametype; - if(s_aGametype[0] && UI()->DoButtonLogic(&s_AddGametype, &Button)) - { - for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + CUIRect ButtonLine; + ServerFilter.HSplitTop(LineSize, &ButtonLine, &ServerFilter); + + CUIRect EditBox, AddIncButton, AddExlButton, ClearButton; + ButtonLine.VSplitRight(40.0f, &ButtonLine, &ClearButton); + ButtonLine.VSplitRight(10.0f, &ButtonLine, 0); + ButtonLine.VSplitRight(ButtonLine.h, &ButtonLine, &AddExlButton); + ButtonLine.VSplitRight(ButtonLine.h, &EditBox, &AddIncButton); + + static char s_aGametype[16] = { 0 }; + static float s_OffsetGametype = 0.0f; + DoEditBox(&s_OffsetGametype, &EditBox, s_aGametype, sizeof(s_aGametype), FontSize, &s_OffsetGametype, false, CUI::CORNER_L); + + static CButtonContainer s_AddInclusiveGametype; + if(DoButton_Menu(&s_AddInclusiveGametype, "+", 0, &AddIncButton, 0, 0) && s_aGametype[0]) { - if(!FilterInfo.m_aGametype[i][0]) + for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) { - str_copy(FilterInfo.m_aGametype[i], s_aGametype, sizeof(FilterInfo.m_aGametype[i])); - UpdateFilter = true; - s_aGametype[0] = 0; - break; + if(!FilterInfo.m_aGametype[i][0]) + { + str_copy(FilterInfo.m_aGametype[i], s_aGametype, sizeof(FilterInfo.m_aGametype[i])); + FilterInfo.m_aGametypeExclusive[i] = false; + UpdateFilter = true; + s_aGametype[0] = 0; + break; + } } } - } - Icon.VSplitLeft(10.0f, 0, &Icon); - Icon.VSplitLeft(40.0f, &Button, 0); - static CButtonContainer s_ClearGametypes; - if(DoButton_MenuTabTop(&s_ClearGametypes, Localize("Clear", "clear gametype filters"), false, &Button)) - { - for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + + static CButtonContainer s_AddExclusiveGametype; + if(DoButton_Menu(&s_AddExclusiveGametype, "-", 0, &AddExlButton, 0, CUI::CORNER_R) && s_aGametype[0]) { - FilterInfo.m_aGametype[i][0] = 0; + for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { + if(!FilterInfo.m_aGametype[i][0]) + { + str_copy(FilterInfo.m_aGametype[i], s_aGametype, sizeof(FilterInfo.m_aGametype[i])); + FilterInfo.m_aGametypeExclusive[i] = true; + UpdateFilter = true; + s_aGametype[0] = 0; + break; + } + } } - UpdateFilter = true; + + static CButtonContainer s_ClearGametypes; + if(DoButton_MenuTabTop(&s_ClearGametypes, Localize("Clear", "clear gametype filters"), false, &ClearButton)) + { + for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i) + { + FilterInfo.m_aGametype[i][0] = 0; + FilterInfo.m_aGametypeExclusive[i] = false; + } + UpdateFilter = true; + } + + ServerFilter.HSplitTop(3.0f, 0, &ServerFilter); } + // ping ServerFilter.HSplitTop(LineSize - 4.f, &Button, &ServerFilter); - { int Value = FilterInfo.m_Ping, Min = 20, Max = 999; From 18b768d9013412bc071002e93563b2d4700a1438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 27 Aug 2020 09:36:12 +0200 Subject: [PATCH 395/479] show positive gametype filters in green --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 56ff8a68..ebd60c0d 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1915,7 +1915,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) const float ItemLength = TextRender()->TextWidth(0, FontSize, FilterInfo.m_aGametype[i], -1, -1.0f) + IconWidth + Spacing; CUIRect FilterItem; Button.VSplitLeft(ItemLength, &FilterItem, &Button); - RenderTools()->DrawUIRect(&FilterItem, FilterInfo.m_aGametypeExclusive[i] ? vec4(0.75f, 0.25f, 0.25f, 0.25f) : vec4(0.75f, 0.75f, 0.75f, 0.25f), CUI::CORNER_ALL, 3.0f); + RenderTools()->DrawUIRect(&FilterItem, FilterInfo.m_aGametypeExclusive[i] ? vec4(0.75f, 0.25f, 0.25f, 0.25f) : vec4(0.25f, 0.75f, 0.25f, 0.25f), CUI::CORNER_ALL, 3.0f); FilterItem.VSplitLeft(Spacing, 0, &FilterItem); UI()->DoLabel(&FilterItem, FilterInfo.m_aGametype[i], FontSize, CUI::ALIGN_LEFT); FilterItem.VSplitRight(IconWidth, 0, &FilterItem); From b2e0529202089dc2e62d99b17387d2f382921be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 31 Aug 2020 17:47:14 +0200 Subject: [PATCH 396/479] fix various server browser UI issues, refactoring --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_browser.cpp | 465 ++++++------------- src/game/client/components/menus_ingame.cpp | 3 +- src/game/client/ui.cpp | 38 +- src/game/client/ui.h | 4 +- 5 files changed, 186 insertions(+), 326 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 62f35d3a..279bf534 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -807,7 +807,7 @@ class CMenus : public CComponent void RenderServerbrowserOverlay(); void RenderFilterHeader(CUIRect View, int FilterIndex); void PopupConfirmRemoveFilter(); - int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected); + int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo); void RenderServerbrowser(CUIRect MainView); static void ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainFriendlistUpdate(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 ebd60c0d..b98a2520 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -427,7 +427,7 @@ void CMenus::SetOverlay(int Type, float x, float y, const void *pData) } // 1 = browser entry click, 2 = server info click -int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected) +int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo) { // logic int ReturnValue = 0; @@ -451,18 +451,24 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn if(Inside) { UI()->SetHotItem(pID); - RenderTools()->DrawUIRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 4.0f); + RenderTools()->DrawRoundRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.5f), 5.0f); + } + else if(Selected) + { + RenderTools()->DrawRoundRect(&View, vec4(0.8f, 0.8f, 0.8f, 0.5f), 5.0f); } - vec3 TextBaseColor = vec3(1.0f, 1.0f, 1.0f); + const float FontSize = 12.0f; + const float TextAlpha = (pEntry->m_NumClients == pEntry->m_MaxClients) ? 0.5f : 1.0f; + vec4 TextBaseColor = vec4(1.0f, 1.0f, 1.0f, TextAlpha); vec4 TextBaseOutlineColor = vec4(0.0, 0.0, 0.0, 0.3f); + vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); if(Selected || Inside) { - TextBaseColor = vec3(0.0f, 0.0f, 0.0f); + TextBaseColor = vec4(0.0f, 0.0f, 0.0f, TextAlpha); TextBaseOutlineColor = vec4(0.8f, 0.8f, 0.8f, 0.25f); } - float TextAlpha = (pEntry->m_NumClients == pEntry->m_MaxClients) ? 0.5f : 1.0f; for(int c = 0; c < NUM_BROWSER_COLS; c++) { CUIRect Button = ms_aBrowserCols[c].m_Rect; @@ -488,9 +494,8 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Rect.VSplitLeft(Rect.h, &Icon, &Rect); Icon.Margin(2.0f, &Icon); - int Level = pEntry->m_ServerLevel; - DoIcon(IMAGE_LEVELICONS, Level==0 ? SPRITE_LEVEL_A_ON : Level==1 ? SPRITE_LEVEL_B_ON : SPRITE_LEVEL_C_ON, &Icon); + DoIcon(IMAGE_LEVELICONS, pEntry->m_ServerLevel==0 ? SPRITE_LEVEL_A_ON : pEntry->m_ServerLevel==1 ? SPRITE_LEVEL_B_ON : SPRITE_LEVEL_C_ON, &Icon); Rect.VSplitLeft(Rect.h, &Icon, &Rect); Icon.Margin(2.0f, &Icon); @@ -518,72 +523,20 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } else if(ID == COL_BROWSER_NAME) { - CTextCursor Cursor; - float tw = TextRender()->TextWidth(0, 12.0f, pEntry->m_aName, -1, -1.0f); - if(tw < Button.w) - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER); - else - { - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Button.w; - } - - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextColor(TextBaseColor); TextRender()->TextOutlineColor(TextBaseOutlineColor); - - if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) - { - // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aName, Config()->m_BrFilterString); - if(pStr) - { - TextRender()->TextEx(&Cursor, pEntry->m_aName, (int)(pStr-pEntry->m_aName)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pEntry->m_aName, -1); - } - else - TextRender()->TextEx(&Cursor, pEntry->m_aName, -1); + Button.y += 2.0f; + UI()->DoLabelHighlighted(&Button, pEntry->m_aName, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } else if(ID == COL_BROWSER_MAP) { - CTextCursor Cursor; - float tw = TextRender()->TextWidth(0, 12.0f, pEntry->m_aMap, -1, -1.0f); - if(tw < Button.w) - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER); - else - { - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Button.w; - } - - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - - if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME)) - { - // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aMap, Config()->m_BrFilterString); - if(pStr) - { - TextRender()->TextEx(&Cursor, pEntry->m_aMap, (int)(pStr-pEntry->m_aMap)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pEntry->m_aMap, -1); - } - else - TextRender()->TextEx(&Cursor, pEntry->m_aMap, -1); + TextRender()->TextColor(TextBaseColor); + Button.y += 2.0f; + UI()->DoLabelHighlighted(&Button, pEntry->m_aMap, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } else if(ID == COL_BROWSER_PLAYERS) { - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + TextRender()->TextColor(TextBaseColor); TextRender()->TextOutlineColor(TextBaseOutlineColor); CServerFilterInfo FilterInfo; pFilter->GetFilter(&FilterInfo); @@ -609,10 +562,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } static float RenderOffset = 0.0f; if(RenderOffset == 0.0f) - { - char aChar[2] = "0"; - RenderOffset = TextRender()->TextWidth(0, 12.0f, aChar, -1, -1.0f); - } + RenderOffset = TextRender()->TextWidth(0, FontSize, "0", -1, -1.0f); str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max); if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) @@ -625,8 +575,8 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Button.x += RenderOffset; if(!Num) TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Button, aTemp, 12.0f, CUI::ALIGN_LEFT); - Button.x += TextRender()->TextWidth(0, 12.0f, aTemp, -1, -1.0f); + UI()->DoLabel(&Button, aTemp, FontSize, CUI::ALIGN_LEFT); + Button.x += TextRender()->TextWidth(0, FontSize, aTemp, -1, -1.0f); } else if(ID == COL_BROWSER_PING) { @@ -635,7 +585,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn vec4 Color; if(Selected || Inside) { - Color = vec4(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); + Color = TextBaseColor; } else { @@ -664,7 +614,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn TextRender()->TextOutlineColor(TextBaseOutlineColor); Button.y += 2.0f; Button.w -= 4.0f; - UI()->DoLabel(&Button, aTemp, 12.0f, CUI::ALIGN_RIGHT); + UI()->DoLabel(&Button, aTemp, FontSize, CUI::ALIGN_RIGHT); } else if(ID == COL_BROWSER_GAMETYPE) { @@ -675,37 +625,15 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn DoGameIcon(pEntry->m_aGameType, &Icon); // gametype text - CTextCursor Cursor; - TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Button.w; - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - - if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE)) - { - // highlight the part that matches - const char *pStr = str_find_nocase(pEntry->m_aGameType, Config()->m_BrFilterString); - if(pStr) - { - TextRender()->TextEx(&Cursor, pEntry->m_aGameType, (int)(pStr-pEntry->m_aGameType)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextEx(&Cursor, pStr+str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); - } - else - { - TextRender()->TextColor(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha); - TextRender()->TextOutlineColor(TextBaseOutlineColor); - TextRender()->TextEx(&Cursor, pEntry->m_aGameType, -1); - } + TextRender()->TextColor(TextBaseColor); + TextRender()->TextOutlineColor(TextBaseOutlineColor); + Button.y += 2.0f; + UI()->DoLabelHighlighted(&Button, pEntry->m_aGameType, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } } // show server info - if(!m_SidebarActive && m_ShowServerDetails && Selected) + if(ShowServerInfo) { CUIRect Info; View.HSplitTop(ms_aBrowserCols[0].m_Rect.h, 0, &View); @@ -716,9 +644,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn View.VSplitLeft(160.0f, &Info, &View); RenderDetailInfo(Info, pEntry); - UI()->ClipEnable(&View); - RenderDetailScoreboard(View, pEntry, 4, vec4(TextBaseColor.r, TextBaseColor.g, TextBaseColor.b, TextAlpha), TextBaseOutlineColor); - UI()->ClipDisable(); + RenderDetailScoreboard(View, pEntry, 4, TextBaseColor, TextBaseOutlineColor); } TextRender()->TextColor(CUI::ms_DefaultTextColor); @@ -844,9 +770,10 @@ void CMenus::RenderServerbrowserOverlay() return; } - int Type = m_InfoOverlay.m_Type; - CUIRect View; + const int Type = m_InfoOverlay.m_Type; + const float FontSize = 12.0f; + CUIRect View; if(Type == CInfoOverlay::OVERLAY_HEADERINFO) { CBrowserFilter *pFilter = (CBrowserFilter*)m_InfoOverlay.m_pData; @@ -858,7 +785,7 @@ void CMenus::RenderServerbrowserOverlay() View.h = 30.0f; // render background - RenderTools()->DrawUIRect(&View, vec4(0.25f, 0.25f, 0.25f, 1.0f), CUI::CORNER_ALL, 6.0f); + RenderTools()->DrawRoundRect(&View, vec4(0.25f, 0.25f, 0.25f, 1.0f), 6.0f); View.Margin(2.0f, &View); CUIRect NumServers, NumPlayers; @@ -866,10 +793,10 @@ void CMenus::RenderServerbrowserOverlay() char aBuf[128]; str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Servers"), pFilter->NumSortedServers()); - UI()->DoLabel(&NumServers, aBuf, 12.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&NumServers, aBuf, FontSize, CUI::ALIGN_CENTER); str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Players"), pFilter->NumPlayers()); - UI()->DoLabel(&NumPlayers, aBuf, 12.0f, CUI::ALIGN_CENTER); + UI()->DoLabel(&NumPlayers, aBuf, FontSize, CUI::ALIGN_CENTER); } else if(Type == CInfoOverlay::OVERLAY_SERVERINFO) { @@ -884,7 +811,7 @@ void CMenus::RenderServerbrowserOverlay() View.y -= View.y+View.h - 590.0f; // render background - RenderTools()->DrawUIRect(&View, vec4(0.25f, 0.25f, 0.25f, 1.0f), CUI::CORNER_ALL, 6.0f); + RenderTools()->DrawRoundRect(&View, vec4(0.25f, 0.25f, 0.25f, 1.0f), 6.0f); RenderServerbrowserServerDetail(View, pInfo); } @@ -914,11 +841,10 @@ void CMenus::RenderServerbrowserOverlay() View.y -= View.y+View.h - 590.0f; // render background - RenderTools()->DrawUIRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.75f), CUI::CORNER_ALL, 6.0f); + RenderTools()->DrawRoundRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.75f), 6.0f); CUIRect ServerScoreBoard = View; CTextCursor Cursor; - const float FontSize = 12.0f; for (int i = 0; i < pInfo->m_NumClients; i++) { CUIRect Name, Clan, Score, Flag; @@ -933,9 +859,10 @@ void CMenus::RenderServerbrowserOverlay() Client()->ServerBrowserUpdate(); } - vec4 Colour = pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_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); + vec4 BackgroundColor = pInfo->m_aClients[i].m_FriendState == CContactInfo::CONTACT_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()->DrawRoundRect(&Name, BackgroundColor, 4.0f); Name.VSplitLeft(5.0f, 0, &Name); Name.VSplitLeft(30.0f, &Score, &Name); Name.VSplitRight(34.0f, &Name, &Flag); @@ -953,52 +880,16 @@ void CMenus::RenderServerbrowserOverlay() } // name - TextRender()->SetCursor(&Cursor, Name.x, Name.y+(Name.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Name.w; - const char *pName = pInfo->m_aClients[i].m_aName; - if(Config()->m_BrFilterString[0]) - { - // highlight the part that matches - const char *s = str_find_nocase(pName, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); - TextRender()->TextColor(CUI::ms_HighlightTextColor); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(CUI::ms_DefaultTextColor); - TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pName, -1); - } - else - TextRender()->TextEx(&Cursor, pName, -1); + Name.y += 2.0f; + UI()->DoLabelHighlighted(&Name, pInfo->m_aClients[i].m_aName, Config()->m_BrFilterString, FontSize, CUI::ms_DefaultTextColor, CUI::ms_HighlightTextColor); // clan - TextRender()->SetCursor(&Cursor, Clan.x, Clan.y+(Clan.h-FontSize)/4.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Clan.w; - const char *pClan = pInfo->m_aClients[i].m_aClan; - if(Config()->m_BrFilterString[0]) - { - // highlight the part that matches - const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan)); - TextRender()->TextColor(CUI::ms_HighlightTextColor); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(CUI::ms_DefaultTextColor); - TextRender()->TextEx(&Cursor, s+str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pClan, -1); - } - else - TextRender()->TextEx(&Cursor, pClan, -1); + Clan.y += 2.0f; + UI()->DoLabelHighlighted(&Clan, pInfo->m_aClients[i].m_aClan, Config()->m_BrFilterString, FontSize, CUI::ms_DefaultTextColor, CUI::ms_HighlightTextColor); // flag - vec4 Color(1.0f, 1.0f, 1.0f, 0.75f); - m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &Color, Flag.x, Flag.y, Flag.w, Flag.h); + vec4 FlagColor(1.0f, 1.0f, 1.0f, 0.75f); + m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &FlagColor, Flag.x, Flag.y, Flag.w, Flag.h); } } else @@ -1016,7 +907,7 @@ void CMenus::RenderServerbrowserOverlay() View.y -= View.y+View.h - 590.0f; // render background - RenderTools()->DrawUIRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.75f), CUI::CORNER_ALL, 6.0f); + RenderTools()->DrawRoundRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.75f), 6.0f); View.y += 2.0f; UI()->DoLabel(&View, Localize("no players", "server browser message"), View.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); @@ -1194,6 +1085,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) const bool CtrlPressed = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL); // handle arrow hotkeys + const int LastSelectedFilter = m_aSelectedFilters[BrowserType]; + const int LastSelectedServer = m_aSelectedServers[BrowserType]; if(SelectedFilter > -1) { int NewFilter = SelectedFilter; @@ -1242,7 +1135,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(m_aSelectedServers[BrowserType] != ToBeSelectedServer) { m_aSelectedServers[BrowserType] = ToBeSelectedServer; - m_ShowServerDetails = true; + m_ShowServerDetails = false; // close server details when scrolling with arrows, as this leads to flicking m_AddressSelection |= ADDR_SELECTION_REVEAL; } @@ -1302,11 +1195,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } } - float ItemHeight = HeaderHeight; - if(!m_SidebarActive && IsSelected && m_ShowServerDetails) - { - ItemHeight *= 6.0f; - } + const bool ShowServerInfo = !m_SidebarActive && m_ShowServerDetails && IsSelected; + const float ItemHeight = HeaderHeight * (ShowServerInfo ? 6.0f : 1.0f); + CUIRect Row; View.HSplitTop(ItemHeight, &Row, &View); s_ScrollRegion.AddRect(Row); @@ -1316,19 +1207,15 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) s_ScrollRegion.ScrollHere(); m_AddressSelection &= ~ADDR_SELECTION_REVEAL; } - - if(s_ScrollRegion.IsRectClipped(Row)) + else if(s_ScrollRegion.IsRectClipped(Row)) { // only those in the view are rendered and can be selected continue; } - if(IsSelected) - { - RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f); - } - - if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected)) + // Prevent flickering entry background and text by drawing it as selected for one more frame after the selection has changed + const bool WasSelected = LastSelectedFilter >= 0 && LastSelectedServer >= 0 && FilterIndex == LastSelectedFilter && ServerIndex == LastSelectedServer; + if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected || WasSelected, ShowServerInfo)) { m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details m_aSelectedFilters[BrowserType] = FilterIndex; @@ -1464,10 +1351,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // todo: move this to a helper function static float RenderOffset = 0.0f; if(RenderOffset == 0.0f) - { - char aChar[2] = "0"; - RenderOffset = TextRender()->TextWidth(0, 12.0f, aChar, -1, -1.0f); - } + RenderOffset = TextRender()->TextWidth(0, FontSize, "0", -1, -1.0f); float OffsetServer = 0.0f, OffsetPlayer = 0.0f; int Num = ServerBrowser()->NumServers(); @@ -1484,6 +1368,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) OffsetPlayer += RenderOffset; if(NumPlayers < 10) OffsetPlayer += RenderOffset; + char aBuf[128]; Status.VSplitLeft(20.0f, 0, &Status); Status.HSplitTop(ButtonHeight/1.5f, 0, &Status); @@ -1492,6 +1377,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Label.y += 2.0f; Label.x += OffsetServer; UI()->DoLabel(&Label, aBuf, 14.0f, CUI::ALIGN_LEFT); + Status.HSplitTop(SpacingH, 0, &Status); Status.HSplitTop(ButtonHeight, &Label, 0); str_format(aBuf, sizeof(aBuf), Localize("%d players"), NumPlayers); @@ -1806,12 +1692,16 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) Label.HMargin(2.0f, &Label); UI()->DoLabel(&Label, Localize("New filter"), FontSize, CUI::ALIGN_LEFT); if(s_aFilterName[0]) - DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); - static CButtonContainer s_AddFilter; - if(s_aFilterName[0] && UI()->DoButtonLogic(&s_AddFilter, &Button)) { - m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_CUSTOM, s_aFilterName, ServerBrowser())); - s_aFilterName[0] = 0; + DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); + static CButtonContainer s_AddFilter; + if(UI()->DoButtonLogic(&s_AddFilter, &Button)) + { + m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_CUSTOM, s_aFilterName, ServerBrowser())); + m_lFilters[m_lFilters.size()-1].Switch(); + s_aFilterName[0] = 0; + Client()->ServerBrowserUpdate(); + } } CBrowserFilter *pFilter = GetSelectedBrowserFilter(); @@ -1832,48 +1722,48 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterEmpty = 0; if(DoButton_CheckBox(&s_BrFilterEmpty, Localize("Has people playing"), FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_EMPTY; + NewSortHash ^= IServerBrowser::FILTER_EMPTY; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterSpectators = 0; if(DoButton_CheckBox(&s_BrFilterSpectators, Localize("Count players only"), FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_SPECTATORS; + NewSortHash ^= IServerBrowser::FILTER_SPECTATORS; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterFull = 0; if(DoButton_CheckBox(&s_BrFilterFull, Localize("Server not full"), FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_FULL; + NewSortHash ^= IServerBrowser::FILTER_FULL; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterFriends = 0; if(DoButton_CheckBox(&s_BrFilterFriends, Localize("Show friends only"), FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_FRIENDS; + NewSortHash ^= IServerBrowser::FILTER_FRIENDS; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterBots = 0; if(DoButton_CheckBox(&s_BrFilterBots, Localize("Hide bots"), FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_BOTS; + NewSortHash ^= IServerBrowser::FILTER_BOTS; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterPw = 0; if(DoButton_CheckBox(&s_BrFilterPw, Localize("No password"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PW, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PW; + NewSortHash ^= IServerBrowser::FILTER_PW; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterCompatversion = 0; if(DoButton_CheckBox(&s_BrFilterCompatversion, Localize("Compatible version"), FilterInfo.m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_COMPAT_VERSION; + NewSortHash ^= IServerBrowser::FILTER_COMPAT_VERSION; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); const bool Locked = pFilter->Custom() == CBrowserFilter::FILTER_STANDARD; static int s_BrFilterPure = 0; if(DoButton_CheckBox(&s_BrFilterPure, Localize("Standard gametype"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE, &Button, Locked)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PURE; + NewSortHash ^= IServerBrowser::FILTER_PURE; ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); static int s_BrFilterPureMap = 0; if(DoButton_CheckBox(&s_BrFilterPureMap, Localize("Standard map"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE_MAP, &Button)) - NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PURE_MAP; + NewSortHash ^= IServerBrowser::FILTER_PURE_MAP; bool UpdateFilter = false; if(FilterInfo.m_SortHash != NewSortHash) @@ -1885,10 +1775,8 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) // game types filter { ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); UI()->DoLabel(&Button, Localize("Game types:"), FontSize, CUI::ALIGN_LEFT); - ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter); RenderTools()->DrawUIRect(&Button, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 2.0f); @@ -2126,69 +2014,77 @@ void CMenus::RenderServerbrowserInfoTab(CUIRect View) void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) { - CUIRect ServerHeader; const float FontSize = 10.0f; + const float RowHeight = 15.0f; + + CUIRect ServerHeader; View.HSplitTop(GetListHeaderHeight(), &ServerHeader, &View); - RenderTools()->DrawUIRect(&ServerHeader, vec4(1, 1, 1, 0.25f), CUI::CORNER_T, 4.0f); - RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); + RenderTools()->DrawUIRect(&ServerHeader, vec4(1, 1, 1, 0.25f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 5.0f); ServerHeader.HMargin(2.0f, &ServerHeader); UI()->DoLabel(&ServerHeader, Localize("Server details"), FontSize + 2.0f, CUI::ALIGN_CENTER); - if(pInfo) - { - CUIRect Row; - // Localize("Map:"); Localize("Game type:"); Localize("Version:"); Localize("Difficulty:"); Localize("Casual", "Server difficulty"); Localize("Normal", "Server difficulty"); Localize("Competitive", "Server difficulty"); - static CLocConstString s_aLabels[] = { - "Map:", - "Game type:", - "Version:", - "Difficulty:" }; - static CLocConstString s_aDifficultyLabels[] = { - "Casual", - "Normal", - "Competitive" }; - static int s_aDifficultySpriteIds[] = { - SPRITE_LEVEL_A_ON, - SPRITE_LEVEL_B_ON, - SPRITE_LEVEL_C_ON }; - - CUIRect LeftColumn, RightColumn; - View.VMargin(2.0f, &View); - View.VSplitLeft(70.0f, &LeftColumn, &RightColumn); - - for(unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++) - { - LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn); - UI()->DoLabel(&Row, s_aLabels[i], FontSize, CUI::ALIGN_LEFT, Row.w, false); - } + if(!pInfo) + return; - // map - RightColumn.HSplitTop(15.0f, &Row, &RightColumn); - UI()->DoLabel(&Row, pInfo->m_aMap, FontSize, CUI::ALIGN_LEFT, Row.w, false); - - // game type - RightColumn.HSplitTop(15.0f, &Row, &RightColumn); - CUIRect Icon; - Row.VSplitLeft(Row.h, &Icon, &Row); - Icon.y -= 2.0f; - DoGameIcon(pInfo->m_aGameType, &Icon); - UI()->DoLabel(&Row, pInfo->m_aGameType, FontSize, CUI::ALIGN_LEFT, Row.w, false); - - // version - RightColumn.HSplitTop(15.0f, &Row, &RightColumn); - UI()->DoLabel(&Row, pInfo->m_aVersion, FontSize, CUI::ALIGN_LEFT, Row.w, false); - - // difficulty - RightColumn.HSplitTop(15.0f, &Row, &RightColumn); - Row.VSplitLeft(Row.h, &Icon, &Row); - Icon.y -= 2.0f; - DoIcon(IMAGE_LEVELICONS, s_aDifficultySpriteIds[pInfo->m_ServerLevel], &Icon); - UI()->DoLabel(&Row, s_aDifficultyLabels[pInfo->m_ServerLevel], FontSize, CUI::ALIGN_LEFT, Row.w, false); - } + CUIRect Row; + // Localize("Map:"); Localize("Game type:"); Localize("Version:"); Localize("Difficulty:"); Localize("Casual", "Server difficulty"); Localize("Normal", "Server difficulty"); Localize("Competitive", "Server difficulty"); + static CLocConstString s_aLabels[] = { + "Map:", + "Game type:", + "Version:", + "Difficulty:" }; + static CLocConstString s_aDifficultyLabels[] = { + "Casual", + "Normal", + "Competitive" }; + static int s_aDifficultySpriteIds[] = { + SPRITE_LEVEL_A_ON, + SPRITE_LEVEL_B_ON, + SPRITE_LEVEL_C_ON }; + + CUIRect LeftColumn, RightColumn; + View.VMargin(2.0f, &View); + View.VSplitLeft(70.0f, &LeftColumn, &RightColumn); + + for(unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++) + { + LeftColumn.HSplitTop(RowHeight, &Row, &LeftColumn); + UI()->DoLabel(&Row, s_aLabels[i], FontSize, CUI::ALIGN_LEFT, Row.w, false); + } + + // map + RightColumn.HSplitTop(RowHeight, &Row, &RightColumn); + UI()->DoLabel(&Row, pInfo->m_aMap, FontSize, CUI::ALIGN_LEFT, Row.w, false); + + // game type + RightColumn.HSplitTop(RowHeight, &Row, &RightColumn); + CUIRect Icon; + Row.VSplitLeft(Row.h, &Icon, &Row); + Icon.y -= 2.0f; + DoGameIcon(pInfo->m_aGameType, &Icon); + UI()->DoLabel(&Row, pInfo->m_aGameType, FontSize, CUI::ALIGN_LEFT, Row.w, false); + + // version + RightColumn.HSplitTop(RowHeight, &Row, &RightColumn); + UI()->DoLabel(&Row, pInfo->m_aVersion, FontSize, CUI::ALIGN_LEFT, Row.w, false); + + // difficulty + RightColumn.HSplitTop(RowHeight, &Row, &RightColumn); + Row.VSplitLeft(Row.h, &Icon, &Row); + Icon.y -= 2.0f; + DoIcon(IMAGE_LEVELICONS, s_aDifficultySpriteIds[pInfo->m_ServerLevel], &Icon); + UI()->DoLabel(&Row, s_aDifficultyLabels[pInfo->m_ServerLevel], FontSize, CUI::ALIGN_LEFT, Row.w, false); } void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor, vec4 TextOutlineColor) { + RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), RowCount > 0 ? CUI::CORNER_B|CUI::CORNER_TL : CUI::CORNER_B, 5.0f); + View.Margin(2.0f, &View); + + if(!pInfo) + return; + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); CServerFilterInfo FilterInfo; if(pFilter) @@ -2197,22 +2093,13 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int TextRender()->TextColor(TextColor); TextRender()->TextOutlineColor(TextOutlineColor); - // server scoreboard - CTextCursor Cursor; - const float FontSize = 8.0f; - int ActColumn = 0; - RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), CUI::CORNER_B, 4.0f); - View.Margin(2.0f, &View); - - if(!pInfo) - return; static const CServerInfo *s_pLastInfo = pInfo; - bool ResetScroll = s_pLastInfo != pInfo; + const bool ResetScroll = s_pLastInfo != pInfo; s_pLastInfo = pInfo; - CUIRect Scroll; - - float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); + const float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); + const float FontSize = 8.0f; + const vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); float LineHeight = 20.0f; static CScrollRegion s_ScrollRegion; @@ -2225,7 +2112,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int ScrollParams.m_ScrollSpeed = 15; s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; - if(RowCount != 0) + if(RowCount > 0) { const float Width = RowWidth * ((pInfo->m_NumClients+RowCount-1) / RowCount); static float s_ScrollValue = 0.0f; @@ -2235,6 +2122,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int } if(Width > View.w) { + CUIRect Scroll; View.HSplitBottom(14.0f, &View, &Scroll); Scroll.VMargin(5.0f, &Scroll); s_ScrollValue = DoScrollbarH(&s_ScrollValue, &Scroll, s_ScrollValue); @@ -2254,22 +2142,18 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int CUIRect Name, Clan, Score, Flag, Icon; if(RowCount > 0 && Count % RowCount == 0) - { View.VSplitLeft(RowWidth, &Row, &View); - ActColumn++; - } Row.HSplitTop(LineHeight, &Name, &Row); s_ScrollRegion.AddRect(Name); if(Count == 0 && ResetScroll) - { s_ScrollRegion.ScrollHere(CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); - } + Count++; if(s_ScrollRegion.IsRectClipped(Name)) continue; - RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f); + RenderTools()->DrawRoundRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 ? 1 : 2)*0.05f), 5.0f); // friend if(UI()->DoButtonLogic(&pInfo->m_aClients[i], &Name)) @@ -2289,69 +2173,28 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int Name.VSplitLeft(2.0f, 0, &Name); Name.VSplitLeft(25.0f, &Score, &Name); Name.VSplitRight(2*(Name.h-8.0f), &Name, &Flag); - Flag.HMargin(4.0f, &Flag); Name.HSplitTop(LineHeight*0.5f, &Name, &Clan); // score if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)) { + Score.y += 4.0f; char aTemp[16]; FormatScore(aTemp, sizeof(aTemp), pInfo->m_Flags&IServerBrowser::FLAG_TIMESCORE, &pInfo->m_aClients[i]); - TextRender()->SetCursor(&Cursor, Score.x, Score.y + (Score.h - FontSize) / 4.0f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Score.w; - TextRender()->TextEx(&Cursor, aTemp, -1); + UI()->DoLabel(&Score, aTemp, FontSize, CUI::ALIGN_LEFT); } // name - TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Name.w; - const char *pName = pInfo->m_aClients[i].m_aName; - if(Config()->m_BrFilterString[0]) - { - // highlight the part that matches - const char *s = str_find_nocase(pName, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pName, (int)(s - pName)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor); - TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pName, -1); - } - else - TextRender()->TextEx(&Cursor, pName, -1); + UI()->DoLabelHighlighted(&Name, pInfo->m_aClients[i].m_aName, Config()->m_BrFilterString, FontSize, TextColor, HighlightColor); // clan - TextRender()->SetCursor(&Cursor, Clan.x, Clan.y, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = Clan.w; - const char *pClan = pInfo->m_aClients[i].m_aClan; - if(Config()->m_BrFilterString[0]) - { - // highlight the part that matches - const char *s = str_find_nocase(pClan, Config()->m_BrFilterString); - if(s) - { - TextRender()->TextEx(&Cursor, pClan, (int)(s - pClan)); - TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); - TextRender()->TextEx(&Cursor, s, str_length(Config()->m_BrFilterString)); - TextRender()->TextColor(TextColor); - TextRender()->TextEx(&Cursor, s + str_length(Config()->m_BrFilterString), -1); - } - else - TextRender()->TextEx(&Cursor, pClan, -1); - } - else - TextRender()->TextEx(&Cursor, pClan, -1); + UI()->DoLabelHighlighted(&Clan, pInfo->m_aClients[i].m_aClan, Config()->m_BrFilterString, FontSize, TextColor, HighlightColor); // flag + Flag.HMargin(4.0f, &Flag); Flag.w = Flag.h*2; vec4 FlagColor(1.0f, 1.0f, 1.0f, 0.5f); m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &FlagColor, Flag.x, Flag.y, Flag.w, Flag.h); - - ++Count; } s_ScrollRegion.End(); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 8f2c62cf..7ed31cb4 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -281,10 +281,11 @@ void CMenus::RenderPlayers(CUIRect MainView) MainView.HSplitTop(ButtonHeight, &Row, &MainView); s_ScrollRegion.AddRect(Row); + Count++; if(s_ScrollRegion.IsRectClipped(Row)) continue; - if(Count++ % 2 == 0) + if(Count % 2 == 1) RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); // player info diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 1a164859..251754e8 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -379,28 +379,44 @@ bool CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float return true; } -void CUI::DoLabel(const CUIRect *r, const char *pText, float Size, EAlignment Align, float LineWidth, bool MultiLine) +void CUI::DoLabel(const CUIRect *pRect, const char *pText, float FontSize, EAlignment Align, float LineWidth, bool MultiLine) { // TODO: FIX ME!!!! //Graphics()->BlendNormal(); + + float TextX = pRect->x; switch(Align) { case ALIGN_CENTER: - { - float tw = TextRender()->TextWidth(0, Size, pText, -1, LineWidth); - TextRender()->Text(0, r->x + r->w/2-tw/2, r->y - Size/10, Size, pText, LineWidth, MultiLine); + TextX += pRect->w/2.0f - TextRender()->TextWidth(0, FontSize, pText, -1, LineWidth)/2.0f; break; - } case ALIGN_LEFT: - { - TextRender()->Text(0, r->x, r->y - Size/10, Size, pText, LineWidth, MultiLine); + // default is left aligned break; - } case ALIGN_RIGHT: - { - float tw = TextRender()->TextWidth(0, Size, pText, -1, LineWidth); - TextRender()->Text(0, r->x + r->w-tw, r->y - Size/10, Size, pText, LineWidth, MultiLine); + TextX += pRect->w - TextRender()->TextWidth(0, FontSize, pText, -1, LineWidth); break; } + + TextRender()->Text(0, TextX, pRect->y - FontSize/10.0f, FontSize, pText, LineWidth, MultiLine); +} + +void CUI::DoLabelHighlighted(const CUIRect *pRect, const char *pText, const char *pHighlighted, float FontSize, const vec4 &TextColor, const vec4 &HighlightColor) +{ + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, pRect->x, pRect->y, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = pRect->w; + + TextRender()->TextColor(TextColor); + const char *pMatch = pHighlighted && pHighlighted[0] ? str_find_nocase(pText, pHighlighted) : 0; + if(pMatch) + { + TextRender()->TextEx(&Cursor, pText, (int)(pMatch - pText)); + TextRender()->TextColor(HighlightColor); + TextRender()->TextEx(&Cursor, pMatch, str_length(pHighlighted)); + TextRender()->TextColor(TextColor); + TextRender()->TextEx(&Cursor, pMatch + str_length(pHighlighted), -1); } + else + TextRender()->TextEx(&Cursor, pText, -1); } diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 1ae68706..b25f2f39 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -130,8 +130,8 @@ class CUI int DoButtonLogic(const void *pID, const CUIRect *pRect); bool DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); - // TODO: Refactor: Remove this? - void DoLabel(const CUIRect *pRect, const char *pText, float Size, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); + void DoLabel(const CUIRect *pRect, const char *pText, float FontSize, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); + void DoLabelHighlighted(const CUIRect *pRect, const char *pText, const char *pHighlighted, float FontSize, const vec4 &TextColor, const vec4 &HighlightColor); }; From 610249c9e30fe9763e88cb293989dace11337e03 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 1 Sep 2020 10:36:57 +0200 Subject: [PATCH 397/479] improved net address comparism --- src/base/system.c | 4 ++-- src/base/system.h | 9 +++++++-- src/engine/client/client.cpp | 4 ++-- src/engine/client/serverbrowser.cpp | 2 +- src/engine/client/serverbrowser_fav.cpp | 6 +++--- src/engine/server/register.cpp | 8 ++------ src/engine/shared/netban.h | 6 +++--- src/engine/shared/network_client.cpp | 4 ++-- src/engine/shared/network_conn.cpp | 2 +- src/engine/shared/network_console.cpp | 2 +- src/engine/shared/network_server.cpp | 12 ++++-------- src/engine/shared/network_token.cpp | 5 ++--- src/mastersrv/mastersrv.cpp | 6 +++--- src/tools/crapnet.cpp | 2 +- 14 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 71d0f4fc..baccf47b 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -762,9 +762,9 @@ static void sockaddr_to_netaddr(const struct sockaddr *src, NETADDR *dst) } } -int net_addr_comp(const NETADDR *a, const NETADDR *b) +int net_addr_comp(const NETADDR *a, const NETADDR *b, int check_port) { - if(mem_comp(a->ip, b->ip, sizeof(a->ip)) == 0 && a->port == b->port && a->type == b->type) + if(a->type == b->type && mem_comp(a->ip, b->ip, a->type == NETTYPE_IPV4 ? NETADDR_SIZE_IPV4 : NETADDR_SIZE_IPV6) == 0 && (!check_port || a->port == b->port)) return 0; return -1; } diff --git a/src/base/system.h b/src/base/system.h index 49f1fd62..cf496c3d 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -596,6 +596,9 @@ enum { NETADDR_MAXSTRSIZE = 1+(8*4+7)+1+1+5+1, // [XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX]:XXXXX + NETADDR_SIZE_IPV4 = 4, + NETADDR_SIZE_IPV6 = 16, + NETTYPE_INVALID = 0, NETTYPE_IPV4 = 1, NETTYPE_IPV6 = 2, @@ -606,8 +609,9 @@ enum typedef struct { unsigned int type; - unsigned char ip[16]; + unsigned char ip[NETADDR_SIZE_IPV6]; unsigned short port; + unsigned short reserved; } NETADDR; /* @@ -648,13 +652,14 @@ int net_host_lookup(const char *hostname, NETADDR *addr, int types); Parameters: a - Address to compare b - Address to compare to. + check_port - compares port or not Returns: <0 - Address a is lesser then address b 0 - Address a is equal to address b >0 - Address a is greater then address b */ -int net_addr_comp(const NETADDR *a, const NETADDR *b); +int net_addr_comp(const NETADDR *a, const NETADDR *b, int check_port); /* Function: net_addr_str diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 9695ac04..6ea231ae 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1019,7 +1019,7 @@ inline void SortClients(CServerInfo *pInfo) void CClient::ProcessConnlessPacket(CNetChunk *pPacket) { // version server - if(m_VersionInfo.m_State == CVersionInfo::STATE_READY && net_addr_comp(&pPacket->m_Address, &m_VersionInfo.m_VersionServeraddr.m_Addr) == 0) + if(m_VersionInfo.m_State == CVersionInfo::STATE_READY && net_addr_comp(&pPacket->m_Address, &m_VersionInfo.m_VersionServeraddr.m_Addr, true) == 0) { // version info if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(GAME_RELEASE_VERSION)) && @@ -1076,7 +1076,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) if(m_pMasterServer->IsValid(i)) { NETADDR Addr = m_pMasterServer->GetAddr(i); - if(net_addr_comp(&pPacket->m_Address, &Addr) == 0) + if(net_addr_comp(&pPacket->m_Address, &Addr, true) == 0) { Valid = true; break; diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 767045cd..55dbedb2 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -473,7 +473,7 @@ CServerEntry *CServerBrowser::Find(int ServerlistType, const NETADDR &Addr) { for(CServerEntry *pEntry = m_aServerlist[ServerlistType].m_aServerlistIp[AddrHash(&Addr)]; pEntry; pEntry = pEntry->m_pNextIp) { - if(net_addr_comp(&pEntry->m_Addr, &Addr) == 0) + if(net_addr_comp(&pEntry->m_Addr, &Addr, true) == 0) return pEntry; } return (CServerEntry*)0; diff --git a/src/engine/client/serverbrowser_fav.cpp b/src/engine/client/serverbrowser_fav.cpp index a2e58db2..4c3f5557 100644 --- a/src/engine/client/serverbrowser_fav.cpp +++ b/src/engine/client/serverbrowser_fav.cpp @@ -63,7 +63,7 @@ bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR return false; // check if hostname does not match given address - if(DoCheck && net_addr_comp(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, pAddr) != 0) + if(DoCheck && net_addr_comp(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, pAddr, true) != 0) return false; // add the server to the list @@ -106,7 +106,7 @@ CServerBrowserFavorites::CFavoriteServer *CServerBrowserFavorites::FindFavoriteB { for(int i = 0; i < m_NumFavoriteServers; i++) { - if(m_aFavoriteServers[i].m_State >= FAVSTATE_ADDR && net_addr_comp(&Addr, &m_aFavoriteServers[i].m_Addr) == 0) + if(m_aFavoriteServers[i].m_State >= FAVSTATE_ADDR && net_addr_comp(&Addr, &m_aFavoriteServers[i].m_Addr, true) == 0) { if(Index) *Index = i; @@ -196,7 +196,7 @@ const NETADDR *CServerBrowserFavorites::UpdateFavorites() { // address wasn't in the list yet -> add it (optional check if hostname matches given address -> drop entry on fail) if(m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_State == FAVSTATE_LOOKUP || - net_addr_comp(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, &m_FavLookup.m_HostLookup.m_Addr) == 0) + net_addr_comp(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, &m_FavLookup.m_HostLookup.m_Addr, true) == 0) { m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_Addr = m_FavLookup.m_HostLookup.m_Addr; m_aFavoriteServers[m_FavLookup.m_FavoriteIndex].m_State = FAVSTATE_HOST; diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index 6b6e9df9..6826681b 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -83,7 +83,7 @@ void CRegister::RegisterGotCount(CNetChunk *pChunk) for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++) { - if(net_addr_comp(&m_aMasterserverInfo[i].m_Addr, &pChunk->m_Address) == 0) + if(net_addr_comp(&m_aMasterserverInfo[i].m_Addr, &pChunk->m_Address, true) == 0) { m_aMasterserverInfo[i].m_Count = Count; break; @@ -241,13 +241,9 @@ int CRegister::RegisterProcessPacket(CNetChunk *pPacket, TOKEN Token) { // check for masterserver address bool Valid = false; - NETADDR Addr1 = pPacket->m_Address; - Addr1.port = 0; for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++) { - NETADDR Addr2 = m_aMasterserverInfo[i].m_Addr; - Addr2.port = 0; - if(net_addr_comp(&Addr1, &Addr2) == 0) + if(net_addr_comp(&pPacket->m_Address, &m_aMasterserverInfo[i].m_Addr, false) == 0) { Valid = true; break; diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h index 2d35fe01..c7d77a0c 100644 --- a/src/engine/shared/netban.h +++ b/src/engine/shared/netban.h @@ -6,7 +6,7 @@ inline int NetComp(const NETADDR *pAddr1, const NETADDR *pAddr2) { - return mem_comp(pAddr1, pAddr2, pAddr1->type==NETTYPE_IPV4 ? 8 : 20); + return net_addr_comp(pAddr1, pAddr2, false); } class CNetRange @@ -15,12 +15,12 @@ class CNetRange NETADDR m_LB; NETADDR m_UB; - bool IsValid() const { return m_LB.type == m_UB.type && NetComp(&m_LB, &m_UB) < 0; } + bool IsValid() const { return m_LB.type == m_UB.type && mem_comp(m_LB.ip, m_UB.ip, m_LB.type==NETTYPE_IPV4 ? NETADDR_SIZE_IPV4 : NETADDR_SIZE_IPV6) < 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); + return net_addr_comp(&pRange1->m_LB, &pRange2->m_LB, false) || net_addr_comp(&pRange1->m_UB, &pRange2->m_UB, false); } diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index 0384fef8..ef7c3403 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -81,7 +81,7 @@ int CNetClient::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) if(!Result) { - if(m_Connection.State() != NET_CONNSTATE_OFFLINE && m_Connection.State() != NET_CONNSTATE_ERROR && net_addr_comp(m_Connection.PeerAddress(), &Addr) == 0) + if(m_Connection.State() != NET_CONNSTATE_OFFLINE && m_Connection.State() != NET_CONNSTATE_ERROR && net_addr_comp(m_Connection.PeerAddress(), &Addr, true) == 0) { if(m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) { @@ -128,7 +128,7 @@ int CNetClient::Send(CNetChunk *pChunk, TOKEN Token, CSendCBData *pCallbackData) return -1; } - if(pChunk->m_ClientID == -1 && net_addr_comp(&pChunk->m_Address, m_Connection.PeerAddress()) == 0) + if(pChunk->m_ClientID == -1 && net_addr_comp(&pChunk->m_Address, m_Connection.PeerAddress(), true) == 0) { // upgrade the packet, now that we know its recipent pChunk->m_ClientID = 0; diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index 6ebb5d7a..dac402ac 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -264,7 +264,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) if(CtrlMsg == NET_CTRLMSG_CLOSE) { - if(net_addr_comp(&m_PeerAddr, pAddr) == 0) + if(net_addr_comp(&m_PeerAddr, pAddr, true) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; diff --git a/src/engine/shared/network_console.cpp b/src/engine/shared/network_console.cpp index c30872a0..4d7fa38e 100644 --- a/src/engine/shared/network_console.cpp +++ b/src/engine/shared/network_console.cpp @@ -66,7 +66,7 @@ int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr) FreeSlot = i; if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE) { - if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0) + if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress(), true) == 0) { str_copy(aError, "only one client per IP allowed", sizeof(aError)); break; diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 8ef5e291..4cb8bfc6 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -129,7 +129,7 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; - if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) + if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr, true) == 0) { if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) { @@ -174,19 +174,15 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) } // only allow a specific number of players with the same ip - NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 1; - ThisAddr.port = 0; - + bool Continue = false; for(int i = 0; i < NET_MAX_CLIENTS; i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; - OtherAddr = *m_aSlots[i].m_Connection.PeerAddress(); - OtherAddr.port = 0; - if(!net_addr_comp(&ThisAddr, &OtherAddr)) + if(!net_addr_comp(&Addr, m_aSlots[i].m_Connection.PeerAddress(), false)) { if(FoundAddr++ >= m_MaxClientsPerIP) { @@ -251,7 +247,7 @@ int CNetServer::Send(CNetChunk *pChunk, TOKEN Token) if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; - if(net_addr_comp(&pChunk->m_Address, m_aSlots[i].m_Connection.PeerAddress()) == 0) + if(net_addr_comp(&pChunk->m_Address, m_aSlots[i].m_Connection.PeerAddress(), true) == 0) { // upgrade the packet, now that we know its recipent pChunk->m_ClientID = i; diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index 43183051..78c37418 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -237,7 +237,7 @@ TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr) CAddressInfo *pInfo = m_TokenCache.Last(); while(pInfo) { - if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0) + if(net_addr_comp(&pInfo->m_Addr, pAddr, true) == 0) return pInfo->m_Token; pInfo = m_TokenCache.Prev(pInfo); } @@ -263,8 +263,7 @@ void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag) { NETADDR NullAddr = { 0 }; NullAddr.type = 7; // cover broadcasts - NullAddr.port = pAddr->port; - if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || ((TokenFLag&NET_TOKENFLAG_ALLOWBROADCAST) && net_addr_comp(&pInfo->m_Addr, &NullAddr) == 0)) + if(net_addr_comp(&pInfo->m_Addr, pAddr, true) == 0 || ((TokenFLag&NET_TOKENFLAG_ALLOWBROADCAST) && net_addr_comp(&pInfo->m_Addr, &NullAddr, false) == 0)) { // notify the user that the packet gets delivered if(pInfo->m_pfnCallback) diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 727ab1ed..624a9f3f 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -193,7 +193,7 @@ void AddServer(NETADDR *pInfo, ServerType Type) // see if server already exists in list for(int i = 0; i < m_NumServers; i++) { - if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0) + if(net_addr_comp(&m_aServers[i].m_Address, pInfo, true) == 0) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true); @@ -421,8 +421,8 @@ int main(int argc, const char **argv) // ignore_convention // remove it from checking for(int i = 0; i < m_NumCheckServers; i++) { - if(net_addr_comp(&m_aCheckServers[i].m_Address, &Packet.m_Address) == 0 || - net_addr_comp(&m_aCheckServers[i].m_AltAddress, &Packet.m_Address) == 0) + if(net_addr_comp(&m_aCheckServers[i].m_Address, &Packet.m_Address, true) == 0 || + net_addr_comp(&m_aCheckServers[i].m_AltAddress, &Packet.m_Address, true) == 0) { Type = m_aCheckServers[i].m_Type; m_NumCheckServers--; diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp index 65be48b6..2fa3fbf7 100644 --- a/src/tools/crapnet.cpp +++ b/src/tools/crapnet.cpp @@ -81,7 +81,7 @@ void Run(unsigned short Port, NETADDR Dest) // create new packet CPacket *p = (CPacket *)mem_alloc(sizeof(CPacket)+Bytes, 1); - if(net_addr_comp(&From, &Dest) == 0) + if(net_addr_comp(&From, &Dest, true) == 0) p->m_SendTo = Src; // from the server else { From 4a0eac97a700dd947150eb80de40cf7e730b718d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 1 Sep 2020 15:55:14 +0200 Subject: [PATCH 398/479] always use normal text alpha for server details --- src/game/client/components/menus.h | 4 ++-- src/game/client/components/menus_browser.cpp | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 279bf534..3d467c9e 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -800,8 +800,8 @@ class CMenus : public CComponent void RenderServerbrowserFilterTab(CUIRect View); void RenderServerbrowserInfoTab(CUIRect View); void RenderServerbrowserFriendList(CUIRect View); - void RenderDetailInfo(CUIRect View, const CServerInfo *pInfo); - void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor, vec4 TextOutlineColor); + void RenderDetailInfo(CUIRect View, const CServerInfo *pInfo, const vec4 &TextColor, const vec4 &TextOutlineColor); + void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, const vec4 &TextColor, const vec4 &TextOutlineColor); void RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pInfo); void RenderServerbrowserBottomBox(CUIRect View); void RenderServerbrowserOverlay(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b98a2520..d3b4211a 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -462,10 +462,12 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn const float TextAlpha = (pEntry->m_NumClients == pEntry->m_MaxClients) ? 0.5f : 1.0f; vec4 TextBaseColor = vec4(1.0f, 1.0f, 1.0f, TextAlpha); vec4 TextBaseOutlineColor = vec4(0.0, 0.0, 0.0, 0.3f); + vec4 ServerInfoTextBaseColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); if(Selected || Inside) { TextBaseColor = vec4(0.0f, 0.0f, 0.0f, TextAlpha); + ServerInfoTextBaseColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); TextBaseOutlineColor = vec4(0.8f, 0.8f, 0.8f, 0.25f); } @@ -635,16 +637,15 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn // show server info if(ShowServerInfo) { - CUIRect Info; View.HSplitTop(ms_aBrowserCols[0].m_Rect.h, 0, &View); if(ReturnValue && UI()->MouseInside(&View)) ReturnValue++; - View.VSplitLeft(160.0f, &Info, &View); - RenderDetailInfo(Info, pEntry); - - RenderDetailScoreboard(View, pEntry, 4, TextBaseColor, TextBaseOutlineColor); + CUIRect Info, Scoreboard; + View.VSplitLeft(160.0f, &Info, &Scoreboard); + RenderDetailInfo(Info, pEntry, ServerInfoTextBaseColor, TextBaseOutlineColor); + RenderDetailScoreboard(Scoreboard, pEntry, 4, ServerInfoTextBaseColor, TextBaseOutlineColor); } TextRender()->TextColor(CUI::ms_DefaultTextColor); @@ -2012,11 +2013,14 @@ void CMenus::RenderServerbrowserInfoTab(CUIRect View) } } -void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) +void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo, const vec4 &TextColor, const vec4 &TextOutlineColor) { const float FontSize = 10.0f; const float RowHeight = 15.0f; + TextRender()->TextColor(TextColor); + TextRender()->TextOutlineColor(TextOutlineColor); + CUIRect ServerHeader; View.HSplitTop(GetListHeaderHeight(), &ServerHeader, &View); RenderTools()->DrawUIRect(&ServerHeader, vec4(1, 1, 1, 0.25f), CUI::CORNER_T, 5.0f); @@ -2077,7 +2081,7 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo) UI()->DoLabel(&Row, s_aDifficultyLabels[pInfo->m_ServerLevel], FontSize, CUI::ALIGN_LEFT, Row.w, false); } -void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, vec4 TextColor, vec4 TextOutlineColor) +void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int RowCount, const vec4 &TextColor, const vec4 &TextOutlineColor) { RenderTools()->DrawUIRect(&View, vec4(0, 0, 0, 0.15f), RowCount > 0 ? CUI::CORNER_B|CUI::CORNER_TL : CUI::CORNER_B, 5.0f); View.Margin(2.0f, &View); @@ -2208,7 +2212,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pI View.HSplitTop(80.0f, &ServerDetails, &ServerScoreboard); // server details - RenderDetailInfo(ServerDetails, pInfo); + RenderDetailInfo(ServerDetails, pInfo, CUI::ms_DefaultTextColor, CUI::ms_DefaultTextOutlineColor); // server scoreboard ServerScoreboard.HSplitTop(GetListHeaderHeight(), &ServerHeader, &ServerScoreboard); From 009ef11f6dba3788949b5faeafcc2d48d2eedc0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 1 Sep 2020 16:34:39 +0200 Subject: [PATCH 399/479] change all scrollbars to require clicking --- src/game/client/components/menus.cpp | 45 ++++++++++--------- .../client/components/menus_scrollregion.cpp | 24 +++++----- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 4911fcb0..15239490 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -797,7 +797,7 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) pRect->VMargin(5.0f, &Rail); // logic - static float OffsetY; + static float s_OffsetY; const bool InsideHandle = UI()->MouseInside(&Handle); const bool InsideRail = UI()->MouseInside(&Rail); float ReturnValue = Current; @@ -805,37 +805,38 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) if(UI()->CheckActiveItem(pID)) { - if(!UI()->MouseButton(0)) + if(UI()->MouseButton(0)) + Grabbed = true; + else UI()->SetActiveItem(0); - - Grabbed = true; } else if(UI()->HotItem() == pID) { if(UI()->MouseButton(0)) { UI()->SetActiveItem(pID); - OffsetY = UI()->MouseY()-Handle.y; + s_OffsetY = UI()->MouseY()-Handle.y; } } - else if(UI()->MouseButton(0) && !InsideHandle && InsideRail) + else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail) { - bool Up = UI()->MouseY() < Handle.y + Handle.h/2; - OffsetY = UI()->MouseY() - Handle.y + 8 * (Up ? 1 : -1); + s_OffsetY = Handle.h * 0.5f; + UI()->SetActiveItem(pID); Grabbed = true; } + else if(InsideHandle) + { + UI()->SetHotItem(pID); + } if(Grabbed) { const float Min = pRect->y; const float Max = pRect->h-Handle.h; - const float Cur = UI()->MouseY()-OffsetY; + const float Cur = UI()->MouseY()-s_OffsetY; ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f); } - if(InsideHandle) - UI()->SetHotItem(pID); - // render RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.w/2.0f); @@ -863,7 +864,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) pRect->HMargin(5.0f, &Rail); // logic - static float OffsetX; + static float s_OffsetX; const bool InsideHandle = UI()->MouseInside(&Handle); const bool InsideRail = UI()->MouseInside(&Rail); float ReturnValue = Current; @@ -871,36 +872,38 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) if(UI()->CheckActiveItem(pID)) { - if(!UI()->MouseButton(0)) + if(UI()->MouseButton(0)) + Grabbed = true; + else UI()->SetActiveItem(0); - Grabbed = true; } else if(UI()->HotItem() == pID) { if(UI()->MouseButton(0)) { UI()->SetActiveItem(pID); - OffsetX = UI()->MouseX()-Handle.x; + s_OffsetX = UI()->MouseX()-Handle.x; } } else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail) { - OffsetX = Handle.w * 0.5f; + s_OffsetX = Handle.w * 0.5f; UI()->SetActiveItem(pID); Grabbed = true; } + else if(InsideHandle) + { + UI()->SetHotItem(pID); + } if(Grabbed) { const float Min = pRect->x; const float Max = pRect->w-Handle.w; - const float Cur = UI()->MouseX()-OffsetX; + const float Cur = UI()->MouseX()-s_OffsetX; ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f); } - if(InsideHandle) - UI()->SetHotItem(pID); - // render RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.h/2.0f); diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 64e768ca..36fad1a7 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -108,35 +108,37 @@ void CMenus::CScrollRegion::End() Hovered = true; } - else if(InsideRail && m_pUI->MouseButton(0)) + else if(InsideRail && m_pUI->MouseButtonClicked(0)) { - const float SliderDistance = m_pUI->MouseY() - (Slider.y+Slider.h/2); - m_ScrollY += sign(SliderDistance) * log(abs(SliderDistance)); // slow down to reasonable scroll speed; keep sign with logarithm + m_ScrollY += m_pUI->MouseY() - (Slider.y+Slider.h/2); + m_pUI->SetActiveItem(pID); + m_MouseGrabStart.y = m_pUI->MouseY(); Hovered = true; } - - if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) + else if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) + { m_pUI->SetActiveItem(0); + } // move slider if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) { - float my = m_pUI->MouseY(); - m_ScrollY += my - m_MouseGrabStart.y; - m_MouseGrabStart.y = my; - + float MouseY = m_pUI->MouseY(); + m_ScrollY += MouseY - m_MouseGrabStart.y; + m_MouseGrabStart.y = MouseY; Grabbed = true; } m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); m_ContentScrollOff.y = -m_ScrollY/MaxScroll * (m_ContentH - m_ClipRect.h); - vec4 SliderColor = m_Params.m_SliderColor; + vec4 SliderColor; if(Grabbed) SliderColor = m_Params.m_SliderColorGrabbed; else if(Hovered) SliderColor = m_Params.m_SliderColorHover; - + else + SliderColor = m_Params.m_SliderColor; m_pRenderTools->DrawRoundRect(&Slider, SliderColor, Slider.w/2.0f); } From 89780d37fc1eb457accd03a0d3cac8b7c0180e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Sep 2020 10:39:39 +0200 Subject: [PATCH 400/479] fix scrollbar hotitem not being set in some cases --- src/game/client/components/menus.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 15239490..9024b8ea 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -814,8 +814,9 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) { if(UI()->MouseButton(0)) { - UI()->SetActiveItem(pID); s_OffsetY = UI()->MouseY()-Handle.y; + UI()->SetActiveItem(pID); + Grabbed = true; } } else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail) @@ -824,7 +825,8 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) UI()->SetActiveItem(pID); Grabbed = true; } - else if(InsideHandle) + + if(InsideHandle) { UI()->SetHotItem(pID); } @@ -838,7 +840,7 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) } // render - RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.w/2.0f); + RenderTools()->DrawRoundRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.w/2.0f); vec4 Color; if(Grabbed) @@ -847,7 +849,7 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) Color = vec4(1.0f, 1.0f, 1.0f, 1.0f); else Color = vec4(0.8f, 0.8f, 0.8f, 1.0f); - RenderTools()->DrawUIRect(&Handle, Color, CUI::CORNER_ALL, Handle.w/2.0f); + RenderTools()->DrawRoundRect(&Handle, Color, Handle.w/2.0f); return ReturnValue; } @@ -881,8 +883,9 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) { if(UI()->MouseButton(0)) { - UI()->SetActiveItem(pID); s_OffsetX = UI()->MouseX()-Handle.x; + UI()->SetActiveItem(pID); + Grabbed = true; } } else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail) @@ -891,7 +894,8 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) UI()->SetActiveItem(pID); Grabbed = true; } - else if(InsideHandle) + + if(InsideHandle) { UI()->SetHotItem(pID); } @@ -905,7 +909,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) } // render - RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.h/2.0f); + RenderTools()->DrawRoundRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.h/2.0f); vec4 Color; if(Grabbed) @@ -914,7 +918,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) Color = vec4(1.0f, 1.0f, 1.0f, 1.0f); else Color = vec4(0.8f, 0.8f, 0.8f, 1.0f); - RenderTools()->DrawUIRect(&Handle, Color, CUI::CORNER_ALL, Handle.h/2.0f); + RenderTools()->DrawRoundRect(&Handle, Color, Handle.h/2.0f); return ReturnValue; } From aedd56547e629ff6fd22cd313d35702abde36aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Sep 2020 10:56:10 +0200 Subject: [PATCH 401/479] decrease mouse wheel scroll speed in server browser --- src/game/client/components/menus_browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index d3b4211a..32afe4ca 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1151,7 +1151,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) ScrollParams.m_ClipBgColor = vec4(0,0,0,0); ScrollParams.m_Flags = CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; ScrollParams.m_SliderMinHeight = 5; - ScrollParams.m_ScrollSpeed = 10; + ScrollParams.m_ScrollSpeed = 5; View.w += ScrollParams.m_ScrollbarWidth; s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; From c9055a49d16629f4e85a71a853d4dc0fbd27f0ef Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 5 Sep 2020 11:36:24 +0200 Subject: [PATCH 402/479] fixed style issues caused by the github editor --- src/game/client/components/players.cpp | 2 +- src/game/client/gameclient.cpp | 4134 ++++++++++++------------ 2 files changed, 2068 insertions(+), 2068 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index f3367bdb..9b526cf2 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -192,7 +192,7 @@ void CPlayers::RenderPlayer( { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } - const bool WorldPaused = m_pClient->IsWorldPaused(); + const bool WorldPaused = m_pClient->IsWorldPaused(); vec2 Direction = direction(Angle); vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d80c2fb8..742c8d3f 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1,2067 +1,2067 @@ -/* (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 -#include - -#include -#include - -#include -#include "localization.h" -#include "render.h" - -#include "gameclient.h" - -#include "components/binds.h" -#include "components/broadcast.h" -#include "components/camera.h" -#include "components/chat.h" -#include "components/console.h" -#include "components/controls.h" -#include "components/countryflags.h" -#include "components/damageind.h" -#include "components/debughud.h" -#include "components/effects.h" -#include "components/emoticon.h" -#include "components/flow.h" -#include "components/hud.h" -#include "components/items.h" -#include "components/infomessages.h" -#include "components/mapimages.h" -#include "components/maplayers.h" -#include "components/menus.h" -#include "components/motd.h" -#include "components/notifications.h" -#include "components/particles.h" -#include "components/players.h" -#include "components/nameplates.h" -#include "components/scoreboard.h" -#include "components/skins.h" -#include "components/sounds.h" -#include "components/spectator.h" -#include "components/stats.h" -#include "components/voting.h" - -inline void AppendDecimals(char *pBuf, int Size, int Time, int Precision) -{ - if(Precision > 0) - { - char aInvalid[] = ".---"; - char aMSec[] = { - '.', - (char)('0' + (Time / 100) % 10), - (char)('0' + (Time / 10) % 10), - (char)('0' + Time % 10), - 0 - }; - char *pDecimals = Time < 0 ? aInvalid : aMSec; - pDecimals[min(Precision, 3)+1] = 0; - str_append(pBuf, pDecimals, Size); - } -} - -void FormatTime(char *pBuf, int Size, int Time, int Precision) -{ - if(Time < 0) - str_copy(pBuf, "-:--", Size); - else - str_format(pBuf, Size, "%02d:%02d", Time / (60 * 1000), (Time / 1000) % 60); - AppendDecimals(pBuf, Size, Time, Precision); -} - -void FormatTimeDiff(char *pBuf, int Size, int Time, int Precision, bool ForceSign) -{ - const char *pPositive = ForceSign ? "+" : ""; - const char *pSign = Time < 0 ? "-" : pPositive; - Time = absolute(Time); - str_format(pBuf, Size, "%s%d", pSign, Time / 1000); - AppendDecimals(pBuf, Size, Time, Precision); -} - -// instantiate all systems -static CInfoMessages gs_InfoMessages; -static CCamera gs_Camera; -static CChat gs_Chat; -static CMotd gs_Motd; -static CBroadcast gs_Broadcast; -static CGameConsole gs_GameConsole; -static CBinds gs_Binds; -static CParticles gs_Particles; -static CMenus gs_Menus; -static CSkins gs_Skins; -static CCountryFlags gs_CountryFlags; -static CFlow gs_Flow; -static CHud gs_Hud; -static CDebugHud gs_DebugHud; -static CNotifications gs_Notifications; -static CControls gs_Controls; -static CEffects gs_Effects; -static CScoreboard gs_Scoreboard; -static CSounds gs_Sounds; -static CEmoticon gs_Emoticon; -static CDamageInd gsDamageInd; -static CVoting gs_Voting; -static CSpectator gs_Spectator; -static CStats gs_Stats; - -static CPlayers gs_Players; -static CNamePlates gs_NamePlates; -static CItems gs_Items; -static CMapImages gs_MapImages; - -static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND); -static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND); - -CGameClient::CStack::CStack() { m_Num = 0; } -void CGameClient::CStack::Add(class CComponent *pComponent) { m_paComponents[m_Num++] = pComponent; } - -const char *CGameClient::Version() const { return GAME_VERSION; } -const char *CGameClient::NetVersion() const { return GAME_NETVERSION; } -const char *CGameClient::NetVersionHashUsed() const { return GAME_NETVERSION_HASH_FORCED; } -const char *CGameClient::NetVersionHashReal() const{ return GAME_NETVERSION_HASH; } -int CGameClient::ClientVersion() const { return CLIENT_VERSION; } -const char *CGameClient::GetItemName(int Type) const { return m_NetObjHandler.GetObjName(Type); } -bool CGameClient::IsXmas() const { return Config()->m_ClShowXmasHats == 2 || (Config()->m_ClShowXmasHats == 1 && m_IsXmasDay); } -bool CGameClient::IsEaster() const { return Config()->m_ClShowEasterEggs == 2 || (Config()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } - -enum -{ - STR_TEAM_GAME, - STR_TEAM_RED, - STR_TEAM_BLUE, - STR_TEAM_SPECTATORS, -}; - -static int GetStrTeam(int Team, bool Teamplay) -{ - if(Teamplay) - { - if(Team == TEAM_RED) - return STR_TEAM_RED; - else if(Team == TEAM_BLUE) - return STR_TEAM_BLUE; - } - else if(Team == 0) - return STR_TEAM_GAME; - - return STR_TEAM_SPECTATORS; -} - -void CGameClient::GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName) -{ - if(!Config()->m_ClShowsocial) - str_format(aBuf, BufferSize, "%2d:", ClientID); - else if(Config()->m_ClShowUserId) - str_format(aBuf, BufferSize, "%2d: %s", ClientID, ClientName); - else - str_format(aBuf, BufferSize, "%s", ClientName); -} - -enum -{ - DO_CHAT=0, - DO_BROADCAST, - DO_SPECIAL, - - PARA_NONE=0, - PARA_I, - PARA_II, - PARA_III, -}; - -struct CGameMsg -{ - int m_Action; - int m_ParaType; - const char *m_pText; -}; - -static CGameMsg gs_GameMsgList[NUM_GAMEMSGS] = { - {/*GAMEMSG_TEAM_SWAP*/ DO_CHAT, PARA_NONE, "Teams were swapped"}, // Localize("Teams were swapped") - {/*GAMEMSG_SPEC_INVALIDID*/ DO_CHAT, PARA_NONE, "Invalid spectator id used"}, //! - {/*GAMEMSG_TEAM_SHUFFLE*/ DO_CHAT, PARA_NONE, "Teams were shuffled"}, // Localize("Teams were shuffled") - {/*GAMEMSG_TEAM_BALANCE*/ DO_CHAT, PARA_NONE, "Teams have been balanced"}, // Localize("Teams have been balanced") - {/*GAMEMSG_CTF_DROP*/ DO_SPECIAL, PARA_NONE, ""}, // special - play ctf drop sound - {/*GAMEMSG_CTF_RETURN*/ DO_SPECIAL, PARA_NONE, ""}, // special - play ctf return sound - - {/*GAMEMSG_TEAM_ALL*/ DO_SPECIAL, PARA_I, ""}, // special - add team name - {/*GAMEMSG_TEAM_BALANCE_VICTIM*/ DO_SPECIAL, PARA_I, ""}, // special - add team name - {/*GAMEMSG_CTF_GRAB*/ DO_SPECIAL, PARA_I, ""}, // special - play ctf grab sound based on team - - {/*GAMEMSG_CTF_CAPTURE*/ DO_SPECIAL, PARA_III, ""}, // special - play ctf capture sound + capture chat message - - {/*GAMEMSG_GAME_PAUSED*/ DO_SPECIAL, PARA_I, ""}, // special - add player name -}; - -void CGameClient::OnConsoleInit() -{ - m_InitComplete = false; - m_pEngine = Kernel()->RequestInterface(); - m_pClient = Kernel()->RequestInterface(); - m_pTextRender = Kernel()->RequestInterface(); - m_pSound = Kernel()->RequestInterface(); - m_pInput = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface()->Values(); - m_pConsole = Kernel()->RequestInterface(); - m_pStorage = Kernel()->RequestInterface(); - m_pDemoPlayer = Kernel()->RequestInterface(); - m_pDemoRecorder = Kernel()->RequestInterface(); - m_pServerBrowser = Kernel()->RequestInterface(); - m_pEditor = Kernel()->RequestInterface(); - m_pFriends = Kernel()->RequestInterface(); - m_pBlacklist = Kernel()->RequestInterface(); - - // setup pointers - m_pBinds = &::gs_Binds; - m_pBroadcast = &::gs_Broadcast; - m_pGameConsole = &::gs_GameConsole; - m_pParticles = &::gs_Particles; - m_pMenus = &::gs_Menus; - m_pSkins = &::gs_Skins; - m_pCountryFlags = &::gs_CountryFlags; - m_pChat = &::gs_Chat; - m_pFlow = &::gs_Flow; - m_pCamera = &::gs_Camera; - m_pControls = &::gs_Controls; - m_pEffects = &::gs_Effects; - m_pSounds = &::gs_Sounds; - m_pMotd = &::gs_Motd; - m_pDamageind = &::gsDamageInd; - m_pMapimages = &::gs_MapImages; - m_pVoting = &::gs_Voting; - m_pScoreboard = &::gs_Scoreboard; - m_pItems = &::gs_Items; - m_pMapLayersBackGround = &::gs_MapLayersBackGround; - m_pMapLayersForeGround = &::gs_MapLayersForeGround; - m_pStats = &::gs_Stats; - - // make a list of all the systems, make sure to add them in the corrent render order - m_All.Add(m_pSkins); - m_All.Add(m_pCountryFlags); - m_All.Add(m_pMapimages); - m_All.Add(m_pEffects); // doesn't render anything, just updates effects - m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles - m_All.Add(m_pBinds); - m_All.Add(&m_pBinds->m_SpecialBinds); - m_All.Add(m_pControls); - m_All.Add(m_pCamera); - m_All.Add(m_pSounds); - m_All.Add(m_pVoting); - - m_All.Add(&gs_MapLayersBackGround); // first to render - m_All.Add(&m_pParticles->m_RenderTrail); - m_All.Add(m_pItems); - m_All.Add(&gs_Players); - m_All.Add(&gs_MapLayersForeGround); - m_All.Add(&m_pParticles->m_RenderExplosions); - m_All.Add(&gs_NamePlates); - m_All.Add(&m_pParticles->m_RenderGeneral); - m_All.Add(m_pDamageind); - m_All.Add(&gs_Hud); - m_All.Add(&gs_Spectator); - m_All.Add(&gs_Emoticon); - m_All.Add(&gs_InfoMessages); - m_All.Add(m_pChat); - m_All.Add(&gs_Broadcast); - m_All.Add(&gs_DebugHud); - m_All.Add(&gs_Notifications); - m_All.Add(&gs_Scoreboard); - m_All.Add(m_pStats); - m_All.Add(m_pMotd); - m_All.Add(m_pMenus); - m_All.Add(&m_pMenus->m_Binder); - m_All.Add(m_pGameConsole); - - // build the input stack - m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key - m_Input.Add(&m_pBinds->m_SpecialBinds); - m_Input.Add(m_pGameConsole); - m_Input.Add(m_pChat); // chat has higher prio due to tha you can quit it by pressing esc - m_Input.Add(m_pMotd); // for pressing esc to remove it - m_Input.Add(m_pMenus); - m_Input.Add(&gs_Spectator); - m_Input.Add(&gs_Emoticon); - m_Input.Add(m_pControls); - m_Input.Add(m_pBinds); - - // add the some console commands - Console()->Register("team", "i[team]", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); - Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself"); - Console()->Register("ready_change", "", CFGFLAG_CLIENT, ConReadyChange, this, "Change ready state"); - - Console()->Chain("add_friend", ConchainFriendUpdate, this); - Console()->Chain("remove_friend", ConchainFriendUpdate, this); - Console()->Chain("add_ignore", ConchainBlacklistUpdate, this); - Console()->Chain("remove_ignore", ConchainBlacklistUpdate, this); - Console()->Chain("cl_show_xmas_hats", ConchainXmasHatUpdate, this); - Console()->Chain("player_color_body", ConchainSkinChange, this); - Console()->Chain("player_color_marking", ConchainSkinChange, this); - Console()->Chain("player_color_decoration", ConchainSkinChange, this); - Console()->Chain("player_color_hands", ConchainSkinChange, this); - Console()->Chain("player_color_feet", ConchainSkinChange, this); - Console()->Chain("player_color_eyes", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_body", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_marking", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_decoration", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_hands", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_feet", ConchainSkinChange, this); - Console()->Chain("player_use_custom_color_eyes", ConchainSkinChange, this); - Console()->Chain("player_skin", ConchainSkinChange, this); - Console()->Chain("player_skin_body", ConchainSkinChange, this); - Console()->Chain("player_skin_marking", ConchainSkinChange, this); - Console()->Chain("player_skin_decoration", ConchainSkinChange, this); - Console()->Chain("player_skin_hands", ConchainSkinChange, this); - Console()->Chain("player_skin_feet", ConchainSkinChange, this); - Console()->Chain("player_skin_eyes", ConchainSkinChange, this); - - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->m_pClient = this; - - // let all the other components register their console commands - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnConsoleInit(); - - // - m_SuppressEvents = false; -} - -void CGameClient::OnInit() -{ - m_pGraphics = Kernel()->RequestInterface(); - - // propagate pointers - m_UI.Init(Config(), Graphics(), TextRender()); - m_RenderTools.Init(Config(), Graphics(), UI()); - - int64 Start = time_get(); - - // Render load screen at 0% to get graphics sooner. - // Swap again to minimize initial flashing color. - m_pMenus->InitLoading(1); - m_pMenus->RenderLoading(); - m_pGraphics->Swap(); - - // TODO: this should be different - // setup item sizes - // HACK: only set static size for items, which were available in the first 0.7 release - // so new items don't break the snapshot delta - static const int OLD_NUM_NETOBJTYPES = 23; - for(int i = 0; i < OLD_NUM_NETOBJTYPES; i++) - Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); - - // determine total work for loading all components - int TotalWorkAmount = g_pData->m_NumImages + 4 + 1 + 1 + 2; // +4=load init, +1=font, +1=localization, +2=editor - for(int i = m_All.m_Num-1; i >= 0; --i) - TotalWorkAmount += m_All.m_paComponents[i]->GetInitAmount(); - - m_pMenus->InitLoading(TotalWorkAmount); - m_pMenus->RenderLoading(4); - - // load default font - char aFontName[IO_MAX_PATH_LENGTH]; - str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->m_ClFontfile); - char aFilename[IO_MAX_PATH_LENGTH]; - IOHANDLE File = Storage()->OpenFile(aFontName, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); - if(File) - { - io_close(File); - if(TextRender()->LoadFont(aFilename)) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "failed to load font. filename='%s'", aFontName); - Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", aBuf); - } - } - m_pMenus->RenderLoading(1); - - // set the language - g_Localization.Load(Config()->m_ClLanguagefile, Storage(), Console()); - m_pMenus->RenderLoading(1); - - // init all components - for(int i = m_All.m_Num-1; i >= 0; --i) - m_All.m_paComponents[i]->OnInit(); // this will call RenderLoading again - - // load textures - for(int i = 0; i < g_pData->m_NumImages; i++) - { - g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, g_pData->m_aImages[i].m_Flag ? IGraphics::TEXLOAD_LINEARMIPMAPS : 0); - m_pMenus->RenderLoading(1); - } - - // init the editor - m_pEditor->Init(); - m_pMenus->RenderLoading(2); - - OnReset(); - - m_ServerMode = SERVERMODE_PURE; - - m_IsXmasDay = time_isxmasday(); - m_IsEasterDay = time_iseasterday(); - m_pMenus->RenderLoading(); - m_InitComplete = true; - - int64 End = time_get(); - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End - Start) * 1000) / (float)time_freq()); - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); -} - -void CGameClient::OnUpdate() -{ - // handle mouse and joystick movement, prefer mouse movement - float x = 0.0f, y = 0.0f; - int CursorType = Input()->CursorRelative(&x, &y); - if(CursorType != IInput::CURSOR_NONE) - { - for(int h = 0; h < m_Input.m_Num; h++) - { - if(m_Input.m_paComponents[h]->OnCursorMove(x, y, CursorType)) - break; - } - } - - // handle key presses - for(int i = 0; i < Input()->NumEvents(); i++) - { - IInput::CEvent e = Input()->GetEvent(i); - if(!Input()->IsEventValid(&e)) - continue; - - for(int h = 0; h < m_Input.m_Num; h++) - { - if(m_Input.m_paComponents[h]->OnInput(e)) - break; - } - } -} - -int CGameClient::OnSnapInput(int *pData) -{ - return m_pControls->SnapInput(pData); -} - -void CGameClient::OnConnected() -{ - m_Layers.Init(Kernel()); - m_Collision.Init(Layers()); - - for(int i = 0; i < m_All.m_Num; i++) - { - m_All.m_paComponents[i]->OnMapLoad(); - m_All.m_paComponents[i]->OnReset(); - } - - m_ServerMode = SERVERMODE_PURE; - - // send the inital info - SendStartInfo(); -} - -void CGameClient::OnReset() -{ - // clear out the invalid pointers - m_LastNewPredictedTick = -1; - mem_zero(&m_Snap, sizeof(m_Snap)); - - for(int i = 0; i < MAX_CLIENTS; i++) - m_aClients[i].Reset(this, i); - - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnReset(); - - m_LocalClientID = -1; - m_TeamCooldownTick = 0; - m_TeamChangeTime = 0.0f; - m_LastSkinChangeTime = Client()->LocalTime(); - mem_zero(&m_GameInfo, sizeof(m_GameInfo)); - m_DemoSpecMode = SPEC_FREEVIEW; - m_DemoSpecID = -1; - m_Tuning = CTuningParams(); - m_MuteServerBroadcast = false; - m_LastGameStartTick = -1; - m_LastFlagCarrierRed = FLAG_MISSING; - m_LastFlagCarrierBlue = FLAG_MISSING; -} - -void CGameClient::UpdatePositions() -{ - // `m_LocalCharacterPos` is used for many things besides rendering the - // player (e.g. camera position, mouse input), which is why we set it here. - if(ShouldUsePredicted() && ShouldUsePredictedLocalChar()) - { - m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); - } - else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) - { - m_LocalCharacterPos = UnpredictedCharPos(m_LocalClientID); - } - - // spectator position - if(m_Snap.m_SpecInfo.m_Active) - { - if(Client()->State() == IClient::STATE_DEMOPLAYBACK && - DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && - m_Snap.m_SpecInfo.m_SpectatorID != -1) - { - m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos(m_Snap.m_SpecInfo.m_SpectatorID); - m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; - m_Snap.m_SpecInfo.m_UsePosition = true; - } - else if( - m_Snap.m_pSpectatorInfo && - ( - Client()->State() == IClient::STATE_DEMOPLAYBACK || - m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW || - ( - m_Snap.m_pLocalInfo && - (m_Snap.m_pLocalInfo->m_PlayerFlags & PLAYERFLAG_DEAD) && - m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW - ) - )) - { - if(m_Snap.m_pPrevSpectatorInfo) - m_Snap.m_SpecInfo.m_Position = mix( - vec2( - m_Snap.m_pPrevSpectatorInfo->m_X, - m_Snap.m_pPrevSpectatorInfo->m_Y - ), - vec2( - m_Snap.m_pSpectatorInfo->m_X, - m_Snap.m_pSpectatorInfo->m_Y - ), - Client()->IntraGameTick() - ); - else - m_Snap.m_SpecInfo.m_Position = vec2( - m_Snap.m_pSpectatorInfo->m_X, - m_Snap.m_pSpectatorInfo->m_Y - ); - - m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; - m_Snap.m_SpecInfo.m_UsePosition = true; - } - } -} - -void CGameClient::EvolveCharacter(CNetObj_Character *pCharacter, int Tick) -{ - CWorldCore TempWorld; - CCharacterCore TempCore; - mem_zero(&TempCore, sizeof(TempCore)); - TempCore.Init(&TempWorld, Collision()); - TempCore.Read(pCharacter); - - while(pCharacter->m_Tick < Tick) - { - pCharacter->m_Tick++; - TempCore.Tick(false); - TempCore.Move(); - TempCore.Quantize(); - } - - TempCore.Write(pCharacter); -} - -void CGameClient::StartRendering() -{ - if(Config()->m_GfxClear) - { - if(m_pMenus->IsBackgroundNeeded()) - Graphics()->Clear(0.45f, 0.45f, 0.45f); - else - Graphics()->Clear(1.0f, 1.0f, 0.0f); - } - else if(m_pMenus->IsBackgroundNeeded()) - { - // render background color - float sw = 300 * Graphics()->ScreenAspect(); - float sh = 300; - Graphics()->MapScreen(0, 0, sw, sh); - Graphics()->TextureClear(); - Graphics()->QuadsBegin(); - vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); - vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); - IGraphics::CColorVertex Array[4] = { - IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), - IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), - IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a) }; - Graphics()->SetColorVertex(Array, 4); - IGraphics::CQuadItem QuadItem(0, 0, sw, sh); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - } -} - -void CGameClient::OnRender() -{ - // update the local character and spectate position - UpdatePositions(); - - StartRendering(); - - // render all systems - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnRender(); - - // clear all events/input for this frame - Input()->Clear(); -} - -void CGameClient::OnRelease() -{ - // release all systems - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnRelease(); -} - -void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) -{ - Client()->RecordGameMessage(true); - - // special messages - if(MsgId == NETMSGTYPE_SV_TUNEPARAMS && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - // unpack the new tuning - CTuningParams NewTuning; - int *pParams = (int *)&NewTuning; - for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++) - pParams[i] = pUnpacker->GetInt(); - - // check for unpacking errors - if(pUnpacker->Error()) - return; - - m_ServerMode = SERVERMODE_PURE; - - // apply new tuning - m_Tuning = NewTuning; - return; - } - else if(MsgId == NETMSGTYPE_SV_VOTEOPTIONLISTADD) - { - int NumOptions = pUnpacker->GetInt(); - for(int i = 0; i < NumOptions; i++) - { - const char *pDescription = pUnpacker->GetString(CUnpacker::SANITIZE_CC); - if(pUnpacker->Error()) - return; - - m_pVoting->AddOption(pDescription); - } - } - else if(MsgId == NETMSGTYPE_SV_GAMEMSG) - { - int GameMsgID = pUnpacker->GetInt(); - - // check for valid gamemsgid - if(GameMsgID < 0 || GameMsgID >= NUM_GAMEMSGS) - return; - - int aParaI[3]; - int NumParaI = 0; - - // get paras - switch(gs_GameMsgList[GameMsgID].m_ParaType) - { - case PARA_I: NumParaI = 1; break; - case PARA_II: NumParaI = 2; break; - case PARA_III: NumParaI = 3; break; - } - for(int i = 0; i < NumParaI; i++) - { - aParaI[i] = pUnpacker->GetInt(); - } - - // check for unpacking errors - if(pUnpacker->Error()) - return; - - // handle special messages - char aBuf[256]; - bool TeamPlay = m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS; - if(gs_GameMsgList[GameMsgID].m_Action == DO_SPECIAL) - { - switch(GameMsgID) - { - case GAMEMSG_CTF_DROP: - if(m_SuppressEvents) - return; - m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_DROP); - break; - case GAMEMSG_CTF_RETURN: - if(m_SuppressEvents) - return; - m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_RETURN); - break; - case GAMEMSG_TEAM_ALL: - { - const char *pMsg; - switch(GetStrTeam(aParaI[0], TeamPlay)) - { - case STR_TEAM_GAME: pMsg = Localize("All players were moved to the game"); break; - case STR_TEAM_RED: pMsg = Localize("All players were moved to the red team"); break; - case STR_TEAM_BLUE: pMsg = Localize("All players were moved to the blue team"); break; - case STR_TEAM_SPECTATORS: pMsg = Localize("All players were moved to the spectators"); break; - } - m_pBroadcast->DoBroadcast(pMsg); - } - break; - case GAMEMSG_TEAM_BALANCE_VICTIM: - { - const char *pMsg = ""; - switch(GetStrTeam(aParaI[0], TeamPlay)) - { - case STR_TEAM_RED: pMsg = Localize("You were moved to the red team due to team balancing"); break; - case STR_TEAM_BLUE: pMsg = Localize("You were moved to the blue team due to team balancing"); break; - } - m_pBroadcast->DoBroadcast(pMsg); - } - break; - case GAMEMSG_CTF_GRAB: - if(m_SuppressEvents) - return; - if(m_LocalClientID != -1 && (m_aClients[m_LocalClientID].m_Team != aParaI[0] || (m_Snap.m_SpecInfo.m_Active && - ((m_Snap.m_SpecInfo.m_SpectatorID != -1 && m_aClients[m_Snap.m_SpecInfo.m_SpectatorID].m_Team != aParaI[0]) || - (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGRED && aParaI[0] != TEAM_RED) || - (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGBLUE && aParaI[0] != TEAM_BLUE))))) - m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_PL); - else - m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_EN); - break; - case GAMEMSG_GAME_PAUSED: - { - int ClientID = clamp(aParaI[0], 0, MAX_CLIENTS - 1); - char aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, m_aClients[ClientID].m_aName); - str_format(aBuf, sizeof(aBuf), Localize("'%s' initiated a pause"), aLabel); - m_pChat->AddLine(aBuf); - } - break; - case GAMEMSG_CTF_CAPTURE: - m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_CAPTURE); - int ClientID = clamp(aParaI[1], 0, MAX_CLIENTS - 1); - m_pStats->OnFlagCapture(ClientID); - char aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, m_aClients[ClientID].m_aName); - - float Time = aParaI[2] / (float)Client()->GameTickSpeed(); - if(Time <= 60) - { - if(aParaI[0]) - { - str_format(aBuf, sizeof(aBuf), Localize("The blue flag was captured by '%s' (%.2f seconds)"), aLabel, Time); - } - else - { - str_format(aBuf, sizeof(aBuf), Localize("The red flag was captured by '%s' (%.2f seconds)"), aLabel, Time); - } - } - else - { - if(aParaI[0]) - { - str_format(aBuf, sizeof(aBuf), Localize("The blue flag was captured by '%s'"), aLabel); - } - else - { - str_format(aBuf, sizeof(aBuf), Localize("The red flag was captured by '%s'"), aLabel); - } - } - m_pChat->AddLine(aBuf); - } - return; - } - - // build message - const char *pText = ""; - if(NumParaI == 0) - { - pText = Localize(gs_GameMsgList[GameMsgID].m_pText); - } - - // handle message - switch(gs_GameMsgList[GameMsgID].m_Action) - { - case DO_CHAT: - m_pChat->AddLine(pText); - break; - case DO_BROADCAST: - m_pBroadcast->DoBroadcast(pText); - break; - } - } - - void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); - if(!pRawMsg) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); - return; - } - - // TODO: this should be done smarter - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); - - if(MsgId == NETMSGTYPE_SV_CLIENTINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - CNetMsg_Sv_ClientInfo *pMsg = (CNetMsg_Sv_ClientInfo *)pRawMsg; - - if(pMsg->m_Local) - { - if(m_LocalClientID != -1) - { - if(Config()->m_Debug) - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid local clientinfo"); - return; - } - m_LocalClientID = pMsg->m_ClientID; - m_TeamChangeTime = Client()->LocalTime(); - } - else - { - if(m_aClients[pMsg->m_ClientID].m_Active) - { - if(Config()->m_Debug) - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientinfo"); - return; - } - - if(m_LocalClientID != -1 && !pMsg->m_Silent) - { - DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); - - if(m_pDemoRecorder->IsRecording()) - { - CNetMsg_De_ClientEnter Msg; - Msg.m_pName = pMsg->m_pName; - Msg.m_ClientID = pMsg->m_ClientID; - Msg.m_Team = pMsg->m_Team; - Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); - } - } - } - - m_aClients[pMsg->m_ClientID].m_Active = true; - m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; - str_copy(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_pName, sizeof(m_aClients[pMsg->m_ClientID].m_aName)); - str_copy(m_aClients[pMsg->m_ClientID].m_aClan, pMsg->m_pClan, sizeof(m_aClients[pMsg->m_ClientID].m_aClan)); - m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; - for(int i = 0; i < NUM_SKINPARTS; i++) - { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); - m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; - m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; - } - - // update friend state - m_aClients[pMsg->m_ClientID].m_Friend = Friends()->IsFriend(m_aClients[pMsg->m_ClientID].m_aName, m_aClients[pMsg->m_ClientID].m_aClan, true); - // update chat ignore state - m_aClients[pMsg->m_ClientID].m_ChatIgnore = Blacklist()->IsIgnored(m_aClients[pMsg->m_ClientID].m_aName, m_aClients[pMsg->m_ClientID].m_aClan, true); - if(m_aClients[pMsg->m_ClientID].m_ChatIgnore) - { - char aBuf[128]; - char aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), pMsg->m_ClientID, m_aClients[pMsg->m_ClientID].m_aName); - str_format(aBuf, sizeof(aBuf), Localize("%s is muted by you"), aLabel); - m_pChat->AddLine(aBuf, CChat::CLIENT_MSG); - } - - m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, true); - - m_GameInfo.m_NumPlayers++; - // calculate team-balance - if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) - m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; - - m_pStats->OnPlayerEnter(pMsg->m_ClientID, pMsg->m_Team); - } - else if(MsgId == NETMSGTYPE_SV_CLIENTDROP && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - CNetMsg_Sv_ClientDrop *pMsg = (CNetMsg_Sv_ClientDrop *)pRawMsg; - - if(m_LocalClientID == pMsg->m_ClientID || !m_aClients[pMsg->m_ClientID].m_Active) - { - if(Config()->m_Debug) - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop"); - return; - } - - if(!pMsg->m_Silent) - { - DoLeaveMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_pReason); - - CNetMsg_De_ClientLeave Msg; - Msg.m_pName = m_aClients[pMsg->m_ClientID].m_aName; - Msg.m_ClientID = pMsg->m_ClientID; - Msg.m_pReason = pMsg->m_pReason; - Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD); - } - - m_GameInfo.m_NumPlayers--; - // calculate team-balance - if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) - m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; - - m_aClients[pMsg->m_ClientID].Reset(this, pMsg->m_ClientID); - m_pStats->OnPlayerLeave(pMsg->m_ClientID); - } - else if(MsgId == NETMSGTYPE_SV_SKINCHANGE && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - CNetMsg_Sv_SkinChange *pMsg = (CNetMsg_Sv_SkinChange *)pRawMsg; - - if(!m_aClients[pMsg->m_ClientID].m_Active) - { - if(Config()->m_Debug) - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid skin info"); - return; - } - - for(int i = 0; i < NUM_SKINPARTS; i++) - { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); - m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; - m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; - } - m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, true); - } - else if(MsgId == NETMSGTYPE_SV_GAMEINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - CNetMsg_Sv_GameInfo *pMsg = (CNetMsg_Sv_GameInfo *)pRawMsg; - - m_GameInfo.m_GameFlags = pMsg->m_GameFlags; - m_GameInfo.m_ScoreLimit = pMsg->m_ScoreLimit; - m_GameInfo.m_TimeLimit = pMsg->m_TimeLimit; - m_GameInfo.m_MatchNum = pMsg->m_MatchNum; - m_GameInfo.m_MatchCurrent = pMsg->m_MatchCurrent; - } - else if(MsgId == NETMSGTYPE_SV_SERVERSETTINGS && Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - Client()->RecordGameMessage(false); - CNetMsg_Sv_ServerSettings *pMsg = (CNetMsg_Sv_ServerSettings *)pRawMsg; - - if(!m_ServerSettings.m_TeamLock && pMsg->m_TeamLock) - m_pChat->AddLine(Localize("Teams were locked")); - else if(m_ServerSettings.m_TeamLock && !pMsg->m_TeamLock) - m_pChat->AddLine(Localize("Teams were unlocked")); - - m_ServerSettings.m_KickVote = pMsg->m_KickVote; - m_ServerSettings.m_KickMin = pMsg->m_KickMin; - m_ServerSettings.m_SpecVote = pMsg->m_SpecVote; - m_ServerSettings.m_TeamLock = pMsg->m_TeamLock; - m_ServerSettings.m_TeamBalance = pMsg->m_TeamBalance; - m_ServerSettings.m_PlayerSlots = pMsg->m_PlayerSlots; - } - else if(MsgId == NETMSGTYPE_SV_TEAM) - { - CNetMsg_Sv_Team *pMsg = (CNetMsg_Sv_Team *)pRawMsg; - - if(Client()->State() != IClient::STATE_DEMOPLAYBACK) - { - // calculate team-balance - if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) - m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; - m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; - if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) - m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; - - m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, false); - - if(pMsg->m_ClientID == m_LocalClientID) - { - m_TeamCooldownTick = pMsg->m_CooldownTick; - m_TeamChangeTime = Client()->LocalTime(); - } - } - - if(pMsg->m_Silent == 0) - { - DoTeamChangeMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_Team); - } - } - else if(MsgId == NETMSGTYPE_SV_READYTOENTER) - { - Client()->EnterGame(); - } - else if (MsgId == NETMSGTYPE_SV_EMOTICON) - { - CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg; - - // apply - m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon; - m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(); - } - else if(MsgId == NETMSGTYPE_DE_CLIENTENTER && Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - CNetMsg_De_ClientEnter *pMsg = (CNetMsg_De_ClientEnter *)pRawMsg; - DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); - m_pStats->OnPlayerEnter(pMsg->m_ClientID, pMsg->m_Team); - } - else if(MsgId == NETMSGTYPE_DE_CLIENTLEAVE && Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - CNetMsg_De_ClientLeave *pMsg = (CNetMsg_De_ClientLeave *)pRawMsg; - DoLeaveMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_pReason); - m_pStats->OnPlayerLeave(pMsg->m_ClientID); - } -} - -void CGameClient::OnStateChange(int NewState, int OldState) -{ - // reset everything when not already connected (to keep gathered stuff) - if(NewState < IClient::STATE_ONLINE) - OnReset(); - - // then change the state - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnStateChange(NewState, OldState); -} - -void CGameClient::OnShutdown() -{ - for(int i = 0; i < m_All.m_Num; i++) - m_All.m_paComponents[i]->OnShutdown(); -} -void CGameClient::OnEnterGame() {} - -void CGameClient::OnGameOver() -{ - if(Client()->State() != IClient::STATE_DEMOPLAYBACK && Config()->m_ClEditor == 0) - Client()->AutoScreenshot_Start(); -} - -void CGameClient::OnStartGame() -{ - if(Client()->State() != IClient::STATE_DEMOPLAYBACK) - Client()->DemoRecorder_HandleAutoStart(); -} - -void CGameClient::OnRconLine(const char *pLine) -{ - m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); -} - -void CGameClient::ProcessEvents() -{ - if(m_SuppressEvents) - return; - - int SnapType = IClient::SNAP_CURRENT; - int Num = Client()->SnapNumItems(SnapType); - for(int Index = 0; Index < Num; Index++) - { - IClient::CSnapItem Item; - const void *pData = Client()->SnapGetItem(SnapType, Index, &Item); - - if(Item.m_Type == NETEVENTTYPE_DAMAGE) - { - CNetEvent_Damage *ev = (CNetEvent_Damage *)pData; - m_pEffects->DamageIndicator(vec2(ev->m_X, ev->m_Y), ev->m_HealthAmount + ev->m_ArmorAmount); - } - else if(Item.m_Type == NETEVENTTYPE_EXPLOSION) - { - CNetEvent_Explosion *ev = (CNetEvent_Explosion *)pData; - m_pEffects->Explosion(vec2(ev->m_X, ev->m_Y)); - } - else if(Item.m_Type == NETEVENTTYPE_HAMMERHIT) - { - CNetEvent_HammerHit *ev = (CNetEvent_HammerHit *)pData; - m_pEffects->HammerHit(vec2(ev->m_X, ev->m_Y)); - } - else if(Item.m_Type == NETEVENTTYPE_SPAWN) - { - CNetEvent_Spawn *ev = (CNetEvent_Spawn *)pData; - m_pEffects->PlayerSpawn(vec2(ev->m_X, ev->m_Y)); - } - else if(Item.m_Type == NETEVENTTYPE_DEATH) - { - CNetEvent_Death *ev = (CNetEvent_Death *)pData; - m_pEffects->PlayerDeath(vec2(ev->m_X, ev->m_Y), ev->m_ClientID); - } - else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD) - { - CNetEvent_SoundWorld *ev = (CNetEvent_SoundWorld *)pData; - m_pSounds->PlayAt(CSounds::CHN_WORLD, ev->m_SoundID, 1.0f, vec2(ev->m_X, ev->m_Y)); - } - } -} - -void CGameClient::ProcessTriggeredEvents(int Events, vec2 Pos) -{ - if(m_SuppressEvents) - return; - - if(Events&COREEVENTFLAG_GROUND_JUMP) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos); - if(Events&COREEVENTFLAG_AIR_JUMP) - m_pEffects->AirJump(Pos); - if(Events&COREEVENTFLAG_HOOK_ATTACH_PLAYER) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, Pos); - if(Events&COREEVENTFLAG_HOOK_ATTACH_GROUND) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos); - if(Events&COREEVENTFLAG_HOOK_HIT_NOHOOK) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos); - /*if(Events&COREEVENTFLAG_HOOK_LAUNCH) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, Pos); - if(Events&COREEVENTFLAG_HOOK_RETRACT) - m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos);*/ -} - -typedef bool (*FCompareFunc)(const CNetObj_PlayerInfo*, const CNetObj_PlayerInfo*); - -bool CompareScore(const CNetObj_PlayerInfo *Pl1, const CNetObj_PlayerInfo *Pl2) -{ - return Pl1->m_Score < Pl2->m_Score; -} - -bool CompareTime(const CNetObj_PlayerInfo *Pl1, const CNetObj_PlayerInfo *Pl2) -{ - if(Pl1->m_Score < 0) - return true; - if(Pl2->m_Score < 0) - return false; - return Pl1->m_Score > Pl2->m_Score; -} - -void CGameClient::OnNewSnapshot() -{ - // clear out the invalid pointers - mem_zero(&m_Snap, sizeof(m_Snap)); - - // secure snapshot - { - int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); - for(int Index = 0; Index < Num; Index++) - { - IClient::CSnapItem Item; - const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); - if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) - { - if(Config()->m_Debug) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID); - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - } - Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index); - } - } - } - - ProcessEvents(); - - if(Config()->m_DbgStress) - { - if((Client()->GameTick()%100) == 0) - { - char aMessage[64]; - int MsgLen = random_int()%(sizeof(aMessage)-1); - for(int i = 0; i < MsgLen; i++) - aMessage[i] = 'a'+(random_int()%('z'-'a')); - aMessage[MsgLen] = 0; - - CNetMsg_Cl_Say Msg; - Msg.m_Mode = random_int()&1; - Msg.m_Target = -1; - Msg.m_pMessage = aMessage; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); - } - } - - CTuningParams StandardTuning; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - m_Tuning = StandardTuning; - mem_zero(&m_GameInfo, sizeof(m_GameInfo)); - } - - // go trough all the items in the snapshot and gather the info we want - { - int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); - for(int i = 0; i < Num; i++) - { - IClient::CSnapItem Item; - const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - - // demo items - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - if(Item.m_Type == NETOBJTYPE_DE_CLIENTINFO) - { - const CNetObj_De_ClientInfo *pInfo = (const CNetObj_De_ClientInfo *)pData; - int ClientID = Item.m_ID; - if(ClientID < MAX_CLIENTS) - { - CClientData *pClient = &m_aClients[ClientID]; - - if(pInfo->m_Local) - m_LocalClientID = ClientID; - pClient->m_Active = true; - pClient->m_Team = pInfo->m_Team; - IntsToStr(pInfo->m_aName, 4, pClient->m_aName); - IntsToStr(pInfo->m_aClan, 3, pClient->m_aClan); - pClient->m_Country = pInfo->m_Country; - - for(int p = 0; p < NUM_SKINPARTS; p++) - { - IntsToStr(pInfo->m_aaSkinPartNames[p], 6, pClient->m_aaSkinPartNames[p]); - pClient->m_aUseCustomColors[p] = pInfo->m_aUseCustomColors[p]; - pClient->m_aSkinPartColors[p] = pInfo->m_aSkinPartColors[p]; - } - - m_GameInfo.m_NumPlayers++; - // calculate team-balance - if(pClient->m_Team != TEAM_SPECTATORS) - m_GameInfo.m_aTeamSize[pClient->m_Team]++; - } - } - else if(Item.m_Type == NETOBJTYPE_DE_GAMEINFO) - { - const CNetObj_De_GameInfo *pInfo = (const CNetObj_De_GameInfo *)pData; - - m_GameInfo.m_GameFlags = pInfo->m_GameFlags; - m_GameInfo.m_ScoreLimit = pInfo->m_ScoreLimit; - m_GameInfo.m_TimeLimit = pInfo->m_TimeLimit; - m_GameInfo.m_MatchNum = pInfo->m_MatchNum; - m_GameInfo.m_MatchCurrent = pInfo->m_MatchCurrent; - } - else if(Item.m_Type == NETOBJTYPE_DE_TUNEPARAMS) - { - const CNetObj_De_TuneParams *pInfo = (const CNetObj_De_TuneParams *)pData; - - mem_copy(&m_Tuning, pInfo->m_aTuneParams, sizeof(m_Tuning)); - m_ServerMode = SERVERMODE_PURE; - } - } - - // network items - if(Item.m_Type == NETOBJTYPE_PLAYERINFO) - { - const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; - int ClientID = Item.m_ID; - if(ClientID < MAX_CLIENTS && m_aClients[ClientID].m_Active) - { - m_Snap.m_paPlayerInfos[ClientID] = pInfo; - m_Snap.m_aInfoByScore[ClientID].m_pPlayerInfo = pInfo; - m_Snap.m_aInfoByScore[ClientID].m_ClientID = ClientID; - - if(m_LocalClientID == ClientID) - { - m_Snap.m_pLocalInfo = pInfo; - - if(m_aClients[ClientID].m_Team == TEAM_SPECTATORS) - { - m_Snap.m_SpecInfo.m_Active = true; - m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; - m_Snap.m_SpecInfo.m_SpectatorID = -1; - } - } - m_aClients[ClientID].UpdateBotRenderInfo(this, ClientID); - } - } - else if(Item.m_Type == NETOBJTYPE_PLAYERINFORACE) - { - const CNetObj_PlayerInfoRace *pInfo = (const CNetObj_PlayerInfoRace *)pData; - int ClientID = Item.m_ID; - if(ClientID < MAX_CLIENTS && m_aClients[ClientID].m_Active) - { - m_Snap.m_paPlayerInfosRace[ClientID] = pInfo; - } - } - else if(Item.m_Type == NETOBJTYPE_CHARACTER) - { - if(Item.m_ID < MAX_CLIENTS) - { - CSnapState::CCharacterInfo *pCharInfo = &m_Snap.m_aCharacters[Item.m_ID]; - const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID); - pCharInfo->m_Cur = *((const CNetObj_Character *)pData); - - // clamp ammo count for non ninja weapon - if(pCharInfo->m_Cur.m_Weapon != WEAPON_NINJA) - pCharInfo->m_Cur.m_AmmoCount = clamp(pCharInfo->m_Cur.m_AmmoCount, 0, 10); - - if(pOld) - { - pCharInfo->m_Active = true; - pCharInfo->m_Prev = *((const CNetObj_Character *)pOld); - - // limit evolving to 3 seconds - int EvolvePrevTick = min(pCharInfo->m_Prev.m_Tick + Client()->GameTickSpeed()*3, Client()->PrevGameTick()); - int EvolveCurTick = min(pCharInfo->m_Cur.m_Tick + Client()->GameTickSpeed()*3, Client()->GameTick()); - - // reuse the evolved char - if(m_aClients[Item.m_ID].m_Evolved.m_Tick == EvolvePrevTick) - { - pCharInfo->m_Prev = m_aClients[Item.m_ID].m_Evolved; - if(mem_comp(pData, pOld, sizeof(CNetObj_Character)) == 0) - pCharInfo->m_Cur = m_aClients[Item.m_ID].m_Evolved; - } - - if(pCharInfo->m_Prev.m_Tick) - EvolveCharacter(&pCharInfo->m_Prev, EvolvePrevTick); - if(pCharInfo->m_Cur.m_Tick) - EvolveCharacter(&pCharInfo->m_Cur, EvolveCurTick); - - m_aClients[Item.m_ID].m_Evolved = m_Snap.m_aCharacters[Item.m_ID].m_Cur; - } - - if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK) - ProcessTriggeredEvents(pCharInfo->m_Cur.m_TriggeredEvents, vec2(pCharInfo->m_Cur.m_X, pCharInfo->m_Cur.m_Y)); - } - } - else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO) - { - m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData; - m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID); - m_Snap.m_SpecInfo.m_Active = true; - m_Snap.m_SpecInfo.m_SpecMode = m_Snap.m_pSpectatorInfo->m_SpecMode; - m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID; - } - else if(Item.m_Type == NETOBJTYPE_GAMEDATA) - { - m_Snap.m_pGameData = (const CNetObj_GameData *)pData; - - static int s_LastGameFlags = 0; - int GameFlags = m_Snap.m_pGameData->m_GameStateFlags; - if(!(s_LastGameFlags&GAMESTATEFLAG_GAMEOVER) && GameFlags&GAMESTATEFLAG_GAMEOVER) - OnGameOver(); - else if(s_LastGameFlags&GAMESTATEFLAG_GAMEOVER && !(GameFlags&GAMESTATEFLAG_GAMEOVER)) - OnStartGame(); - - // stats - if(m_Snap.m_pGameData->m_GameStartTick != m_LastGameStartTick && !(s_LastGameFlags&GAMESTATEFLAG_ROUNDOVER) - && !(s_LastGameFlags&GAMESTATEFLAG_PAUSED) && (!(GameFlags&GAMESTATEFLAG_PAUSED) || GameFlags&GAMESTATEFLAG_STARTCOUNTDOWN)) - { - m_pStats->OnMatchStart(); - } - - if(!(GameFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) - m_pStats->UpdatePlayTime(Client()->GameTick() - Client()->PrevGameTick()); - - s_LastGameFlags = GameFlags; - m_LastGameStartTick = m_Snap.m_pGameData->m_GameStartTick; - } - else if(Item.m_Type == NETOBJTYPE_GAMEDATATEAM) - { - m_Snap.m_pGameDataTeam = (const CNetObj_GameDataTeam *)pData; - } - else if(Item.m_Type == NETOBJTYPE_GAMEDATAFLAG) - { - m_Snap.m_pGameDataFlag = (const CNetObj_GameDataFlag *)pData; - m_Snap.m_GameDataFlagSnapID = Item.m_ID; - - // stats - if(m_LastFlagCarrierRed == FLAG_ATSTAND && m_Snap.m_pGameDataFlag->m_FlagCarrierRed >= 0) - m_pStats->OnFlagGrab(m_Snap.m_pGameDataFlag->m_FlagCarrierRed); - else if(m_LastFlagCarrierBlue == FLAG_ATSTAND && m_Snap.m_pGameDataFlag->m_FlagCarrierBlue >= 0) - m_pStats->OnFlagGrab(m_Snap.m_pGameDataFlag->m_FlagCarrierBlue); - - m_LastFlagCarrierRed = m_Snap.m_pGameDataFlag->m_FlagCarrierRed; - m_LastFlagCarrierBlue = m_Snap.m_pGameDataFlag->m_FlagCarrierBlue; - } - else if(Item.m_Type == NETOBJTYPE_GAMEDATARACE) - { - m_Snap.m_pGameDataRace = (const CNetObj_GameDataRace *)pData; - } - else if(Item.m_Type == NETOBJTYPE_FLAG) - { - m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData; - } - } - } - - // setup local pointers - if(m_LocalClientID >= 0) - { - CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_LocalClientID]; - if(c->m_Active) - { - if (!m_Snap.m_SpecInfo.m_Active) - { - m_Snap.m_pLocalCharacter = &c->m_Cur; - m_Snap.m_pLocalPrevCharacter = &c->m_Prev; - m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); - } - } - else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_LocalClientID)) - { - // player died - m_pControls->OnPlayerDeath(); - } - } - else - { - m_Snap.m_SpecInfo.m_Active = true; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && - m_DemoSpecID != -1 && m_Snap.m_aCharacters[m_DemoSpecID].m_Active) - { - m_Snap.m_SpecInfo.m_SpecMode = SPEC_PLAYER; - m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; - } - else - { - if (m_DemoSpecMode == SPEC_PLAYER) - { - m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; - m_Snap.m_SpecInfo.m_SpectatorID = -1; - } - else - { - m_Snap.m_SpecInfo.m_SpecMode = m_DemoSpecMode; - m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; - } - } - } - - // sort player infos by score - FCompareFunc Compare = (m_GameInfo.m_GameFlags&GAMEFLAG_RACE) ? CompareTime : CompareScore; - - for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort - { - for(int i = 0; i < MAX_CLIENTS-k-1; i++) - { - if(m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo && (!m_Snap.m_aInfoByScore[i].m_pPlayerInfo || - Compare(m_Snap.m_aInfoByScore[i].m_pPlayerInfo, m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo))) - { - CPlayerInfoItem Tmp = m_Snap.m_aInfoByScore[i]; - m_Snap.m_aInfoByScore[i] = m_Snap.m_aInfoByScore[i+1]; - m_Snap.m_aInfoByScore[i+1] = Tmp; - } - } - } - - // calc some player stats - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(!m_Snap.m_paPlayerInfos[i]) - continue; - - // count not ready players - if(m_Snap.m_pGameData && (m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_WARMUP)) && - m_Snap.m_pGameData->m_GameStateEndTick == 0 && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY)) - m_Snap.m_NotReadyCount++; - - // count alive players per team - if((m_GameInfo.m_GameFlags&GAMEFLAG_SURVIVAL) && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD)) - m_Snap.m_AliveCount[m_aClients[i].m_Team]++; - } - - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(m_aClients[i].m_Active) - m_aClients[i].UpdateRenderInfo(this, i, true); - } - } - - CServerInfo CurrentServerInfo; - Client()->GetServerInfo(&CurrentServerInfo); - if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0 && - str_comp(CurrentServerInfo.m_aGameType, "LMS") != 0 && str_comp(CurrentServerInfo.m_aGameType, "LTS") != 0) - m_ServerMode = SERVERMODE_MOD; - else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0) - m_ServerMode = SERVERMODE_PURE; - else - m_ServerMode = SERVERMODE_PUREMOD; -} - -void CGameClient::OnDemoRecSnap() -{ - // add client info - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(!m_aClients[i].m_Active) - continue; - - CNetObj_De_ClientInfo *pClientInfo = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_CLIENTINFO, i, sizeof(CNetObj_De_ClientInfo))); - if(!pClientInfo) - return; - - pClientInfo->m_Local = i==m_LocalClientID ? 1 : 0; - pClientInfo->m_Team = m_aClients[i].m_Team; - StrToInts(pClientInfo->m_aName, 4, m_aClients[i].m_aName); - StrToInts(pClientInfo->m_aClan, 3, m_aClients[i].m_aClan); - pClientInfo->m_Country = m_aClients[i].m_Country; - - for(int p = 0; p < NUM_SKINPARTS; p++) - { - StrToInts(pClientInfo->m_aaSkinPartNames[p], 6, m_aClients[i].m_aaSkinPartNames[p]); - pClientInfo->m_aUseCustomColors[p] = m_aClients[i].m_aUseCustomColors[p]; - pClientInfo->m_aSkinPartColors[p] = m_aClients[i].m_aSkinPartColors[p]; - } - } - - // add tuning - CTuningParams StandardTuning; - if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) != 0) - { - CNetObj_De_TuneParams *pTuneParams = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_TUNEPARAMS, 0, sizeof(CNetObj_De_TuneParams))); - if(!pTuneParams) - return; - - mem_copy(pTuneParams->m_aTuneParams, &m_Tuning, sizeof(pTuneParams->m_aTuneParams)); - } - - // add game info - CNetObj_De_GameInfo *pGameInfo = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_GAMEINFO, 0, sizeof(CNetObj_De_GameInfo))); - if(!pGameInfo) - return; - - pGameInfo->m_GameFlags = m_GameInfo.m_GameFlags; - pGameInfo->m_ScoreLimit = m_GameInfo.m_ScoreLimit; - pGameInfo->m_TimeLimit = m_GameInfo.m_TimeLimit; - pGameInfo->m_MatchNum = m_GameInfo.m_MatchNum; - pGameInfo->m_MatchCurrent = m_GameInfo.m_MatchCurrent; -} - -void CGameClient::OnPredict() -{ - // Here we predict player movements. For the local player, we also predict - // the result of the local input to make the game appear responsive even at - // high latencies. For non-local players, we predict what will happen if - // they don't apply any inputs. In both cases we are extrapolating - // (predicting) what will happen between `GameTick` and `PredGameTick`. - - // don't predict anything if we are paused or round/game is over - if(IsWorldPaused()) - { - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(!m_Snap.m_aCharacters[i].m_Active) - continue; - - // instead of predicting into the future, just use the current and - // previous snapshots that we already have - m_aPredictedPrevChars[i].Read(&m_Snap.m_aCharacters[i].m_Prev); - m_aPredictedChars[i].Read(&m_Snap.m_aCharacters[i].m_Cur); - } - - return; - } - - // repredict character - CWorldCore World; - World.m_Tuning = m_Tuning; - - // search for players - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(!m_Snap.m_aCharacters[i].m_Active) - continue; - - m_aClients[i].m_Predicted.Init(&World, Collision()); - World.m_apCharacters[i] = &m_aClients[i].m_Predicted; - m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); - } - - // predict - for(int Tick = Client()->GameTick() + 1; - Tick <= Client()->PredGameTick(); - Tick++) - { - // first calculate where everyone should move - for(int c = 0; c < MAX_CLIENTS; c++) - { - if(!World.m_apCharacters[c]) - continue; - - // Before running the last iteration, store our predictions. We use - // `Prev` because we haven't run the last iteration yet, so our - // data is from the previous tick. - if(Tick == Client()->PredGameTick()) - m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; - - mem_zero( - &World.m_apCharacters[c]->m_Input, - sizeof(World.m_apCharacters[c]->m_Input) - ); - - if(m_LocalClientID == c) - { - // apply player input - const int *pInput = Client()->GetInput(Tick); - if (pInput) - World.m_apCharacters[c]->m_Input = *( - (const CNetObj_PlayerInput*)pInput - ); - - World.m_apCharacters[c]->Tick(true); - } - else - { - // don't apply inputs for non-local players - World.m_apCharacters[c]->Tick(false); - } - } - - // move all players and quantize their data - for(int c = 0; c < MAX_CLIENTS; c++) - { - if (!World.m_apCharacters[c]) - continue; - - World.m_apCharacters[c]->AddDragVelocity(); - World.m_apCharacters[c]->ResetDragVelocity(); - World.m_apCharacters[c]->Move(); - World.m_apCharacters[c]->Quantize(); - } - - // check if we want to trigger effects - if(Tick > m_LastNewPredictedTick) - { - m_LastNewPredictedTick = Tick; - - // Only trigger effects for the local character here. Effects for - // non-local characters are triggered in `OnNewSnapshot`. Since we - // don't apply any inputs to non-local characters, it's not - // necessary to trigger events for them here. Also, our predictions - // for other players will often be wrong, so it's safer not to - // trigger events here. - if(m_LocalClientID != -1 && - World.m_apCharacters[m_LocalClientID]) - { - ProcessTriggeredEvents( - World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, - World.m_apCharacters[m_LocalClientID]->m_Pos - ); - } - } - - // After running the last iteration, store our final prediction. We should - // now have the following predictions: - // - `m_aPredictedPrevChars` stores character predictions at time - // `PredGameTick - 1` - // - `m_aPredictedChars` stores character predictions at time - // `PredGameTick` - if(Tick == Client()->PredGameTick()) - { - for(int c = 0; c < MAX_CLIENTS; c++) - { - if(World.m_apCharacters[c]) - m_aPredictedChars[c] = *World.m_apCharacters[c]; - } - } - } - - m_PredictedTick = Client()->PredGameTick(); -} - - -bool CGameClient::ShouldUsePredicted() -{ - // We don't use predictions when: - // - Viewing a demo - // - When the game is paused or waiting - // - When we are spectating - return - Client()->State() != IClient::STATE_DEMOPLAYBACK && - !( - m_Snap.m_pGameData && - m_Snap.m_pGameData->m_GameStateFlags & ( - GAMESTATEFLAG_PAUSED | - GAMESTATEFLAG_ROUNDOVER | - GAMESTATEFLAG_GAMEOVER - ) - ) && - !(m_Snap.m_SpecInfo.m_Active); -} - -bool CGameClient::ShouldUsePredictedLocalChar() -{ - // Not sure if `m_Snap.m_pLocalCharacter` is necessary, but the old code - // checked it so I will too. - return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; -} - -bool CGameClient::ShouldUsePredictedNonLocalChars() -{ - return Config()->m_ClPredictPlayers; -} - -bool CGameClient::ShouldUsePredictedChar(int ClientID) -{ - if(ClientID == m_LocalClientID) - return ShouldUsePredictedLocalChar(); - else - // Might want to check if `ClientID` exists in `m_Snap.m_aCharacters`, - // similar to how we check if `m_pLocalCharacter` is not null in - // `ShouldUsePredictedLocalChar` - return ShouldUsePredictedNonLocalChars(); -} - -void CGameClient::UsePredictedChar( - CNetObj_Character *pPrevChar, - CNetObj_Character *pPlayerChar, - float *IntraTick, - int ClientID - ) -{ - m_aPredictedPrevChars[ClientID].Write(pPrevChar); - m_aPredictedChars[ClientID].Write(pPlayerChar); - *IntraTick = Client()->PredIntraGameTick(); -} - -vec2 CGameClient::PredictedCharPos(int ClientID) -{ - return mix( - vec2( - m_aPredictedPrevChars[ClientID].m_Pos.x, - m_aPredictedPrevChars[ClientID].m_Pos.y - ), - vec2( - m_aPredictedChars[ClientID].m_Pos.x, - m_aPredictedChars[ClientID].m_Pos.y - ), - Client()->PredIntraGameTick() - ); -} - -vec2 CGameClient::UnpredictedCharPos(int ClientID) -{ - return mix( - vec2( - m_Snap.m_aCharacters[ClientID].m_Prev.m_X, - m_Snap.m_aCharacters[ClientID].m_Prev.m_Y - ), - vec2( - m_Snap.m_aCharacters[ClientID].m_Cur.m_X, - m_Snap.m_aCharacters[ClientID].m_Cur.m_Y - ), - Client()->IntraGameTick() - ); -} - -void CGameClient::OnActivateEditor() -{ - OnRelease(); -} - -void CGameClient::CClientData::UpdateBotRenderInfo(CGameClient *pGameClient, int ClientID) -{ - static const unsigned char s_aBotColors[][3] = { - {0xff,0x00,0x00}, - {0xff,0x66,0x00}, - {0x4d,0x9f,0x45}, - {0xd5,0x9e,0x29}, - {0x9f,0xd3,0xa9}, - {0xbd,0xd8,0x5e}, - {0xc0,0x7f,0x94}, - {0xc3,0xa2,0x67}, - {0xf8,0xa8,0x3b}, - {0xcc,0xe2,0xbf}, - {0xe6,0xb4,0x98}, - {0x74,0xc7,0xa3}, - }; - - if(pGameClient->m_Snap.m_paPlayerInfos[ClientID] && pGameClient->m_Snap.m_paPlayerInfos[ClientID]->m_PlayerFlags&PLAYERFLAG_BOT) - { - m_RenderInfo.m_BotTexture = pGameClient->m_pSkins->m_BotTexture; - if(!m_RenderInfo.m_BotColor.a) // bot color has not been set; pick a random color once - { - const unsigned char* pBotColor = s_aBotColors[rand()%(sizeof(s_aBotColors)/sizeof(s_aBotColors[0]))]; - m_RenderInfo.m_BotColor = vec4(pBotColor[0]/255.f, pBotColor[1]/255.f, pBotColor[2]/255.f, 1.0f); - } - } - else - { - m_RenderInfo.m_BotTexture.Invalidate(); - m_RenderInfo.m_BotColor = vec4(0.0f, 0.0f, 0.0f, 0.0f); - } -} - -void CGameClient::CClientData::UpdateRenderInfo(CGameClient *pGameClient, int ClientID, bool UpdateSkinInfo) -{ - // update skin info - if(UpdateSkinInfo) - { - char* apSkinParts[NUM_SKINPARTS]; - for(int p = 0; p < NUM_SKINPARTS; p++) - apSkinParts[p] = m_aaSkinPartNames[p]; - - pGameClient->m_pSkins->ValidateSkinParts(apSkinParts, m_aUseCustomColors, m_aSkinPartColors, pGameClient->m_GameInfo.m_GameFlags); - - m_SkinInfo.m_Size = 64; - if(pGameClient->IsXmas()) - { - m_SkinInfo.m_HatTexture = pGameClient->m_pSkins->m_XmasHatTexture; - m_SkinInfo.m_HatSpriteIndex = ClientID % CSkins::HAT_NUM; - } - else - m_SkinInfo.m_HatTexture.Invalidate(); - - for(int p = 0; p < NUM_SKINPARTS; p++) - { - int ID = pGameClient->m_pSkins->FindSkinPart(p, m_aaSkinPartNames[p], false); - if(ID < 0) - { - if(p == SKINPART_MARKING || p == SKINPART_DECORATION) - ID = pGameClient->m_pSkins->FindSkinPart(p, "", false); - else - ID = pGameClient->m_pSkins->FindSkinPart(p, "standard", false); - - if(ID < 0) - m_SkinPartIDs[p] = 0; - else - m_SkinPartIDs[p] = ID; - } - else - { - if(m_SkinInfo.m_HatTexture.IsValid()) - { - if(p == SKINPART_BODY && str_comp(m_aaSkinPartNames[p], "standard")) - m_SkinInfo.m_HatSpriteIndex = CSkins::HAT_OFFSET_SIDE + (ClientID%CSkins::HAT_NUM); - if(p == SKINPART_DECORATION && !str_comp(m_aaSkinPartNames[p], "twinbopp")) - m_SkinInfo.m_HatSpriteIndex = CSkins::HAT_OFFSET_SIDE + (ClientID%CSkins::HAT_NUM); - } - m_SkinPartIDs[p] = ID; - } - - const CSkins::CSkinPart *pSkinPart = pGameClient->m_pSkins->GetSkinPart(p, m_SkinPartIDs[p]); - if(m_aUseCustomColors[p]) - { - m_SkinInfo.m_aTextures[p] = pSkinPart->m_ColorTexture; - m_SkinInfo.m_aColors[p] = pGameClient->m_pSkins->GetColorV4(m_aSkinPartColors[p], p==SKINPART_MARKING); - } - else - { - m_SkinInfo.m_aTextures[p] = pSkinPart->m_OrgTexture; - m_SkinInfo.m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); - } - } - } - - m_RenderInfo = m_SkinInfo; - - // force team colors - if(pGameClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) - { - for(int p = 0; p < NUM_SKINPARTS; p++) - { - m_RenderInfo.m_aTextures[p] = pGameClient->m_pSkins->GetSkinPart(p, m_SkinPartIDs[p])->m_ColorTexture; - int ColorVal = pGameClient->m_pSkins->GetTeamColor(m_aUseCustomColors[p], m_aSkinPartColors[p], m_Team, p); - m_RenderInfo.m_aColors[p] = pGameClient->m_pSkins->GetColorV4(ColorVal, p==SKINPART_MARKING); - } - } -} - -void CGameClient::CClientData::Reset(CGameClient *pGameClient, int ClientID) -{ - m_aName[0] = 0; - m_aClan[0] = 0; - m_Country = -1; - m_Team = 0; - m_Angle = 0; - m_Emoticon = 0; - m_EmoticonStart = -1; - m_Active = false; - m_ChatIgnore = false; - m_Friend = false; - m_Evolved.m_Tick = -1; - for(int p = 0; p < NUM_SKINPARTS; p++) - { - m_SkinPartIDs[p] = 0; - m_SkinInfo.m_aTextures[p] = pGameClient->m_pSkins->GetSkinPart(p, 0)->m_ColorTexture; - m_SkinInfo.m_aColors[p] = vec4(1.0f, 1.0f, 1.0f , 1.0f); - } - UpdateRenderInfo(pGameClient, ClientID, false); -} - -void CGameClient::DoEnterMessage(const char *pName, int ClientID, int Team) -{ - char aBuf[128], aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); - switch(GetStrTeam(Team, m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)) - { - case STR_TEAM_GAME: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the game"), aLabel); break; - case STR_TEAM_RED: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the red team"), aLabel); break; - case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the blue team"), aLabel); break; - case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the spectators"), aLabel); break; - } - m_pChat->AddLine(aBuf); -} - -void CGameClient::DoLeaveMessage(const char *pName, int ClientID, const char *pReason) -{ - char aBuf[128], aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); - if(pReason[0]) - str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game (%s)"), aLabel, pReason); - else - str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game"), aLabel); - m_pChat->AddLine(aBuf); -} - -void CGameClient::DoTeamChangeMessage(const char *pName, int ClientID, int Team) -{ - char aBuf[128]; - char aLabel[64]; - GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); - switch(GetStrTeam(Team, m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)) - { - case STR_TEAM_GAME: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the game"), aLabel); break; - case STR_TEAM_RED: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the red team"), aLabel); break; - case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the blue team"), aLabel); break; - case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the spectators"), aLabel); break; - } - m_pChat->AddLine(aBuf); -} - -void CGameClient::SendSwitchTeam(int Team) -{ - CNetMsg_Cl_SetTeam Msg; - Msg.m_Team = Team; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); -} - -void CGameClient::SendStartInfo() -{ - CNetMsg_Cl_StartInfo Msg; - Msg.m_pName = Config()->m_PlayerName; - Msg.m_pClan = Config()->m_PlayerClan; - Msg.m_Country = Config()->m_PlayerCountry; - for(int p = 0; p < NUM_SKINPARTS; p++) - { - Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; - Msg.m_aUseCustomColors[p] = *CSkins::ms_apUCCVariables[p]; - Msg.m_aSkinPartColors[p] = *CSkins::ms_apColorVariables[p]; - } - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); -} - -void CGameClient::SendKill() -{ - CNetMsg_Cl_Kill Msg; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); -} - -void CGameClient::SendReadyChange() -{ - CNetMsg_Cl_ReadyChange Msg; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); -} - -void CGameClient::SendSkinChange() -{ - CNetMsg_Cl_SkinChange Msg; - for(int p = 0; p < NUM_SKINPARTS; p++) - { - Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; - Msg.m_aUseCustomColors[p] = *CSkins::ms_apUCCVariables[p]; - Msg.m_aSkinPartColors[p] = *CSkins::ms_apColorVariables[p]; - } - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD|MSGFLAG_FLUSH); - m_LastSkinChangeTime = Client()->LocalTime(); -} - -int CGameClient::GetClientID(const char *pName) -{ - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(!m_aClients[i].m_Active || i == m_LocalClientID) // skip local user - continue; - - if(!str_comp(m_aClients[i].m_aName, pName)) - return i; - } - - return -1; -} - -void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData) -{ - CGameClient *pClient = static_cast(pUserData); - if(pClient->Client()->State() != IClient::STATE_ONLINE || pClient->m_LocalClientID == -1) - return; - CMenus::CSwitchTeamInfo Info; - pClient->m_pMenus->GetSwitchTeamInfo(&Info); - int Team = pResult->GetInteger(0); - if(pClient->m_aClients[pClient->m_LocalClientID].m_Team == Team || (Team == TEAM_SPECTATORS && !(Info.m_AllowSpec)) || (Team != TEAM_SPECTATORS && Info.m_aNotification[0])) - { - if(Info.m_aNotification[0]) - pClient->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", Info.m_aNotification); - return; - } - pClient->SendSwitchTeam(Team); -} - -void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData) -{ - CGameClient *pClient = static_cast(pUserData); - if(pClient->Client()->State() == IClient::STATE_ONLINE) - pClient->SendKill(); -} - -void CGameClient::ConReadyChange(IConsole::IResult *pResult, void *pUserData) -{ - CGameClient *pClient = static_cast(pUserData); - if(pClient->Client()->State() == IClient::STATE_ONLINE) - pClient->SendReadyChange(); -} - -void CGameClient::ConchainSkinChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) -{ - pfnCallback(pResult, pCallbackUserData); - CGameClient *pClient = static_cast(pUserData); - if(pClient->Client()->State() == IClient::STATE_ONLINE && pResult->NumArguments()) - pClient->SendSkinChange(); -} - -void CGameClient::ConchainFriendUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) -{ - pfnCallback(pResult, pCallbackUserData); - CGameClient *pClient = static_cast(pUserData); - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(pClient->m_aClients[i].m_Active) - pClient->m_aClients[i].m_Friend = pClient->Friends()->IsFriend(pClient->m_aClients[i].m_aName, pClient->m_aClients[i].m_aClan, true); - } -} - -void CGameClient::ConchainBlacklistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) -{ - pfnCallback(pResult, pCallbackUserData); - CGameClient *pClient = static_cast(pUserData); - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(pClient->m_aClients[i].m_Active) - pClient->m_aClients[i].m_ChatIgnore = pClient->Blacklist()->IsIgnored(pClient->m_aClients[i].m_aName, pClient->m_aClients[i].m_aClan, true); - } -} - -void CGameClient::ConchainXmasHatUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) -{ - pfnCallback(pResult, pCallbackUserData); - CGameClient *pClient = static_cast(pUserData); - if(pClient->Client()->State() != IClient::STATE_ONLINE) - return; - - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(pClient->m_aClients[i].m_Active) - pClient->m_aClients[i].UpdateRenderInfo(pClient, i, true); - } -} - -IGameClient *CreateGameClient() -{ - return new CGameClient(); -} +/* (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 +#include + +#include +#include + +#include +#include "localization.h" +#include "render.h" + +#include "gameclient.h" + +#include "components/binds.h" +#include "components/broadcast.h" +#include "components/camera.h" +#include "components/chat.h" +#include "components/console.h" +#include "components/controls.h" +#include "components/countryflags.h" +#include "components/damageind.h" +#include "components/debughud.h" +#include "components/effects.h" +#include "components/emoticon.h" +#include "components/flow.h" +#include "components/hud.h" +#include "components/items.h" +#include "components/infomessages.h" +#include "components/mapimages.h" +#include "components/maplayers.h" +#include "components/menus.h" +#include "components/motd.h" +#include "components/notifications.h" +#include "components/particles.h" +#include "components/players.h" +#include "components/nameplates.h" +#include "components/scoreboard.h" +#include "components/skins.h" +#include "components/sounds.h" +#include "components/spectator.h" +#include "components/stats.h" +#include "components/voting.h" + +inline void AppendDecimals(char *pBuf, int Size, int Time, int Precision) +{ + if(Precision > 0) + { + char aInvalid[] = ".---"; + char aMSec[] = { + '.', + (char)('0' + (Time / 100) % 10), + (char)('0' + (Time / 10) % 10), + (char)('0' + Time % 10), + 0 + }; + char *pDecimals = Time < 0 ? aInvalid : aMSec; + pDecimals[min(Precision, 3)+1] = 0; + str_append(pBuf, pDecimals, Size); + } +} + +void FormatTime(char *pBuf, int Size, int Time, int Precision) +{ + if(Time < 0) + str_copy(pBuf, "-:--", Size); + else + str_format(pBuf, Size, "%02d:%02d", Time / (60 * 1000), (Time / 1000) % 60); + AppendDecimals(pBuf, Size, Time, Precision); +} + +void FormatTimeDiff(char *pBuf, int Size, int Time, int Precision, bool ForceSign) +{ + const char *pPositive = ForceSign ? "+" : ""; + const char *pSign = Time < 0 ? "-" : pPositive; + Time = absolute(Time); + str_format(pBuf, Size, "%s%d", pSign, Time / 1000); + AppendDecimals(pBuf, Size, Time, Precision); +} + +// instantiate all systems +static CInfoMessages gs_InfoMessages; +static CCamera gs_Camera; +static CChat gs_Chat; +static CMotd gs_Motd; +static CBroadcast gs_Broadcast; +static CGameConsole gs_GameConsole; +static CBinds gs_Binds; +static CParticles gs_Particles; +static CMenus gs_Menus; +static CSkins gs_Skins; +static CCountryFlags gs_CountryFlags; +static CFlow gs_Flow; +static CHud gs_Hud; +static CDebugHud gs_DebugHud; +static CNotifications gs_Notifications; +static CControls gs_Controls; +static CEffects gs_Effects; +static CScoreboard gs_Scoreboard; +static CSounds gs_Sounds; +static CEmoticon gs_Emoticon; +static CDamageInd gsDamageInd; +static CVoting gs_Voting; +static CSpectator gs_Spectator; +static CStats gs_Stats; + +static CPlayers gs_Players; +static CNamePlates gs_NamePlates; +static CItems gs_Items; +static CMapImages gs_MapImages; + +static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND); +static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND); + +CGameClient::CStack::CStack() { m_Num = 0; } +void CGameClient::CStack::Add(class CComponent *pComponent) { m_paComponents[m_Num++] = pComponent; } + +const char *CGameClient::Version() const { return GAME_VERSION; } +const char *CGameClient::NetVersion() const { return GAME_NETVERSION; } +const char *CGameClient::NetVersionHashUsed() const { return GAME_NETVERSION_HASH_FORCED; } +const char *CGameClient::NetVersionHashReal() const{ return GAME_NETVERSION_HASH; } +int CGameClient::ClientVersion() const { return CLIENT_VERSION; } +const char *CGameClient::GetItemName(int Type) const { return m_NetObjHandler.GetObjName(Type); } +bool CGameClient::IsXmas() const { return Config()->m_ClShowXmasHats == 2 || (Config()->m_ClShowXmasHats == 1 && m_IsXmasDay); } +bool CGameClient::IsEaster() const { return Config()->m_ClShowEasterEggs == 2 || (Config()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } + +enum +{ + STR_TEAM_GAME, + STR_TEAM_RED, + STR_TEAM_BLUE, + STR_TEAM_SPECTATORS, +}; + +static int GetStrTeam(int Team, bool Teamplay) +{ + if(Teamplay) + { + if(Team == TEAM_RED) + return STR_TEAM_RED; + else if(Team == TEAM_BLUE) + return STR_TEAM_BLUE; + } + else if(Team == 0) + return STR_TEAM_GAME; + + return STR_TEAM_SPECTATORS; +} + +void CGameClient::GetPlayerLabel(char* aBuf, int BufferSize, int ClientID, const char* ClientName) +{ + if(!Config()->m_ClShowsocial) + str_format(aBuf, BufferSize, "%2d:", ClientID); + else if(Config()->m_ClShowUserId) + str_format(aBuf, BufferSize, "%2d: %s", ClientID, ClientName); + else + str_format(aBuf, BufferSize, "%s", ClientName); +} + +enum +{ + DO_CHAT=0, + DO_BROADCAST, + DO_SPECIAL, + + PARA_NONE=0, + PARA_I, + PARA_II, + PARA_III, +}; + +struct CGameMsg +{ + int m_Action; + int m_ParaType; + const char *m_pText; +}; + +static CGameMsg gs_GameMsgList[NUM_GAMEMSGS] = { + {/*GAMEMSG_TEAM_SWAP*/ DO_CHAT, PARA_NONE, "Teams were swapped"}, // Localize("Teams were swapped") + {/*GAMEMSG_SPEC_INVALIDID*/ DO_CHAT, PARA_NONE, "Invalid spectator id used"}, //! + {/*GAMEMSG_TEAM_SHUFFLE*/ DO_CHAT, PARA_NONE, "Teams were shuffled"}, // Localize("Teams were shuffled") + {/*GAMEMSG_TEAM_BALANCE*/ DO_CHAT, PARA_NONE, "Teams have been balanced"}, // Localize("Teams have been balanced") + {/*GAMEMSG_CTF_DROP*/ DO_SPECIAL, PARA_NONE, ""}, // special - play ctf drop sound + {/*GAMEMSG_CTF_RETURN*/ DO_SPECIAL, PARA_NONE, ""}, // special - play ctf return sound + + {/*GAMEMSG_TEAM_ALL*/ DO_SPECIAL, PARA_I, ""}, // special - add team name + {/*GAMEMSG_TEAM_BALANCE_VICTIM*/ DO_SPECIAL, PARA_I, ""}, // special - add team name + {/*GAMEMSG_CTF_GRAB*/ DO_SPECIAL, PARA_I, ""}, // special - play ctf grab sound based on team + + {/*GAMEMSG_CTF_CAPTURE*/ DO_SPECIAL, PARA_III, ""}, // special - play ctf capture sound + capture chat message + + {/*GAMEMSG_GAME_PAUSED*/ DO_SPECIAL, PARA_I, ""}, // special - add player name +}; + +void CGameClient::OnConsoleInit() +{ + m_InitComplete = false; + m_pEngine = Kernel()->RequestInterface(); + m_pClient = Kernel()->RequestInterface(); + m_pTextRender = Kernel()->RequestInterface(); + m_pSound = Kernel()->RequestInterface(); + m_pInput = Kernel()->RequestInterface(); + m_pConfig = Kernel()->RequestInterface()->Values(); + m_pConsole = Kernel()->RequestInterface(); + m_pStorage = Kernel()->RequestInterface(); + m_pDemoPlayer = Kernel()->RequestInterface(); + m_pDemoRecorder = Kernel()->RequestInterface(); + m_pServerBrowser = Kernel()->RequestInterface(); + m_pEditor = Kernel()->RequestInterface(); + m_pFriends = Kernel()->RequestInterface(); + m_pBlacklist = Kernel()->RequestInterface(); + + // setup pointers + m_pBinds = &::gs_Binds; + m_pBroadcast = &::gs_Broadcast; + m_pGameConsole = &::gs_GameConsole; + m_pParticles = &::gs_Particles; + m_pMenus = &::gs_Menus; + m_pSkins = &::gs_Skins; + m_pCountryFlags = &::gs_CountryFlags; + m_pChat = &::gs_Chat; + m_pFlow = &::gs_Flow; + m_pCamera = &::gs_Camera; + m_pControls = &::gs_Controls; + m_pEffects = &::gs_Effects; + m_pSounds = &::gs_Sounds; + m_pMotd = &::gs_Motd; + m_pDamageind = &::gsDamageInd; + m_pMapimages = &::gs_MapImages; + m_pVoting = &::gs_Voting; + m_pScoreboard = &::gs_Scoreboard; + m_pItems = &::gs_Items; + m_pMapLayersBackGround = &::gs_MapLayersBackGround; + m_pMapLayersForeGround = &::gs_MapLayersForeGround; + m_pStats = &::gs_Stats; + + // make a list of all the systems, make sure to add them in the corrent render order + m_All.Add(m_pSkins); + m_All.Add(m_pCountryFlags); + m_All.Add(m_pMapimages); + m_All.Add(m_pEffects); // doesn't render anything, just updates effects + m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles + m_All.Add(m_pBinds); + m_All.Add(&m_pBinds->m_SpecialBinds); + m_All.Add(m_pControls); + m_All.Add(m_pCamera); + m_All.Add(m_pSounds); + m_All.Add(m_pVoting); + + m_All.Add(&gs_MapLayersBackGround); // first to render + m_All.Add(&m_pParticles->m_RenderTrail); + m_All.Add(m_pItems); + m_All.Add(&gs_Players); + m_All.Add(&gs_MapLayersForeGround); + m_All.Add(&m_pParticles->m_RenderExplosions); + m_All.Add(&gs_NamePlates); + m_All.Add(&m_pParticles->m_RenderGeneral); + m_All.Add(m_pDamageind); + m_All.Add(&gs_Hud); + m_All.Add(&gs_Spectator); + m_All.Add(&gs_Emoticon); + m_All.Add(&gs_InfoMessages); + m_All.Add(m_pChat); + m_All.Add(&gs_Broadcast); + m_All.Add(&gs_DebugHud); + m_All.Add(&gs_Notifications); + m_All.Add(&gs_Scoreboard); + m_All.Add(m_pStats); + m_All.Add(m_pMotd); + m_All.Add(m_pMenus); + m_All.Add(&m_pMenus->m_Binder); + m_All.Add(m_pGameConsole); + + // build the input stack + m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key + m_Input.Add(&m_pBinds->m_SpecialBinds); + m_Input.Add(m_pGameConsole); + m_Input.Add(m_pChat); // chat has higher prio due to tha you can quit it by pressing esc + m_Input.Add(m_pMotd); // for pressing esc to remove it + m_Input.Add(m_pMenus); + m_Input.Add(&gs_Spectator); + m_Input.Add(&gs_Emoticon); + m_Input.Add(m_pControls); + m_Input.Add(m_pBinds); + + // add the some console commands + Console()->Register("team", "i[team]", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); + Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself"); + Console()->Register("ready_change", "", CFGFLAG_CLIENT, ConReadyChange, this, "Change ready state"); + + Console()->Chain("add_friend", ConchainFriendUpdate, this); + Console()->Chain("remove_friend", ConchainFriendUpdate, this); + Console()->Chain("add_ignore", ConchainBlacklistUpdate, this); + Console()->Chain("remove_ignore", ConchainBlacklistUpdate, this); + Console()->Chain("cl_show_xmas_hats", ConchainXmasHatUpdate, this); + Console()->Chain("player_color_body", ConchainSkinChange, this); + Console()->Chain("player_color_marking", ConchainSkinChange, this); + Console()->Chain("player_color_decoration", ConchainSkinChange, this); + Console()->Chain("player_color_hands", ConchainSkinChange, this); + Console()->Chain("player_color_feet", ConchainSkinChange, this); + Console()->Chain("player_color_eyes", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_body", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_marking", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_decoration", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_hands", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_feet", ConchainSkinChange, this); + Console()->Chain("player_use_custom_color_eyes", ConchainSkinChange, this); + Console()->Chain("player_skin", ConchainSkinChange, this); + Console()->Chain("player_skin_body", ConchainSkinChange, this); + Console()->Chain("player_skin_marking", ConchainSkinChange, this); + Console()->Chain("player_skin_decoration", ConchainSkinChange, this); + Console()->Chain("player_skin_hands", ConchainSkinChange, this); + Console()->Chain("player_skin_feet", ConchainSkinChange, this); + Console()->Chain("player_skin_eyes", ConchainSkinChange, this); + + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->m_pClient = this; + + // let all the other components register their console commands + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnConsoleInit(); + + // + m_SuppressEvents = false; +} + +void CGameClient::OnInit() +{ + m_pGraphics = Kernel()->RequestInterface(); + + // propagate pointers + m_UI.Init(Config(), Graphics(), TextRender()); + m_RenderTools.Init(Config(), Graphics(), UI()); + + int64 Start = time_get(); + + // Render load screen at 0% to get graphics sooner. + // Swap again to minimize initial flashing color. + m_pMenus->InitLoading(1); + m_pMenus->RenderLoading(); + m_pGraphics->Swap(); + + // TODO: this should be different + // setup item sizes + // HACK: only set static size for items, which were available in the first 0.7 release + // so new items don't break the snapshot delta + static const int OLD_NUM_NETOBJTYPES = 23; + for(int i = 0; i < OLD_NUM_NETOBJTYPES; i++) + Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); + + // determine total work for loading all components + int TotalWorkAmount = g_pData->m_NumImages + 4 + 1 + 1 + 2; // +4=load init, +1=font, +1=localization, +2=editor + for(int i = m_All.m_Num-1; i >= 0; --i) + TotalWorkAmount += m_All.m_paComponents[i]->GetInitAmount(); + + m_pMenus->InitLoading(TotalWorkAmount); + m_pMenus->RenderLoading(4); + + // load default font + char aFontName[IO_MAX_PATH_LENGTH]; + str_format(aFontName, sizeof(aFontName), "fonts/%s", Config()->m_ClFontfile); + char aFilename[IO_MAX_PATH_LENGTH]; + IOHANDLE File = Storage()->OpenFile(aFontName, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); + if(File) + { + io_close(File); + if(TextRender()->LoadFont(aFilename)) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "failed to load font. filename='%s'", aFontName); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", aBuf); + } + } + m_pMenus->RenderLoading(1); + + // set the language + g_Localization.Load(Config()->m_ClLanguagefile, Storage(), Console()); + m_pMenus->RenderLoading(1); + + // init all components + for(int i = m_All.m_Num-1; i >= 0; --i) + m_All.m_paComponents[i]->OnInit(); // this will call RenderLoading again + + // load textures + for(int i = 0; i < g_pData->m_NumImages; i++) + { + g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, g_pData->m_aImages[i].m_Flag ? IGraphics::TEXLOAD_LINEARMIPMAPS : 0); + m_pMenus->RenderLoading(1); + } + + // init the editor + m_pEditor->Init(); + m_pMenus->RenderLoading(2); + + OnReset(); + + m_ServerMode = SERVERMODE_PURE; + + m_IsXmasDay = time_isxmasday(); + m_IsEasterDay = time_iseasterday(); + m_pMenus->RenderLoading(); + m_InitComplete = true; + + int64 End = time_get(); + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End - Start) * 1000) / (float)time_freq()); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); +} + +void CGameClient::OnUpdate() +{ + // handle mouse and joystick movement, prefer mouse movement + float x = 0.0f, y = 0.0f; + int CursorType = Input()->CursorRelative(&x, &y); + if(CursorType != IInput::CURSOR_NONE) + { + for(int h = 0; h < m_Input.m_Num; h++) + { + if(m_Input.m_paComponents[h]->OnCursorMove(x, y, CursorType)) + break; + } + } + + // handle key presses + for(int i = 0; i < Input()->NumEvents(); i++) + { + IInput::CEvent e = Input()->GetEvent(i); + if(!Input()->IsEventValid(&e)) + continue; + + for(int h = 0; h < m_Input.m_Num; h++) + { + if(m_Input.m_paComponents[h]->OnInput(e)) + break; + } + } +} + +int CGameClient::OnSnapInput(int *pData) +{ + return m_pControls->SnapInput(pData); +} + +void CGameClient::OnConnected() +{ + m_Layers.Init(Kernel()); + m_Collision.Init(Layers()); + + for(int i = 0; i < m_All.m_Num; i++) + { + m_All.m_paComponents[i]->OnMapLoad(); + m_All.m_paComponents[i]->OnReset(); + } + + m_ServerMode = SERVERMODE_PURE; + + // send the inital info + SendStartInfo(); +} + +void CGameClient::OnReset() +{ + // clear out the invalid pointers + m_LastNewPredictedTick = -1; + mem_zero(&m_Snap, sizeof(m_Snap)); + + for(int i = 0; i < MAX_CLIENTS; i++) + m_aClients[i].Reset(this, i); + + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnReset(); + + m_LocalClientID = -1; + m_TeamCooldownTick = 0; + m_TeamChangeTime = 0.0f; + m_LastSkinChangeTime = Client()->LocalTime(); + mem_zero(&m_GameInfo, sizeof(m_GameInfo)); + m_DemoSpecMode = SPEC_FREEVIEW; + m_DemoSpecID = -1; + m_Tuning = CTuningParams(); + m_MuteServerBroadcast = false; + m_LastGameStartTick = -1; + m_LastFlagCarrierRed = FLAG_MISSING; + m_LastFlagCarrierBlue = FLAG_MISSING; +} + +void CGameClient::UpdatePositions() +{ + // `m_LocalCharacterPos` is used for many things besides rendering the + // player (e.g. camera position, mouse input), which is why we set it here. + if(ShouldUsePredicted() && ShouldUsePredictedLocalChar()) + { + m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); + } + else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) + { + m_LocalCharacterPos = UnpredictedCharPos(m_LocalClientID); + } + + // spectator position + if(m_Snap.m_SpecInfo.m_Active) + { + if(Client()->State() == IClient::STATE_DEMOPLAYBACK && + DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && + m_Snap.m_SpecInfo.m_SpectatorID != -1) + { + m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos(m_Snap.m_SpecInfo.m_SpectatorID); + m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; + m_Snap.m_SpecInfo.m_UsePosition = true; + } + else if( + m_Snap.m_pSpectatorInfo && + ( + Client()->State() == IClient::STATE_DEMOPLAYBACK || + m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW || + ( + m_Snap.m_pLocalInfo && + (m_Snap.m_pLocalInfo->m_PlayerFlags & PLAYERFLAG_DEAD) && + m_Snap.m_SpecInfo.m_SpecMode != SPEC_FREEVIEW + ) + )) + { + if(m_Snap.m_pPrevSpectatorInfo) + m_Snap.m_SpecInfo.m_Position = mix( + vec2( + m_Snap.m_pPrevSpectatorInfo->m_X, + m_Snap.m_pPrevSpectatorInfo->m_Y + ), + vec2( + m_Snap.m_pSpectatorInfo->m_X, + m_Snap.m_pSpectatorInfo->m_Y + ), + Client()->IntraGameTick() + ); + else + m_Snap.m_SpecInfo.m_Position = vec2( + m_Snap.m_pSpectatorInfo->m_X, + m_Snap.m_pSpectatorInfo->m_Y + ); + + m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; + m_Snap.m_SpecInfo.m_UsePosition = true; + } + } +} + +void CGameClient::EvolveCharacter(CNetObj_Character *pCharacter, int Tick) +{ + CWorldCore TempWorld; + CCharacterCore TempCore; + mem_zero(&TempCore, sizeof(TempCore)); + TempCore.Init(&TempWorld, Collision()); + TempCore.Read(pCharacter); + + while(pCharacter->m_Tick < Tick) + { + pCharacter->m_Tick++; + TempCore.Tick(false); + TempCore.Move(); + TempCore.Quantize(); + } + + TempCore.Write(pCharacter); +} + +void CGameClient::StartRendering() +{ + if(Config()->m_GfxClear) + { + if(m_pMenus->IsBackgroundNeeded()) + Graphics()->Clear(0.45f, 0.45f, 0.45f); + else + Graphics()->Clear(1.0f, 1.0f, 0.0f); + } + else if(m_pMenus->IsBackgroundNeeded()) + { + // render background color + float sw = 300 * Graphics()->ScreenAspect(); + float sh = 300; + Graphics()->MapScreen(0, 0, sw, sh); + Graphics()->TextureClear(); + Graphics()->QuadsBegin(); + vec4 Bottom(0.45f, 0.45f, 0.45f, 1.0f); + vec4 Top(0.45f, 0.45f, 0.45f, 1.0f); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), + IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a) }; + Graphics()->SetColorVertex(Array, 4); + IGraphics::CQuadItem QuadItem(0, 0, sw, sh); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } +} + +void CGameClient::OnRender() +{ + // update the local character and spectate position + UpdatePositions(); + + StartRendering(); + + // render all systems + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnRender(); + + // clear all events/input for this frame + Input()->Clear(); +} + +void CGameClient::OnRelease() +{ + // release all systems + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnRelease(); +} + +void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) +{ + Client()->RecordGameMessage(true); + + // special messages + if(MsgId == NETMSGTYPE_SV_TUNEPARAMS && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + // unpack the new tuning + CTuningParams NewTuning; + int *pParams = (int *)&NewTuning; + for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++) + pParams[i] = pUnpacker->GetInt(); + + // check for unpacking errors + if(pUnpacker->Error()) + return; + + m_ServerMode = SERVERMODE_PURE; + + // apply new tuning + m_Tuning = NewTuning; + return; + } + else if(MsgId == NETMSGTYPE_SV_VOTEOPTIONLISTADD) + { + int NumOptions = pUnpacker->GetInt(); + for(int i = 0; i < NumOptions; i++) + { + const char *pDescription = pUnpacker->GetString(CUnpacker::SANITIZE_CC); + if(pUnpacker->Error()) + return; + + m_pVoting->AddOption(pDescription); + } + } + else if(MsgId == NETMSGTYPE_SV_GAMEMSG) + { + int GameMsgID = pUnpacker->GetInt(); + + // check for valid gamemsgid + if(GameMsgID < 0 || GameMsgID >= NUM_GAMEMSGS) + return; + + int aParaI[3]; + int NumParaI = 0; + + // get paras + switch(gs_GameMsgList[GameMsgID].m_ParaType) + { + case PARA_I: NumParaI = 1; break; + case PARA_II: NumParaI = 2; break; + case PARA_III: NumParaI = 3; break; + } + for(int i = 0; i < NumParaI; i++) + { + aParaI[i] = pUnpacker->GetInt(); + } + + // check for unpacking errors + if(pUnpacker->Error()) + return; + + // handle special messages + char aBuf[256]; + bool TeamPlay = m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS; + if(gs_GameMsgList[GameMsgID].m_Action == DO_SPECIAL) + { + switch(GameMsgID) + { + case GAMEMSG_CTF_DROP: + if(m_SuppressEvents) + return; + m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_DROP); + break; + case GAMEMSG_CTF_RETURN: + if(m_SuppressEvents) + return; + m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_RETURN); + break; + case GAMEMSG_TEAM_ALL: + { + const char *pMsg; + switch(GetStrTeam(aParaI[0], TeamPlay)) + { + case STR_TEAM_GAME: pMsg = Localize("All players were moved to the game"); break; + case STR_TEAM_RED: pMsg = Localize("All players were moved to the red team"); break; + case STR_TEAM_BLUE: pMsg = Localize("All players were moved to the blue team"); break; + case STR_TEAM_SPECTATORS: pMsg = Localize("All players were moved to the spectators"); break; + } + m_pBroadcast->DoBroadcast(pMsg); + } + break; + case GAMEMSG_TEAM_BALANCE_VICTIM: + { + const char *pMsg = ""; + switch(GetStrTeam(aParaI[0], TeamPlay)) + { + case STR_TEAM_RED: pMsg = Localize("You were moved to the red team due to team balancing"); break; + case STR_TEAM_BLUE: pMsg = Localize("You were moved to the blue team due to team balancing"); break; + } + m_pBroadcast->DoBroadcast(pMsg); + } + break; + case GAMEMSG_CTF_GRAB: + if(m_SuppressEvents) + return; + if(m_LocalClientID != -1 && (m_aClients[m_LocalClientID].m_Team != aParaI[0] || (m_Snap.m_SpecInfo.m_Active && + ((m_Snap.m_SpecInfo.m_SpectatorID != -1 && m_aClients[m_Snap.m_SpecInfo.m_SpectatorID].m_Team != aParaI[0]) || + (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGRED && aParaI[0] != TEAM_RED) || + (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGBLUE && aParaI[0] != TEAM_BLUE))))) + m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_PL); + else + m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_EN); + break; + case GAMEMSG_GAME_PAUSED: + { + int ClientID = clamp(aParaI[0], 0, MAX_CLIENTS - 1); + char aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, m_aClients[ClientID].m_aName); + str_format(aBuf, sizeof(aBuf), Localize("'%s' initiated a pause"), aLabel); + m_pChat->AddLine(aBuf); + } + break; + case GAMEMSG_CTF_CAPTURE: + m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_CAPTURE); + int ClientID = clamp(aParaI[1], 0, MAX_CLIENTS - 1); + m_pStats->OnFlagCapture(ClientID); + char aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, m_aClients[ClientID].m_aName); + + float Time = aParaI[2] / (float)Client()->GameTickSpeed(); + if(Time <= 60) + { + if(aParaI[0]) + { + str_format(aBuf, sizeof(aBuf), Localize("The blue flag was captured by '%s' (%.2f seconds)"), aLabel, Time); + } + else + { + str_format(aBuf, sizeof(aBuf), Localize("The red flag was captured by '%s' (%.2f seconds)"), aLabel, Time); + } + } + else + { + if(aParaI[0]) + { + str_format(aBuf, sizeof(aBuf), Localize("The blue flag was captured by '%s'"), aLabel); + } + else + { + str_format(aBuf, sizeof(aBuf), Localize("The red flag was captured by '%s'"), aLabel); + } + } + m_pChat->AddLine(aBuf); + } + return; + } + + // build message + const char *pText = ""; + if(NumParaI == 0) + { + pText = Localize(gs_GameMsgList[GameMsgID].m_pText); + } + + // handle message + switch(gs_GameMsgList[GameMsgID].m_Action) + { + case DO_CHAT: + m_pChat->AddLine(pText); + break; + case DO_BROADCAST: + m_pBroadcast->DoBroadcast(pText); + break; + } + } + + void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); + if(!pRawMsg) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); + return; + } + + // TODO: this should be done smarter + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); + + if(MsgId == NETMSGTYPE_SV_CLIENTINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + CNetMsg_Sv_ClientInfo *pMsg = (CNetMsg_Sv_ClientInfo *)pRawMsg; + + if(pMsg->m_Local) + { + if(m_LocalClientID != -1) + { + if(Config()->m_Debug) + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid local clientinfo"); + return; + } + m_LocalClientID = pMsg->m_ClientID; + m_TeamChangeTime = Client()->LocalTime(); + } + else + { + if(m_aClients[pMsg->m_ClientID].m_Active) + { + if(Config()->m_Debug) + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientinfo"); + return; + } + + if(m_LocalClientID != -1 && !pMsg->m_Silent) + { + DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); + + if(m_pDemoRecorder->IsRecording()) + { + CNetMsg_De_ClientEnter Msg; + Msg.m_pName = pMsg->m_pName; + Msg.m_ClientID = pMsg->m_ClientID; + Msg.m_Team = pMsg->m_Team; + Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); + } + } + } + + m_aClients[pMsg->m_ClientID].m_Active = true; + m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; + str_copy(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_pName, sizeof(m_aClients[pMsg->m_ClientID].m_aName)); + str_copy(m_aClients[pMsg->m_ClientID].m_aClan, pMsg->m_pClan, sizeof(m_aClients[pMsg->m_ClientID].m_aClan)); + m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; + for(int i = 0; i < NUM_SKINPARTS; i++) + { + str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); + m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; + m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; + } + + // update friend state + m_aClients[pMsg->m_ClientID].m_Friend = Friends()->IsFriend(m_aClients[pMsg->m_ClientID].m_aName, m_aClients[pMsg->m_ClientID].m_aClan, true); + // update chat ignore state + m_aClients[pMsg->m_ClientID].m_ChatIgnore = Blacklist()->IsIgnored(m_aClients[pMsg->m_ClientID].m_aName, m_aClients[pMsg->m_ClientID].m_aClan, true); + if(m_aClients[pMsg->m_ClientID].m_ChatIgnore) + { + char aBuf[128]; + char aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), pMsg->m_ClientID, m_aClients[pMsg->m_ClientID].m_aName); + str_format(aBuf, sizeof(aBuf), Localize("%s is muted by you"), aLabel); + m_pChat->AddLine(aBuf, CChat::CLIENT_MSG); + } + + m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, true); + + m_GameInfo.m_NumPlayers++; + // calculate team-balance + if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) + m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; + + m_pStats->OnPlayerEnter(pMsg->m_ClientID, pMsg->m_Team); + } + else if(MsgId == NETMSGTYPE_SV_CLIENTDROP && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + CNetMsg_Sv_ClientDrop *pMsg = (CNetMsg_Sv_ClientDrop *)pRawMsg; + + if(m_LocalClientID == pMsg->m_ClientID || !m_aClients[pMsg->m_ClientID].m_Active) + { + if(Config()->m_Debug) + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop"); + return; + } + + if(!pMsg->m_Silent) + { + DoLeaveMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_pReason); + + CNetMsg_De_ClientLeave Msg; + Msg.m_pName = m_aClients[pMsg->m_ClientID].m_aName; + Msg.m_ClientID = pMsg->m_ClientID; + Msg.m_pReason = pMsg->m_pReason; + Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD); + } + + m_GameInfo.m_NumPlayers--; + // calculate team-balance + if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) + m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; + + m_aClients[pMsg->m_ClientID].Reset(this, pMsg->m_ClientID); + m_pStats->OnPlayerLeave(pMsg->m_ClientID); + } + else if(MsgId == NETMSGTYPE_SV_SKINCHANGE && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + CNetMsg_Sv_SkinChange *pMsg = (CNetMsg_Sv_SkinChange *)pRawMsg; + + if(!m_aClients[pMsg->m_ClientID].m_Active) + { + if(Config()->m_Debug) + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid skin info"); + return; + } + + for(int i = 0; i < NUM_SKINPARTS; i++) + { + str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); + m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; + m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; + } + m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, true); + } + else if(MsgId == NETMSGTYPE_SV_GAMEINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + CNetMsg_Sv_GameInfo *pMsg = (CNetMsg_Sv_GameInfo *)pRawMsg; + + m_GameInfo.m_GameFlags = pMsg->m_GameFlags; + m_GameInfo.m_ScoreLimit = pMsg->m_ScoreLimit; + m_GameInfo.m_TimeLimit = pMsg->m_TimeLimit; + m_GameInfo.m_MatchNum = pMsg->m_MatchNum; + m_GameInfo.m_MatchCurrent = pMsg->m_MatchCurrent; + } + else if(MsgId == NETMSGTYPE_SV_SERVERSETTINGS && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + Client()->RecordGameMessage(false); + CNetMsg_Sv_ServerSettings *pMsg = (CNetMsg_Sv_ServerSettings *)pRawMsg; + + if(!m_ServerSettings.m_TeamLock && pMsg->m_TeamLock) + m_pChat->AddLine(Localize("Teams were locked")); + else if(m_ServerSettings.m_TeamLock && !pMsg->m_TeamLock) + m_pChat->AddLine(Localize("Teams were unlocked")); + + m_ServerSettings.m_KickVote = pMsg->m_KickVote; + m_ServerSettings.m_KickMin = pMsg->m_KickMin; + m_ServerSettings.m_SpecVote = pMsg->m_SpecVote; + m_ServerSettings.m_TeamLock = pMsg->m_TeamLock; + m_ServerSettings.m_TeamBalance = pMsg->m_TeamBalance; + m_ServerSettings.m_PlayerSlots = pMsg->m_PlayerSlots; + } + else if(MsgId == NETMSGTYPE_SV_TEAM) + { + CNetMsg_Sv_Team *pMsg = (CNetMsg_Sv_Team *)pRawMsg; + + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + // calculate team-balance + if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) + m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; + m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; + if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) + m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; + + m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, pMsg->m_ClientID, false); + + if(pMsg->m_ClientID == m_LocalClientID) + { + m_TeamCooldownTick = pMsg->m_CooldownTick; + m_TeamChangeTime = Client()->LocalTime(); + } + } + + if(pMsg->m_Silent == 0) + { + DoTeamChangeMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_Team); + } + } + else if(MsgId == NETMSGTYPE_SV_READYTOENTER) + { + Client()->EnterGame(); + } + else if (MsgId == NETMSGTYPE_SV_EMOTICON) + { + CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg; + + // apply + m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon; + m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(); + } + else if(MsgId == NETMSGTYPE_DE_CLIENTENTER && Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + CNetMsg_De_ClientEnter *pMsg = (CNetMsg_De_ClientEnter *)pRawMsg; + DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); + m_pStats->OnPlayerEnter(pMsg->m_ClientID, pMsg->m_Team); + } + else if(MsgId == NETMSGTYPE_DE_CLIENTLEAVE && Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + CNetMsg_De_ClientLeave *pMsg = (CNetMsg_De_ClientLeave *)pRawMsg; + DoLeaveMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_pReason); + m_pStats->OnPlayerLeave(pMsg->m_ClientID); + } +} + +void CGameClient::OnStateChange(int NewState, int OldState) +{ + // reset everything when not already connected (to keep gathered stuff) + if(NewState < IClient::STATE_ONLINE) + OnReset(); + + // then change the state + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnStateChange(NewState, OldState); +} + +void CGameClient::OnShutdown() +{ + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnShutdown(); +} +void CGameClient::OnEnterGame() {} + +void CGameClient::OnGameOver() +{ + if(Client()->State() != IClient::STATE_DEMOPLAYBACK && Config()->m_ClEditor == 0) + Client()->AutoScreenshot_Start(); +} + +void CGameClient::OnStartGame() +{ + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + Client()->DemoRecorder_HandleAutoStart(); +} + +void CGameClient::OnRconLine(const char *pLine) +{ + m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); +} + +void CGameClient::ProcessEvents() +{ + if(m_SuppressEvents) + return; + + int SnapType = IClient::SNAP_CURRENT; + int Num = Client()->SnapNumItems(SnapType); + for(int Index = 0; Index < Num; Index++) + { + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(SnapType, Index, &Item); + + if(Item.m_Type == NETEVENTTYPE_DAMAGE) + { + CNetEvent_Damage *ev = (CNetEvent_Damage *)pData; + m_pEffects->DamageIndicator(vec2(ev->m_X, ev->m_Y), ev->m_HealthAmount + ev->m_ArmorAmount); + } + else if(Item.m_Type == NETEVENTTYPE_EXPLOSION) + { + CNetEvent_Explosion *ev = (CNetEvent_Explosion *)pData; + m_pEffects->Explosion(vec2(ev->m_X, ev->m_Y)); + } + else if(Item.m_Type == NETEVENTTYPE_HAMMERHIT) + { + CNetEvent_HammerHit *ev = (CNetEvent_HammerHit *)pData; + m_pEffects->HammerHit(vec2(ev->m_X, ev->m_Y)); + } + else if(Item.m_Type == NETEVENTTYPE_SPAWN) + { + CNetEvent_Spawn *ev = (CNetEvent_Spawn *)pData; + m_pEffects->PlayerSpawn(vec2(ev->m_X, ev->m_Y)); + } + else if(Item.m_Type == NETEVENTTYPE_DEATH) + { + CNetEvent_Death *ev = (CNetEvent_Death *)pData; + m_pEffects->PlayerDeath(vec2(ev->m_X, ev->m_Y), ev->m_ClientID); + } + else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD) + { + CNetEvent_SoundWorld *ev = (CNetEvent_SoundWorld *)pData; + m_pSounds->PlayAt(CSounds::CHN_WORLD, ev->m_SoundID, 1.0f, vec2(ev->m_X, ev->m_Y)); + } + } +} + +void CGameClient::ProcessTriggeredEvents(int Events, vec2 Pos) +{ + if(m_SuppressEvents) + return; + + if(Events&COREEVENTFLAG_GROUND_JUMP) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos); + if(Events&COREEVENTFLAG_AIR_JUMP) + m_pEffects->AirJump(Pos); + if(Events&COREEVENTFLAG_HOOK_ATTACH_PLAYER) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, Pos); + if(Events&COREEVENTFLAG_HOOK_ATTACH_GROUND) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos); + if(Events&COREEVENTFLAG_HOOK_HIT_NOHOOK) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos); + /*if(Events&COREEVENTFLAG_HOOK_LAUNCH) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, Pos); + if(Events&COREEVENTFLAG_HOOK_RETRACT) + m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos);*/ +} + +typedef bool (*FCompareFunc)(const CNetObj_PlayerInfo*, const CNetObj_PlayerInfo*); + +bool CompareScore(const CNetObj_PlayerInfo *Pl1, const CNetObj_PlayerInfo *Pl2) +{ + return Pl1->m_Score < Pl2->m_Score; +} + +bool CompareTime(const CNetObj_PlayerInfo *Pl1, const CNetObj_PlayerInfo *Pl2) +{ + if(Pl1->m_Score < 0) + return true; + if(Pl2->m_Score < 0) + return false; + return Pl1->m_Score > Pl2->m_Score; +} + +void CGameClient::OnNewSnapshot() +{ + // clear out the invalid pointers + mem_zero(&m_Snap, sizeof(m_Snap)); + + // secure snapshot + { + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); + for(int Index = 0; Index < Num; Index++) + { + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); + if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) + { + if(Config()->m_Debug) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); + } + Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index); + } + } + } + + ProcessEvents(); + + if(Config()->m_DbgStress) + { + if((Client()->GameTick()%100) == 0) + { + char aMessage[64]; + int MsgLen = random_int()%(sizeof(aMessage)-1); + for(int i = 0; i < MsgLen; i++) + aMessage[i] = 'a'+(random_int()%('z'-'a')); + aMessage[MsgLen] = 0; + + CNetMsg_Cl_Say Msg; + Msg.m_Mode = random_int()&1; + Msg.m_Target = -1; + Msg.m_pMessage = aMessage; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + } + } + + CTuningParams StandardTuning; + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + m_Tuning = StandardTuning; + mem_zero(&m_GameInfo, sizeof(m_GameInfo)); + } + + // go trough all the items in the snapshot and gather the info we want + { + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); + for(int i = 0; i < Num; i++) + { + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); + + // demo items + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + if(Item.m_Type == NETOBJTYPE_DE_CLIENTINFO) + { + const CNetObj_De_ClientInfo *pInfo = (const CNetObj_De_ClientInfo *)pData; + int ClientID = Item.m_ID; + if(ClientID < MAX_CLIENTS) + { + CClientData *pClient = &m_aClients[ClientID]; + + if(pInfo->m_Local) + m_LocalClientID = ClientID; + pClient->m_Active = true; + pClient->m_Team = pInfo->m_Team; + IntsToStr(pInfo->m_aName, 4, pClient->m_aName); + IntsToStr(pInfo->m_aClan, 3, pClient->m_aClan); + pClient->m_Country = pInfo->m_Country; + + for(int p = 0; p < NUM_SKINPARTS; p++) + { + IntsToStr(pInfo->m_aaSkinPartNames[p], 6, pClient->m_aaSkinPartNames[p]); + pClient->m_aUseCustomColors[p] = pInfo->m_aUseCustomColors[p]; + pClient->m_aSkinPartColors[p] = pInfo->m_aSkinPartColors[p]; + } + + m_GameInfo.m_NumPlayers++; + // calculate team-balance + if(pClient->m_Team != TEAM_SPECTATORS) + m_GameInfo.m_aTeamSize[pClient->m_Team]++; + } + } + else if(Item.m_Type == NETOBJTYPE_DE_GAMEINFO) + { + const CNetObj_De_GameInfo *pInfo = (const CNetObj_De_GameInfo *)pData; + + m_GameInfo.m_GameFlags = pInfo->m_GameFlags; + m_GameInfo.m_ScoreLimit = pInfo->m_ScoreLimit; + m_GameInfo.m_TimeLimit = pInfo->m_TimeLimit; + m_GameInfo.m_MatchNum = pInfo->m_MatchNum; + m_GameInfo.m_MatchCurrent = pInfo->m_MatchCurrent; + } + else if(Item.m_Type == NETOBJTYPE_DE_TUNEPARAMS) + { + const CNetObj_De_TuneParams *pInfo = (const CNetObj_De_TuneParams *)pData; + + mem_copy(&m_Tuning, pInfo->m_aTuneParams, sizeof(m_Tuning)); + m_ServerMode = SERVERMODE_PURE; + } + } + + // network items + if(Item.m_Type == NETOBJTYPE_PLAYERINFO) + { + const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; + int ClientID = Item.m_ID; + if(ClientID < MAX_CLIENTS && m_aClients[ClientID].m_Active) + { + m_Snap.m_paPlayerInfos[ClientID] = pInfo; + m_Snap.m_aInfoByScore[ClientID].m_pPlayerInfo = pInfo; + m_Snap.m_aInfoByScore[ClientID].m_ClientID = ClientID; + + if(m_LocalClientID == ClientID) + { + m_Snap.m_pLocalInfo = pInfo; + + if(m_aClients[ClientID].m_Team == TEAM_SPECTATORS) + { + m_Snap.m_SpecInfo.m_Active = true; + m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; + m_Snap.m_SpecInfo.m_SpectatorID = -1; + } + } + m_aClients[ClientID].UpdateBotRenderInfo(this, ClientID); + } + } + else if(Item.m_Type == NETOBJTYPE_PLAYERINFORACE) + { + const CNetObj_PlayerInfoRace *pInfo = (const CNetObj_PlayerInfoRace *)pData; + int ClientID = Item.m_ID; + if(ClientID < MAX_CLIENTS && m_aClients[ClientID].m_Active) + { + m_Snap.m_paPlayerInfosRace[ClientID] = pInfo; + } + } + else if(Item.m_Type == NETOBJTYPE_CHARACTER) + { + if(Item.m_ID < MAX_CLIENTS) + { + CSnapState::CCharacterInfo *pCharInfo = &m_Snap.m_aCharacters[Item.m_ID]; + const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID); + pCharInfo->m_Cur = *((const CNetObj_Character *)pData); + + // clamp ammo count for non ninja weapon + if(pCharInfo->m_Cur.m_Weapon != WEAPON_NINJA) + pCharInfo->m_Cur.m_AmmoCount = clamp(pCharInfo->m_Cur.m_AmmoCount, 0, 10); + + if(pOld) + { + pCharInfo->m_Active = true; + pCharInfo->m_Prev = *((const CNetObj_Character *)pOld); + + // limit evolving to 3 seconds + int EvolvePrevTick = min(pCharInfo->m_Prev.m_Tick + Client()->GameTickSpeed()*3, Client()->PrevGameTick()); + int EvolveCurTick = min(pCharInfo->m_Cur.m_Tick + Client()->GameTickSpeed()*3, Client()->GameTick()); + + // reuse the evolved char + if(m_aClients[Item.m_ID].m_Evolved.m_Tick == EvolvePrevTick) + { + pCharInfo->m_Prev = m_aClients[Item.m_ID].m_Evolved; + if(mem_comp(pData, pOld, sizeof(CNetObj_Character)) == 0) + pCharInfo->m_Cur = m_aClients[Item.m_ID].m_Evolved; + } + + if(pCharInfo->m_Prev.m_Tick) + EvolveCharacter(&pCharInfo->m_Prev, EvolvePrevTick); + if(pCharInfo->m_Cur.m_Tick) + EvolveCharacter(&pCharInfo->m_Cur, EvolveCurTick); + + m_aClients[Item.m_ID].m_Evolved = m_Snap.m_aCharacters[Item.m_ID].m_Cur; + } + + if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK) + ProcessTriggeredEvents(pCharInfo->m_Cur.m_TriggeredEvents, vec2(pCharInfo->m_Cur.m_X, pCharInfo->m_Cur.m_Y)); + } + } + else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO) + { + m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData; + m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID); + m_Snap.m_SpecInfo.m_Active = true; + m_Snap.m_SpecInfo.m_SpecMode = m_Snap.m_pSpectatorInfo->m_SpecMode; + m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID; + } + else if(Item.m_Type == NETOBJTYPE_GAMEDATA) + { + m_Snap.m_pGameData = (const CNetObj_GameData *)pData; + + static int s_LastGameFlags = 0; + int GameFlags = m_Snap.m_pGameData->m_GameStateFlags; + if(!(s_LastGameFlags&GAMESTATEFLAG_GAMEOVER) && GameFlags&GAMESTATEFLAG_GAMEOVER) + OnGameOver(); + else if(s_LastGameFlags&GAMESTATEFLAG_GAMEOVER && !(GameFlags&GAMESTATEFLAG_GAMEOVER)) + OnStartGame(); + + // stats + if(m_Snap.m_pGameData->m_GameStartTick != m_LastGameStartTick && !(s_LastGameFlags&GAMESTATEFLAG_ROUNDOVER) + && !(s_LastGameFlags&GAMESTATEFLAG_PAUSED) && (!(GameFlags&GAMESTATEFLAG_PAUSED) || GameFlags&GAMESTATEFLAG_STARTCOUNTDOWN)) + { + m_pStats->OnMatchStart(); + } + + if(!(GameFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) + m_pStats->UpdatePlayTime(Client()->GameTick() - Client()->PrevGameTick()); + + s_LastGameFlags = GameFlags; + m_LastGameStartTick = m_Snap.m_pGameData->m_GameStartTick; + } + else if(Item.m_Type == NETOBJTYPE_GAMEDATATEAM) + { + m_Snap.m_pGameDataTeam = (const CNetObj_GameDataTeam *)pData; + } + else if(Item.m_Type == NETOBJTYPE_GAMEDATAFLAG) + { + m_Snap.m_pGameDataFlag = (const CNetObj_GameDataFlag *)pData; + m_Snap.m_GameDataFlagSnapID = Item.m_ID; + + // stats + if(m_LastFlagCarrierRed == FLAG_ATSTAND && m_Snap.m_pGameDataFlag->m_FlagCarrierRed >= 0) + m_pStats->OnFlagGrab(m_Snap.m_pGameDataFlag->m_FlagCarrierRed); + else if(m_LastFlagCarrierBlue == FLAG_ATSTAND && m_Snap.m_pGameDataFlag->m_FlagCarrierBlue >= 0) + m_pStats->OnFlagGrab(m_Snap.m_pGameDataFlag->m_FlagCarrierBlue); + + m_LastFlagCarrierRed = m_Snap.m_pGameDataFlag->m_FlagCarrierRed; + m_LastFlagCarrierBlue = m_Snap.m_pGameDataFlag->m_FlagCarrierBlue; + } + else if(Item.m_Type == NETOBJTYPE_GAMEDATARACE) + { + m_Snap.m_pGameDataRace = (const CNetObj_GameDataRace *)pData; + } + else if(Item.m_Type == NETOBJTYPE_FLAG) + { + m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData; + } + } + } + + // setup local pointers + if(m_LocalClientID >= 0) + { + CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_LocalClientID]; + if(c->m_Active) + { + if (!m_Snap.m_SpecInfo.m_Active) + { + m_Snap.m_pLocalCharacter = &c->m_Cur; + m_Snap.m_pLocalPrevCharacter = &c->m_Prev; + m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); + } + } + else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_LocalClientID)) + { + // player died + m_pControls->OnPlayerDeath(); + } + } + else + { + m_Snap.m_SpecInfo.m_Active = true; + if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && + m_DemoSpecID != -1 && m_Snap.m_aCharacters[m_DemoSpecID].m_Active) + { + m_Snap.m_SpecInfo.m_SpecMode = SPEC_PLAYER; + m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; + } + else + { + if (m_DemoSpecMode == SPEC_PLAYER) + { + m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; + m_Snap.m_SpecInfo.m_SpectatorID = -1; + } + else + { + m_Snap.m_SpecInfo.m_SpecMode = m_DemoSpecMode; + m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; + } + } + } + + // sort player infos by score + FCompareFunc Compare = (m_GameInfo.m_GameFlags&GAMEFLAG_RACE) ? CompareTime : CompareScore; + + for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort + { + for(int i = 0; i < MAX_CLIENTS-k-1; i++) + { + if(m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo && (!m_Snap.m_aInfoByScore[i].m_pPlayerInfo || + Compare(m_Snap.m_aInfoByScore[i].m_pPlayerInfo, m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo))) + { + CPlayerInfoItem Tmp = m_Snap.m_aInfoByScore[i]; + m_Snap.m_aInfoByScore[i] = m_Snap.m_aInfoByScore[i+1]; + m_Snap.m_aInfoByScore[i+1] = Tmp; + } + } + } + + // calc some player stats + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(!m_Snap.m_paPlayerInfos[i]) + continue; + + // count not ready players + if(m_Snap.m_pGameData && (m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_WARMUP)) && + m_Snap.m_pGameData->m_GameStateEndTick == 0 && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY)) + m_Snap.m_NotReadyCount++; + + // count alive players per team + if((m_GameInfo.m_GameFlags&GAMEFLAG_SURVIVAL) && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD)) + m_Snap.m_AliveCount[m_aClients[i].m_Team]++; + } + + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(m_aClients[i].m_Active) + m_aClients[i].UpdateRenderInfo(this, i, true); + } + } + + CServerInfo CurrentServerInfo; + Client()->GetServerInfo(&CurrentServerInfo); + if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0 && + str_comp(CurrentServerInfo.m_aGameType, "LMS") != 0 && str_comp(CurrentServerInfo.m_aGameType, "LTS") != 0) + m_ServerMode = SERVERMODE_MOD; + else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0) + m_ServerMode = SERVERMODE_PURE; + else + m_ServerMode = SERVERMODE_PUREMOD; +} + +void CGameClient::OnDemoRecSnap() +{ + // add client info + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(!m_aClients[i].m_Active) + continue; + + CNetObj_De_ClientInfo *pClientInfo = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_CLIENTINFO, i, sizeof(CNetObj_De_ClientInfo))); + if(!pClientInfo) + return; + + pClientInfo->m_Local = i==m_LocalClientID ? 1 : 0; + pClientInfo->m_Team = m_aClients[i].m_Team; + StrToInts(pClientInfo->m_aName, 4, m_aClients[i].m_aName); + StrToInts(pClientInfo->m_aClan, 3, m_aClients[i].m_aClan); + pClientInfo->m_Country = m_aClients[i].m_Country; + + for(int p = 0; p < NUM_SKINPARTS; p++) + { + StrToInts(pClientInfo->m_aaSkinPartNames[p], 6, m_aClients[i].m_aaSkinPartNames[p]); + pClientInfo->m_aUseCustomColors[p] = m_aClients[i].m_aUseCustomColors[p]; + pClientInfo->m_aSkinPartColors[p] = m_aClients[i].m_aSkinPartColors[p]; + } + } + + // add tuning + CTuningParams StandardTuning; + if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) != 0) + { + CNetObj_De_TuneParams *pTuneParams = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_TUNEPARAMS, 0, sizeof(CNetObj_De_TuneParams))); + if(!pTuneParams) + return; + + mem_copy(pTuneParams->m_aTuneParams, &m_Tuning, sizeof(pTuneParams->m_aTuneParams)); + } + + // add game info + CNetObj_De_GameInfo *pGameInfo = static_cast(Client()->SnapNewItem(NETOBJTYPE_DE_GAMEINFO, 0, sizeof(CNetObj_De_GameInfo))); + if(!pGameInfo) + return; + + pGameInfo->m_GameFlags = m_GameInfo.m_GameFlags; + pGameInfo->m_ScoreLimit = m_GameInfo.m_ScoreLimit; + pGameInfo->m_TimeLimit = m_GameInfo.m_TimeLimit; + pGameInfo->m_MatchNum = m_GameInfo.m_MatchNum; + pGameInfo->m_MatchCurrent = m_GameInfo.m_MatchCurrent; +} + +void CGameClient::OnPredict() +{ + // Here we predict player movements. For the local player, we also predict + // the result of the local input to make the game appear responsive even at + // high latencies. For non-local players, we predict what will happen if + // they don't apply any inputs. In both cases we are extrapolating + // (predicting) what will happen between `GameTick` and `PredGameTick`. + + // don't predict anything if we are paused or round/game is over + if(IsWorldPaused()) + { + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_Snap.m_aCharacters[i].m_Active) + continue; + + // instead of predicting into the future, just use the current and + // previous snapshots that we already have + m_aPredictedPrevChars[i].Read(&m_Snap.m_aCharacters[i].m_Prev); + m_aPredictedChars[i].Read(&m_Snap.m_aCharacters[i].m_Cur); + } + + return; + } + + // repredict character + CWorldCore World; + World.m_Tuning = m_Tuning; + + // search for players + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_Snap.m_aCharacters[i].m_Active) + continue; + + m_aClients[i].m_Predicted.Init(&World, Collision()); + World.m_apCharacters[i] = &m_aClients[i].m_Predicted; + m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); + } + + // predict + for(int Tick = Client()->GameTick() + 1; + Tick <= Client()->PredGameTick(); + Tick++) + { + // first calculate where everyone should move + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(!World.m_apCharacters[c]) + continue; + + // Before running the last iteration, store our predictions. We use + // `Prev` because we haven't run the last iteration yet, so our + // data is from the previous tick. + if(Tick == Client()->PredGameTick()) + m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; + + mem_zero( + &World.m_apCharacters[c]->m_Input, + sizeof(World.m_apCharacters[c]->m_Input) + ); + + if(m_LocalClientID == c) + { + // apply player input + const int *pInput = Client()->GetInput(Tick); + if (pInput) + World.m_apCharacters[c]->m_Input = *( + (const CNetObj_PlayerInput*)pInput + ); + + World.m_apCharacters[c]->Tick(true); + } + else + { + // don't apply inputs for non-local players + World.m_apCharacters[c]->Tick(false); + } + } + + // move all players and quantize their data + for(int c = 0; c < MAX_CLIENTS; c++) + { + if (!World.m_apCharacters[c]) + continue; + + World.m_apCharacters[c]->AddDragVelocity(); + World.m_apCharacters[c]->ResetDragVelocity(); + World.m_apCharacters[c]->Move(); + World.m_apCharacters[c]->Quantize(); + } + + // check if we want to trigger effects + if(Tick > m_LastNewPredictedTick) + { + m_LastNewPredictedTick = Tick; + + // Only trigger effects for the local character here. Effects for + // non-local characters are triggered in `OnNewSnapshot`. Since we + // don't apply any inputs to non-local characters, it's not + // necessary to trigger events for them here. Also, our predictions + // for other players will often be wrong, so it's safer not to + // trigger events here. + if(m_LocalClientID != -1 && + World.m_apCharacters[m_LocalClientID]) + { + ProcessTriggeredEvents( + World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, + World.m_apCharacters[m_LocalClientID]->m_Pos + ); + } + } + + // After running the last iteration, store our final prediction. We should + // now have the following predictions: + // - `m_aPredictedPrevChars` stores character predictions at time + // `PredGameTick - 1` + // - `m_aPredictedChars` stores character predictions at time + // `PredGameTick` + if(Tick == Client()->PredGameTick()) + { + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(World.m_apCharacters[c]) + m_aPredictedChars[c] = *World.m_apCharacters[c]; + } + } + } + + m_PredictedTick = Client()->PredGameTick(); +} + + +bool CGameClient::ShouldUsePredicted() +{ + // We don't use predictions when: + // - Viewing a demo + // - When the game is paused or waiting + // - When we are spectating + return + Client()->State() != IClient::STATE_DEMOPLAYBACK && + !( + m_Snap.m_pGameData && + m_Snap.m_pGameData->m_GameStateFlags & ( + GAMESTATEFLAG_PAUSED | + GAMESTATEFLAG_ROUNDOVER | + GAMESTATEFLAG_GAMEOVER + ) + ) && + !(m_Snap.m_SpecInfo.m_Active); +} + +bool CGameClient::ShouldUsePredictedLocalChar() +{ + // Not sure if `m_Snap.m_pLocalCharacter` is necessary, but the old code + // checked it so I will too. + return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; +} + +bool CGameClient::ShouldUsePredictedNonLocalChars() +{ + return Config()->m_ClPredictPlayers; +} + +bool CGameClient::ShouldUsePredictedChar(int ClientID) +{ + if(ClientID == m_LocalClientID) + return ShouldUsePredictedLocalChar(); + else + // Might want to check if `ClientID` exists in `m_Snap.m_aCharacters`, + // similar to how we check if `m_pLocalCharacter` is not null in + // `ShouldUsePredictedLocalChar` + return ShouldUsePredictedNonLocalChars(); +} + +void CGameClient::UsePredictedChar( + CNetObj_Character *pPrevChar, + CNetObj_Character *pPlayerChar, + float *IntraTick, + int ClientID + ) +{ + m_aPredictedPrevChars[ClientID].Write(pPrevChar); + m_aPredictedChars[ClientID].Write(pPlayerChar); + *IntraTick = Client()->PredIntraGameTick(); +} + +vec2 CGameClient::PredictedCharPos(int ClientID) +{ + return mix( + vec2( + m_aPredictedPrevChars[ClientID].m_Pos.x, + m_aPredictedPrevChars[ClientID].m_Pos.y + ), + vec2( + m_aPredictedChars[ClientID].m_Pos.x, + m_aPredictedChars[ClientID].m_Pos.y + ), + Client()->PredIntraGameTick() + ); +} + +vec2 CGameClient::UnpredictedCharPos(int ClientID) +{ + return mix( + vec2( + m_Snap.m_aCharacters[ClientID].m_Prev.m_X, + m_Snap.m_aCharacters[ClientID].m_Prev.m_Y + ), + vec2( + m_Snap.m_aCharacters[ClientID].m_Cur.m_X, + m_Snap.m_aCharacters[ClientID].m_Cur.m_Y + ), + Client()->IntraGameTick() + ); +} + +void CGameClient::OnActivateEditor() +{ + OnRelease(); +} + +void CGameClient::CClientData::UpdateBotRenderInfo(CGameClient *pGameClient, int ClientID) +{ + static const unsigned char s_aBotColors[][3] = { + {0xff,0x00,0x00}, + {0xff,0x66,0x00}, + {0x4d,0x9f,0x45}, + {0xd5,0x9e,0x29}, + {0x9f,0xd3,0xa9}, + {0xbd,0xd8,0x5e}, + {0xc0,0x7f,0x94}, + {0xc3,0xa2,0x67}, + {0xf8,0xa8,0x3b}, + {0xcc,0xe2,0xbf}, + {0xe6,0xb4,0x98}, + {0x74,0xc7,0xa3}, + }; + + if(pGameClient->m_Snap.m_paPlayerInfos[ClientID] && pGameClient->m_Snap.m_paPlayerInfos[ClientID]->m_PlayerFlags&PLAYERFLAG_BOT) + { + m_RenderInfo.m_BotTexture = pGameClient->m_pSkins->m_BotTexture; + if(!m_RenderInfo.m_BotColor.a) // bot color has not been set; pick a random color once + { + const unsigned char* pBotColor = s_aBotColors[rand()%(sizeof(s_aBotColors)/sizeof(s_aBotColors[0]))]; + m_RenderInfo.m_BotColor = vec4(pBotColor[0]/255.f, pBotColor[1]/255.f, pBotColor[2]/255.f, 1.0f); + } + } + else + { + m_RenderInfo.m_BotTexture.Invalidate(); + m_RenderInfo.m_BotColor = vec4(0.0f, 0.0f, 0.0f, 0.0f); + } +} + +void CGameClient::CClientData::UpdateRenderInfo(CGameClient *pGameClient, int ClientID, bool UpdateSkinInfo) +{ + // update skin info + if(UpdateSkinInfo) + { + char* apSkinParts[NUM_SKINPARTS]; + for(int p = 0; p < NUM_SKINPARTS; p++) + apSkinParts[p] = m_aaSkinPartNames[p]; + + pGameClient->m_pSkins->ValidateSkinParts(apSkinParts, m_aUseCustomColors, m_aSkinPartColors, pGameClient->m_GameInfo.m_GameFlags); + + m_SkinInfo.m_Size = 64; + if(pGameClient->IsXmas()) + { + m_SkinInfo.m_HatTexture = pGameClient->m_pSkins->m_XmasHatTexture; + m_SkinInfo.m_HatSpriteIndex = ClientID % CSkins::HAT_NUM; + } + else + m_SkinInfo.m_HatTexture.Invalidate(); + + for(int p = 0; p < NUM_SKINPARTS; p++) + { + int ID = pGameClient->m_pSkins->FindSkinPart(p, m_aaSkinPartNames[p], false); + if(ID < 0) + { + if(p == SKINPART_MARKING || p == SKINPART_DECORATION) + ID = pGameClient->m_pSkins->FindSkinPart(p, "", false); + else + ID = pGameClient->m_pSkins->FindSkinPart(p, "standard", false); + + if(ID < 0) + m_SkinPartIDs[p] = 0; + else + m_SkinPartIDs[p] = ID; + } + else + { + if(m_SkinInfo.m_HatTexture.IsValid()) + { + if(p == SKINPART_BODY && str_comp(m_aaSkinPartNames[p], "standard")) + m_SkinInfo.m_HatSpriteIndex = CSkins::HAT_OFFSET_SIDE + (ClientID%CSkins::HAT_NUM); + if(p == SKINPART_DECORATION && !str_comp(m_aaSkinPartNames[p], "twinbopp")) + m_SkinInfo.m_HatSpriteIndex = CSkins::HAT_OFFSET_SIDE + (ClientID%CSkins::HAT_NUM); + } + m_SkinPartIDs[p] = ID; + } + + const CSkins::CSkinPart *pSkinPart = pGameClient->m_pSkins->GetSkinPart(p, m_SkinPartIDs[p]); + if(m_aUseCustomColors[p]) + { + m_SkinInfo.m_aTextures[p] = pSkinPart->m_ColorTexture; + m_SkinInfo.m_aColors[p] = pGameClient->m_pSkins->GetColorV4(m_aSkinPartColors[p], p==SKINPART_MARKING); + } + else + { + m_SkinInfo.m_aTextures[p] = pSkinPart->m_OrgTexture; + m_SkinInfo.m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); + } + } + } + + m_RenderInfo = m_SkinInfo; + + // force team colors + if(pGameClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + { + for(int p = 0; p < NUM_SKINPARTS; p++) + { + m_RenderInfo.m_aTextures[p] = pGameClient->m_pSkins->GetSkinPart(p, m_SkinPartIDs[p])->m_ColorTexture; + int ColorVal = pGameClient->m_pSkins->GetTeamColor(m_aUseCustomColors[p], m_aSkinPartColors[p], m_Team, p); + m_RenderInfo.m_aColors[p] = pGameClient->m_pSkins->GetColorV4(ColorVal, p==SKINPART_MARKING); + } + } +} + +void CGameClient::CClientData::Reset(CGameClient *pGameClient, int ClientID) +{ + m_aName[0] = 0; + m_aClan[0] = 0; + m_Country = -1; + m_Team = 0; + m_Angle = 0; + m_Emoticon = 0; + m_EmoticonStart = -1; + m_Active = false; + m_ChatIgnore = false; + m_Friend = false; + m_Evolved.m_Tick = -1; + for(int p = 0; p < NUM_SKINPARTS; p++) + { + m_SkinPartIDs[p] = 0; + m_SkinInfo.m_aTextures[p] = pGameClient->m_pSkins->GetSkinPart(p, 0)->m_ColorTexture; + m_SkinInfo.m_aColors[p] = vec4(1.0f, 1.0f, 1.0f , 1.0f); + } + UpdateRenderInfo(pGameClient, ClientID, false); +} + +void CGameClient::DoEnterMessage(const char *pName, int ClientID, int Team) +{ + char aBuf[128], aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); + switch(GetStrTeam(Team, m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)) + { + case STR_TEAM_GAME: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the game"), aLabel); break; + case STR_TEAM_RED: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the red team"), aLabel); break; + case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the blue team"), aLabel); break; + case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' entered and joined the spectators"), aLabel); break; + } + m_pChat->AddLine(aBuf); +} + +void CGameClient::DoLeaveMessage(const char *pName, int ClientID, const char *pReason) +{ + char aBuf[128], aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); + if(pReason[0]) + str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game (%s)"), aLabel, pReason); + else + str_format(aBuf, sizeof(aBuf), Localize("'%s' has left the game"), aLabel); + m_pChat->AddLine(aBuf); +} + +void CGameClient::DoTeamChangeMessage(const char *pName, int ClientID, int Team) +{ + char aBuf[128]; + char aLabel[64]; + GetPlayerLabel(aLabel, sizeof(aLabel), ClientID, pName); + switch(GetStrTeam(Team, m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)) + { + case STR_TEAM_GAME: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the game"), aLabel); break; + case STR_TEAM_RED: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the red team"), aLabel); break; + case STR_TEAM_BLUE: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the blue team"), aLabel); break; + case STR_TEAM_SPECTATORS: str_format(aBuf, sizeof(aBuf), Localize("'%s' joined the spectators"), aLabel); break; + } + m_pChat->AddLine(aBuf); +} + +void CGameClient::SendSwitchTeam(int Team) +{ + CNetMsg_Cl_SetTeam Msg; + Msg.m_Team = Team; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); +} + +void CGameClient::SendStartInfo() +{ + CNetMsg_Cl_StartInfo Msg; + Msg.m_pName = Config()->m_PlayerName; + Msg.m_pClan = Config()->m_PlayerClan; + Msg.m_Country = Config()->m_PlayerCountry; + for(int p = 0; p < NUM_SKINPARTS; p++) + { + Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; + Msg.m_aUseCustomColors[p] = *CSkins::ms_apUCCVariables[p]; + Msg.m_aSkinPartColors[p] = *CSkins::ms_apColorVariables[p]; + } + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); +} + +void CGameClient::SendKill() +{ + CNetMsg_Cl_Kill Msg; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); +} + +void CGameClient::SendReadyChange() +{ + CNetMsg_Cl_ReadyChange Msg; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); +} + +void CGameClient::SendSkinChange() +{ + CNetMsg_Cl_SkinChange Msg; + for(int p = 0; p < NUM_SKINPARTS; p++) + { + Msg.m_apSkinPartNames[p] = CSkins::ms_apSkinVariables[p]; + Msg.m_aUseCustomColors[p] = *CSkins::ms_apUCCVariables[p]; + Msg.m_aSkinPartColors[p] = *CSkins::ms_apColorVariables[p]; + } + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD|MSGFLAG_FLUSH); + m_LastSkinChangeTime = Client()->LocalTime(); +} + +int CGameClient::GetClientID(const char *pName) +{ + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!m_aClients[i].m_Active || i == m_LocalClientID) // skip local user + continue; + + if(!str_comp(m_aClients[i].m_aName, pName)) + return i; + } + + return -1; +} + +void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData) +{ + CGameClient *pClient = static_cast(pUserData); + if(pClient->Client()->State() != IClient::STATE_ONLINE || pClient->m_LocalClientID == -1) + return; + CMenus::CSwitchTeamInfo Info; + pClient->m_pMenus->GetSwitchTeamInfo(&Info); + int Team = pResult->GetInteger(0); + if(pClient->m_aClients[pClient->m_LocalClientID].m_Team == Team || (Team == TEAM_SPECTATORS && !(Info.m_AllowSpec)) || (Team != TEAM_SPECTATORS && Info.m_aNotification[0])) + { + if(Info.m_aNotification[0]) + pClient->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", Info.m_aNotification); + return; + } + pClient->SendSwitchTeam(Team); +} + +void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData) +{ + CGameClient *pClient = static_cast(pUserData); + if(pClient->Client()->State() == IClient::STATE_ONLINE) + pClient->SendKill(); +} + +void CGameClient::ConReadyChange(IConsole::IResult *pResult, void *pUserData) +{ + CGameClient *pClient = static_cast(pUserData); + if(pClient->Client()->State() == IClient::STATE_ONLINE) + pClient->SendReadyChange(); +} + +void CGameClient::ConchainSkinChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + CGameClient *pClient = static_cast(pUserData); + if(pClient->Client()->State() == IClient::STATE_ONLINE && pResult->NumArguments()) + pClient->SendSkinChange(); +} + +void CGameClient::ConchainFriendUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + CGameClient *pClient = static_cast(pUserData); + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(pClient->m_aClients[i].m_Active) + pClient->m_aClients[i].m_Friend = pClient->Friends()->IsFriend(pClient->m_aClients[i].m_aName, pClient->m_aClients[i].m_aClan, true); + } +} + +void CGameClient::ConchainBlacklistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + CGameClient *pClient = static_cast(pUserData); + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(pClient->m_aClients[i].m_Active) + pClient->m_aClients[i].m_ChatIgnore = pClient->Blacklist()->IsIgnored(pClient->m_aClients[i].m_aName, pClient->m_aClients[i].m_aClan, true); + } +} + +void CGameClient::ConchainXmasHatUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + CGameClient *pClient = static_cast(pUserData); + if(pClient->Client()->State() != IClient::STATE_ONLINE) + return; + + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(pClient->m_aClients[i].m_Active) + pClient->m_aClients[i].UpdateRenderInfo(pClient, i, true); + } +} + +IGameClient *CreateGameClient() +{ + return new CGameClient(); +} From dccfaf9354af1dcfbdf60fc517f669346aa8b578 Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 5 Sep 2020 11:40:25 +0200 Subject: [PATCH 403/479] small improvement --- src/game/client/gameclient.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 742c8d3f..6cef378c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1674,14 +1674,7 @@ bool CGameClient::ShouldUsePredicted() // - When we are spectating return Client()->State() != IClient::STATE_DEMOPLAYBACK && - !( - m_Snap.m_pGameData && - m_Snap.m_pGameData->m_GameStateFlags & ( - GAMESTATEFLAG_PAUSED | - GAMESTATEFLAG_ROUNDOVER | - GAMESTATEFLAG_GAMEOVER - ) - ) && + !(IsWorldPaused()) && !(m_Snap.m_SpecInfo.m_Active); } From de8539537bff61bf39b3651d95a4e155db566b25 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sat, 5 Sep 2020 23:01:22 +0100 Subject: [PATCH 404/479] Scrollregion: m_ScrollY now ties to content height --- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 11 ++++---- src/game/client/components/menus_browser.cpp | 6 ++--- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_ingame.cpp | 6 ++--- src/game/client/components/menus_listbox.cpp | 8 +++--- .../client/components/menus_scrollregion.cpp | 27 ++++++++++++------- src/game/client/components/menus_settings.cpp | 13 ++++----- 8 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 9024b8ea..a9390c4e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1957,7 +1957,7 @@ int CMenus::Render() s_ActSelection = FilterInfo.m_Country; static CListBox s_ListBox; int OldSelected = -1; - s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 12, OldSelected, &Box, false); + s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 12, 1, OldSelected, &Box, false); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 3d467c9e..68c8961a 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -150,7 +150,7 @@ class CMenus : public CComponent float m_ScrollbarWidth; float m_ScrollbarMargin; float m_SliderMinHeight; - float m_ScrollSpeed; + float m_ScrollUnit; vec4 m_ClipBgColor; vec4 m_ScrollbarBgColor; vec4 m_RailBgColor; @@ -160,7 +160,8 @@ class CMenus : public CComponent int m_Flags; enum { - FLAG_CONTENT_STATIC_WIDTH = 0x1 + FLAG_CONTENT_STATIC_WIDTH = 0x1, + FLAG_NO_SMOOTH_SCROLLING = 0x2, }; CScrollRegionParams() @@ -168,7 +169,7 @@ class CMenus : public CComponent m_ScrollbarWidth = 20; m_ScrollbarMargin = 5; m_SliderMinHeight = 25; - m_ScrollSpeed = 5; + m_ScrollUnit = 10; m_ClipBgColor = vec4(0.0f, 0.0f, 0.0f, 0.25f); m_ScrollbarBgColor = vec4(0.0f, 0.0f, 0.0f, 0.25f); m_RailBgColor = vec4(1.0f, 1.0f, 1.0f, 0.25f); @@ -226,7 +227,7 @@ class CMenus : public CComponent }; CScrollRegion(); - void Begin(CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams = 0); + void Begin(CUIRect* pClipRect, vec2* pOutOffset, CScrollRegionParams* pParams = 0); void End(); void AddRect(CUIRect Rect); void ScrollHere(int Option = CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); @@ -273,7 +274,7 @@ class CMenus : public CComponent void DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight = 20.0f, float Spacing = 2.0f); bool DoFilter(float FilterHeight = 20.0f, float Spacing = 2.0f); void DoFooter(const char *pBottomText, float FooterHeight = 20.0f); // call before DoStart to create a footer - void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, + void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, const CUIRect *pRect = 0, bool Background = true, bool *pActive = 0); CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = 0); int DoEnd(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 32afe4ca..57547463 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1151,7 +1151,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) ScrollParams.m_ClipBgColor = vec4(0,0,0,0); ScrollParams.m_Flags = CScrollRegionParams::FLAG_CONTENT_STATIC_WIDTH; ScrollParams.m_SliderMinHeight = 5; - ScrollParams.m_ScrollSpeed = 5; + ScrollParams.m_ScrollUnit = 60.0f; // 3 rows per scroll View.w += ScrollParams.m_ScrollbarWidth; s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; @@ -1511,7 +1511,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarWidth = 14; ScrollParams.m_ScrollbarMargin = 5; - ScrollParams.m_ScrollSpeed = 15; + ScrollParams.m_ScrollUnit = 40.0f; // various sized content, 40 units per scroll; s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; @@ -2113,7 +2113,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarWidth = 5; ScrollParams.m_ScrollbarMargin = 1; - ScrollParams.m_ScrollSpeed = 15; + ScrollParams.m_ScrollUnit = 40.0f; // 2 players per scroll s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; if(RowCount > 0) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index dc8b1edc..bd109edc 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -525,7 +525,7 @@ void CMenus::RenderDemoList(CUIRect MainView) static CListBox s_ListBox; s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); - s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, m_DemolistSelectedIndex); + s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, 3, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { CListboxItem Item = s_ListBox.DoNextItem(&r.front(), (&r.front() - m_lDemos.base_ptr()) == m_DemolistSelectedIndex); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 7ed31cb4..52891b92 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -235,7 +235,7 @@ void CMenus::RenderPlayers(CUIRect MainView) CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); - ScrollParams.m_ScrollSpeed = 15; + ScrollParams.m_ScrollUnit = ButtonHeight * 3; // 3 players per scroll if(s_ScrollRegion.IsScrollbarShown()) Row.VSplitRight(ScrollParams.m_ScrollbarWidth, &Row, 0); @@ -508,7 +508,7 @@ bool CMenus::RenderServerControlServer(CUIRect MainView) static CListBox s_ListBox; CUIRect List = MainView; s_ListBox.DoHeader(&List, Localize("Option"), GetListHeaderHeight()); - s_ListBox.DoStart(20.0f, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true); + s_ListBox.DoStart(20.0f, m_pClient->m_pVoting->m_NumVoteOptions, 1, 3, m_CallvoteSelectedOption, 0, true); for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { @@ -556,7 +556,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) static CListBox s_ListBox; CUIRect List = MainView; s_ListBox.DoHeader(&List, Localize("Player"), GetListHeaderHeight()); - s_ListBox.DoStart(20.0f, NumOptions, 1, Selected, 0, true); + s_ListBox.DoStart(20.0f, NumOptions, 1, 3, Selected, 0, true); for(int i = 0; i < NumOptions; i++) { diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 218c8a69..61e41a14 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -74,8 +74,8 @@ void CMenus::CListBox::DoFooter(const char *pBottomText, float FooterHeight) m_FooterHeight = FooterHeight; } -void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int SelectedIndex, - const CUIRect *pRect, bool Background, bool *pActive) +void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, + int SelectedIndex, const CUIRect *pRect, bool Background, bool *pActive) { CUIRect View; if(pRect) @@ -120,7 +120,9 @@ void CMenus::CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, i // setup the scrollbar m_ScrollOffset = vec2(0, 0); - m_ScrollRegion.Begin(&m_ListBoxView, &m_ScrollOffset); + CScrollRegionParams ScrollParams; + ScrollParams.m_ScrollUnit = m_ListBoxRowHeight * RowsPerScroll; + m_ScrollRegion.Begin(&m_ListBoxView, &m_ScrollOffset, &ScrollParams); m_ListBoxView.y += m_ScrollOffset.y; } diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 36fad1a7..dee3d87f 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -21,7 +21,7 @@ CMenus::CScrollRegion::CScrollRegion() m_Params = CScrollRegionParams(); } -void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, const CScrollRegionParams* pParams) +void CMenus::CScrollRegion::Begin(CUIRect* pClipRect, vec2* pOutOffset, CScrollRegionParams* pParams) { if(pParams) m_Params = *pParams; @@ -66,12 +66,15 @@ void CMenus::CScrollRegion::End() // scroll wheel CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; + + const bool isPageScroll = m_pInput->KeyIsPressed(KEY_LALT) || m_pInput->KeyIsPressed(KEY_RALT); if(m_pUI->MouseInside(&RegionRect)) - { + { + float ScrollUnit = isPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit; if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_UP)) - m_ScrollY -= m_Params.m_ScrollSpeed; + m_ScrollY -= ScrollUnit; else if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_DOWN)) - m_ScrollY += m_Params.m_ScrollSpeed; + m_ScrollY += ScrollUnit; } const float SliderHeight = max(m_Params.m_SliderMinHeight, @@ -79,16 +82,21 @@ void CMenus::CScrollRegion::End() CUIRect Slider = m_RailRect; Slider.h = SliderHeight; - const float MaxScroll = m_RailRect.h - SliderHeight; + + const float MaxSlider = m_RailRect.h - SliderHeight; + const float MaxScroll = m_ContentH - m_ClipRect.h; if(m_RequestScrollY >= 0) { - m_ScrollY = m_RequestScrollY/(m_ContentH - m_ClipRect.h) * MaxScroll; + m_ScrollY = m_RequestScrollY; m_RequestScrollY = -1; } m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); - Slider.y += m_ScrollY; + + + + Slider.y += m_ScrollY/MaxScroll * MaxSlider; bool Hovered = false; bool Grabbed = false; @@ -105,7 +113,6 @@ void CMenus::CScrollRegion::End() m_pUI->SetActiveItem(pID); m_MouseGrabStart.y = m_pUI->MouseY(); } - Hovered = true; } else if(InsideRail && m_pUI->MouseButtonClicked(0)) @@ -124,13 +131,13 @@ void CMenus::CScrollRegion::End() if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) { float MouseY = m_pUI->MouseY(); - m_ScrollY += MouseY - m_MouseGrabStart.y; + m_ScrollY += (MouseY - m_MouseGrabStart.y) / MaxSlider * MaxScroll; m_MouseGrabStart.y = MouseY; Grabbed = true; } m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); - m_ContentScrollOff.y = -m_ScrollY/MaxScroll * (m_ContentH - m_ClipRect.h); + m_ContentScrollOff.y = -m_ScrollY; vec4 SliderColor; if(Grabbed) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 4585027d..566abd01 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -357,7 +357,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) int OldSelected = -1; s_ListBox.DoHeader(&MainView, Localize("Skins"), GetListHeaderHeight()); m_RefreshSkinSelector = s_ListBox.DoFilter(); - s_ListBox.DoStart(50.0f, s_paSkinList.size(), 10, OldSelected); + s_ListBox.DoStart(50.0f, s_paSkinList.size(), 10, 1, OldSelected); for(int i = 0; i < s_paSkinList.size(); ++i) { @@ -436,7 +436,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) static int OldSelected = -1; s_ListBox.DoHeader(&MainView, Localize(CSkins::ms_apSkinPartNames[m_TeePartSelected]), GetListHeaderHeight()); s_InitSkinPartList = s_ListBox.DoFilter(); - s_ListBox.DoStart(50.0f, s_paList[m_TeePartSelected].size(), 5, OldSelected); + s_ListBox.DoStart(50.0f, s_paList[m_TeePartSelected].size(), 5, 1, OldSelected); for(int i = 0; i < s_paList[m_TeePartSelected].size(); ++i) { @@ -712,7 +712,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header) if(Header) s_ListBox.DoHeader(&MainView, Localize("Language"), GetListHeaderHeight()); bool IsActive = m_ActiveListBox == ACTLB_LANG; - s_ListBox.DoStart(20.0f, s_Languages.size(), 1, s_SelectedLanguage, Header?0:&MainView, Header, &IsActive); + s_ListBox.DoStart(20.0f, s_Languages.size(), 1, 3, s_SelectedLanguage, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { @@ -780,7 +780,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header) s_ListBox.DoHeader(&MainView, Localize("Theme"), GetListHeaderHeight()); bool IsActive = m_ActiveListBox == ACTLB_THEME; - s_ListBox.DoStart(20.0f, m_lThemes.size(), 1, SelectedTheme, Header?0:&MainView, Header, &IsActive); + s_ListBox.DoStart(20.0f, m_lThemes.size(), 1, 3, SelectedTheme, Header?0:&MainView, Header, &IsActive); for(sorted_array::range r = m_lThemes.all(); !r.empty(); r.pop_front()) { @@ -1129,7 +1129,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) static CListBox s_ListBox; int OldSelected = -1; s_ListBox.DoHeader(&MainView, Localize("Country"), GetListHeaderHeight()); - s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 18, OldSelected); + s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 18, 1, OldSelected); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -1470,6 +1470,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); + ScrollParams.m_ScrollUnit = 40.0f; // inconsistent margin, 2 category header per scroll s_ScrollRegion.Begin(&MainView, &ScrollOffset, &ScrollParams); MainView.y += ScrollOffset.y; @@ -1599,7 +1600,7 @@ bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, int OldSelected = -1; char aBuf[32]; - pListBox->DoStart(20.0f, lModes.size(), 1, OldSelected, pRect); + pListBox->DoStart(20.0f, lModes.size(), 1, 3, OldSelected, pRect); for(int i = 0; i < lModes.size(); ++i) { From c876164daafff4e29d9feb4cc994b166ab17b6cb Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sat, 5 Sep 2020 23:19:57 +0100 Subject: [PATCH 405/479] Remove excessive empty lines and a unused enum --- src/game/client/components/menus.h | 3 +-- src/game/client/components/menus_scrollregion.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 68c8961a..87a3b5f6 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -160,8 +160,7 @@ class CMenus : public CComponent int m_Flags; enum { - FLAG_CONTENT_STATIC_WIDTH = 0x1, - FLAG_NO_SMOOTH_SCROLLING = 0x2, + FLAG_CONTENT_STATIC_WIDTH = 0x1 }; CScrollRegionParams() diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index dee3d87f..c69a868d 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -93,9 +93,6 @@ void CMenus::CScrollRegion::End() } m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); - - - Slider.y += m_ScrollY/MaxScroll * MaxSlider; bool Hovered = false; From 112c070cbfce3871b7391a52e7e54fe2083782d7 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 06:39:23 +0100 Subject: [PATCH 406/479] Show skin names inside skin buttons. --- src/game/client/components/menus_settings.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 4585027d..8d47371c 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -357,7 +357,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) int OldSelected = -1; s_ListBox.DoHeader(&MainView, Localize("Skins"), GetListHeaderHeight()); m_RefreshSkinSelector = s_ListBox.DoFilter(); - s_ListBox.DoStart(50.0f, s_paSkinList.size(), 10, OldSelected); + s_ListBox.DoStart(60.0f, s_paSkinList.size(), 10, OldSelected); for(int i = 0; i < s_paSkinList.size(); ++i) { @@ -391,6 +391,22 @@ void CMenus::RenderSkinSelection(CUIRect MainView) Info.m_Size = 50.0f; Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); + + CUIRect Label; + Item.m_Rect.Margin(5.0f, &Item.m_Rect); + Item.m_Rect.HSplitBottom(10.0f, &Item.m_Rect, &Label); + + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_HighlightTextColor); + TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); + } + UI()->DoLabel(&Label, s->m_aName, 10.0f, CUI::ALIGN_CENTER); + if(Item.m_Selected) + { + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); + } } } From 809d384c0cd284e66ff17a6d223bc2916eddfad3 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 09:18:31 +0100 Subject: [PATCH 407/479] Optimize slider grab experience --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_browser.cpp | 2 +- .../client/components/menus_scrollregion.cpp | 24 +++++++++---------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 87a3b5f6..e79c7bf1 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -214,7 +214,7 @@ class CMenus : public CComponent CUIRect m_ClipRect; CUIRect m_RailRect; CUIRect m_LastAddedRect; // saved for ScrollHere() - vec2 m_MouseGrabStart; + vec2 m_SliderGrabPos; // where did user grab the slider vec2 m_ContentScrollOff; CScrollRegionParams m_Params; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 57547463..021e733f 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1511,7 +1511,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarWidth = 14; ScrollParams.m_ScrollbarMargin = 5; - ScrollParams.m_ScrollUnit = 40.0f; // various sized content, 40 units per scroll; + ScrollParams.m_ScrollUnit = 40.0f; // various sized content, 40 units per scroll s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index c69a868d..9db9b9e5 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -101,22 +101,29 @@ void CMenus::CScrollRegion::End() const bool InsideSlider = m_pUI->MouseInside(&Slider); const bool InsideRail = m_pUI->MouseInside(&m_RailRect); - if(InsideSlider) + if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) + { + float MouseY = m_pUI->MouseY(); + m_ScrollY += (MouseY - (Slider.y + m_SliderGrabPos.y)) / MaxSlider * MaxScroll; + m_SliderGrabPos.y = clamp(m_SliderGrabPos.y, 0.0f, SliderHeight); + Grabbed = true; + } + else if(InsideSlider) { m_pUI->SetHotItem(pID); if(!m_pUI->CheckActiveItem(pID) && m_pUI->MouseButtonClicked(0)) { m_pUI->SetActiveItem(pID); - m_MouseGrabStart.y = m_pUI->MouseY(); + m_SliderGrabPos.y = m_pUI->MouseY() - Slider.y; } Hovered = true; } else if(InsideRail && m_pUI->MouseButtonClicked(0)) { - m_ScrollY += m_pUI->MouseY() - (Slider.y+Slider.h/2); + m_ScrollY += (m_pUI->MouseY() - (Slider.y+Slider.h/2)) / MaxSlider * MaxScroll; m_pUI->SetActiveItem(pID); - m_MouseGrabStart.y = m_pUI->MouseY(); + m_SliderGrabPos.y = Slider.h/2; Hovered = true; } else if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) @@ -124,15 +131,6 @@ void CMenus::CScrollRegion::End() m_pUI->SetActiveItem(0); } - // move slider - if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) - { - float MouseY = m_pUI->MouseY(); - m_ScrollY += (MouseY - m_MouseGrabStart.y) / MaxSlider * MaxScroll; - m_MouseGrabStart.y = MouseY; - Grabbed = true; - } - m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); m_ContentScrollOff.y = -m_ScrollY; From c50795d95019f038574e506a0a0bef41ab27972b Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 12:23:37 +0100 Subject: [PATCH 408/479] Smooth scrolling --- src/game/client/components/menus.h | 5 +++ src/game/client/components/menus_browser.cpp | 2 +- .../client/components/menus_scrollregion.cpp | 40 +++++++++++++++++-- src/game/client/components/menus_settings.cpp | 2 +- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e79c7bf1..bb94fe23 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -211,6 +211,11 @@ class CMenus : public CComponent float m_ScrollY; float m_ContentH; float m_RequestScrollY; // [0, ContentHeight] + + float m_AnimTime; + float m_AnimInitScrollY; + float m_AnimTargetScrollY; + CUIRect m_ClipRect; CUIRect m_RailRect; CUIRect m_LastAddedRect; // saved for ScrollHere() diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 021e733f..9cf2dc40 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2113,7 +2113,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int ScrollParams.m_ScrollbarBgColor = vec4(0,0,0,0); ScrollParams.m_ScrollbarWidth = 5; ScrollParams.m_ScrollbarMargin = 1; - ScrollParams.m_ScrollUnit = 40.0f; // 2 players per scroll + ScrollParams.m_ScrollUnit = 60.0f; // 3 players per scroll s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); View.y += ScrollOffset.y; if(RowCount > 0) diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 9db9b9e5..a9b237ce 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -16,6 +16,9 @@ CMenus::CScrollRegion::CScrollRegion() { m_ScrollY = 0; m_ContentH = 0; + m_AnimTime = 0; + m_AnimInitScrollY = 0; + m_AnimTargetScrollY = 0; m_RequestScrollY = -1; m_ContentScrollOff = vec2(0,0); m_Params = CScrollRegionParams(); @@ -67,14 +70,24 @@ void CMenus::CScrollRegion::End() CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; + float AnimationDuration = 0.3f; + const bool isPageScroll = m_pInput->KeyIsPressed(KEY_LALT) || m_pInput->KeyIsPressed(KEY_RALT); if(m_pUI->MouseInside(&RegionRect)) { float ScrollUnit = isPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit; if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_UP)) - m_ScrollY -= ScrollUnit; + { + m_AnimTime = AnimationDuration; + m_AnimInitScrollY = m_ScrollY; + m_AnimTargetScrollY -= ScrollUnit; + } else if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_DOWN)) - m_ScrollY += ScrollUnit; + { + m_AnimTime = AnimationDuration; + m_AnimInitScrollY = m_ScrollY; + m_AnimTargetScrollY += ScrollUnit; + } } const float SliderHeight = max(m_Params.m_SliderMinHeight, @@ -88,11 +101,24 @@ void CMenus::CScrollRegion::End() if(m_RequestScrollY >= 0) { - m_ScrollY = m_RequestScrollY; + m_AnimTargetScrollY = m_RequestScrollY; + m_AnimTime = 0; m_RequestScrollY = -1; } - m_ScrollY = clamp(m_ScrollY, 0.0f, MaxScroll); + m_AnimTargetScrollY = clamp(m_AnimTargetScrollY, 0.0f, MaxScroll); + + if (m_AnimTime > 0) + { + m_AnimTime -= m_pMenus->Client()->RenderFrameTime(); + float AnimProgress = (1 - pow(m_AnimTime / AnimationDuration, 3)); // cubic ease out + m_ScrollY = m_AnimInitScrollY + (m_AnimTargetScrollY - m_AnimInitScrollY) * AnimProgress; + } + else + { + m_ScrollY = m_AnimTargetScrollY; + } + Slider.y += m_ScrollY/MaxScroll * MaxSlider; bool Hovered = false; @@ -106,6 +132,8 @@ void CMenus::CScrollRegion::End() float MouseY = m_pUI->MouseY(); m_ScrollY += (MouseY - (Slider.y + m_SliderGrabPos.y)) / MaxSlider * MaxScroll; m_SliderGrabPos.y = clamp(m_SliderGrabPos.y, 0.0f, SliderHeight); + m_AnimTargetScrollY = m_ScrollY; + m_AnimTime = 0; Grabbed = true; } else if(InsideSlider) @@ -116,6 +144,8 @@ void CMenus::CScrollRegion::End() { m_pUI->SetActiveItem(pID); m_SliderGrabPos.y = m_pUI->MouseY() - Slider.y; + m_AnimTargetScrollY = m_ScrollY; + m_AnimTime = 0; } Hovered = true; } @@ -124,6 +154,8 @@ void CMenus::CScrollRegion::End() m_ScrollY += (m_pUI->MouseY() - (Slider.y+Slider.h/2)) / MaxSlider * MaxScroll; m_pUI->SetActiveItem(pID); m_SliderGrabPos.y = Slider.h/2; + m_AnimTargetScrollY = m_ScrollY; + m_AnimTime = 0; Hovered = true; } else if(m_pUI->CheckActiveItem(pID) && !m_pUI->MouseButton(0)) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index ea88bd49..e60b1110 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1486,7 +1486,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) vec2 ScrollOffset(0, 0); CScrollRegionParams ScrollParams; ScrollParams.m_ClipBgColor = vec4(0,0,0,0); - ScrollParams.m_ScrollUnit = 40.0f; // inconsistent margin, 2 category header per scroll + ScrollParams.m_ScrollUnit = 60.0f; // inconsistent margin, 3 category header per scroll s_ScrollRegion.Begin(&MainView, &ScrollOffset, &ScrollParams); MainView.y += ScrollOffset.y; From 435fb05de161c7851b5ad466ebea290fe809d6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 6 Sep 2020 14:46:53 +0200 Subject: [PATCH 409/479] fix button and hovering logic, cleanup and refactoring --- src/engine/client/graphics_threaded.cpp | 2 +- src/engine/client/graphics_threaded.h | 2 +- src/engine/graphics.h | 2 +- src/game/client/components/console.cpp | 4 +- src/game/client/components/menus.cpp | 364 +++++------------- src/game/client/components/menus.h | 88 ++--- src/game/client/components/menus_browser.cpp | 46 +-- src/game/client/components/menus_callback.cpp | 14 +- src/game/client/components/menus_demo.cpp | 6 +- src/game/client/components/menus_ingame.cpp | 3 +- src/game/client/components/menus_popups.cpp | 5 +- .../client/components/menus_scrollregion.cpp | 12 +- src/game/client/components/menus_settings.cpp | 17 - src/game/client/gameclient.cpp | 2 +- src/game/client/ui.cpp | 87 ++--- src/game/client/ui.h | 23 +- src/game/editor/editor.cpp | 32 +- 17 files changed, 257 insertions(+), 452 deletions(-) diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index fe10aa5f..74923b9f 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -566,7 +566,7 @@ void CGraphics_Threaded::SetColor(float r, float g, float b, float a) SetColorVertex(Array, 4); } -void CGraphics_Threaded::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) +void CGraphics_Threaded::SetColor4(const vec4 &TopLeft, const vec4 &TopRight, const vec4 &BottomLeft, const vec4 &BottomRight) { dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin"); CColorVertex Array[4] = { diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index 91d1202d..35a9fa33 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -424,7 +424,7 @@ class CGraphics_Threaded : public IEngineGraphics virtual void SetColorVertex(const CColorVertex *pArray, int Num); virtual void SetColor(float r, float g, float b, float a); - virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight); + virtual void SetColor4(const vec4 &TopLeft, const vec4 &TopRight, const vec4 &BottomLeft, const vec4 &BottomRight); void TilesetFallbackSystem(int TextureIndex); virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex = -1); diff --git a/src/engine/graphics.h b/src/engine/graphics.h index c2e40be3..52384334 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -172,7 +172,7 @@ class IGraphics : public IInterface }; virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0; virtual void SetColor(float r, float g, float b, float a) = 0; - virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) = 0; + virtual void SetColor4(const vec4 &TopLeft, const vec4 &TopRight, const vec4 &BottomLeft, const vec4 &BottomRight) = 0; virtual void ReadBackbuffer(unsigned char **ppPixels, int x, int y, int w, int h) = 0; virtual void TakeScreenshot(const char *pFilename) = 0; diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 2ddb9cdb..48abad4f 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -645,7 +645,7 @@ void CGameConsole::Toggle(int Type) if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_CLOSING) { Input()->MouseModeAbsolute(); - m_pClient->m_pMenus->UseMouseButtons(false); + UI()->UseMouseButtons(false); m_ConsoleState = CONSOLE_OPENING; // reset controls m_pClient->m_pControls->OnReset(); @@ -653,7 +653,7 @@ void CGameConsole::Toggle(int Type) else { Input()->MouseModeRelative(); - m_pClient->m_pMenus->UseMouseButtons(true); + UI()->UseMouseButtons(true); m_pClient->OnRelease(); m_ConsoleState = CONSOLE_CLOSING; } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index a9390c4e..8aae27ee 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -41,7 +41,7 @@ CMenus *CMenus::CUIElementBase::m_pMenus = 0; CRenderTools *CMenus::CUIElementBase::m_pRenderTools = 0; CUI *CMenus::CUIElementBase::m_pUI = 0; IInput *CMenus::CUIElementBase::m_pInput = 0; - +IClient *CMenus::CUIElementBase::m_pClient = 0; CMenus::CMenus() { @@ -70,7 +70,6 @@ CMenus::CMenus() m_MenuActive = true; m_SeekBarActivatedTime = 0; m_SeekBarActive = true; - m_UseMouseButtons = true; m_SkinModified = false; m_KeyReaderWasActive = false; m_KeyReaderIsActive = false; @@ -99,49 +98,41 @@ CMenus::CMenus() m_ActiveListBox = ACTLB_NONE; } -float CMenus::ButtonFade(CButtonContainer *pBC, float Seconds, int Checked) +float CMenus::CButtonContainer::GetFade(bool Checked, float Seconds) { - if(UI()->HotItem() == pBC->GetID() || Checked) + if(m_pUI->HotItem() == GetID() || Checked) { - pBC->m_FadeStartTime = Client()->LocalTime(); - return Seconds; + m_FadeStartTime = m_pClient->LocalTime(); + return 1.0f; } - return max(0.0f, pBC->m_FadeStartTime - Client()->LocalTime() + Seconds); -} - -int CMenus::DoIcon(int ImageId, int SpriteId, const CUIRect *pRect) -{ - Graphics()->TextureSet(g_pData->m_aImages[ImageId].m_Id); - - Graphics()->QuadsBegin(); - RenderTools()->SelectSprite(SpriteId); - IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - return 0; + return max(0.0f, m_FadeStartTime - m_pClient->LocalTime() + Seconds)/Seconds; } -void CMenus::DoIconColor(int ImageId, int SpriteId, const CUIRect* pRect, const vec4& Color) +void CMenus::DoIcon(int ImageId, int SpriteId, const CUIRect *pRect, const vec4 *pColor) { Graphics()->TextureSet(g_pData->m_aImages[ImageId].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(SpriteId); - Graphics()->SetColor(Color.r*Color.a, Color.g*Color.a, Color.b*Color.a, Color.a); + if(pColor) + { + Graphics()->SetColor(pColor->r*pColor->a, pColor->g*pColor->a, pColor->b*pColor->a, pColor->a); + } IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } -int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active) +bool CMenus::DoButton_Toggle(const void *pID, bool 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); + } + 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 && Active) @@ -155,15 +146,12 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, return Active && UI()->DoButtonLogic(pID, pRect); } -int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, bool TextFade) +bool CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, bool Checked, const CUIRect *pRect, const char *pImageName, int Corners, float Rounding, float FontFactor, vec4 ColorHot, bool TextFade) { - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds, Checked); - float FadeVal = Fade/Seconds; - CUIRect Text = *pRect; + const float FadeVal = pBC->GetFade(Checked); - vec4 Color = mix(vec4(0.0f, 0.0f, 0.0f, 0.25f), ColorHot, FadeVal); - RenderTools()->DrawUIRect(pRect, Color, Corners, r); + CUIRect Text = *pRect; + RenderTools()->DrawUIRect(pRect, mix(vec4(0.0f, 0.0f, 0.0f, 0.25f), ColorHot, FadeVal), Corners, Rounding); if(pImageName) { @@ -183,7 +171,7 @@ int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - if(Fade > 0.0f) + if(FadeVal > 0.0f) { Graphics()->TextureSet(pImage->m_OrgTexture); Graphics()->WrapClamp(); @@ -196,7 +184,7 @@ int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, } } - Text.HMargin(pRect->h>=20.0f?2.0f:1.0f, &Text); + Text.HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Text); Text.HMargin((Text.h*FontFactor)/2.0f, &Text); if(TextFade) { @@ -212,61 +200,40 @@ int CMenus::DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, return UI()->DoButtonLogic(pBC->GetID(), pRect); } -void CMenus::DoButton_KeySelect(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect) +void CMenus::DoButton_KeySelect(CButtonContainer *pBC, const char *pText, const CUIRect *pRect) { - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds, Checked); - float FadeVal = Fade/Seconds; + const float FadeVal = pBC->GetFade(); RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), CUI::CORNER_ALL, 5.0f); - CUIRect Temp; - pRect->HMargin(1.0f, &Temp); + + CUIRect Label; + pRect->HMargin(1.0f, &Label); TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); - UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); + UI()->DoLabel(&Label, pText, Label.h*ms_FontmodHeight, CUI::ALIGN_CENTER); TextRender()->TextColor(CUI::ms_DefaultTextColor); TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } -int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) +bool CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, bool Checked, const CUIRect *pRect, float Alpha, float FontAlpha, int Corners, float Rounding, float FontFactor) { - if(Checked) - RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.25f), Corners, 10.0f); - else - { - RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 10.0f); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.7f); - } + const float ActualAlpha = UI()->MouseHovered(pRect) ? 1.0f : Alpha; + const float FadeVal = pBC->GetFade(Checked)*FontAlpha; - CUIRect Temp; - pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); - UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); - - TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); - return UI()->DoButtonLogic(pID, pRect); -} + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, Config()->m_ClMenuAlpha/100.0f*ActualAlpha+FadeVal*0.5f), Corners, Rounding); -int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha, float FontAlpha, int Corners, float r, float FontFactor) -{ - if(UI()->MouseInside(pRect)) - Alpha = 1.0f; - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds, Checked); - float FadeVal = (Fade/Seconds)*FontAlpha; - - RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, Config()->m_ClMenuAlpha/100.0f*Alpha+FadeVal*0.5f), Corners, r); - CUIRect Temp; - pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); - Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp); + CUIRect Label; + pRect->HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Label); + Label.HMargin((Label.h*FontFactor)/2.0f, &Label); TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, FontAlpha); TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f*FontAlpha); - UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER); + UI()->DoLabel(&Label, pText, Label.h*ms_FontmodHeight, CUI::ALIGN_CENTER); TextRender()->TextColor(CUI::ms_DefaultTextColor); TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); return UI()->DoButtonLogic(pBC->GetID(), pRect); } -int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect) +bool CMenus::DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect) { if(Checked) { @@ -281,7 +248,7 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUIRect Label; pRect->VMargin(2.0f, &Label); - Label.y+=2.0f; + Label.y += 2.0f; UI()->DoLabel(&Label, pText, pRect->h*ms_FontmodHeight*0.8f, Align); if(Checked) @@ -293,18 +260,23 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, return UI()->DoButtonLogic(pID, pRect); } -int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked, bool Locked) +bool CMenus::DoButton_CheckBox(const void *pID, const char *pText, bool Checked, const CUIRect *pRect, bool Locked) { + if(Locked) + { + TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); + } + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - CUIRect c = *pRect; - CUIRect t = *pRect; - c.w = c.h; - t.x += c.w; - t.w -= c.w; - t.VSplitLeft(5.0f, 0, &t); + CUIRect Checkbox = *pRect; + CUIRect Label = *pRect; + Checkbox.w = Checkbox.h; + Label.x += Checkbox.w; + Label.w -= Checkbox.w; + Label.VSplitLeft(5.0f, 0, &Label); - c.Margin(2.0f, &c); + Checkbox.Margin(2.0f, &Checkbox); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_MENUICONS].m_Id); Graphics()->QuadsBegin(); if(Locked) @@ -315,52 +287,45 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c if(UI()->HotItem() == pID) { RenderTools()->SelectSprite(SPRITE_MENU_CHECKBOX_HOVER); - IGraphics::CQuadItem QuadItem(c.x, c.y, c.w, c.h); + IGraphics::CQuadItem QuadItem(Checkbox.x, Checkbox.y, Checkbox.w, Checkbox.h); Graphics()->QuadsDrawTL(&QuadItem, 1); } RenderTools()->SelectSprite(Checked ? SPRITE_MENU_CHECKBOX_ACTIVE : SPRITE_MENU_CHECKBOX_INACTIVE); - IGraphics::CQuadItem QuadItem(c.x, c.y, c.w, c.h); + IGraphics::CQuadItem QuadItem(Checkbox.x, Checkbox.y, Checkbox.w, Checkbox.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - t.y += 1.0f; // lame fix - UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, CUI::ALIGN_CENTER); - UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); - return UI()->DoButtonLogic(pID, pRect); -} + Label.y += 1.0f; // lame fix + UI()->DoLabel(&Label, pText, pRect->h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); -int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect, bool Locked) -{ if(Locked) { - TextRender()->TextColor(0.5f, 0.5f, 0.5f, 1.0f); - DoButton_CheckBox_Common(pID, pText, "", pRect, Checked, Locked); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); return false; } - return DoButton_CheckBox_Common(pID, pText, "", pRect, Checked, Locked); + return UI()->DoButtonLogic(pID, pRect); } -int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int SelectedNumber, const CUIRect *pRect) +bool CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners, float Rounding, bool Fade) { - char aBuf[16]; - str_format(aBuf, sizeof(aBuf), "%d", SelectedNumber); - return DoButton_CheckBox_Common(pID, pText, aBuf, pRect); -} + const float FadeVal = Fade ? pBC->GetFade(Checked) : 0.0f; -int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners, float r, bool Fade) -{ - float Seconds = 0.6f; // 0.6 seconds for fade - float FadeVal = Fade ? ButtonFade(pBC, Seconds, Checked) / Seconds : 0.0f; + CUIRect Icon = *pRect; + + if(FadeVal > 0.0f || !pBC->IsCleanBackground()) + { + RenderTools()->DrawUIRect(pRect, vec4(0.0f + FadeVal, 0.0f + FadeVal, 0.0f + FadeVal, 0.25f + FadeVal * 0.5f), Corners, Rounding); + } - RenderTools()->DrawUIRect(pRect, vec4(0.0f + FadeVal, 0.0f + FadeVal, 0.0f + FadeVal, 0.25f + FadeVal * 0.5f), Corners, r); + if(!pBC->IsCleanBackground()) + { + if(Icon.w > Icon.h) + Icon.VMargin((Icon.w - Icon.h) / 2, &Icon); + else if(Icon.w < Icon.h) + Icon.HMargin((Icon.h - Icon.w) / 2, &Icon); + Icon.Margin(2.0f, &Icon); + } - CUIRect Icon = *pRect; - if(Icon.w > Icon.h) - Icon.VMargin((Icon.w - Icon.h) / 2, &Icon); - else if(Icon.w < Icon.h) - Icon.HMargin((Icon.h - Icon.w) / 2, &Icon); - Icon.Margin(2.0f, &Icon); Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -372,58 +337,9 @@ int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, return UI()->DoButtonLogic(pBC->GetID(), pRect); } -int CMenus::DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect) -{ - bool Inside = UI()->MouseInside(pRect); - - Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, Inside ? 1.0f : 0.6f); - RenderTools()->SelectSprite(SpriteID); - IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - int ReturnValue = 0; - if(Inside && Input()->KeyPress(KEY_MOUSE_1)) - ReturnValue = 1; - - return ReturnValue; -} - -int CMenus::DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, const CUIRect *pRect, bool Blend) -{ - bool Inside = UI()->MouseInside(pRect); - - Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, !Blend || Inside ? 1.0f : 0.6f); - RenderTools()->SelectSprite(SpriteID); - IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - return UI()->DoButtonLogic(pID, pRect); -} - -int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) -{ - bool Inside = UI()->MouseInside(pRect); - - Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, Inside ? 1.0f : 0.6f); - RenderTools()->SelectSprite(SpriteID); - IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - return Inside; -} - bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners) { - bool Inside = UI()->MouseInside(pRect); + bool Inside = UI()->MouseHovered(pRect); bool Changed = false; bool UpdateOffset = false; static int s_AtIndex = 0; @@ -525,8 +441,7 @@ bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str else Color = vec4(0.0f, 0.0f, 0.0f, 0.25f); RenderTools()->DrawUIRect(&Textbox, Color, Corners, 5.0f); - Textbox.VMargin(2.0f, &Textbox); - Textbox.HMargin(2.0f, &Textbox); + Textbox.Margin(2.0f, &Textbox); const char *pDisplayStr = pStr; char aStars[128]; @@ -577,13 +492,14 @@ bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str // set cursor active m_CursorActive = true; - float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex, -1.0f); - Textbox = *pRect; - Textbox.VSplitLeft(2.0f, 0, &Textbox); - Textbox.x += (w-*pOffset-TextRender()->TextWidth(0, FontSize, "|", -1, -1.0f)/2); - if((2*time_get()/time_freq()) % 2) // make it blink + { + float TextWidth = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex, -1.0f); + Textbox = *pRect; + Textbox.VSplitLeft(2.0f, 0, &Textbox); + Textbox.x += TextWidth - *pOffset - TextRender()->TextWidth(0, FontSize, "|", -1, -1.0f)/2; UI()->DoLabel(&Textbox, "|", FontSize, CUI::ALIGN_LEFT); + } } UI()->ClipDisable(); @@ -646,7 +562,7 @@ void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, co void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char* aLabels[], int Num, IScrollbarScale *pScale) { int Value = clamp(*pOption, 0, Num - 1); - int Max = Num - 1; + const int Max = Num - 1; char aBuf[128]; str_format(aBuf, sizeof(aBuf), "%s: %s", pStr, aLabels[Value]); @@ -668,70 +584,15 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR *pOption = clamp(Value, 0, Max); } -float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback) -{ - CUIRect View = *pRect; - CUIRect Header, Label; - - bool Active = pID == m_pActiveDropdown; - int Corners = Active ? CUI::CORNER_T : CUI::CORNER_ALL; - - View.HSplitTop(HeaderHeight, &Header, &View); - - // background - RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 5.0f); - - // render icon - CUIRect Button; - Header.VSplitLeft(Header.h, &Button, 0); - Button.Margin(2.0f, &Button); - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_MENUICONS].m_Id); - Graphics()->QuadsBegin(); - if(UI()->MouseInside(&Header)) - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - else - Graphics()->SetColor(0.6f, 0.6f, 0.6f, 1.0f); - if(Active) - RenderTools()->SelectSprite(SPRITE_MENU_EXPANDED); - else - RenderTools()->SelectSprite(SPRITE_MENU_COLLAPSED); - IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - Graphics()->QuadsEnd(); - - // label - Label = Header; - Label.y += 2.0f; - UI()->DoLabel(&Label, pStr, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - - if(UI()->DoButtonLogic(pID, &Header)) - { - if(Active) - m_pActiveDropdown = 0; - else - m_pActiveDropdown = (int*)pID; - } - - // render content of expanded menu - if(Active) - return HeaderHeight + (this->*pfnCallback)(View); - - return HeaderHeight; -} - -float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive) +float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool *pActive) { CUIRect View = *pRect; CUIRect Header, Label; - bool Active = *pActive; - int Corners = Active ? CUI::CORNER_T : CUI::CORNER_ALL; - View.HSplitTop(HeaderHeight, &Header, &View); // background - RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 5.0f); + RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), *pActive ? CUI::CORNER_T : CUI::CORNER_ALL, 5.0f); // render icon CUIRect Button; @@ -739,14 +600,11 @@ float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const c Button.Margin(2.0f, &Button); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_MENUICONS].m_Id); Graphics()->QuadsBegin(); - if(UI()->MouseInside(&Header)) + if(UI()->MouseHovered(&Header)) Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); else Graphics()->SetColor(0.6f, 0.6f, 0.6f, 1.0f); - if(Active) - RenderTools()->SelectSprite(SPRITE_MENU_EXPANDED); - else - RenderTools()->SelectSprite(SPRITE_MENU_COLLAPSED); + RenderTools()->SelectSprite(*pActive ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED); IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -761,7 +619,7 @@ float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const c *pActive ^= 1; // render content of expanded menu - if(Active) + if(*pActive) return HeaderHeight + (this->*pfnCallback)(View); return HeaderHeight; @@ -798,8 +656,8 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) // logic static float s_OffsetY; - const bool InsideHandle = UI()->MouseInside(&Handle); - const bool InsideRail = UI()->MouseInside(&Rail); + const bool InsideHandle = UI()->MouseHovered(&Handle); + const bool InsideRail = UI()->MouseHovered(&Rail); float ReturnValue = Current; bool Grabbed = false; // whether to apply the offset @@ -867,8 +725,8 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) // logic static float s_OffsetX; - const bool InsideHandle = UI()->MouseInside(&Handle); - const bool InsideRail = UI()->MouseInside(&Rail); + const bool InsideHandle = UI()->MouseHovered(&Handle); + const bool InsideRail = UI()->MouseHovered(&Rail); float ReturnValue = Current; bool Grabbed = false; // whether to apply the offset @@ -953,7 +811,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in static const void *pGrabbedID = 0; static bool MouseReleased = true; static int ButtonUsed = 0; - bool Inside = UI()->MouseInside(pRect) && UI()->MouseInsideClip(); + const bool Hovered = UI()->MouseHovered(pRect); int NewKey = Key; *NewModifier = Modifier; @@ -978,7 +836,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in if(ButtonUsed == 1 && !UI()->MouseButton(1)) { - if(Inside) + if(Hovered) NewKey = 0; UI()->SetActiveItem(0); } @@ -1003,24 +861,24 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in } } - if(Inside) + if(Hovered) UI()->SetHotItem(pBC->GetID()); // draw if(UI()->CheckActiveItem(pBC->GetID()) && ButtonUsed == 0) { - DoButton_KeySelect(pBC, "???", 0, pRect); + DoButton_KeySelect(pBC, "???", pRect); m_KeyReaderIsActive = true; } else { if(Key == 0) - DoButton_KeySelect(pBC, "", 0, pRect); + DoButton_KeySelect(pBC, "", pRect); else { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s%s", CBinds::GetModifierName(*NewModifier), Input()->KeyName(Key)); - DoButton_KeySelect(pBC, aBuf, 0, pRect); + DoButton_KeySelect(pBC, aBuf, pRect); } } return NewKey; @@ -1088,9 +946,11 @@ void CMenus::RenderMenubar(CUIRect Rect) Right.VSplitRight(Spacing, &Right, 0); // little space Right.VSplitRight(ButtonWidth/2.0f, &Right, &Button); static CButtonContainer s_ServerBrowserButton; - if(DoButton_SpriteID(&s_ServerBrowserButton, IMAGE_BROWSER, UI()->MouseInside(&Button) || m_GamePage == PAGE_INTERNET || m_GamePage == PAGE_LAN ? SPRITE_BROWSER_B : SPRITE_BROWSER_A, + if(DoButton_SpriteID(&s_ServerBrowserButton, IMAGE_BROWSER, UI()->MouseHovered(&Button) || m_GamePage == PAGE_INTERNET || m_GamePage == PAGE_LAN ? SPRITE_BROWSER_B : SPRITE_BROWSER_A, m_GamePage == PAGE_INTERNET || m_GamePage == PAGE_LAN, &Button) || CheckHotKey(KEY_B)) + { NewPage = ServerBrowser()->GetType() == IServerBrowser::TYPE_INTERNET ? PAGE_INTERNET : PAGE_LAN; + } Rect.HSplitTop(Spacing, 0, &Rect); Rect.HSplitTop(25.0f, &Box, &Rect); @@ -1642,16 +1502,14 @@ int CMenus::Render() static CButtonContainer s_QuitButton; // draw red-blending button - vec4 Color = mix(vec4(0.f, 0.f, 0.f, 0.25f), vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.75f), ButtonFade(&s_QuitButton, 0.6f, 0)/0.6f); + vec4 Color = mix(vec4(0.f, 0.f, 0.f, 0.25f), vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.75f), s_QuitButton.GetFade()); RenderTools()->DrawUIRect(&Button, Color, CUI::CORNER_BL, 5.0f); // draw non-blending X CUIRect XText = Button; - // XText.HMargin(Button.h>=20.0f?2.0f:1.0f, &XText); UI()->DoLabel(&XText, "\xE2\x9C\x95", XText.h*ms_FontmodHeight, CUI::ALIGN_CENTER); if(UI()->DoButtonLogic(s_QuitButton.GetID(), &Button)) - // if(DoButton_SpriteCleanID(&s_QuitButton, IMAGE_FRIENDICONS, SPRITE_FRIEND_X_A, &Button, false)) m_Popup = POPUP_QUIT; // settings button @@ -2351,19 +2209,10 @@ void CMenus::OnRender() } // update the ui - CUIRect *pScreen = UI()->Screen(); - float mx = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w; - float my = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h; - - int Buttons = 0; - if(m_UseMouseButtons) - { - if(Input()->KeyIsPressed(KEY_MOUSE_1)) Buttons |= 1; - if(Input()->KeyIsPressed(KEY_MOUSE_2)) Buttons |= 2; - if(Input()->KeyIsPressed(KEY_MOUSE_3)) Buttons |= 4; - } - - UI()->Update(mx,my,mx*3.0f,my*3.0f,Buttons); + const CUIRect *pScreen = UI()->Screen(); + float MouseX = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w; + float MouseY = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h; + UI()->Update(MouseX, MouseY, MouseX*3.0f, MouseY*3.0f); // render if(Client()->State() != IClient::STATE_DEMOPLAYBACK) @@ -2374,7 +2223,7 @@ void CMenus::OnRender() Graphics()->WrapClamp(); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); - IGraphics::CQuadItem QuadItem(mx, my, 24, 24); + IGraphics::CQuadItem QuadItem(MouseX, MouseY, 24, 24); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); Graphics()->WrapNormal(); @@ -2382,8 +2231,7 @@ void CMenus::OnRender() // render debug information if(Config()->m_Debug) { - CUIRect Screen = *UI()->Screen(); - Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); + Graphics()->MapScreen(pScreen->x, pScreen->y, pScreen->w, pScreen->h); char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->GetActiveItem(), UI()->LastActiveItem()); @@ -2415,8 +2263,8 @@ bool CMenus::IsBackgroundNeeded() const void CMenus::RenderBackground(float Time) { - float ScreenWidth = 300*Graphics()->ScreenAspect(); float ScreenHeight = 300; + float ScreenWidth = ScreenHeight*Graphics()->ScreenAspect(); Graphics()->MapScreen(0, 0, ScreenWidth, ScreenHeight); // render the tiles diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e79c7bf1..edf342fb 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -84,65 +84,55 @@ static class CLogarithmicScrollbarScale : public IScrollbarScale class CMenus : public CComponent { public: - class CButtonContainer + class CUIElementBase { + protected: + static CMenus *m_pMenus; // TODO: Refactor in order to remove this reference to menus + static CRenderTools *m_pRenderTools; + static CUI *m_pUI; + static IInput *m_pInput; + static IClient *m_pClient; + public: - float m_FadeStartTime; + static void Init(CMenus *pMenus) { m_pMenus = pMenus; m_pRenderTools = pMenus->RenderTools(); m_pUI = pMenus->UI(); m_pInput = pMenus->Input(); m_pClient = pMenus->Client(); }; + }; + class CButtonContainer : public CUIElementBase + { + bool m_CleanBackground; + float m_FadeStartTime; + public: + CButtonContainer(bool CleanBackground = false) { m_CleanBackground = CleanBackground; } const void *GetID() const { return &m_FadeStartTime; } + float GetFade(bool Checked = false, float Seconds = 0.6f); + bool IsCleanBackground() const { return m_CleanBackground; } }; private: typedef float (CMenus::*FDropdownCallback)(CUIRect View); - float ButtonFade(CButtonContainer *pBC, float Seconds, int Checked=0); - - int DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners=CUI::CORNER_ALL, float r=5.0f, bool Fade=true); - int DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect); - int DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, const CUIRect *pRect, bool Blend=true); - int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active); - int DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName=0, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f, vec4 ColorHot=vec4(1.0f, 1.0f, 1.0f, 0.75f), bool TextFade=true); - int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); - int DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha=1.0f, float FontAlpha=1.0f, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f); - int DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle Texture, int SpriteID, const CUIRect *pRect, float ImageRatio); - - int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked=false, bool Locked=false); - int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect, bool Locked=false); - int DoButton_CheckBox_Number(const void *pID, const char *pText, int SelectedNumber, const CUIRect *pRect); - - int DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect); - - int DoIcon(int ImageId, int SpriteId, const CUIRect *pRect); - void DoIconColor(int ImageId, int SpriteId, const CUIRect *pRect, const vec4& Color); - int DoButton_GridHeader(const void *pID, const char *pText, int Checked, CUI::EAlignment Align, const CUIRect *pRect); - - bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); - void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false); - void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite=false); - void DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char* aLabels[], int Num, IScrollbarScale *pScale = &LinearScrollbarScale); - float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); - float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive); + bool DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners = CUI::CORNER_ALL, float Rounding = 5.0f, bool Fade = true); + bool DoButton_Toggle(const void *pID, bool Checked, const CUIRect *pRect, bool Active); + bool DoButton_Menu(CButtonContainer *pBC, const char *pText, bool Checked, const CUIRect *pRect, const char *pImageName = 0, int Corners = CUI::CORNER_ALL, float Rounding = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), bool TextFade = true); + bool DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, bool Checked, const CUIRect *pRect, float Alpha = 1.0f, float FontAlpha = 1.0f, int Corners = CUI::CORNER_ALL, float Rounding = 5.0f, float FontFactor = 0.0f); + + bool DoButton_CheckBox(const void *pID, const char *pText, bool Checked, const CUIRect *pRect, bool Locked = false); + + void DoIcon(int ImageId, int SpriteId, const CUIRect *pRect, const vec4 *pColor = 0); + bool DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect); + + bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = CUI::CORNER_ALL); + void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden = false); + void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite = false); + void DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char *apLabels[], int Num, IScrollbarScale *pScale = &LinearScrollbarScale); + float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool *pActive); void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue); float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current); float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current); void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active); - void DoButton_KeySelect(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect); - int DoKeyReader(CButtonContainer *pPC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier); - void UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing); - - - class CUIElementBase - { - protected: - static CMenus *m_pMenus; // TODO: Refactor in order to remove this reference to menus - static CRenderTools *m_pRenderTools; - static CUI *m_pUI; - static IInput *m_pInput; - - public: - static void Init(CMenus *pMenus) { m_pMenus = pMenus; m_pRenderTools = pMenus->RenderTools(); m_pUI = pMenus->UI(); m_pInput = pMenus->Input(); }; - }; + void DoButton_KeySelect(CButtonContainer *pBC, const char *pText, const CUIRect *pRect); + int DoKeyReader(CButtonContainer *pPC, const CUIRect *pRect, int Key, int Modifier, int *pNewModifier); // Scroll region : found in menus_scrollregion.cpp struct CScrollRegionParams @@ -329,7 +319,6 @@ class CMenus : public CComponent int m_MenuPage; int m_MenuPageOld; bool m_MenuActive; - bool m_UseMouseButtons; vec2 m_MousePos; vec2 m_PrevMousePos; bool m_CursorActive; @@ -617,7 +606,9 @@ class CMenus : public CComponent // buttons var int m_SwitchButton; - int m_aButtonID[3]; + CButtonContainer m_DeleteButtonContainer; + CButtonContainer m_UpButtonContainer; + CButtonContainer m_DownButtonContainer; CBrowserFilter() {} CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser); @@ -853,6 +844,7 @@ class CMenus : public CComponent float RenderSettingsControlsScoreboard(CUIRect View); float RenderSettingsControlsStats(CUIRect View); float RenderSettingsControlsMisc(CUIRect View); + void DoSettingsControlsButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing); void DoJoystickAxisPicker(CUIRect View); @@ -884,8 +876,6 @@ class CMenus : public CComponent }; void GetSwitchTeamInfo(CSwitchTeamInfo *pInfo); - void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; } - static CMenusKeyBinder m_Binder; CMenus(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 021e733f..c5693e9c 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -41,6 +41,7 @@ vec3 TextHighlightColor = vec3(0.4f, 0.4f, 1.0f); // filters CMenus::CBrowserFilter::CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser) + : m_DeleteButtonContainer(true), m_UpButtonContainer(true), m_DownButtonContainer(true) { m_Extended = false; m_Custom = Custom; @@ -431,13 +432,13 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { // logic int ReturnValue = 0; - bool Inside = UI()->MouseInside(&View) && UI()->MouseInsideClip(); + const bool Hovered = UI()->MouseHovered(&View); if(UI()->CheckActiveItem(pID)) { if(!UI()->MouseButton(0)) { - if(Inside) + if(Hovered) ReturnValue = 1; UI()->SetActiveItem(0); } @@ -448,7 +449,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn UI()->SetActiveItem(pID); } - if(Inside) + if(Hovered) { UI()->SetHotItem(pID); RenderTools()->DrawRoundRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.5f), 5.0f); @@ -464,7 +465,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn vec4 TextBaseOutlineColor = vec4(0.0, 0.0, 0.0, 0.3f); vec4 ServerInfoTextBaseColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - if(Selected || Inside) + if(Selected || Hovered) { TextBaseColor = vec4(0.0f, 0.0f, 0.0f, TextAlpha); ServerInfoTextBaseColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); @@ -501,7 +502,8 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Rect.VSplitLeft(Rect.h, &Icon, &Rect); Icon.Margin(2.0f, &Icon); - if(DoButton_SpriteClean(IMAGE_BROWSEICONS, pEntry->m_Favorite ? SPRITE_BROWSE_STAR_A : SPRITE_BROWSE_STAR_B, &Icon)) + DoIcon(IMAGE_BROWSEICONS, pEntry->m_Favorite ? SPRITE_BROWSE_STAR_A : SPRITE_BROWSE_STAR_B, &Icon); + if(UI()->DoButtonLogic(&pEntry->m_Favorite, &Icon)) { if(!pEntry->m_Favorite) ServerBrowser()->AddFavorite(pEntry); @@ -585,7 +587,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn int Ping = pEntry->m_Latency; vec4 Color; - if(Selected || Inside) + if(Selected || Hovered) { Color = TextBaseColor; } @@ -639,7 +641,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { View.HSplitTop(ms_aBrowserCols[0].m_Rect.h, 0, &View); - if(ReturnValue && UI()->MouseInside(&View)) + if(ReturnValue && UI()->MouseHovered(&View)) ReturnValue++; CUIRect Info, Scoreboard; @@ -669,10 +671,10 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) { Switch = true; // switch later, to make sure we haven't clicked one of the filter buttons (edit...) } - vec4 Color = UI()->MouseInside(&View) ? vec4(1.0f, 1.0f, 1.0f, 1.0f) : vec4(0.6f, 0.6f, 0.6f, 1.0f); + vec4 Color = UI()->MouseHovered(&View) ? vec4(1.0f, 1.0f, 1.0f, 1.0f) : vec4(0.6f, 0.6f, 0.6f, 1.0f); View.VSplitLeft(20.0f, &Button, &View); Button.Margin(2.0f, &Button); - DoIconColor(IMAGE_MENUICONS, pFilter->Extended() ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED, &Button, Color); + DoIcon(IMAGE_MENUICONS, pFilter->Extended() ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED, &Button, &Color); // split buttons from label View.VSplitLeft(Spacing, 0, &View); @@ -691,7 +693,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) Button.Margin(2.0f, &Button); if(pFilter->Custom() == CBrowserFilter::FILTER_CUSTOM) { - if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_A, &Button)) + if(DoButton_SpriteID(&pFilter->m_DeleteButtonContainer, IMAGE_TOOLICONS, SPRITE_TOOL_X_A, false, &Button)) { m_RemoveFilterIndex = FilterIndex; str_format(aBuf, sizeof(aBuf), Localize("Are you sure that you want to remove the filter '%s' from the server browser?"), pFilter->Name()); @@ -706,8 +708,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) Button.Margin(2.0f, &Button); if(FilterIndex > 0 && (pFilter->Custom() > CBrowserFilter::FILTER_ALL || m_lFilters[FilterIndex-1].Custom() != CBrowserFilter::FILTER_STANDARD)) { - DoIcon(IMAGE_TOOLICONS, SPRITE_TOOL_UP_A, &Button); - if(UI()->DoButtonLogic(&pFilter->m_aButtonID[0], &Button)) + if(DoButton_SpriteID(&pFilter->m_UpButtonContainer, IMAGE_TOOLICONS, SPRITE_TOOL_UP_A, false, &Button)) { Move(true, FilterIndex); Switch = false; @@ -721,8 +722,7 @@ void CMenus::RenderFilterHeader(CUIRect View, int FilterIndex) Button.Margin(2.0f, &Button); if(FilterIndex >= 0 && FilterIndex < m_lFilters.size()-1 && (pFilter->Custom() != CBrowserFilter::FILTER_STANDARD || m_lFilters[FilterIndex+1].Custom() > CBrowserFilter::FILTER_ALL)) { - DoIcon(IMAGE_TOOLICONS, SPRITE_TOOL_DOWN_A, &Button); - if(UI()->DoButtonLogic(&pFilter->m_aButtonID[1], &Button)) + if(DoButton_SpriteID(&pFilter->m_DownButtonContainer, IMAGE_TOOLICONS, SPRITE_TOOL_DOWN_A, false, &Button)) { Move(false, FilterIndex); Switch = false; @@ -922,7 +922,7 @@ void CMenus::RenderServerbrowserOverlay() vec2 OverlayCenter = vec2(View.x+View.w/2.0f, View.y+View.h/2.0f); float MouseDistance = distance(m_MousePos, OverlayCenter); float PrefMouseDistance = distance(m_PrevMousePos, OverlayCenter); - if(PrefMouseDistance > MouseDistance && !UI()->MouseInside(&View)) + if(PrefMouseDistance > MouseDistance && !UI()->MouseHovered(&View)) { m_InfoOverlayActive = false; m_InfoOverlay.m_Reset = true; @@ -1541,7 +1541,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) if(s_ScrollRegion.IsRectClipped(Rect)) continue; - const bool Inside = UI()->MouseInside(&Rect); + const bool Inside = UI()->MouseHovered(&Rect); bool ButtonResult = UI()->DoButtonLogic(&(s_FriendButtons[ButtonId%20]), &Rect); RenderTools()->DrawUIRect(&Rect, vec4(s_ListColor[i].r, s_ListColor[i].g, s_ListColor[i].b, Inside ? 0.5f : 0.3f), CUI::CORNER_ALL, 5.0f); Rect.Margin(2.0f, &Rect); @@ -1572,7 +1572,8 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) Icon.HSplitTop(14.0f, &Rect, 0); Rect.VSplitRight(12.0f, 0, &Icon); Icon.HMargin((Icon.h - Icon.w) / 2, &Icon); - if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &Icon)) + DoIcon(IMAGE_TOOLICONS, UI()->MouseHovered(&Icon) ? SPRITE_TOOL_X_A : SPRITE_TOOL_X_B, &Icon); + if(UI()->DoButtonLogic(&m_lFriendList[i][f], &Icon)) { m_pDeleteFriend = &m_lFriendList[i][f]; ButtonResult = false; @@ -1599,8 +1600,8 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) // header RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); Header.VSplitLeft(Header.h, &Icon, &Label); - vec4 Color = UI()->MouseInside(&Header) ? vec4(1.0f, 1.0f, 1.0f, 1.0f) : vec4(0.6f, 0.6f, 0.6f, 1.0f); - DoIconColor(IMAGE_MENUICONS, s_ListExtended[i] ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED, &Icon, Color); + vec4 Color = UI()->MouseHovered(&Header) ? vec4(1.0f, 1.0f, 1.0f, 1.0f) : vec4(0.6f, 0.6f, 0.6f, 1.0f); + DoIcon(IMAGE_MENUICONS, s_ListExtended[i] ? SPRITE_MENU_EXPANDED : SPRITE_MENU_COLLAPSED, &Icon, &Color); int ListSize = m_lFriendList[i].size(); switch(i) { @@ -1645,7 +1646,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) const char *pButtonText = (!s_aName[0] && !s_aClan[0]) ? Localize("Add friend/clan") : s_aName[0] ? Localize("Add friend") : Localize("Add clan"); UI()->DoLabel(&Label, pButtonText, FontSize, CUI::ALIGN_CENTER); if(s_aName[0] || s_aClan[0]) - DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button)?SPRITE_FRIEND_PLUS_A:SPRITE_FRIEND_PLUS_B, &Icon); + DoIcon(IMAGE_FRIENDICONS, UI()->MouseHovered(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); static CButtonContainer s_AddFriend; if((s_aName[0] || s_aClan[0]) && UI()->DoButtonLogic(&s_AddFriend, &Button)) { @@ -1694,7 +1695,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) UI()->DoLabel(&Label, Localize("New filter"), FontSize, CUI::ALIGN_LEFT); if(s_aFilterName[0]) { - DoIcon(IMAGE_FRIENDICONS, UI()->MouseInside(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); + DoIcon(IMAGE_FRIENDICONS, UI()->MouseHovered(&Button) ? SPRITE_FRIEND_PLUS_A : SPRITE_FRIEND_PLUS_B, &Icon); static CButtonContainer s_AddFilter; if(UI()->DoButtonLogic(&s_AddFilter, &Button)) { @@ -1808,7 +1809,8 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) FilterItem.VSplitLeft(Spacing, 0, &FilterItem); UI()->DoLabel(&FilterItem, FilterInfo.m_aGametype[i], FontSize, CUI::ALIGN_LEFT); FilterItem.VSplitRight(IconWidth, 0, &FilterItem); - if(DoButton_SpriteClean(IMAGE_TOOLICONS, SPRITE_TOOL_X_B, &FilterItem)) + DoIcon(IMAGE_TOOLICONS, UI()->MouseHovered(&FilterItem) ? SPRITE_TOOL_X_A : SPRITE_TOOL_X_B, &FilterItem); + if(UI()->DoButtonLogic(&FilterInfo.m_aGametype[i], &FilterItem)) { // remove gametype entry if((i == CServerFilterInfo::MAX_GAMETYPES - 1) || !FilterInfo.m_aGametype[i + 1][0]) diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index b1fb130b..7cb8f280 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -65,7 +65,7 @@ static CKeyInfo gs_aKeys[] = const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); -void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing) +void CMenus::DoSettingsControlsButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spacing) { for (int i = Start; i < Stop; i++) { @@ -247,7 +247,7 @@ float CMenus::RenderSettingsControlsMovement(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(0, 5, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(0, 5, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -264,7 +264,7 @@ float CMenus::RenderSettingsControlsWeapon(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(5, 12, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(5, 12, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -281,7 +281,7 @@ float CMenus::RenderSettingsControlsVoting(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(12, 14, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(12, 14, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -298,7 +298,7 @@ float CMenus::RenderSettingsControlsChat(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(14, 18, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(14, 18, View, ButtonHeight, Spacing); return BackgroundHeight; } @@ -339,7 +339,7 @@ float CMenus::RenderSettingsControlsScoreboard(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); View.HSplitTop(ButtonHeight*2+Spacing*3, 0, &View); View.VSplitLeft(View.w/3, 0, &View); @@ -364,7 +364,7 @@ float CMenus::RenderSettingsControlsMisc(CUIRect View) View.HSplitTop(BackgroundHeight, &View, 0); RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - UiDoGetButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); + DoSettingsControlsButtons(StartOption, StartOption+NumOptions, View, ButtonHeight, Spacing); return BackgroundHeight; } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index bd109edc..70aa5cc3 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -125,8 +125,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, CUI::ALIGN_CENTER); // do the logic - bool Inside = UI()->MouseInside(&SeekBar); - if(UI()->CheckActiveItem(&s_PrevAmount)) { if(!UI()->MouseButton(0)) @@ -157,7 +155,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } - if(Inside) + if(UI()->MouseHovered(&SeekBar)) UI()->SetHotItem(&s_PrevAmount); } @@ -549,7 +547,7 @@ void CMenus::RenderDemoList(CUIRect MainView) IconColor = vec4(0.5, 1, 0.5, 1); } - DoIconColor(IMAGE_FILEICONS, DemoItem.m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon, IconColor); + DoIcon(IMAGE_FILEICONS, DemoItem.m_IsDir ? SPRITE_FILE_FOLDER : SPRITE_FILE_DEMO1, &FileIcon, &IconColor); for(int c = 0; c < NumCols; c++) { diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 52891b92..746997d4 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -780,8 +780,7 @@ void CMenus::RenderServerControl(CUIRect MainView) // clear button { static CButtonContainer s_ClearButton; - float Fade = ButtonFade(&s_ClearButton, 0.6f); - RenderTools()->DrawUIRect(&ClearButton, vec4(1.0f, 1.0f, 1.0f, 0.33f+(Fade/0.6f)*0.165f), CUI::CORNER_R, 3.0f); + RenderTools()->DrawUIRect(&ClearButton, vec4(1.0f, 1.0f, 1.0f, 0.33f+s_ClearButton.GetFade()*0.165f), CUI::CORNER_R, 3.0f); Label = ClearButton; Label.y += 2.0f; UI()->DoLabel(&Label, "x", Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); diff --git a/src/game/client/components/menus_popups.cpp b/src/game/client/components/menus_popups.cpp index b488344f..3e8ce9bc 100644 --- a/src/game/client/components/menus_popups.cpp +++ b/src/game/client/components/menus_popups.cpp @@ -53,15 +53,14 @@ void CMenus::DoPopupMenu() { if(m_PopupActive) { - bool Inside = UI()->MouseInside(&s_Popups.m_Rect); UI()->SetHotItem(&s_Popups.m_pId); if(UI()->CheckActiveItem(&s_Popups.m_pId)) { if(!UI()->MouseButton(0)) { - if(!Inside) - m_PopupActive = false; + if(!UI()->MouseHovered(&s_Popups.m_Rect)) + m_PopupActive = false; UI()->SetActiveItem(0); } } diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 9db9b9e5..5d4b243f 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -67,10 +67,10 @@ void CMenus::CScrollRegion::End() CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; - const bool isPageScroll = m_pInput->KeyIsPressed(KEY_LALT) || m_pInput->KeyIsPressed(KEY_RALT); - if(m_pUI->MouseInside(&RegionRect)) - { - float ScrollUnit = isPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit; + const bool IsPageScroll = m_pInput->KeyIsPressed(KEY_LALT) || m_pInput->KeyIsPressed(KEY_RALT); + if(m_pUI->MouseHovered(&RegionRect)) + { + const float ScrollUnit = IsPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit; if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_UP)) m_ScrollY -= ScrollUnit; else if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_DOWN)) @@ -98,8 +98,8 @@ void CMenus::CScrollRegion::End() bool Hovered = false; bool Grabbed = false; const void* pID = &m_ScrollY; - const bool InsideSlider = m_pUI->MouseInside(&Slider); - const bool InsideRail = m_pUI->MouseInside(&m_RailRect); + const bool InsideSlider = m_pUI->MouseHovered(&Slider); + const bool InsideRail = m_pUI->MouseHovered(&m_RailRect); if(m_pUI->CheckActiveItem(pID) && m_pUI->MouseButton(0)) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index ea88bd49..c8dd52fa 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -63,23 +63,6 @@ bool CMenusKeyBinder::OnInput(IInput::CEvent Event) return false; } -int CMenus::DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle Texture, int SpriteID, const CUIRect *pRect, float ImageRatio) -{ - float Seconds = 0.6f; // 0.6 seconds for fade - float Fade = ButtonFade(pBC, Seconds); - - RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.5f+(Fade/Seconds)*0.25f), CUI::CORNER_ALL, 10.0f); - Graphics()->TextureSet(Texture); - Graphics()->QuadsBegin(); - RenderTools()->SelectSprite(SpriteID); - float Height = pRect->w/ImageRatio; - IGraphics::CQuadItem QuadItem(pRect->x, pRect->y+(pRect->h-Height)/2, pRect->w, Height); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - return UI()->DoButtonLogic(pBC->GetID(), pRect); -} - void CMenus::RenderHSLPicker(CUIRect MainView) { CUIRect Label, Button, Picker; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 6cef378c..d8d81772 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -340,7 +340,7 @@ void CGameClient::OnInit() m_pGraphics = Kernel()->RequestInterface(); // propagate pointers - m_UI.Init(Config(), Graphics(), TextRender()); + m_UI.Init(Config(), Graphics(), Input(), TextRender()); m_RenderTools.Init(Config(), Graphics(), UI()); int64 Start = time_get(); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 251754e8..f8d892ab 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "ui.h" @@ -31,41 +32,34 @@ CUI::CUI() m_MouseWorldY = 0; m_MouseButtons = 0; m_LastMouseButtons = 0; + m_UseMouseButtons = true; m_Screen.x = 0; m_Screen.y = 0; - m_Screen.w = 848.0f; - m_Screen.h = 480.0f; m_NumClips = 0; } -int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) +void CUI::Update(float MouseX, float MouseY, float MouseWorldX, float MouseWorldY) { - m_MouseX = Mx; - m_MouseY = My; - m_MouseWorldX = Mwx; - m_MouseWorldY = Mwy; + unsigned MouseButtons = 0; + if(m_UseMouseButtons) + { + if(Input()->KeyIsPressed(KEY_MOUSE_1)) MouseButtons |= 1; + if(Input()->KeyIsPressed(KEY_MOUSE_2)) MouseButtons |= 2; + if(Input()->KeyIsPressed(KEY_MOUSE_3)) MouseButtons |= 4; + } + + m_MouseX = MouseX; + m_MouseY = MouseY; + m_MouseWorldX = MouseWorldX; + m_MouseWorldY = MouseWorldY; m_LastMouseButtons = m_MouseButtons; - m_MouseButtons = Buttons; + m_MouseButtons = MouseButtons; m_pHotItem = m_pBecommingHotItem; if(m_pActiveItem) m_pHotItem = m_pActiveItem; m_pBecommingHotItem = 0; - return 0; -} - -bool CUI::MouseInside(const CUIRect *r) const -{ - return m_MouseX >= r->x - && m_MouseX < r->x+r->w - && m_MouseY >= r->y - && m_MouseY < r->y+r->h; -} - -bool CUI::MouseInsideClip() const -{ - return !IsClipped() || MouseInside(ClipArea()); } void CUI::ConvertCursorMove(float *pX, float *pY, int CursorType) const @@ -84,17 +78,10 @@ void CUI::ConvertCursorMove(float *pX, float *pY, int CursorType) const *pY *= Factor; } -CUIRect *CUI::Screen() +const CUIRect *CUI::Screen() { - float Aspect = Graphics()->ScreenAspect(); - float w, h; - - h = 600; - w = Aspect*h; - - m_Screen.w = w; - m_Screen.h = h; - + m_Screen.h = 600; + m_Screen.w = Graphics()->ScreenAspect()*m_Screen.h; return &m_Screen; } @@ -313,19 +300,26 @@ void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const pOtherRect->h = r.h - 2*Cut; } -int CUI::DoButtonLogic(const void *pID, const CUIRect *pRect) +bool CUIRect::Inside(float x, float y) const +{ + return x >= this->x + && x < this->x + this->w + && y >= this->y + && y < this->y + this->h; +} + +bool CUI::DoButtonLogic(const void *pID, const CUIRect *pRect) { // logic - int ReturnValue = 0; - bool Inside = MouseInside(pRect) && MouseInsideClip(); - static int ButtonUsed = 0; + bool Clicked = false; + const bool Hovered = MouseHovered(pRect); if(CheckActiveItem(pID)) { - if(!MouseButton(ButtonUsed)) + if(!MouseButton(0)) { - if(Inside) - ReturnValue = 1+ButtonUsed; + if(Hovered) + Clicked = true; SetActiveItem(0); } } @@ -334,26 +328,17 @@ int CUI::DoButtonLogic(const void *pID, const CUIRect *pRect) if(MouseButton(0)) { SetActiveItem(pID); - ButtonUsed = 0; - } - - if(MouseButton(1)) - { - SetActiveItem(pID); - ButtonUsed = 1; } } - if(Inside) + if(Hovered && !MouseButton(0)) SetHotItem(pID); - return ReturnValue; + return Clicked; } bool CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY) { - bool Inside = MouseInside(pRect); - if(CheckActiveItem(pID)) { if(!MouseButton(0)) @@ -365,7 +350,7 @@ bool CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float SetActiveItem(pID); } - if(Inside) + if(MouseHovered(pRect)) SetHotItem(pID); if(!CheckActiveItem(pID)) diff --git a/src/game/client/ui.h b/src/game/client/ui.h index b25f2f39..596d6cde 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -18,6 +18,8 @@ class CUIRect void Margin(float Cut, CUIRect *pOtherRect) const; void VMargin(float Cut, CUIRect *pOtherRect) const; void HMargin(float Cut, CUIRect *pOtherRect) const; + + bool Inside(float x, float y) const; }; class CUI @@ -36,6 +38,7 @@ class CUI float m_MouseWorldX, m_MouseWorldY; // in world space unsigned m_MouseButtons; unsigned m_LastMouseButtons; + bool m_UseMouseButtons; CUIRect m_Screen; @@ -45,6 +48,7 @@ class CUI class CConfig *m_pConfig; class IGraphics *m_pGraphics; + class IInput *m_pInput; class ITextRender *m_pTextRender; public: @@ -55,9 +59,10 @@ class CUI static const vec4 ms_TransparentTextColor; // TODO: Refactor: Fill this in - void Init(class CConfig *pConfig, class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pTextRender = pTextRender; } + void Init(class CConfig *pConfig, class IGraphics *pGraphics, class IInput *pInput, class ITextRender *pTextRender) { m_pConfig = pConfig; m_pGraphics = pGraphics; m_pInput = pInput; m_pTextRender = pTextRender; } class CConfig *Config() const { return m_pConfig; } class IGraphics *Graphics() const { return m_pGraphics; } + class IInput *Input() const { return m_pInput; } class ITextRender *TextRender() const { return m_pTextRender; } CUI(); @@ -94,14 +99,15 @@ class CUI ALIGN_RIGHT, }; - int Update(float mx, float my, float Mwx, float Mwy, int m_Buttons); + void Update(float MouseX, float MouseY, float MouseWorldX, float MouseWorldY); float MouseX() const { return m_MouseX; } float MouseY() const { return m_MouseY; } float MouseWorldX() const { return m_MouseWorldX; } float MouseWorldY() const { return m_MouseWorldY; } - int MouseButton(int Index) const { return (m_MouseButtons>>Index)&1; } - int MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons>>Index)&1) ; } + bool MouseButton(int Index) const { return (m_MouseButtons>>Index)&1; } + bool MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons>>Index)&1) ; } + void UseMouseButtons(bool UseMouseButtons) { m_UseMouseButtons = UseMouseButtons; } void SetHotItem(const void *pID) { m_pBecommingHotItem = pID; } void SetActiveItem(const void *pID) { m_ActiveItemValid = true; m_pActiveItem = pID; if (pID) m_pLastActiveItem = pID; } @@ -115,11 +121,12 @@ class CUI void StartCheck() { m_ActiveItemValid = false; }; void FinishCheck() { if(!m_ActiveItemValid) SetActiveItem(0); }; - bool MouseInside(const CUIRect *pRect) const; - bool MouseInsideClip() const; + bool MouseInside(const CUIRect *pRect) const { return pRect->Inside(m_MouseX, m_MouseY); }; + bool MouseInsideClip() const { return !IsClipped() || MouseInside(ClipArea()); }; + bool MouseHovered(const CUIRect *pRect) const { return MouseInside(pRect) && MouseInsideClip(); }; void ConvertCursorMove(float *pX, float *pY, int CursorType) const; - CUIRect *Screen(); + const CUIRect *Screen(); float PixelSize(); void ClipEnable(const CUIRect *pRect); @@ -127,7 +134,7 @@ class CUI const CUIRect *ClipArea() const; inline bool IsClipped() const { return m_NumClips > 0; }; - int DoButtonLogic(const void *pID, const CUIRect *pRect); + bool DoButtonLogic(const void *pID, const CUIRect *pRect); bool DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); void DoLabel(const CUIRect *pRect, const char *pText, float FontSize, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index b1d72644..0cce0b54 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3075,8 +3075,8 @@ void CEditor::AddFileDialogEntry(int Index, CUIRect *pView) void CEditor::RenderFileDialog() { // GUI coordsys - Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); CUIRect View = *UI()->Screen(); + Graphics()->MapScreen(View.x, View.y, View.w, View.h); CUIRect Preview; float Width = View.w, Height = View.h; @@ -4138,7 +4138,7 @@ void CEditor::Render() // basic start Graphics()->Clear(1.0f, 0.0f, 1.0f); CUIRect View = *UI()->Screen(); - Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); + Graphics()->MapScreen(View.x, View.y, View.w, View.h); float Width = View.w; float Height = View.h; @@ -4503,7 +4503,7 @@ void CEditor::Init() m_pTextRender = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); m_RenderTools.Init(m_pConfig, m_pGraphics, &m_UI); - m_UI.Init(m_pConfig, m_pGraphics, m_pTextRender); + m_UI.Init(m_pConfig, m_pGraphics, m_pInput, m_pTextRender); m_Map.m_pEditor = this; m_CheckerTexture = Graphics()->LoadTexture("editor/checker.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); @@ -4646,7 +4646,6 @@ void CEditor::UpdateAndRender() // handle cursor movement { - float mx, my, Mwx, Mwy, Mdx, Mdy; float rx = 0.0f, ry = 0.0f; int CursorType = Input()->CursorRelative(&rx, &ry); UI()->ConvertCursorMove(&rx, &ry, CursorType); @@ -4664,19 +4663,19 @@ void CEditor::UpdateAndRender() s_MouseY = clamp(s_MouseY, 0.0f, (float)Graphics()->ScreenHeight()); // update the ui - mx = (s_MouseX/(float)Graphics()->ScreenWidth())*UI()->Screen()->w; - my = (s_MouseY/(float)Graphics()->ScreenHeight())*UI()->Screen()->h; - Mdx = (m_MouseDeltaX/(float)Graphics()->ScreenWidth())*UI()->Screen()->w; - Mdy = (m_MouseDeltaY/(float)Graphics()->ScreenHeight())*UI()->Screen()->h; - Mwx = 0; - Mwy = 0; + float mx = (s_MouseX/(float)Graphics()->ScreenWidth())*UI()->Screen()->w; + float my = (s_MouseY/(float)Graphics()->ScreenHeight())*UI()->Screen()->h; + float Mdx = (m_MouseDeltaX/(float)Graphics()->ScreenWidth())*UI()->Screen()->w; + float Mdy = (m_MouseDeltaY/(float)Graphics()->ScreenHeight())*UI()->Screen()->h; + float Mwx = 0; + float Mwy = 0; // fix correct world x and y - CLayerGroup *g = GetSelectedGroup(); - if(g) + CLayerGroup *pSelectedGroup = GetSelectedGroup(); + if(pSelectedGroup) { float aPoints[4]; - g->Mapping(aPoints); + pSelectedGroup->Mapping(aPoints); float WorldWidth = aPoints[2]-aPoints[0]; float WorldHeight = aPoints[3]-aPoints[1]; @@ -4687,12 +4686,7 @@ void CEditor::UpdateAndRender() m_MouseDeltaWy = Mdy*(WorldHeight / UI()->Screen()->h); } - int Buttons = 0; - if(Input()->KeyIsPressed(KEY_MOUSE_1)) Buttons |= 1; - if(Input()->KeyIsPressed(KEY_MOUSE_2)) Buttons |= 2; - if(Input()->KeyIsPressed(KEY_MOUSE_3)) Buttons |= 4; - - UI()->Update(mx,my,Mwx,Mwy,Buttons); + UI()->Update(mx, my, Mwx, Mwy); } // toggle gui From 8401446eeac73748bf0d8ef6fc3afbdea799e93b Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 14:11:08 +0100 Subject: [PATCH 410/479] No highlight in browser & listbox while scrolling --- src/game/client/components/menus.h | 3 ++- src/game/client/components/menus_browser.cpp | 11 ++++++----- src/game/client/components/menus_listbox.cpp | 2 +- src/game/client/components/menus_scrollregion.cpp | 7 ++++++- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index bb94fe23..7a04a989 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -237,6 +237,7 @@ class CMenus : public CComponent void ScrollHere(int Option = CScrollRegion::SCROLLHERE_KEEP_IN_VIEW); bool IsRectClipped(const CUIRect& Rect) const; bool IsScrollbarShown() const; + bool IsAnimating() const; }; // Listbox : found in menus_listbox.cpp @@ -812,7 +813,7 @@ class CMenus : public CComponent void RenderServerbrowserOverlay(); void RenderFilterHeader(CUIRect View, int FilterIndex); void PopupConfirmRemoveFilter(); - int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo); + int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo, CScrollRegion *pScroll = 0); void RenderServerbrowser(CUIRect MainView); static void ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainFriendlistUpdate(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 9cf2dc40..ab852681 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -427,11 +427,12 @@ void CMenus::SetOverlay(int Type, float x, float y, const void *pData) } // 1 = browser entry click, 2 = server info click -int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo) +int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo, CScrollRegion *pScroll) { // logic int ReturnValue = 0; bool Inside = UI()->MouseInside(&View) && UI()->MouseInsideClip(); + bool Highlighted = Inside && (!pScroll || !pScroll->IsAnimating()); if(UI()->CheckActiveItem(pID)) { @@ -448,7 +449,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn UI()->SetActiveItem(pID); } - if(Inside) + if(Highlighted) { UI()->SetHotItem(pID); RenderTools()->DrawRoundRect(&View, vec4(1.0f, 1.0f, 1.0f, 0.5f), 5.0f); @@ -464,7 +465,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn vec4 TextBaseOutlineColor = vec4(0.0, 0.0, 0.0, 0.3f); vec4 ServerInfoTextBaseColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - if(Selected || Inside) + if(Selected || Highlighted) { TextBaseColor = vec4(0.0f, 0.0f, 0.0f, TextAlpha); ServerInfoTextBaseColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); @@ -585,7 +586,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn int Ping = pEntry->m_Latency; vec4 Color; - if(Selected || Inside) + if(Selected || Highlighted) { Color = TextBaseColor; } @@ -1216,7 +1217,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) // Prevent flickering entry background and text by drawing it as selected for one more frame after the selection has changed const bool WasSelected = LastSelectedFilter >= 0 && LastSelectedServer >= 0 && FilterIndex == LastSelectedFilter && ServerIndex == LastSelectedServer; - if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected || WasSelected, ShowServerInfo)) + if(int ReturnValue = DoBrowserEntry(pFilter->ID(ServerIndex), Row, pItem, pFilter, IsSelected || WasSelected, ShowServerInfo, &s_ScrollRegion)) { m_ShowServerDetails = !m_ShowServerDetails || ReturnValue == 2 || m_aSelectedServers[BrowserType] != ServerIndex; // click twice on line => fold server details m_aSelectedFilters[BrowserType] = FilterIndex; diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 61e41a14..748c8e58 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -191,7 +191,7 @@ CMenus::CListboxItem CMenus::CListBox::DoNextItem(const void *pId, bool Selected CUIRect r = Item.m_Rect; m_pRenderTools->DrawUIRect(&r, vec4(1, 1, 1, ProcessInput ? 0.5f : 0.33f), CUI::CORNER_ALL, 5.0f); } - /*else*/ if(m_pUI->HotItem() == pId) + /*else*/ if(m_pUI->HotItem() == pId && !m_ScrollRegion.IsAnimating()) { CUIRect r = Item.m_Rect; m_pRenderTools->DrawUIRect(&r, vec4(1, 1, 1, 0.33f), CUI::CORNER_ALL, 5.0f); diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index a9b237ce..4efcf0c7 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -70,7 +70,7 @@ void CMenus::CScrollRegion::End() CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; - float AnimationDuration = 0.3f; + float AnimationDuration = 0.5f; const bool isPageScroll = m_pInput->KeyIsPressed(KEY_LALT) || m_pInput->KeyIsPressed(KEY_RALT); if(m_pUI->MouseInside(&RegionRect)) @@ -223,4 +223,9 @@ bool CMenus::CScrollRegion::IsRectClipped(const CUIRect& Rect) const bool CMenus::CScrollRegion::IsScrollbarShown() const { return m_ContentH > m_ClipRect.h; +} + +bool CMenus::CScrollRegion::IsAnimating() const +{ + return m_AnimTime > 0; } \ No newline at end of file From 161ff2f49eabe507c3d87016f7160799be6dca3e Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 14:21:13 +0100 Subject: [PATCH 411/479] Fix highlight hiding when the list doesn't actually scroll --- src/game/client/components/menus_scrollregion.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 4efcf0c7..48fe61e7 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -108,6 +108,9 @@ void CMenus::CScrollRegion::End() m_AnimTargetScrollY = clamp(m_AnimTargetScrollY, 0.0f, MaxScroll); + if (abs(m_AnimInitScrollY - m_AnimTargetScrollY) < 0.5f) + m_AnimTime = 0; + if (m_AnimTime > 0) { m_AnimTime -= m_pMenus->Client()->RenderFrameTime(); From 0187e54a8502aa12ae53fe8a118785068e63b33d Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 6 Sep 2020 18:36:29 +0100 Subject: [PATCH 412/479] Style fixes --- src/game/client/components/menus_scrollregion.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 48fe61e7..6e681a20 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -108,10 +108,10 @@ void CMenus::CScrollRegion::End() m_AnimTargetScrollY = clamp(m_AnimTargetScrollY, 0.0f, MaxScroll); - if (abs(m_AnimInitScrollY - m_AnimTargetScrollY) < 0.5f) + if(absolute(m_AnimInitScrollY - m_AnimTargetScrollY) < 0.5f) m_AnimTime = 0; - if (m_AnimTime > 0) + if(m_AnimTime > 0) { m_AnimTime -= m_pMenus->Client()->RenderFrameTime(); float AnimProgress = (1 - pow(m_AnimTime / AnimationDuration, 3)); // cubic ease out @@ -231,4 +231,4 @@ bool CMenus::CScrollRegion::IsScrollbarShown() const bool CMenus::CScrollRegion::IsAnimating() const { return m_AnimTime > 0; -} \ No newline at end of file +} From fe5daf82e0b6bc2748f4fee62824a6ec3b142866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 6 Sep 2020 19:56:58 +0200 Subject: [PATCH 413/479] use absolute instead of abs --- src/game/client/components/menus_demo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 70aa5cc3..567bfcb5 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -201,7 +201,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++) { const int MarkerTick = pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick; - if(abs(MarkerTick-CurrentTick) < Threshold) + if(absolute(MarkerTick-CurrentTick) < Threshold) { if(i+1 < pInfo->m_NumTimelineMarkers) DesiredTick = pInfo->m_aTimelineMarkers[i+1]-pInfo->m_FirstTick; @@ -220,7 +220,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) for(int i = pInfo->m_NumTimelineMarkers-1; i >= 0; i--) { const int MarkerTick = pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick; - if(abs(MarkerTick-CurrentTick) < Threshold) + if(absolute(MarkerTick-CurrentTick) < Threshold) { if(i > 0) DesiredTick = pInfo->m_aTimelineMarkers[i-1]-pInfo->m_FirstTick; From eca66f8ab1dd07a98cf0059f9bf2c0c68a6bf940 Mon Sep 17 00:00:00 2001 From: ChillerDrgon Date: Tue, 8 Sep 2020 12:03:30 +0200 Subject: [PATCH 414/479] Add eval_if console command (closed #2670) SYNOPSIS eval_if s[config] s[comparison] s[value] s[command] ?s[else] ?s[command] EXAMPLE eval_if ui_server_address == "localhost" "rcon_auth rcon" else "rcon_auth strong_password" --- src/engine/console.h | 2 ++ src/engine/shared/console.cpp | 45 +++++++++++++++++++++++++++++++++++ src/engine/shared/console.h | 1 + 3 files changed, 48 insertions(+) diff --git a/src/engine/console.h b/src/engine/console.h index 9d34864c..b9bb6bcc 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -35,6 +35,8 @@ class IConsole : public IInterface protected: unsigned m_NumArgs; public: + int m_Value; + char m_aValue[128]; IResult() { m_NumArgs = 0; } virtual ~IResult() {} diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 80d7f018..2bd941ee 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -632,6 +632,7 @@ static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData) char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "Value: %d", *(pData->m_pVariable)); pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Console", aBuf); + pResult->m_Value = *(pData->m_pVariable); } } @@ -667,9 +668,52 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData) char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "Value: %s", pData->m_pStr); pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Console", aBuf); + str_copy(pResult->m_aValue, pData->m_pStr, sizeof(pResult->m_aValue)); } } +void CConsole::Con_EvalIf(IResult *pResult, void *pUserData) +{ + CResult Result; + CConsole* pConsole = static_cast(pUserData); + CCommand *pCommand = ((CConsole*)pUserData)->FindCommand(pResult->GetString(0), ((CConsole*)pUserData)->m_FlagMask); + char aBuf[128]; + if(!pCommand) + { + str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(0)); + ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf); + return; + } + pCommand->m_pfnCallback(&Result, pCommand->m_pUserData); + bool condition = false; + if(pCommand->m_pfnCallback == IntVariableCommand) + condition = Result.m_Value == atoi(pResult->GetString(2)); + else + condition = !str_comp_nocase(Result.m_aValue, pResult->GetString(2)); + if(!str_comp_num(pResult->GetString(1), "!=", 3)) + condition = !condition; + else if(str_comp_num(pResult->GetString(1), "==", 3) && pCommand->m_pfnCallback == StrVariableCommand) + ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type string"); + else if(!str_comp_num(pResult->GetString(1), ">", 2)) + condition = Result.m_Value > atoi(pResult->GetString(2)); + else if(!str_comp_num(pResult->GetString(1), "<", 2)) + condition = Result.m_Value < atoi(pResult->GetString(2)); + else if(!str_comp_num(pResult->GetString(1), "<=", 3)) + condition = Result.m_Value <= atoi(pResult->GetString(2)); + else if(!str_comp_num(pResult->GetString(1), ">=", 3)) + condition = Result.m_Value >= atoi(pResult->GetString(2)); + else if(str_comp_num(pResult->GetString(1), "==", 3)) + ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type integer"); + + if(pResult->NumArguments() > 4 && str_comp_num(pResult->GetString(4), "else", 5)) + ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: expected else"); + + if(condition) + pConsole->ExecuteLine(pResult->GetString(3)); + else if(pResult->NumArguments() == 6) + pConsole->ExecuteLine(pResult->GetString(5)); +} + void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser) { CConsole* pConsole = static_cast(pUser); @@ -763,6 +807,7 @@ CConsole::CConsole(int FlagMask) // register some basic commands Register("echo", "r[text]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text"); Register("exec", "r[file]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file"); + Register("eval_if", "s[config] s[comparison] s[value] s[command] ?s[else] ?s[command]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_EvalIf, this, "Execute command if condition is true"); Register("toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConToggle, this, "Toggle config value"); Register("+toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress"); diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index c5c121d6..2c398b4c 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -57,6 +57,7 @@ class CConsole : public IConsole static void Con_Chain(IResult *pResult, void *pUserData); static void Con_Echo(IResult *pResult, void *pUserData); static void Con_Exec(IResult *pResult, void *pUserData); + static void Con_EvalIf(IResult *pResult, void *pUserData); static void ConToggle(IResult *pResult, void *pUser); static void ConToggleStroke(IResult *pResult, void *pUser); static void ConModCommandAccess(IResult *pResult, void *pUser); From 5e88fa996f3e49a5aa673aafcc42e5f0e5f5d32d Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 9 Sep 2020 10:15:16 +0200 Subject: [PATCH 415/479] EvalIf code style improvements (thanks to @Robyt3) --- src/engine/shared/console.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 2bd941ee..37ad661c 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -674,8 +674,6 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData) void CConsole::Con_EvalIf(IResult *pResult, void *pUserData) { - CResult Result; - CConsole* pConsole = static_cast(pUserData); CCommand *pCommand = ((CConsole*)pUserData)->FindCommand(pResult->GetString(0), ((CConsole*)pUserData)->m_FlagMask); char aBuf[128]; if(!pCommand) @@ -684,31 +682,33 @@ void CConsole::Con_EvalIf(IResult *pResult, void *pUserData) ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf); return; } + CResult Result; pCommand->m_pfnCallback(&Result, pCommand->m_pUserData); - bool condition = false; + bool Condition = false; if(pCommand->m_pfnCallback == IntVariableCommand) - condition = Result.m_Value == atoi(pResult->GetString(2)); + Condition = Result.m_Value == atoi(pResult->GetString(2)); else - condition = !str_comp_nocase(Result.m_aValue, pResult->GetString(2)); + Condition = !str_comp_nocase(Result.m_aValue, pResult->GetString(2)); if(!str_comp_num(pResult->GetString(1), "!=", 3)) - condition = !condition; + Condition = !Condition; else if(str_comp_num(pResult->GetString(1), "==", 3) && pCommand->m_pfnCallback == StrVariableCommand) ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type string"); else if(!str_comp_num(pResult->GetString(1), ">", 2)) - condition = Result.m_Value > atoi(pResult->GetString(2)); + Condition = Result.m_Value > atoi(pResult->GetString(2)); else if(!str_comp_num(pResult->GetString(1), "<", 2)) - condition = Result.m_Value < atoi(pResult->GetString(2)); + Condition = Result.m_Value < atoi(pResult->GetString(2)); else if(!str_comp_num(pResult->GetString(1), "<=", 3)) - condition = Result.m_Value <= atoi(pResult->GetString(2)); + Condition = Result.m_Value <= atoi(pResult->GetString(2)); else if(!str_comp_num(pResult->GetString(1), ">=", 3)) - condition = Result.m_Value >= atoi(pResult->GetString(2)); + Condition = Result.m_Value >= atoi(pResult->GetString(2)); else if(str_comp_num(pResult->GetString(1), "==", 3)) ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type integer"); if(pResult->NumArguments() > 4 && str_comp_num(pResult->GetString(4), "else", 5)) ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: expected else"); - if(condition) + CConsole* pConsole = static_cast(pUserData); + if(Condition) pConsole->ExecuteLine(pResult->GetString(3)); else if(pResult->NumArguments() == 6) pConsole->ExecuteLine(pResult->GetString(5)); From 503d49938a723c4c5844dd7470af6d154362ac10 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 9 Sep 2020 19:07:33 +0200 Subject: [PATCH 416/479] update comment --- src/base/system.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/base/system.h b/src/base/system.h index cf496c3d..e27dcbf7 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -655,9 +655,8 @@ int net_host_lookup(const char *hostname, NETADDR *addr, int types); check_port - compares port or not Returns: - <0 - Address a is lesser then address b 0 - Address a is equal to address b - >0 - Address a is greater then address b + -1 - Address a differs from address b */ int net_addr_comp(const NETADDR *a, const NETADDR *b, int check_port); From 6b430545d91fc451f246cdce556dfc384aadaf97 Mon Sep 17 00:00:00 2001 From: Redix Date: Wed, 9 Sep 2020 20:07:24 +0200 Subject: [PATCH 417/479] Add basic prediction for projectile positions (disabled by default) --- src/game/client/components/items.cpp | 8 +++++++- src/game/variables.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 4db5b2d2..bd5d4d8e 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -2,6 +2,7 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include #include +#include #include #include @@ -39,7 +40,12 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) static float s_LastGameTickTime = Client()->GameTickTime(); if(!m_pClient->IsWorldPaused()) s_LastGameTickTime = Client()->GameTickTime(); - float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; + + float Ct; + if(m_pClient->ShouldUsePredicted() && Config()->m_ClPredictProjectiles) + Ct = ((float)(Client()->PredGameTick() - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick())/(float)SERVER_TICK_SPEED; + else + Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) return; // projectile haven't been shot yet diff --git a/src/game/variables.h b/src/game/variables.h index ae8d87d8..595b130e 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -8,6 +8,7 @@ // client MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") MACRO_CONFIG_INT(ClPredictPlayers, cl_predict_players, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict movements of other players") +MACRO_CONFIG_INT(ClPredictProjectiles, cl_predict_projectiles, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict position of projectiles") MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show name plates") MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show name plates disregarding of distance") MACRO_CONFIG_INT(ClNameplatesTeamcolors, cl_nameplates_teamcolors, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use team colors for name plates") From 9362c1a5b22af83ce6853c6969d45d1fe1aa5f72 Mon Sep 17 00:00:00 2001 From: Redix Date: Tue, 11 Aug 2020 19:19:14 +0200 Subject: [PATCH 418/479] Use new submodules option from actions/checkout@v2 --- .github/workflows/build.yaml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c8c936f5..a681acec 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -40,12 +40,8 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Checkout submodules - shell: bash - run: | - auth_header="$(git config --local --get http.https://github.com/.extraheader)" - git submodule sync --recursive - git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodules: true - name: Prepare Linux if: contains(matrix.os, 'ubuntu') @@ -107,12 +103,8 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Checkout submodules - shell: bash - run: | - auth_header="$(git config --local --get http.https://github.com/.extraheader)" - git submodule sync --recursive - git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodules: true - name: Checkout bam uses: actions/checkout@v2 From 4bcae3d77b4c88d442dac4fa4b72e4c48939c964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 10 Sep 2020 21:19:50 +0200 Subject: [PATCH 419/479] fix hotkeys and scrolling being enabled when console is open --- src/game/client/components/console.cpp | 4 ++-- src/game/client/components/maplayers.cpp | 2 +- src/game/client/components/menus.cpp | 12 +++++++----- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 14 +++++++------- src/game/client/components/menus_popups.cpp | 2 +- src/game/client/components/menus_scrollregion.cpp | 4 ++-- src/game/client/ui.cpp | 14 ++++++++++++-- src/game/client/ui.h | 10 ++++++++-- 9 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 48abad4f..297bee7c 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -645,7 +645,7 @@ void CGameConsole::Toggle(int Type) if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_CLOSING) { Input()->MouseModeAbsolute(); - UI()->UseMouseButtons(false); + UI()->SetEnabled(false); m_ConsoleState = CONSOLE_OPENING; // reset controls m_pClient->m_pControls->OnReset(); @@ -653,7 +653,7 @@ void CGameConsole::Toggle(int Type) else { Input()->MouseModeRelative(); - UI()->UseMouseButtons(true); + UI()->SetEnabled(true); m_pClient->OnRelease(); m_ConsoleState = CONSOLE_CLOSING; } diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 24a8a4c3..ad9b5441 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -355,7 +355,7 @@ void CMapLayers::OnRender() // skip rendering if detail layers is not wanted if(!(pLayer->m_Flags&LAYERFLAG_DETAIL && !Config()->m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK))) { - if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0)) + if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && UI()->KeyPress(KEY_KP_0)) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTMap->m_Data); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8aae27ee..8cfb92a2 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -397,7 +397,7 @@ bool CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str UI()->ClearLastActiveItem(); } - if(UI()->LastActiveItem() == pID && !m_pClient->m_pGameConsole->IsConsoleActive()) + if(UI()->LastActiveItem() == pID && UI()->Enabled()) { for(int i = 0; i < Input()->NumEvents(); i++) { @@ -2098,7 +2098,7 @@ bool CMenus::OnInput(IInput::CEvent e) // special for popups if(e.m_Key == KEY_RETURN || e.m_Key == KEY_KP_ENTER) m_EnterPressed = true; - else if(e.m_Key == KEY_TAB && !Input()->KeyPress(KEY_LALT) && !Input()->KeyPress(KEY_RALT)) + else if(e.m_Key == KEY_TAB && !Input()->KeyIsPressed(KEY_LALT) && !Input()->KeyIsPressed(KEY_RALT)) m_TabPressed = true; else if(e.m_Key == KEY_DELETE) m_DeletePressed = true; @@ -2251,9 +2251,11 @@ void CMenus::OnRender() bool CMenus::CheckHotKey(int Key) const { - return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive && - !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier - Input()->KeyIsPressed(Key) && !m_pClient->m_pGameConsole->IsConsoleActive(); + return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !m_PrevCursorActive && !m_PopupActive + && !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) + && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) + && !Input()->KeyIsPressed(KEY_LALT) + && UI()->KeyIsPressed(Key); } bool CMenus::IsBackgroundNeeded() const diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 592896e9..7620f9c4 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2245,7 +2245,7 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView) MainView.HSplitTop(25.0f, &MainView, 0); MainView.VSplitLeft(ButtonWidth, &Button, &MainView); static CButtonContainer s_RefreshButton; - if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (UI()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) { if(m_MenuPage == PAGE_INTERNET) ServerBrowser()->Refresh(IServerBrowser::REFRESHFLAG_INTERNET); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 567bfcb5..30ed9b8a 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -53,7 +53,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) CUIRect SeekBar, ButtonBar, NameBar; - const bool CtrlDown = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL); + const bool CtrlDown = UI()->KeyIsPressed(KEY_LCTRL) || UI()->KeyIsPressed(KEY_RCTRL); static bool s_LastCtrlDown = CtrlDown; int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick; @@ -167,11 +167,11 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) PositionToSeek = 0.0f; } - bool IncreaseDemoSpeed = Input()->KeyPress(KEY_MOUSE_WHEEL_UP) || Input()->KeyPress(KEY_PLUS) || Input()->KeyPress(KEY_KP_PLUS); - bool DecreaseDemoSpeed = Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN) || Input()->KeyPress(KEY_MINUS) || Input()->KeyPress(KEY_KP_MINUS); + bool IncreaseDemoSpeed = UI()->KeyPress(KEY_MOUSE_WHEEL_UP) || UI()->KeyPress(KEY_PLUS) || UI()->KeyPress(KEY_KP_PLUS); + bool DecreaseDemoSpeed = UI()->KeyPress(KEY_MOUSE_WHEEL_DOWN) || UI()->KeyPress(KEY_MINUS) || UI()->KeyPress(KEY_KP_MINUS); // add spacebar for toggling Play/Pause - if(Input()->KeyPress(KEY_SPACE)) + if(UI()->KeyPress(KEY_SPACE)) { if(!pInfo->m_Paused) DemoPlayer()->Pause(); @@ -181,8 +181,8 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // skip forward/backward using left/right arrow keys const bool ShiftDown = Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT); - const bool SkipBackwards = Input()->KeyPress(KEY_LEFT); - const bool SkipForwards = Input()->KeyPress(KEY_RIGHT); + const bool SkipBackwards = UI()->KeyPress(KEY_LEFT); + const bool SkipForwards = UI()->KeyPress(KEY_RIGHT); if(SkipBackwards || SkipForwards) { int DesiredTick = 0; @@ -655,7 +655,7 @@ void CMenus::RenderDemoList(CUIRect MainView) BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static CButtonContainer s_RefreshButton; - if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button) || (UI()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))) { DemolistPopulate(); DemolistOnUpdate(false); diff --git a/src/game/client/components/menus_popups.cpp b/src/game/client/components/menus_popups.cpp index 3e8ce9bc..95ef6358 100644 --- a/src/game/client/components/menus_popups.cpp +++ b/src/game/client/components/menus_popups.cpp @@ -83,7 +83,7 @@ void CMenus::DoPopupMenu() if(s_Popups.m_pfnFunc(this, r)) m_PopupActive = false; - if(Input()->KeyPress(KEY_ESCAPE)) + if(UI()->KeyPress(KEY_ESCAPE)) m_PopupActive = false; } } diff --git a/src/game/client/components/menus_scrollregion.cpp b/src/game/client/components/menus_scrollregion.cpp index 9758a14b..396616d6 100644 --- a/src/game/client/components/menus_scrollregion.cpp +++ b/src/game/client/components/menus_scrollregion.cpp @@ -76,13 +76,13 @@ void CMenus::CScrollRegion::End() if(m_pUI->MouseHovered(&RegionRect)) { const float ScrollUnit = IsPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit; - if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_UP)) + if(m_pUI->KeyPress(KEY_MOUSE_WHEEL_UP)) { m_AnimTime = AnimationDuration; m_AnimInitScrollY = m_ScrollY; m_AnimTargetScrollY -= ScrollUnit; } - else if(m_pInput->KeyPress(KEY_MOUSE_WHEEL_DOWN)) + else if(m_pUI->KeyPress(KEY_MOUSE_WHEEL_DOWN)) { m_AnimTime = AnimationDuration; m_AnimInitScrollY = m_ScrollY; diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index f8d892ab..ab0be461 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -32,7 +32,7 @@ CUI::CUI() m_MouseWorldY = 0; m_MouseButtons = 0; m_LastMouseButtons = 0; - m_UseMouseButtons = true; + m_Enabled = true; m_Screen.x = 0; m_Screen.y = 0; @@ -43,7 +43,7 @@ CUI::CUI() void CUI::Update(float MouseX, float MouseY, float MouseWorldX, float MouseWorldY) { unsigned MouseButtons = 0; - if(m_UseMouseButtons) + if(Enabled()) { if(Input()->KeyIsPressed(KEY_MOUSE_1)) MouseButtons |= 1; if(Input()->KeyIsPressed(KEY_MOUSE_2)) MouseButtons |= 2; @@ -62,6 +62,16 @@ void CUI::Update(float MouseX, float MouseY, float MouseWorldX, float MouseWorld m_pBecommingHotItem = 0; } +bool CUI::KeyPress(int Key) const +{ + return Enabled() && Input()->KeyPress(Key); +} + +bool CUI::KeyIsPressed(int Key) const +{ + return Enabled() && Input()->KeyIsPressed(Key); +} + void CUI::ConvertCursorMove(float *pX, float *pY, int CursorType) const { float Factor = 1.0f; diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 596d6cde..e1f5d832 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -29,16 +29,18 @@ class CUI MAX_CLIP_NESTING_DEPTH = 16 }; + bool m_Enabled; + const void *m_pHotItem; const void *m_pActiveItem; const void *m_pLastActiveItem; const void *m_pBecommingHotItem; bool m_ActiveItemValid; + float m_MouseX, m_MouseY; // in gui space float m_MouseWorldX, m_MouseWorldY; // in world space unsigned m_MouseButtons; unsigned m_LastMouseButtons; - bool m_UseMouseButtons; CUIRect m_Screen; @@ -99,6 +101,8 @@ class CUI ALIGN_RIGHT, }; + void SetEnabled(bool Enabled) { m_Enabled = Enabled; } + bool Enabled() const { return m_Enabled; } void Update(float MouseX, float MouseY, float MouseWorldX, float MouseWorldY); float MouseX() const { return m_MouseX; } @@ -107,7 +111,6 @@ class CUI float MouseWorldY() const { return m_MouseWorldY; } bool MouseButton(int Index) const { return (m_MouseButtons>>Index)&1; } bool MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons>>Index)&1) ; } - void UseMouseButtons(bool UseMouseButtons) { m_UseMouseButtons = UseMouseButtons; } void SetHotItem(const void *pID) { m_pBecommingHotItem = pID; } void SetActiveItem(const void *pID) { m_ActiveItemValid = true; m_pActiveItem = pID; if (pID) m_pLastActiveItem = pID; } @@ -126,6 +129,9 @@ class CUI bool MouseHovered(const CUIRect *pRect) const { return MouseInside(pRect) && MouseInsideClip(); }; void ConvertCursorMove(float *pX, float *pY, int CursorType) const; + bool KeyPress(int Key) const; + bool KeyIsPressed(int Key) const; + const CUIRect *Screen(); float PixelSize(); From f4b55aaecd8a827abdc43e45aa57b51edcd294e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 12 Sep 2020 21:26:37 +0200 Subject: [PATCH 420/479] change 'no servers found' message to include lan port range --- src/engine/client/serverbrowser.cpp | 4 ++-- src/engine/serverbrowser.h | 5 ++++- src/game/client/components/menus_browser.cpp | 20 ++++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 55dbedb2..17681e12 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -297,9 +297,9 @@ void CServerBrowser::Refresh(int RefreshFlags) Packet.m_pData = Packer.Data(); m_BroadcastTime = time_get(); - for(int i = 8303; i <= 8310; i++) + for(int Port = LAN_PORT_BEGIN; Port <= LAN_PORT_END; Port++) { - Packet.m_Address.port = i; + Packet.m_Address.port = Port; m_pNetClient->Send(&Packet); } diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 3f0c9ebc..695220d7 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -113,7 +113,7 @@ class IServerBrowser : public IInterface SORT_GAMETYPE - Sort by game type. DM, TDM etc. SORT_NUMPLAYERS - Sort after how many players there are on the server. */ - enum{ + enum { SORT_NAME=0, SORT_PING, SORT_MAP, @@ -132,6 +132,9 @@ class IServerBrowser : public IInterface REFRESHFLAG_INTERNET=1, REFRESHFLAG_LAN=2, + LAN_PORT_BEGIN = 8303, + LAN_PORT_END = 8310, + FLAG_PASSWORD=1, FLAG_PURE=2, FLAG_PUREMAP=4, diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 592896e9..e419cee7 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1262,7 +1262,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) s_ScrollRegion.AddRect(MsgBox); if(!s_ScrollRegion.IsRectClipped(MsgBox)) { - const char *pImportantMessage; + char aBuf[128]; + const char *pImportantMessage = 0; if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) pImportantMessage = Localize("Refreshing master servers"); else if(SelectedFilter == -1) @@ -1270,12 +1271,23 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) else if(ServerBrowser()->IsRefreshing()) pImportantMessage = Localize("Fetching server info"); else if(!ServerBrowser()->NumServers()) - pImportantMessage = Localize("No servers found"); + { + if(BrowserType == IServerBrowser::TYPE_INTERNET) + pImportantMessage = Localize("No servers found"); + else if(BrowserType == IServerBrowser::TYPE_LAN) + { + str_format(aBuf, sizeof(aBuf), Localize("No local servers found (ports %d–%d)"), IServerBrowser::LAN_PORT_BEGIN, IServerBrowser::LAN_PORT_END); + pImportantMessage = aBuf; + } + } else pImportantMessage = Localize("No servers match your filter criteria"); - MsgBox.y += MsgBox.h/3.0f; - UI()->DoLabel(&MsgBox, pImportantMessage, 16.0f, CUI::ALIGN_CENTER); + if(pImportantMessage) + { + MsgBox.y += MsgBox.h/3.0f; + UI()->DoLabel(&MsgBox, pImportantMessage, 16.0f, CUI::ALIGN_CENTER); + } } } From a2872d0acd5b52d64e9047729f44439b68bc397f Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 5 Sep 2020 21:09:20 +0200 Subject: [PATCH 421/479] Only use active characters as hook destination --- src/game/client/components/players.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 9b526cf2..85e07a28 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -79,7 +79,7 @@ void CPlayers::RenderHook( vec2 Pos = Position; vec2 HookPos; - if(pPlayerChar->m_HookedPlayer != -1) + if(pPlayerChar->m_HookedPlayer != -1 && m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Active) { // `HookedPlayer != -1` means that a player is being hooked if(m_pClient->ShouldUsePredicted() && From 6763126bb549538e5ee32f89f72ed48126409c7c Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 5 Sep 2020 21:13:42 +0200 Subject: [PATCH 422/479] Do not mix predicted and unpredicted values for rendering the hook --- src/game/client/components/players.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 85e07a28..2269ea54 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -79,17 +79,17 @@ void CPlayers::RenderHook( vec2 Pos = Position; vec2 HookPos; - if(pPlayerChar->m_HookedPlayer != -1 && m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Active) + if(Player.m_HookedPlayer != -1 && m_pClient->m_Snap.m_aCharacters[Player.m_HookedPlayer].m_Active) { // `HookedPlayer != -1` means that a player is being hooked if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pPlayerChar->m_HookedPlayer)) + m_pClient->ShouldUsePredictedChar(Player.m_HookedPlayer)) { - HookPos = m_pClient->PredictedCharPos(pPlayerChar->m_HookedPlayer); + HookPos = m_pClient->PredictedCharPos(Player.m_HookedPlayer); } else { - HookPos = m_pClient->UnpredictedCharPos(pPlayerChar->m_HookedPlayer); + HookPos = m_pClient->UnpredictedCharPos(Player.m_HookedPlayer); } } else From 124e401a25c81a289bb2a6a564ea5479c5960e0e Mon Sep 17 00:00:00 2001 From: Redix Date: Sat, 5 Sep 2020 23:19:26 +0200 Subject: [PATCH 423/479] Clean up player rendering and prediction code a bit --- src/game/client/components/items.cpp | 42 ++----- src/game/client/components/nameplates.cpp | 93 ++++++-------- src/game/client/components/nameplates.h | 3 +- src/game/client/components/players.cpp | 144 ++++++++++------------ src/game/client/components/players.h | 10 +- src/game/client/gameclient.cpp | 125 ++++++------------- src/game/client/gameclient.h | 42 ++----- src/game/gamecore.cpp | 2 +- src/game/gamecore.h | 2 +- src/game/variables.h | 2 +- 10 files changed, 169 insertions(+), 296 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index bd5d4d8e..5afcce4a 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -195,39 +195,15 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, (pCurrent->m_Team == TEAM_BLUE && pPrevGameDataFlag->m_FlagCarrierBlue != pCurGameDataFlag->m_FlagCarrierBlue))) Pos = vec2(pCurrent->m_X, pCurrent->m_Y); - // use predicted carrier position if possible - if(pCurrent->m_Team == TEAM_RED) - { - if(pCurGameDataFlag->m_FlagCarrierRed >= 0) - { - // `FlagCarrier >= 0` means that there is a character carrying the flag - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierRed)) - { - Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); - } - else - { - Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierRed); - } - } - } - else if(pCurrent->m_Team == TEAM_BLUE) - { - if(pCurGameDataFlag->m_FlagCarrierBlue >= 0) - { - // `FlagCarrier >= 0` means that there is a character carrying the flag - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(pCurGameDataFlag->m_FlagCarrierBlue)) - { - Pos = m_pClient->PredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); - } - else - { - Pos = m_pClient->UnpredictedCharPos(pCurGameDataFlag->m_FlagCarrierBlue); - } - } - } + int FlagCarrier = -1; + if(pCurrent->m_Team == TEAM_RED && pCurGameDataFlag->m_FlagCarrierRed >= 0) + FlagCarrier = pCurGameDataFlag->m_FlagCarrierRed; + else if(pCurrent->m_Team == TEAM_BLUE && pCurGameDataFlag->m_FlagCarrierBlue >= 0) + FlagCarrier = pCurGameDataFlag->m_FlagCarrierBlue; + + // make sure to use predicted position + if(FlagCarrier >= 0 && FlagCarrier < MAX_CLIENTS && m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(FlagCarrier)) + Pos = m_pClient->GetCharPos(FlagCarrier, true); } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y-Size*0.75f, Size, Size*2); diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 8e4a5845..a6e9eba0 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -13,66 +13,57 @@ void CNamePlates::RenderNameplate( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPlayerInfo, int ClientID - ) + ) const { - vec2 Position; - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID)) - { - Position = m_pClient->PredictedCharPos(ClientID); - } - else - { - Position = m_pClient->UnpredictedCharPos(ClientID); - } + const CGameClient::CClientData *pClientData = &m_pClient->m_aClients[ClientID]; + + bool Predicted = m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(ClientID); + vec2 Position = m_pClient->GetCharPos(ClientID, Predicted); float FontSize = 18.0f + 20.0f * Config()->m_ClNameplatesSize / 100.0f; // render name plate - if(m_pClient->m_LocalClientID != ClientID) - { - float a = 1; - if(Config()->m_ClNameplatesAlways == 0) - a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); + float a = 1; + if(Config()->m_ClNameplatesAlways == 0) + a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); - char aName[64]; - str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: ""); - CTextCursor Cursor; - float tw = TextRender()->TextWidth(0, FontSize, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(FontSize); - TextRender()->SetCursor(&Cursor, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, TEXTFLAG_RENDER); + char aName[64]; + str_format(aName, sizeof(aName), "%s", Config()->m_ClShowsocial ? pClientData->m_aName: ""); - TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a); - TextRender()->TextColor(1.0f, 1.0f, 1.0f, a); - if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) - { - if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) - TextRender()->TextColor(1.0f, 0.5f, 0.5f, a); - else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE) - TextRender()->TextColor(0.7f, 0.7f, 1.0f, a); - } + CTextCursor Cursor; + float tw = TextRender()->TextWidth(0, FontSize, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(FontSize); + TextRender()->SetCursor(&Cursor, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, TEXTFLAG_RENDER); - const vec4 IdTextColor(0.1f, 0.1f, 0.1f, a); - vec4 BgIdColor(1.0f, 1.0f, 1.0f, a * 0.5f); - if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) - { - if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) - BgIdColor = vec4(1.0f, 0.5f, 0.5f, a * 0.5f); - else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE) - BgIdColor = vec4(0.7f, 0.7f, 1.0f, a * 0.5f); - } + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, a); + if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + { + if(pClientData->m_Team == TEAM_RED) + TextRender()->TextColor(1.0f, 0.5f, 0.5f, a); + else if(pClientData->m_Team == TEAM_BLUE) + TextRender()->TextColor(0.7f, 0.7f, 1.0f, a); + } - if(a > 0.001f) - { - RenderTools()->DrawClientID(TextRender(), &Cursor, ClientID, BgIdColor, IdTextColor); - TextRender()->TextEx(&Cursor, aName, -1); - } + const vec4 IdTextColor(0.1f, 0.1f, 0.1f, a); + vec4 BgIdColor(1.0f, 1.0f, 1.0f, a * 0.5f); + if(Config()->m_ClNameplatesTeamcolors && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) + { + if(pClientData->m_Team == TEAM_RED) + BgIdColor = vec4(1.0f, 0.5f, 0.5f, a * 0.5f); + else if(pClientData->m_Team == TEAM_BLUE) + BgIdColor = vec4(0.7f, 0.7f, 1.0f, a * 0.5f); + } - TextRender()->TextColor(CUI::ms_DefaultTextColor); - TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); + if(a > 0.001f) + { + RenderTools()->DrawClientID(TextRender(), &Cursor, ClientID, BgIdColor, IdTextColor); + TextRender()->TextEx(&Cursor, aName, -1); } + + TextRender()->TextColor(CUI::ms_DefaultTextColor); + TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); } void CNamePlates::OnRender() @@ -83,17 +74,11 @@ void CNamePlates::OnRender() for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters - if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) - continue; - - const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); - - if(pInfo) + if(m_pClient->m_aClients[i].m_Active && m_pClient->m_Snap.m_aCharacters[i].m_Active && m_pClient->m_LocalClientID != i) { RenderNameplate( &m_pClient->m_Snap.m_aCharacters[i].m_Prev, &m_pClient->m_Snap.m_aCharacters[i].m_Cur, - (const CNetObj_PlayerInfo *)pInfo, i); } } diff --git a/src/game/client/components/nameplates.h b/src/game/client/components/nameplates.h index 961c57d8..7cb7a0f7 100644 --- a/src/game/client/components/nameplates.h +++ b/src/game/client/components/nameplates.h @@ -9,9 +9,8 @@ class CNamePlates : public CComponent void RenderNameplate( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPlayerInfo, int ClientID - ); + ) const; public: virtual void OnRender(); diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 2269ea54..6cd39d05 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -40,34 +40,25 @@ inline float AngularApproach(float Src, float Dst, float Amount) void CPlayers::RenderHook( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPrevInfo, - const CNetObj_PlayerInfo *pPlayerInfo, + const CTeeRenderInfo *pRenderInfo, int ClientID - ) + ) const { - CNetObj_Character Prev; - CNetObj_Character Player; - Prev = *pPrevChar; - Player = *pPlayerChar; - - CTeeRenderInfo RenderInfo = m_aRenderInfo[ClientID]; + CNetObj_Character Prev = *pPrevChar; + CNetObj_Character Player = *pPlayerChar; + CTeeRenderInfo RenderInfo = *pRenderInfo; float IntraTick = Client()->IntraGameTick(); // set size RenderInfo.m_Size = 64.0f; - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID)) + if(m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(ClientID)) { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } - vec2 Position = mix( - vec2(Prev.m_X, Prev.m_Y), - vec2(Player.m_X, Player.m_Y), - IntraTick - ); + vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); // draw hook if(Prev.m_HookState>0 && Player.m_HookState>0) @@ -82,24 +73,13 @@ void CPlayers::RenderHook( if(Player.m_HookedPlayer != -1 && m_pClient->m_Snap.m_aCharacters[Player.m_HookedPlayer].m_Active) { // `HookedPlayer != -1` means that a player is being hooked - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(Player.m_HookedPlayer)) - { - HookPos = m_pClient->PredictedCharPos(Player.m_HookedPlayer); - } - else - { - HookPos = m_pClient->UnpredictedCharPos(Player.m_HookedPlayer); - } + bool Predicted = m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(Player.m_HookedPlayer); + HookPos = m_pClient->GetCharPos(Player.m_HookedPlayer, Predicted); } else { - // The hook is in the air or on a hookable tile - HookPos = mix( - vec2(Prev.m_HookX, Prev.m_HookY), - vec2(Player.m_HookX, Player.m_HookY), - IntraTick - ); + // The hook is in the air, on a hookable tile or the hooked player is out of range + HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick); } float d = distance(Pos, HookPos); @@ -133,18 +113,16 @@ void CPlayers::RenderHook( void CPlayers::RenderPlayer( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPrevInfo, const CNetObj_PlayerInfo *pPlayerInfo, + const CTeeRenderInfo *pRenderInfo, int ClientID - ) + ) const { - CNetObj_Character Prev; - CNetObj_Character Player; - Prev = *pPrevChar; - Player = *pPlayerChar; + CNetObj_Character Prev = *pPrevChar; + CNetObj_Character Player = *pPlayerChar; + CTeeRenderInfo RenderInfo = *pRenderInfo; - CNetObj_PlayerInfo pInfo = *pPlayerInfo; - CTeeRenderInfo RenderInfo = m_aRenderInfo[ClientID]; + const CGameClient::CClientData *pClientData = &m_pClient->m_aClients[ClientID]; // set size RenderInfo.m_Size = 64.0f; @@ -187,8 +165,7 @@ void CPlayers::RenderPlayer( g_GameClient.m_aClients[info.cid].angle = angle;*/ } - if(m_pClient->ShouldUsePredicted() && - m_pClient->ShouldUsePredictedChar(ClientID)) + if(m_pClient->ShouldUsePredicted() && m_pClient->ShouldUsePredictedChar(ClientID)) { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } @@ -420,7 +397,7 @@ void CPlayers::RenderPlayer( RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position); - if(pInfo.m_PlayerFlags&PLAYERFLAG_CHATTING) + if(pPlayerInfo->m_PlayerFlags&PLAYERFLAG_CHATTING) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); @@ -430,13 +407,13 @@ void CPlayers::RenderPlayer( Graphics()->QuadsEnd(); } - if (m_pClient->m_aClients[ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick()) + if(pClientData->m_EmoticonStart != -1 && pClientData->m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick()) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); - int SinceStart = Client()->GameTick() - m_pClient->m_aClients[ClientID].m_EmoticonStart; - int FromEnd = m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(); + int SinceStart = Client()->GameTick() - pClientData->m_EmoticonStart; + int FromEnd = pClientData->m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(); float a = 1; @@ -457,7 +434,7 @@ void CPlayers::RenderPlayer( Graphics()->SetColor(1.0f * a, 1.0f * a, 1.0f * a, a); // client_datas::emoticon is an offset from the first emoticon - RenderTools()->SelectSprite(SPRITE_OOP + m_pClient->m_aClients[ClientID].m_Emoticon); + RenderTools()->SelectSprite(SPRITE_OOP + pClientData->m_Emoticon); IGraphics::CQuadItem QuadItem(Position.x, Position.y - 23 - 32*h, 64, 64*h); Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); @@ -469,11 +446,19 @@ void CPlayers::OnRender() if(Client()->State() < IClient::STATE_ONLINE) return; + static const CNetObj_PlayerInfo *s_apInfo[MAX_CLIENTS]; + static CTeeRenderInfo s_aRenderInfo[MAX_CLIENTS]; + // update RenderInfo for ninja bool IsTeamplay = (m_pClient->m_GameInfo.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_Active) + continue; + + s_apInfo[i] = (const CNetObj_PlayerInfo *)Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); + s_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 @@ -485,19 +470,19 @@ void CPlayers::OnRender() { if(IsTeamplay) { - m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; + s_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; int ColorVal = m_pClient->m_pSkins->GetTeamColor(true, pNinja->m_aPartColors[p], m_pClient->m_aClients[i].m_Team, p); - m_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(ColorVal, p==SKINPART_MARKING); + s_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(ColorVal, p==SKINPART_MARKING); } else if(pNinja->m_aUseCustomColors[p]) { - m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; - m_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(pNinja->m_aPartColors[p], p==SKINPART_MARKING); + s_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; + s_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(pNinja->m_aPartColors[p], p==SKINPART_MARKING); } else { - m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_OrgTexture; - m_aRenderInfo[i].m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); + s_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_OrgTexture; + s_aRenderInfo[i].m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); } } } @@ -510,38 +495,35 @@ void CPlayers::OnRender() for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters - if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) + if(!m_pClient->m_Snap.m_aCharacters[i].m_Active || !s_apInfo[i]) continue; - const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); - const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); + // + bool Local = m_pClient->m_LocalClientID == i; + if((p % 2) == 0 && Local) continue; + if((p % 2) == 1 && !Local) continue; + + CNetObj_Character *pPrevChar = &m_pClient->m_Snap.m_aCharacters[i].m_Prev; + CNetObj_Character *pCurChar = &m_pClient->m_Snap.m_aCharacters[i].m_Cur; - if(pPrevInfo && pInfo) + if(p<2) { - // - bool Local = m_pClient->m_LocalClientID == i; - if((p % 2) == 0 && Local) continue; - if((p % 2) == 1 && !Local) continue; - - CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; - CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; - - if(p<2) - RenderHook( - &PrevChar, - &CurChar, - (const CNetObj_PlayerInfo *)pPrevInfo, - (const CNetObj_PlayerInfo *)pInfo, - i - ); - else - RenderPlayer( - &PrevChar, - &CurChar, - (const CNetObj_PlayerInfo *)pPrevInfo, - (const CNetObj_PlayerInfo *)pInfo, - i - ); + RenderHook( + pPrevChar, + pCurChar, + &s_aRenderInfo[i], + i + ); + } + else + { + RenderPlayer( + pPrevChar, + pCurChar, + s_apInfo[i], + &s_aRenderInfo[i], + i + ); } } } diff --git a/src/game/client/components/players.h b/src/game/client/components/players.h index ab9a5af8..e80a9c97 100644 --- a/src/game/client/components/players.h +++ b/src/game/client/components/players.h @@ -6,21 +6,19 @@ class CPlayers : public CComponent { - CTeeRenderInfo m_aRenderInfo[MAX_CLIENTS]; void RenderPlayer( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPrevInfo, const CNetObj_PlayerInfo *pPlayerInfo, + const CTeeRenderInfo *pRenderInfo, int ClientID - ); + ) const; void RenderHook( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, - const CNetObj_PlayerInfo *pPrevInfo, - const CNetObj_PlayerInfo *pPlayerInfo, + const CTeeRenderInfo *pRenderInfo, int ClientID - ); + ) const; public: virtual void OnRender(); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d8d81772..f1be152c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -499,13 +499,9 @@ void CGameClient::UpdatePositions() { // `m_LocalCharacterPos` is used for many things besides rendering the // player (e.g. camera position, mouse input), which is why we set it here. - if(ShouldUsePredicted() && ShouldUsePredictedLocalChar()) + if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { - m_LocalCharacterPos = PredictedCharPos(m_LocalClientID); - } - else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) - { - m_LocalCharacterPos = UnpredictedCharPos(m_LocalClientID); + m_LocalCharacterPos = GetCharPos(m_LocalClientID, ShouldUsePredicted()); } // spectator position @@ -515,7 +511,7 @@ void CGameClient::UpdatePositions() DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && m_Snap.m_SpecInfo.m_SpectatorID != -1) { - m_Snap.m_SpecInfo.m_Position = UnpredictedCharPos(m_Snap.m_SpecInfo.m_SpectatorID); + m_Snap.m_SpecInfo.m_Position = GetCharPos(m_Snap.m_SpecInfo.m_SpectatorID); m_LocalCharacterPos = m_Snap.m_SpecInfo.m_Position; m_Snap.m_SpecInfo.m_UsePosition = true; } @@ -1551,8 +1547,8 @@ void CGameClient::OnPredict() // instead of predicting into the future, just use the current and // previous snapshots that we already have - m_aPredictedPrevChars[i].Read(&m_Snap.m_aCharacters[i].m_Prev); - m_aPredictedChars[i].Read(&m_Snap.m_aCharacters[i].m_Cur); + m_aClients[i].m_PrevPredicted.Read(&m_Snap.m_aCharacters[i].m_Prev); + m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); } return; @@ -1588,21 +1584,16 @@ void CGameClient::OnPredict() // `Prev` because we haven't run the last iteration yet, so our // data is from the previous tick. if(Tick == Client()->PredGameTick()) - m_aPredictedPrevChars[c] = *World.m_apCharacters[c]; + m_aClients[c].m_PrevPredicted = *World.m_apCharacters[c]; - mem_zero( - &World.m_apCharacters[c]->m_Input, - sizeof(World.m_apCharacters[c]->m_Input) - ); + mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input)); if(m_LocalClientID == c) { // apply player input const int *pInput = Client()->GetInput(Tick); - if (pInput) - World.m_apCharacters[c]->m_Input = *( - (const CNetObj_PlayerInput*)pInput - ); + if(pInput) + World.m_apCharacters[c]->m_Input = *((const CNetObj_PlayerInput*)pInput); World.m_apCharacters[c]->Tick(true); } @@ -1636,8 +1627,7 @@ void CGameClient::OnPredict() // necessary to trigger events for them here. Also, our predictions // for other players will often be wrong, so it's safer not to // trigger events here. - if(m_LocalClientID != -1 && - World.m_apCharacters[m_LocalClientID]) + if(m_LocalClientID != -1 && World.m_apCharacters[m_LocalClientID]) { ProcessTriggeredEvents( World.m_apCharacters[m_LocalClientID]->m_TriggeredEvents, @@ -1645,60 +1635,29 @@ void CGameClient::OnPredict() ); } } - - // After running the last iteration, store our final prediction. We should - // now have the following predictions: - // - `m_aPredictedPrevChars` stores character predictions at time - // `PredGameTick - 1` - // - `m_aPredictedChars` stores character predictions at time - // `PredGameTick` - if(Tick == Client()->PredGameTick()) - { - for(int c = 0; c < MAX_CLIENTS; c++) - { - if(World.m_apCharacters[c]) - m_aPredictedChars[c] = *World.m_apCharacters[c]; - } - } } m_PredictedTick = Client()->PredGameTick(); } -bool CGameClient::ShouldUsePredicted() +bool CGameClient::ShouldUsePredicted() const { // We don't use predictions when: // - Viewing a demo // - When the game is paused or waiting // - When we are spectating return + Config()->m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK && - !(IsWorldPaused()) && - !(m_Snap.m_SpecInfo.m_Active); -} - -bool CGameClient::ShouldUsePredictedLocalChar() -{ - // Not sure if `m_Snap.m_pLocalCharacter` is necessary, but the old code - // checked it so I will too. - return Config()->m_ClPredict && m_Snap.m_pLocalCharacter; -} - -bool CGameClient::ShouldUsePredictedNonLocalChars() -{ - return Config()->m_ClPredictPlayers; + !IsWorldPaused() && + !m_Snap.m_SpecInfo.m_Active && + m_LocalClientID != -1; } -bool CGameClient::ShouldUsePredictedChar(int ClientID) +bool CGameClient::ShouldUsePredictedChar(int ClientID) const { - if(ClientID == m_LocalClientID) - return ShouldUsePredictedLocalChar(); - else - // Might want to check if `ClientID` exists in `m_Snap.m_aCharacters`, - // similar to how we check if `m_pLocalCharacter` is not null in - // `ShouldUsePredictedLocalChar` - return ShouldUsePredictedNonLocalChars(); + return ClientID == m_LocalClientID || Config()->m_ClPredictPlayers; } void CGameClient::UsePredictedChar( @@ -1706,41 +1665,31 @@ void CGameClient::UsePredictedChar( CNetObj_Character *pPlayerChar, float *IntraTick, int ClientID - ) + ) const { - m_aPredictedPrevChars[ClientID].Write(pPrevChar); - m_aPredictedChars[ClientID].Write(pPlayerChar); + m_aClients[ClientID].m_PrevPredicted.Write(pPrevChar); + m_aClients[ClientID].m_Predicted.Write(pPlayerChar); *IntraTick = Client()->PredIntraGameTick(); } -vec2 CGameClient::PredictedCharPos(int ClientID) -{ - return mix( - vec2( - m_aPredictedPrevChars[ClientID].m_Pos.x, - m_aPredictedPrevChars[ClientID].m_Pos.y - ), - vec2( - m_aPredictedChars[ClientID].m_Pos.x, - m_aPredictedChars[ClientID].m_Pos.y - ), - Client()->PredIntraGameTick() - ); -} - -vec2 CGameClient::UnpredictedCharPos(int ClientID) +vec2 CGameClient::GetCharPos(int ClientID, bool Predicted) const { - return mix( - vec2( - m_Snap.m_aCharacters[ClientID].m_Prev.m_X, - m_Snap.m_aCharacters[ClientID].m_Prev.m_Y - ), - vec2( - m_Snap.m_aCharacters[ClientID].m_Cur.m_X, - m_Snap.m_aCharacters[ClientID].m_Cur.m_Y - ), - Client()->IntraGameTick() - ); + if(Predicted) + { + return mix( + m_aClients[ClientID].m_PrevPredicted.m_Pos, + m_aClients[ClientID].m_Predicted.m_Pos, + Client()->PredIntraGameTick() + ); + } + else + { + return mix( + vec2(m_Snap.m_aCharacters[ClientID].m_Prev.m_X, m_Snap.m_aCharacters[ClientID].m_Prev.m_Y), + vec2(m_Snap.m_aCharacters[ClientID].m_Cur.m_X, m_Snap.m_aCharacters[ClientID].m_Cur.m_Y), + Client()->IntraGameTick() + ); + } } void CGameClient::OnActivateEditor() diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 1140a50e..d3ee597e 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -116,42 +116,25 @@ class CGameClient : public IGameClient vec2 m_LocalCharacterPos; - // predicted players - - CCharacterCore m_aPredictedPrevChars[MAX_CLIENTS]; - CCharacterCore m_aPredictedChars[MAX_CLIENTS]; - - bool ShouldUsePredicted(); - // Whether we should use/render predicted entities. Depends on client - // and game state. -private: - bool ShouldUsePredictedLocalChar(); - // Whether we should use/render the predicted local character. Depends - // on config and snap state. Should check `ShouldUsePredicted` before - // checking this. - bool ShouldUsePredictedNonLocalChars(); - // Whether we should use/render predicted entities for non-local - // characters. Depends on config. Should check `ShouldUsePredicted` - // before checking this. -public: - bool ShouldUsePredictedChar(int ClientID); - // Whether we should use/render predictions for a specific `ClientID`. - // Should check `ShouldUsePredicted` before checking this. + // Whether we should use/render predicted entities. Depends on client + // and game state. + bool ShouldUsePredicted() const; + + // Whether we should use/render predictions for a specific `ClientID`. + // Should check `ShouldUsePredicted` before checking this. + bool ShouldUsePredictedChar(int ClientID) const; + // Replaces `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted + // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` + // before using this. void UsePredictedChar( CNetObj_Character *pPrevChar, CNetObj_Character *pPlayerChar, float *IntraTick, int ClientID - ); - // Replaces `pPrevChar`, `pPlayerChar`, and `IntraTick` with their predicted - // counterparts for `ClientID`. Should check `ShouldUsePredictedChar` - // before using this. + ) const; - vec2 PredictedCharPos(int ClientID); - // Return the interpolated, predicted position for `ClientID` - vec2 UnpredictedCharPos(int ClientID); - // Return the interpolated, unpredicted position for `ClientID` + vec2 GetCharPos(int ClientID, bool Predicted = false) const; // --- @@ -225,6 +208,7 @@ class CGameClient : public IGameClient int m_Emoticon; int m_EmoticonStart; CCharacterCore m_Predicted; + CCharacterCore m_PrevPredicted; CTeeRenderInfo m_SkinInfo; // this is what the server reports CTeeRenderInfo m_RenderInfo; // this is what we use diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index 22aad193..e6bfa7e2 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -404,7 +404,7 @@ void CCharacterCore::Move() m_Pos = NewPos; } -void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore) +void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore) const { pObjCore->m_X = round_to_int(m_Pos.x); pObjCore->m_Y = round_to_int(m_Pos.y); diff --git a/src/game/gamecore.h b/src/game/gamecore.h index ac61f26b..38fb490e 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -179,7 +179,7 @@ class CCharacterCore void ResetDragVelocity(); void Read(const CNetObj_CharacterCore *pObjCore); - void Write(CNetObj_CharacterCore *pObjCore); + void Write(CNetObj_CharacterCore *pObjCore) const; void Quantize(); }; diff --git a/src/game/variables.h b/src/game/variables.h index 595b130e..17cc3c89 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -6,7 +6,7 @@ // client -MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") +MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use prediction for objects in the game world") MACRO_CONFIG_INT(ClPredictPlayers, cl_predict_players, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict movements of other players") MACRO_CONFIG_INT(ClPredictProjectiles, cl_predict_projectiles, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict position of projectiles") MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show name plates") From 0dd12b25a4c8bc3fe6c0ad16cf2c55c8024a879b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 13 Sep 2020 21:03:37 +0200 Subject: [PATCH 424/479] fix right clicking in editor --- src/game/client/ui.cpp | 11 +++++++---- src/game/client/ui.h | 2 +- src/game/editor/editor.cpp | 9 +++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index f8d892ab..d301b699 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -308,30 +308,33 @@ bool CUIRect::Inside(float x, float y) const && y < this->y + this->h; } -bool CUI::DoButtonLogic(const void *pID, const CUIRect *pRect) +bool CUI::DoButtonLogic(const void *pID, const CUIRect *pRect, int Button) { // logic bool Clicked = false; + static int s_LastButton = -1; const bool Hovered = MouseHovered(pRect); if(CheckActiveItem(pID)) { - if(!MouseButton(0)) + if(s_LastButton == Button && !MouseButton(s_LastButton)) { if(Hovered) Clicked = true; SetActiveItem(0); + s_LastButton = -1; } } else if(HotItem() == pID) { - if(MouseButton(0)) + if(MouseButton(Button)) { SetActiveItem(pID); + s_LastButton = Button; } } - if(Hovered && !MouseButton(0)) + if(Hovered && !MouseButton(Button)) SetHotItem(pID); return Clicked; diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 596d6cde..f66fd68a 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -134,7 +134,7 @@ class CUI const CUIRect *ClipArea() const; inline bool IsClipped() const { return m_NumClips > 0; }; - bool DoButtonLogic(const void *pID, const CUIRect *pRect); + bool DoButtonLogic(const void *pID, const CUIRect *pRect, int Button = 0); bool DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY); void DoLabel(const CUIRect *pRect, const char *pText, float FontSize, EAlignment Align, float LineWidth = -1.0f, bool MultiLine = true); diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 0cce0b54..31725f48 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -533,10 +533,11 @@ int CEditor::DoButton_Editor_Common(const void *pID, const char *pText, int Chec if(UI()->HotItem() == pID && pToolTip) m_pTooltip = (const char *)pToolTip; - return UI()->DoButtonLogic(pID, pRect); - - // Draw here - //return UI()->DoButton(id, text, checked, r, draw_func, 0); + if(UI()->DoButtonLogic(pID, pRect, 0)) + return 1; + if(UI()->DoButtonLogic(pID, pRect, 1)) + return 2; + return 0; } From dc8772a8c68671e2677c36bf9b06894893a11c5a Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 13 Sep 2020 20:19:00 +0100 Subject: [PATCH 425/479] Fix localization string search --- src/game/client/localization.cpp | 2 +- src/game/client/localization.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/localization.cpp b/src/game/client/localization.cpp index 84d4ff8e..3593e10f 100644 --- a/src/game/client/localization.cpp +++ b/src/game/client/localization.cpp @@ -126,7 +126,7 @@ const char *CLocalizationDatabase::FindString(unsigned Hash, unsigned ContextHas { CString String; String.m_Hash = Hash; - String.m_ContextHash = 0; // this is ignored for the search anyway + String.m_ContextHash = ContextHash; sorted_array::range r = ::find_binary(m_Strings.all(), String); if(r.empty()) return 0; diff --git a/src/game/client/localization.h b/src/game/client/localization.h index d5f60967..e3e75ac7 100644 --- a/src/game/client/localization.h +++ b/src/game/client/localization.h @@ -17,8 +17,8 @@ class CLocalizationDatabase string m_Replacement; bool operator <(const CString &Other) const { return m_Hash < Other.m_Hash || (m_Hash == Other.m_Hash && m_ContextHash < Other.m_ContextHash); } - bool operator <=(const CString &Other) const { return m_Hash <= Other.m_Hash; } - bool operator ==(const CString &Other) const { return m_Hash == Other.m_Hash; } + bool operator <=(const CString &Other) const { return m_Hash < Other.m_Hash || (m_Hash == Other.m_Hash && m_ContextHash <= Other.m_ContextHash); } + bool operator ==(const CString &Other) const { return m_Hash == Other.m_Hash && m_ContextHash == Other.m_ContextHash; } }; sorted_array m_Strings; From 52be8304b0676251580c4a1d119eec5eda4dd027 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 13 Sep 2020 20:47:06 +0100 Subject: [PATCH 426/479] Reveal seconds of demofiles' date --- src/game/client/components/menus_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 567bfcb5..c38f4411 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -552,7 +552,7 @@ void CMenus::RenderDemoList(CUIRect MainView) for(int c = 0; c < NumCols; c++) { CUIRect Button; - Button.x = ms_aDemoCols[c].m_Rect.x + FileIcon.w + 10.0f; + Button.x = ms_aDemoCols[c].m_Rect.x; Button.y = FileIcon.y; Button.h = ms_aDemoCols[c].m_Rect.h; Button.w = ms_aDemoCols[c].m_Rect.w; @@ -566,6 +566,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } if(ID == COL_DEMO_NAME) { + Button.x += FileIcon.w + 10.0f; UI()->DoLabel(&Button, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } else if(ID == COL_DEMO_LENGTH && !r.front().m_IsDir && r.front().m_InfosLoaded) From 7dc5bebc174b40670e4d058b1a50650888ce4a59 Mon Sep 17 00:00:00 2001 From: Freddie Wang Date: Mon, 14 Sep 2020 19:22:12 +0100 Subject: [PATCH 427/479] Add RelWithDebInfo to .gitignore (#2735) cmake can build this target --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c98c3d12..7a35f881 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ CPackConfig.cmake CPackSourceConfig.cmake Debug Makefile +RelWithDebInfo Release _CPack_Packages/ build.ninja From baa0fa5ae4c48d87c072432c1c2c6b7f634865a4 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 15 Sep 2020 20:16:06 +0200 Subject: [PATCH 428/479] changed hardcoded build version for the workflow. closes #2727 --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a681acec..35148ce8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -148,4 +148,4 @@ jobs: - name: Create MacOS app using make_release.py if: contains(matrix.os, 'macOS') run: | - sudo python3 scripts/make_release.py 0.7.4 osx + sudo python3 scripts/make_release.py master osx From da77f02c63862897b74b623a56c2acf1e9894714 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Wed, 16 Sep 2020 12:50:53 +0200 Subject: [PATCH 429/479] More EvalIf fine tuning (thanks to @oy) --- src/engine/shared/console.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 37ad661c..8d085add 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -674,12 +674,13 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData) void CConsole::Con_EvalIf(IResult *pResult, void *pUserData) { - CCommand *pCommand = ((CConsole*)pUserData)->FindCommand(pResult->GetString(0), ((CConsole*)pUserData)->m_FlagMask); + CConsole* pConsole = static_cast(pUserData); + CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), pConsole->m_FlagMask); char aBuf[128]; if(!pCommand) { str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(0)); - ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf); + pConsole->Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf); return; } CResult Result; @@ -689,25 +690,24 @@ void CConsole::Con_EvalIf(IResult *pResult, void *pUserData) Condition = Result.m_Value == atoi(pResult->GetString(2)); else Condition = !str_comp_nocase(Result.m_aValue, pResult->GetString(2)); - if(!str_comp_num(pResult->GetString(1), "!=", 3)) + if(!str_comp(pResult->GetString(1), "!=")) Condition = !Condition; - else if(str_comp_num(pResult->GetString(1), "==", 3) && pCommand->m_pfnCallback == StrVariableCommand) - ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type string"); - else if(!str_comp_num(pResult->GetString(1), ">", 2)) + else if(str_comp(pResult->GetString(1), "==") && pCommand->m_pfnCallback == StrVariableCommand) + pConsole->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type string"); + else if(!str_comp(pResult->GetString(1), ">")) Condition = Result.m_Value > atoi(pResult->GetString(2)); - else if(!str_comp_num(pResult->GetString(1), "<", 2)) + else if(!str_comp(pResult->GetString(1), "<")) Condition = Result.m_Value < atoi(pResult->GetString(2)); - else if(!str_comp_num(pResult->GetString(1), "<=", 3)) + else if(!str_comp(pResult->GetString(1), "<=")) Condition = Result.m_Value <= atoi(pResult->GetString(2)); - else if(!str_comp_num(pResult->GetString(1), ">=", 3)) + else if(!str_comp(pResult->GetString(1), ">=")) Condition = Result.m_Value >= atoi(pResult->GetString(2)); - else if(str_comp_num(pResult->GetString(1), "==", 3)) - ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type integer"); + else if(str_comp(pResult->GetString(1), "==")) + pConsole->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: invalid comperator for type integer"); - if(pResult->NumArguments() > 4 && str_comp_num(pResult->GetString(4), "else", 5)) - ((CConsole*)pUserData)->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: expected else"); + if(pResult->NumArguments() > 4 && str_comp(pResult->GetString(4), "else")) + pConsole->Print(OUTPUT_LEVEL_STANDARD, "Console", "Error: expected else"); - CConsole* pConsole = static_cast(pUserData); if(Condition) pConsole->ExecuteLine(pResult->GetString(3)); else if(pResult->NumArguments() == 6) @@ -807,7 +807,7 @@ CConsole::CConsole(int FlagMask) // register some basic commands Register("echo", "r[text]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text"); Register("exec", "r[file]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file"); - Register("eval_if", "s[config] s[comparison] s[value] s[command] ?s[else] ?s[command]", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_EvalIf, this, "Execute command if condition is true"); + Register("eval_if", "s[config] s[comparison] s[value] s[command] ?s[else] ?s[command]", CFGFLAG_SERVER|CFGFLAG_CLIENT|CFGFLAG_STORE, Con_EvalIf, this, "Execute command if condition is true"); Register("toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConToggle, this, "Toggle config value"); Register("+toggle", "s[config-option] i[value1] i[value2]", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress"); From 53423c86d89eb07a842f8546a3e083d1a1e01dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Wed, 16 Sep 2020 16:54:00 +0200 Subject: [PATCH 430/479] fix demo player freezing on seeking --- src/game/client/components/chat.cpp | 21 ++++++----- src/game/client/components/menus_demo.cpp | 2 - src/game/client/components/sounds.cpp | 24 +++++++----- src/game/client/gameclient.cpp | 46 +++++++++++------------ 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index d6b2db49..e88420d0 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -75,15 +75,18 @@ void CChat::OnReset() m_CurrentLineWidth = -1.0f; // init chat commands (must be in alphabetical order) - m_CommandManager.ClearCommands(); - m_CommandManager.AddCommand("all", "Switch to all chat", "?r[message]", &Com_All, this); - m_CommandManager.AddCommand("friend", "Add player as friend", "s[name]", &Com_Befriend, this); - m_CommandManager.AddCommand("m", "Mute a player", "s[name]", &Com_Mute, this); - m_CommandManager.AddCommand("mute", "Mute a player", "s[name]", &Com_Mute, this); - m_CommandManager.AddCommand("r", "Reply to a whisper", "?r[message]", &Com_Reply, this); - m_CommandManager.AddCommand("team", "Switch to team chat", "?r[message]", &Com_Team, this); - m_CommandManager.AddCommand("w", "Whisper another player", "r[name]", &Com_Whisper, this); - m_CommandManager.AddCommand("whisper", "Whisper another player", "r[name]", &Com_Whisper, this); + if(Client()->State() < IClient::STATE_ONLINE) + { + m_CommandManager.ClearCommands(); + m_CommandManager.AddCommand("all", "Switch to all chat", "?r[message]", &Com_All, this); + m_CommandManager.AddCommand("friend", "Add player as friend", "s[name]", &Com_Befriend, this); + m_CommandManager.AddCommand("m", "Mute a player", "s[name]", &Com_Mute, this); + m_CommandManager.AddCommand("mute", "Mute a player", "s[name]", &Com_Mute, this); + m_CommandManager.AddCommand("r", "Reply to a whisper", "?r[message]", &Com_Reply, this); + m_CommandManager.AddCommand("team", "Switch to team chat", "?r[message]", &Com_Team, this); + m_CommandManager.AddCommand("w", "Whisper another player", "r[name]", &Com_Whisper, this); + m_CommandManager.AddCommand("whisper", "Whisper another player", "r[name]", &Com_Whisper, this); + } } void CChat::OnMapLoad() diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 567bfcb5..f3ee9b73 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -162,7 +162,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) // rewind when reaching the end if(CurrentTick == TotalTicks) { - m_pClient->OnReset(); DemoPlayer()->Pause(); PositionToSeek = 0.0f; } @@ -276,7 +275,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) static CButtonContainer s_ResetButton; if(DoButton_SpriteID(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, false, &Button, CUI::CORNER_ALL)) { - m_pClient->OnReset(); DemoPlayer()->Pause(); PositionToSeek = 0.0f; } diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index bf1fefd6..cef384b4 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -147,19 +147,21 @@ void CSounds::ClearQueue() void CSounds::Enqueue(int Channel, int SetId) { - // add sound to the queue - if(m_QueuePos < QUEUE_SIZE) - { - if(Channel == CHN_MUSIC || !Config()->m_ClEditor) - { - m_aQueue[m_QueuePos].m_Channel = Channel; - m_aQueue[m_QueuePos++].m_SetId = SetId; - } - } + if(m_pClient->m_SuppressEvents) + return; + if(m_QueuePos >= QUEUE_SIZE) + return; + if(Channel != CHN_MUSIC && Config()->m_ClEditor) + return; + + m_aQueue[m_QueuePos].m_Channel = Channel; + m_aQueue[m_QueuePos++].m_SetId = SetId; } void CSounds::Play(int Chn, int SetId, float Vol) { + if(m_pClient->m_SuppressEvents) + return; if(Chn == CHN_MUSIC && !Config()->m_SndMusic) return; @@ -176,9 +178,11 @@ void CSounds::Play(int Chn, int SetId, float Vol) void CSounds::PlayAt(int Chn, int SetId, float Vol, vec2 Pos) { + if(m_pClient->m_SuppressEvents) + return; if(Chn == CHN_MUSIC && !Config()->m_SndMusic) return; - + ISound::CSampleHandle SampleId = GetSampleId(SetId); if(!SampleId.IsValid()) return; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d8d81772..f8f2c939 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -471,28 +471,34 @@ void CGameClient::OnConnected() void CGameClient::OnReset() { - // clear out the invalid pointers - m_LastNewPredictedTick = -1; - mem_zero(&m_Snap, sizeof(m_Snap)); + if(Client()->State() < IClient::STATE_ONLINE) + { + // clear out the invalid pointers + m_LastNewPredictedTick = -1; + mem_zero(&m_Snap, sizeof(m_Snap)); - for(int i = 0; i < MAX_CLIENTS; i++) - m_aClients[i].Reset(this, i); + for(int ClientID = 0; ClientID < MAX_CLIENTS; ClientID++) + m_aClients[ClientID].Reset(this, ClientID); + } for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnReset(); - m_LocalClientID = -1; - m_TeamCooldownTick = 0; - m_TeamChangeTime = 0.0f; - m_LastSkinChangeTime = Client()->LocalTime(); - mem_zero(&m_GameInfo, sizeof(m_GameInfo)); - m_DemoSpecMode = SPEC_FREEVIEW; - m_DemoSpecID = -1; - m_Tuning = CTuningParams(); - m_MuteServerBroadcast = false; - m_LastGameStartTick = -1; - m_LastFlagCarrierRed = FLAG_MISSING; - m_LastFlagCarrierBlue = FLAG_MISSING; + if(Client()->State() < IClient::STATE_ONLINE) + { + m_LocalClientID = -1; + m_TeamCooldownTick = 0; + m_TeamChangeTime = 0.0f; + m_LastSkinChangeTime = Client()->LocalTime(); + mem_zero(&m_GameInfo, sizeof(m_GameInfo)); + m_DemoSpecMode = SPEC_FREEVIEW; + m_DemoSpecID = -1; + m_Tuning = CTuningParams(); + m_MuteServerBroadcast = false; + m_LastGameStartTick = -1; + m_LastFlagCarrierRed = FLAG_MISSING; + m_LastFlagCarrierBlue = FLAG_MISSING; + } } void CGameClient::UpdatePositions() @@ -698,13 +704,9 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) switch(GameMsgID) { case GAMEMSG_CTF_DROP: - if(m_SuppressEvents) - return; m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_DROP); break; case GAMEMSG_CTF_RETURN: - if(m_SuppressEvents) - return; m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_RETURN); break; case GAMEMSG_TEAM_ALL: @@ -732,8 +734,6 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) } break; case GAMEMSG_CTF_GRAB: - if(m_SuppressEvents) - return; if(m_LocalClientID != -1 && (m_aClients[m_LocalClientID].m_Team != aParaI[0] || (m_Snap.m_SpecInfo.m_Active && ((m_Snap.m_SpecInfo.m_SpectatorID != -1 && m_aClients[m_Snap.m_SpecInfo.m_SpectatorID].m_Team != aParaI[0]) || (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGRED && aParaI[0] != TEAM_RED) || From 5d00b3946a0c9dfeacef294bbfd6fdb6b29303e6 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 20 Sep 2020 12:49:55 +0100 Subject: [PATCH 431/479] various improvements of demo browser --- src/game/client/components/menus.cpp | 6 +-- src/game/client/components/menus.h | 7 +-- src/game/client/components/menus_demo.cpp | 55 +++++++++----------- src/game/client/components/menus_listbox.cpp | 7 +++ 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8cfb92a2..b2a8cf02 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -233,17 +233,17 @@ bool CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, bool return UI()->DoButtonLogic(pBC->GetID(), pRect); } -bool CMenus::DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect) +bool CMenus::DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect, int Corners) { if(Checked) { - RenderTools()->DrawUIRect(pRect, vec4(0.9f, 0.9f, 0.9f, 0.5f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(pRect, vec4(0.9f, 0.9f, 0.9f, 0.5f), Corners, 5.0f); TextRender()->TextColor(CUI::ms_HighlightTextColor); TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); } else if(UI()->HotItem() == pID) { - RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(pRect, vec4(1.0f, 1.0f, 1.0f, 0.5f), Corners, 5.0f); } CUIRect Label; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e070822b..a6c582b5 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -119,7 +119,7 @@ class CMenus : public CComponent bool DoButton_CheckBox(const void *pID, const char *pText, bool Checked, const CUIRect *pRect, bool Locked = false); void DoIcon(int ImageId, int SpriteId, const CUIRect *pRect, const vec4 *pColor = 0); - bool DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect); + bool DoButton_GridHeader(const void *pID, const char *pText, bool Checked, CUI::EAlignment Align, const CUIRect *pRect, int Corners = CUI::CORNER_ALL); bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = CUI::CORNER_ALL); void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden = false); @@ -267,6 +267,7 @@ class CMenus : public CComponent CListBox(); void DoHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight = 20.0f, float Spacing = 2.0f); + void DoSubHeader(float HeaderHeight = 20.0f, float Spacing = 2.0f); bool DoFilter(float FilterHeight = 20.0f, float Spacing = 2.0f); void DoFooter(const char *pBottomText, float FooterHeight = 20.0f); // call before DoStart to create a footer void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, @@ -275,6 +276,7 @@ class CMenus : public CComponent int DoEnd(); bool FilterMatches(const char *pNeedle) const; bool WasItemActivated() const { return m_ListBoxItemActivated; }; + float GetScrollBarWidth() const { return m_ScrollRegion.IsScrollbarShown() ? 20 : 0; } // defined in menus_scrollregion.cpp }; @@ -689,8 +691,7 @@ class CMenus : public CComponent COL_BROWSER_PING, NUM_BROWSER_COLS, - COL_DEMO_ICON=0, - COL_DEMO_NAME, + COL_DEMO_NAME = 0, COL_DEMO_LENGTH, COL_DEMO_DATE, NUM_DEMO_COLS, diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 4dc28341..a5049166 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -21,10 +21,9 @@ #include "menus.h" CMenus::CColumn CMenus::ms_aDemoCols[] = { - {COL_DEMO_ICON, -1, " ", -1, 0, 0, {0}, {0}, CUI::ALIGN_CENTER}, {COL_DEMO_NAME, CMenus::SORT_DEMONAME, Localize("Name"), 0, 100.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, - {COL_DEMO_LENGTH, CMenus::SORT_LENGTH, Localize("Length"), 1, 100.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, - {COL_DEMO_DATE, CMenus::SORT_DATE, Localize("Date"), 1, 160.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_LENGTH, CMenus::SORT_LENGTH, Localize("Length"), 1, 80.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, + {COL_DEMO_DATE, CMenus::SORT_DATE, Localize("Date"), 1, 170.0f, 0, {0}, {0}, CUI::ALIGN_CENTER}, }; void CMenus::RenderDemoPlayer(CUIRect MainView) @@ -455,10 +454,14 @@ void CMenus::RenderDemoList(CUIRect MainView) CUIRect ListBox, Button, FileIcon; MainView.HSplitTop(MainView.h - BackgroundHeight - 2 * HMargin, &ListBox, &MainView); - // demo list + // demo list header + static CListBox s_ListBox; + s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); + // demo list column headers CUIRect Headers; - ListBox.HSplitTop(GetListHeaderHeight(), &Headers, &ListBox); + ListBox.HMargin(GetListHeaderHeight() + 2.0f, &Headers); + Headers.h = GetListHeaderHeight(); RenderTools()->DrawUIRect(&Headers, vec4(0.0f,0,0,0.15f), 0, 0); @@ -491,15 +494,14 @@ void CMenus::RenderDemoList(CUIRect MainView) { if(ms_aDemoCols[i].m_Direction == 0) ms_aDemoCols[i].m_Rect = Headers; + if(i == NumCols - 1) + ms_aDemoCols[i].m_Rect.w -= s_ListBox.GetScrollBarWidth(); } // do headers for(int i = 0; i < NumCols; i++) { - if(i == COL_DEMO_ICON) - continue; - - if(DoButton_GridHeader(ms_aDemoCols[i].m_Caption, ms_aDemoCols[i].m_Caption, Config()->m_BrDemoSort == ms_aDemoCols[i].m_Sort, ms_aDemoCols[i].m_Align, &ms_aDemoCols[i].m_Rect)) + if(DoButton_GridHeader(ms_aDemoCols[i].m_Caption, ms_aDemoCols[i].m_Caption, Config()->m_BrDemoSort == ms_aDemoCols[i].m_Sort, ms_aDemoCols[i].m_Align, &ms_aDemoCols[i].m_Rect, CUI::CORNER_T)) { if(ms_aDemoCols[i].m_Sort != -1) { @@ -518,8 +520,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } } - static CListBox s_ListBox; - s_ListBox.DoHeader(&ListBox, Localize("Recorded"), GetListHeaderHeight()); + s_ListBox.DoSubHeader(GetListHeaderHeight(), 0.0f); s_ListBox.DoStart(20.0f, m_lDemos.size(), 1, 3, m_DemolistSelectedIndex); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) @@ -569,13 +570,16 @@ void CMenus::RenderDemoList(CUIRect MainView) } else if(ID == COL_DEMO_LENGTH && !r.front().m_IsDir && r.front().m_InfosLoaded) { - int Length = r.front().Length(); - char aLength[32]; - str_format(aLength, sizeof(aLength), "%d:%02d", Length/60, Length%60); - Button.VMargin(4.0f, &Button); - if(!Item.m_Selected) - TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Button, aLength, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + if (DemoItem.m_Valid) + { + int Length = DemoItem.Length(); + char aLength[32]; + str_format(aLength, sizeof(aLength), "%d:%02d", Length/60, Length%60); + Button.VMargin(4.0f, &Button); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Button, aLength, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); + } } else if(ID == COL_DEMO_DATE) { @@ -585,7 +589,7 @@ void CMenus::RenderDemoList(CUIRect MainView) str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); if(!Item.m_Selected) TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Button, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); + UI()->DoLabel(&Button, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } } TextRender()->TextColor(CUI::ms_DefaultTextColor); @@ -599,16 +603,7 @@ void CMenus::RenderDemoList(CUIRect MainView) MainView.HSplitTop(HMargin, 0, &MainView); static int s_DemoDetailsDropdown = 0; - if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) - DoIndependentDropdownMenu(&s_DemoDetailsDropdown, &MainView, aFooterLabel, ButtonHeight, &CMenus::RenderDemoDetails, &s_DemoDetailsActive); - else - { - CUIRect Header; - MainView.HSplitTop(ButtonHeight, &Header, &MainView); - RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Header.y += 2.0f; - UI()->DoLabel(&Header, aFooterLabel, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - } + DoIndependentDropdownMenu(&s_DemoDetailsDropdown, &MainView, aFooterLabel, ButtonHeight, &CMenus::RenderDemoDetails, &s_DemoDetailsActive); // demo buttons int NumButtons = m_DemolistSelectedIsDir ? 3 : 5; @@ -732,7 +727,7 @@ void CMenus::PopupConfirmDeleteDemo() float CMenus::RenderDemoDetails(CUIRect View) { // render demo info - if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) + if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid && m_lDemos[m_DemolistSelectedIndex].m_InfosLoaded) { CUIRect Button; diff --git a/src/game/client/components/menus_listbox.cpp b/src/game/client/components/menus_listbox.cpp index 748c8e58..b27e58e3 100644 --- a/src/game/client/components/menus_listbox.cpp +++ b/src/game/client/components/menus_listbox.cpp @@ -40,6 +40,13 @@ void CMenus::CListBox::DoHeader(const CUIRect *pRect, const char *pTitle, m_ListBoxView = View; } +void CMenus::CListBox::DoSubHeader(float HeaderHeight, float Spacing) +{ + CUIRect View = m_ListBoxView; + View.HSplitTop(HeaderHeight+Spacing, 0, &View); + m_ListBoxView = View; +} + bool CMenus::CListBox::DoFilter(float FilterHeight, float Spacing) { CUIRect Filter; From e82a338908d43fa685b8997ae76fa8352a95018b Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 20 Sep 2020 13:32:29 +0100 Subject: [PATCH 432/479] reviewed changes --- src/game/client/components/menus_demo.cpp | 34 ++++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index a5049166..8ce01db8 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -568,29 +568,23 @@ void CMenus::RenderDemoList(CUIRect MainView) Button.x += FileIcon.w + 10.0f; UI()->DoLabel(&Button, DemoItem.m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT); } - else if(ID == COL_DEMO_LENGTH && !r.front().m_IsDir && r.front().m_InfosLoaded) + else if(ID == COL_DEMO_LENGTH && !DemoItem.m_IsDir && DemoItem.m_InfosLoaded && DemoItem.m_Valid) { - if (DemoItem.m_Valid) - { - int Length = DemoItem.Length(); - char aLength[32]; - str_format(aLength, sizeof(aLength), "%d:%02d", Length/60, Length%60); - Button.VMargin(4.0f, &Button); - if(!Item.m_Selected) - TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Button, aLength, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); - } + int Length = DemoItem.Length(); + char aLength[32]; + str_format(aLength, sizeof(aLength), "%d:%02d", Length/60, Length%60); + Button.VMargin(4.0f, &Button); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Button, aLength, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_RIGHT); } - else if(ID == COL_DEMO_DATE) + else if(ID == COL_DEMO_DATE && !DemoItem.m_IsDir) { - if(!DemoItem.m_IsDir) - { - char aDate[64]; - str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); - if(!Item.m_Selected) - TextRender()->TextColor(CUI::ms_TransparentTextColor); - UI()->DoLabel(&Button, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - } + char aDate[64]; + str_timestamp_ex(DemoItem.m_Date, aDate, sizeof(aDate), FORMAT_SPACE); + if(!Item.m_Selected) + TextRender()->TextColor(CUI::ms_TransparentTextColor); + UI()->DoLabel(&Button, aDate, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); } TextRender()->TextColor(CUI::ms_DefaultTextColor); if(Item.m_Selected) From 1d6714c138a2fe7e82c848ce60ea7aec812ba467 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 20 Sep 2020 13:38:06 +0100 Subject: [PATCH 433/479] prevent messages being processed before any snaps --- src/engine/shared/demo.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 552d925b..26d3a597 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -563,10 +563,9 @@ void CDemoPlayer::DoTick() m_Info.m_NextTick = ChunkTick; break; } - else if(ChunkType == CHUNKTYPE_MESSAGE) + else if(ChunkType == CHUNKTYPE_MESSAGE && m_pListener && m_LastSnapshotDataSize != -1) { - if(m_pListener) - m_pListener->OnDemoPlayerMessage(aData, DataSize); + m_pListener->OnDemoPlayerMessage(aData, DataSize); } } } From 71e83b1b8ac39effae43706c91213c4b923ce488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 20 Sep 2020 18:16:16 +0200 Subject: [PATCH 434/479] fix envelopes resetting to time 0 when demo/world paused --- src/game/client/components/maplayers.cpp | 67 ++++++++++-------------- src/game/client/components/maplayers.h | 1 - 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index ad9b5441..83160aac 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -24,7 +24,6 @@ CMapLayers::CMapLayers(int Type) m_Type = Type; m_CurrentLocalTick = 0; m_LastLocalTick = 0; - m_EnvelopeUpdate = false; m_pMenuMap = 0; m_pMenuLayers = 0; m_OnlineStartTime = 0; @@ -200,7 +199,6 @@ void CMapLayers::EnvelopeUpdate() const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); m_CurrentLocalTick = pInfo->m_CurrentTick; m_LastLocalTick = pInfo->m_CurrentTick; - m_EnvelopeUpdate = true; } } @@ -214,17 +212,15 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void CEnvPoint *pPoints = 0; CLayers *pLayers = 0; + if(pThis->Client()->State() == IClient::STATE_ONLINE || pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { - if(pThis->Client()->State() == IClient::STATE_ONLINE || pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - pLayers = pThis->Layers(); - pPoints = pThis->m_lEnvPoints.base_ptr(); - } - else - { - pLayers = pThis->m_pMenuLayers; - pPoints = pThis->m_lEnvPointsMenu.base_ptr(); - } + pLayers = pThis->Layers(); + pPoints = pThis->m_lEnvPoints.base_ptr(); + } + else + { + pLayers = pThis->m_pMenuLayers; + pPoints = pThis->m_lEnvPointsMenu.base_ptr(); } int Start, Num; @@ -233,60 +229,51 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void if(Env >= Num) return; - CMapItemEnvelope *pItem = (CMapItemEnvelope *)pLayers->Map()->GetItem(Start+Env, 0, 0); - - float Time = 0.0f; + const CMapItemEnvelope *pItem = (CMapItemEnvelope *)pLayers->Map()->GetItem(Start+Env, 0, 0); + const float TickSpeed = (float)pThis->Client()->GameTickSpeed(); + static float s_Time = 0.0f; if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); - - if(!pInfo->m_Paused || pThis->m_EnvelopeUpdate) + if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick) { - if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick) - { - pThis->m_LastLocalTick = pThis->m_CurrentLocalTick; - pThis->m_CurrentLocalTick = pInfo->m_CurrentTick; - } - - Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), - pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + pThis->m_LastLocalTick = pThis->m_CurrentLocalTick; + pThis->m_CurrentLocalTick = pInfo->m_CurrentTick; } - pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); + s_Time = mix( + pThis->m_LastLocalTick / TickSpeed, + pThis->m_CurrentLocalTick / TickSpeed, + pThis->Client()->IntraGameTick()); } - else if(pThis->Client()->State() != IClient::STATE_OFFLINE) + else if(pThis->Client()->State() == IClient::STATE_ONLINE) { if(pThis->m_pClient->m_Snap.m_pGameData && !pThis->m_pClient->IsWorldPaused()) { if(pItem->m_Version < 2 || pItem->m_Synchronized) { - Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(), - (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + s_Time = mix( + (pThis->Client()->PrevGameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / TickSpeed, + (pThis->Client()->GameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / TickSpeed, + pThis->Client()->IntraGameTick()); } else - Time = pThis->Client()->LocalTime()-pThis->m_OnlineStartTime; + s_Time = pThis->Client()->LocalTime() - pThis->m_OnlineStartTime; } - - pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); } else { - Time = pThis->Client()->LocalTime(); - pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); + s_Time = pThis->Client()->LocalTime(); } + pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); } void CMapLayers::OnRender() { - if((Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK && !m_pMenuMap)) - return; - CLayers *pLayers = 0; if(Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK) pLayers = Layers(); - else if(m_pMenuMap->IsLoaded()) + else if(m_pMenuMap && m_pMenuMap->IsLoaded()) pLayers = m_pMenuLayers; if(!pLayers) diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 46f94f83..5ec94862 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -14,7 +14,6 @@ class CMapLayers : public CComponent int m_CurrentLocalTick; int m_LastLocalTick; float m_OnlineStartTime; - bool m_EnvelopeUpdate; array m_lEnvPoints; array m_lEnvPointsMenu; From 84632420f0d33ed0f3d6bc419ce88d5e1500fc5c Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 20 Sep 2020 19:13:25 +0100 Subject: [PATCH 435/479] change wording of menu alpha settings --- src/game/client/components/menus_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d0e0b0d5..4b8a28c6 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1022,7 +1022,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); - DoScrollbarOption(&Config()->m_ClMenuAlpha, &Config()->m_ClMenuAlpha, &Button, Localize("Menu background transparency"), 0, 75); + DoScrollbarOption(&Config()->m_ClMenuAlpha, &Config()->m_ClMenuAlpha, &Button, Localize("Menu background opacity"), 0, 75); Client.HSplitTop(Spacing, 0, &Client); Client.HSplitTop(ButtonHeight, &Button, &Client); From c2d1d6079b21bad0ae7d81e48d539c0fce50e793 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Sun, 20 Sep 2020 23:47:41 +0100 Subject: [PATCH 436/479] merge player and tee settings --- src/game/client/components/camera.cpp | 2 +- src/game/client/components/camera.h | 2 +- src/game/client/components/menus.cpp | 36 +- src/game/client/components/menus.h | 10 +- src/game/client/components/menus_browser.cpp | 14 +- src/game/client/components/menus_settings.cpp | 346 +++++++++--------- 6 files changed, 217 insertions(+), 193 deletions(-) diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp index 63bb8f04..a13f5de0 100644 --- a/src/game/client/components/camera.cpp +++ b/src/game/client/components/camera.cpp @@ -25,7 +25,7 @@ CCamera::CCamera() m_Positions[POS_DEMOS] = vec2(1500.0f, 500.0f); m_Positions[POS_SETTINGS_GENERAL] = vec2(500.0f, 1000.0f); m_Positions[POS_SETTINGS_PLAYER] = vec2(600.0f, 1000.0f); - m_Positions[POS_SETTINGS_TEE] = vec2(700.0f, 1000.0f); + m_Positions[POS_SETTINGS_TBD] = vec2(700.0f, 1000.0f); m_Positions[POS_SETTINGS_CONTROLS] = vec2(800.0f, 1000.0f); m_Positions[POS_SETTINGS_GRAPHICS] = vec2(900.0f, 1000.0f); m_Positions[POS_SETTINGS_SOUND] = vec2(1000.0f, 1000.0f); diff --git a/src/game/client/components/camera.h b/src/game/client/components/camera.h index 06fc1683..95b21630 100644 --- a/src/game/client/components/camera.h +++ b/src/game/client/components/camera.h @@ -16,7 +16,7 @@ class CCamera : public CComponent POS_DEMOS, POS_SETTINGS_GENERAL, // order here should be the same like enum for settings pages in menu POS_SETTINGS_PLAYER, - POS_SETTINGS_TEE, + POS_SETTINGS_TBD, // TODO: change removed tee page to something else POS_SETTINGS_CONTROLS, POS_SETTINGS_GRAPHICS, POS_SETTINGS_SOUND, diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8cfb92a2..90257833 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -96,6 +96,8 @@ CMenus::CMenus() m_aFilterString[0] = 0; m_ActiveListBox = ACTLB_NONE; + + m_PopupSelection = -2; } float CMenus::CButtonContainer::GetFade(bool Checked, float Seconds) @@ -990,15 +992,17 @@ void CMenus::RenderMenubar(CUIRect Rect) } } + + // TODO: replace tee page to something else Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); { static CButtonContainer s_TeeButton; - if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_TEE, &Button, - Config()->m_UiSettingsPage == SETTINGS_TEE ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + if(DoButton_MenuTabTop(&s_TeeButton, Localize("TBD"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_TBD, &Button, + Config()->m_UiSettingsPage == SETTINGS_TBD ? 1.0f : NotActiveAlpha, 1.0f, Corners)) { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TEE); - Config()->m_UiSettingsPage = SETTINGS_TEE; + m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TBD); + Config()->m_UiSettingsPage = SETTINGS_TBD; } } @@ -1425,6 +1429,14 @@ void CMenus::PopupConfirm(const char *pTitle, const char *pMessage, const char * m_Popup = POPUP_CONFIRM; } +void CMenus::PopupCountry(int Selection, FPopupButtonCallback pfnOkButtonCallback) +{ + m_PopupSelection = Selection; + m_aPopupButtons[BUTTON_CONFIRM].m_NextPopup = POPUP_NONE; + m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback = pfnOkButtonCallback; + m_Popup = POPUP_COUNTRY; +} + int CMenus::Render() { @@ -1806,13 +1818,6 @@ int CMenus::Render() else if(m_Popup == POPUP_COUNTRY) { // selected filter - CBrowserFilter *pFilter = GetSelectedBrowserFilter(); - CServerFilterInfo FilterInfo; - pFilter->GetFilter(&FilterInfo); - - static int s_ActSelection = -2; - if(s_ActSelection == -2) - s_ActSelection = FilterInfo.m_Country; static CListBox s_ListBox; int OldSelected = -1; s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 12, 1, OldSelected, &Box, false); @@ -1822,7 +1827,7 @@ int CMenus::Render() const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->GetByIndex(i); if(pEntry->m_Blocked) continue; - if(pEntry->m_CountryCode == s_ActSelection) + if(pEntry->m_CountryCode == m_PopupSelection) OldSelected = i; CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); @@ -1858,21 +1863,20 @@ int CMenus::Render() const int NewSelected = s_ListBox.DoEnd(); if(OldSelected != NewSelected) - s_ActSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; + m_PopupSelection = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; Part.VMargin(120.0f, &Part); static CButtonContainer s_ButtonCountry; if(DoButton_Menu(&s_ButtonCountry, Localize("Ok"), 0, &BottomBar) || m_EnterPressed) { - FilterInfo.m_Country = s_ActSelection; - pFilter->SetFilter(&FilterInfo); + (this->*m_aPopupButtons[BUTTON_CONFIRM].m_pfnCallback)(); m_Popup = POPUP_NONE; } if(m_EscapePressed) { - s_ActSelection = FilterInfo.m_Country; + m_PopupSelection = -2; m_Popup = POPUP_NONE; } } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e070822b..6d8ac396 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -309,7 +309,7 @@ class CMenus : public CComponent SETTINGS_GENERAL=0, SETTINGS_PLAYER, - SETTINGS_TEE, + SETTINGS_TBD, // TODO: replace this removed tee page SETTINGS_CONTROLS, SETTINGS_GRAPHICS, SETTINGS_SOUND, @@ -331,6 +331,7 @@ class CMenus : public CComponent bool m_PrevCursorActive; bool m_PopupActive; int m_ActiveListBox; + int m_PopupSelection; bool m_SkinModified; bool m_KeyReaderWasActive; bool m_KeyReaderIsActive; @@ -340,7 +341,7 @@ class CMenus : public CComponent void DefaultButtonCallback() { /* do nothing */ }; enum { - BUTTON_CONFIRM = 0, // confirm / yes / close + BUTTON_CONFIRM = 0, // confirm / yes / close / ok BUTTON_CANCEL, // cancel / no NUM_BUTTONS }; @@ -359,6 +360,7 @@ class CMenus : public CComponent const char *pConfirmButtonLabel, const char *pCancelButtonLabel, FPopupButtonCallback pfnConfirmButtonCallback = &CMenus::DefaultButtonCallback, int ConfirmNextPopup = POPUP_NONE, FPopupButtonCallback pfnCancelButtonCallback = &CMenus::DefaultButtonCallback, int CancelNextPopup = POPUP_NONE); + void PopupCountry(int Selection, FPopupButtonCallback pfnOkButtonCallback = &CMenus::DefaultButtonCallback); // images struct CMenuImage @@ -804,6 +806,7 @@ class CMenus : public CComponent void RenderServerbrowserOverlay(); void RenderFilterHeader(CUIRect View, int FilterIndex); void PopupConfirmRemoveFilter(); + void PopupConfirmCountryFilter(); int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected, bool ShowServerInfo, CScrollRegion *pScroll = 0); void RenderServerbrowser(CUIRect MainView); static void ConchainConnect(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); @@ -824,7 +827,7 @@ class CMenus : public CComponent void RenderSkinPartPalette(CUIRect MainView); void RenderSettingsGeneral(CUIRect MainView); void RenderSettingsPlayer(CUIRect MainView); - void RenderSettingsTee(CUIRect MainView); + // void RenderSettingsTee(CUIRect MainView); void RenderSettingsTeeBasic(CUIRect MainView); void RenderSettingsTeeCustom(CUIRect MainView); void PopupConfirmDeleteSkin(); @@ -836,6 +839,7 @@ class CMenus : public CComponent void ResetSettingsControls(); void ResetSettingsGraphics(); void ResetSettingsSound(); + void PopupConfirmPlayerCountry(); bool DoResolutionList(CUIRect* pRect, CListBox* pListBox, const sorted_array& lModes); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 8af2771c..751af075 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -757,6 +757,18 @@ void CMenus::PopupConfirmRemoveFilter() } } +void CMenus::PopupConfirmCountryFilter() +{ + CBrowserFilter *pFilter = GetSelectedBrowserFilter(); + CServerFilterInfo FilterInfo; + pFilter->GetFilter(&FilterInfo); + + if(m_PopupSelection != -2) + FilterInfo.m_Country = m_PopupSelection; + + pFilter->SetFilter(&FilterInfo); +} + static void FormatScore(char *pBuf, int BufSize, bool TimeScore, const CServerInfo::CClient *pClient) { if(TimeScore) @@ -1967,7 +1979,7 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View) static int s_BrFilterCountryIndex = 0; if((FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) && UI()->DoButtonLogic(&s_BrFilterCountryIndex, &Rect)) - m_Popup = POPUP_COUNTRY; + PopupCountry(FilterInfo.m_Country, &CMenus::PopupConfirmCountryFilter); } // level diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d0e0b0d5..938866ca 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -65,21 +65,11 @@ bool CMenusKeyBinder::OnInput(IInput::CEvent Event) void CMenus::RenderHSLPicker(CUIRect MainView) { - CUIRect Label, Button, Picker; + CUIRect Label, Button, Picker, Sliders; // background float Spacing = 2.0f; - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - - // use custom color checkbox float ButtonHeight = 20.0f; - MainView.HSplitTop(ButtonHeight, &Button, &MainView); - static int s_CustomColors = 0; - if(DoButton_CheckBox(&s_CustomColors, Localize("Custom colors"), *CSkins::ms_apUCCVariables[m_TeePartSelected], &Button)) - { - *CSkins::ms_apUCCVariables[m_TeePartSelected] ^= 1; - m_SkinModified = true; - } if(!(*CSkins::ms_apUCCVariables[m_TeePartSelected])) return; @@ -97,7 +87,9 @@ void CMenus::RenderHSLPicker(CUIRect MainView) if(UseAlpha) Alp = (Color>>24)&0xff; - MainView.HSplitTop(144.0f, &Picker, &MainView); + + MainView.VSplitMid(&Picker, &Sliders, 5.0f); + float PickerSize = min(Picker.w, Picker.h) - 20.0f; RenderTools()->DrawUIRect(&Picker, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); float Dark = CSkins::DARKEST_COLOR_LGT/255.0f; @@ -105,8 +97,8 @@ void CMenus::RenderHSLPicker(CUIRect MainView) // Hue/Lgt picker : { - Picker.VMargin((Picker.w-128)/2.0f, &Picker); - Picker.HMargin((Picker.h-128.0f)/2.0f, &Picker); + Picker.VMargin((Picker.w-PickerSize)/2.0f, &Picker); + Picker.HMargin((Picker.h-PickerSize)/2.0f, &Picker); // picker Graphics()->TextureClear(); @@ -146,7 +138,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) Graphics()->QuadsEnd(); // marker - vec2 Marker = vec2(Sat/2.0f, Lgt/2.0f); + vec2 Marker = vec2(Sat/255.0f*PickerSize, Lgt/255.0f*PickerSize); Graphics()->TextureClear(); Graphics()->QuadsBegin(); Graphics()->SetColor(0.0f, 0.0f, 0.0f, 1.0f); @@ -167,33 +159,40 @@ void CMenus::RenderHSLPicker(CUIRect MainView) } } - MainView.HSplitTop(Spacing, 0, &MainView); - // H/S/L/A sliders : { int NumBars = UseAlpha ? 4 : 3; const char *const apNames[4] = {Localize("Hue:"), Localize("Sat:"), Localize("Lgt:"), Localize("Alp:")}; int *const apVars[4] = {&Hue, &Sat, &Lgt, &Alp}; static CButtonContainer s_aButtons[12]; + float SectionHeight = 40.0f; float SliderHeight = 16.0f; static const float s_aColorIndices[7][3] = {{1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}; for(int i = 0; i < NumBars; i++) { - CUIRect Bar; + CUIRect Bar, Section; + + Sliders.HSplitTop(SectionHeight, &Section, &Sliders); + Sliders.HSplitTop(Spacing, 0, &Sliders); + RenderTools()->DrawUIRect(&Section, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - MainView.HSplitTop(SliderHeight, &Label, &MainView); - MainView.HSplitTop(Spacing, 0, &MainView); + Section.HSplitTop(SectionHeight-SliderHeight, &Label, &Section); // label - RenderTools()->DrawUIRect(&Label, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Label.VSplitLeft((Label.w-160.0f)/2.0f, &Label, &Button); - Label.y += 2.0f; + Label.VSplitMid(&Label, &Button, 0.0f); + Label.y += 4.0f; UI()->DoLabel(&Label, apNames[i], SliderHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + // value label + char aBuf[16]; + str_format(aBuf, sizeof(aBuf), "%d", *apVars[i]); + Button.y += 4.0f; + UI()->DoLabel(&Button, aBuf, SliderHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + // button < - Button.VSplitLeft(Button.h, &Button, &Bar); + Section.VSplitLeft(SliderHeight, &Button, &Bar); if(DoButton_Menu(&s_aButtons[i*3], "<", 0, &Button, 0, CUI::CORNER_TL|CUI::CORNER_BL)) { *apVars[i] = max(0, *apVars[i]-1); @@ -201,11 +200,11 @@ void CMenus::RenderHSLPicker(CUIRect MainView) } // bar - Bar.VSplitLeft(128.0f, &Bar, &Button); + Bar.VSplitLeft(Section.w-SliderHeight*2, &Bar, &Button); int NumQuads = 1; - if( i == 0) + if(i == 0) NumQuads = 6; - else if ( i == 2) + else if(i == 2) NumQuads = 2; else NumQuads = 1; @@ -280,19 +279,13 @@ void CMenus::RenderHSLPicker(CUIRect MainView) Graphics()->QuadsEnd(); // button > - Button.VSplitLeft(Button.h, &Button, &Label); + Button.VSplitLeft(SliderHeight, &Button, &Label); if(DoButton_Menu(&s_aButtons[i*3+1], ">", 0, &Button, 0, CUI::CORNER_TR|CUI::CORNER_BR)) { *apVars[i] = min(255, *apVars[i]+1); Modified = true; } - // value label - char aBuf[16]; - str_format(aBuf, sizeof(aBuf), "%d", *apVars[i]); - Label.y += 2.0f; - UI()->DoLabel(&Label, aBuf, SliderHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - // logic float X; if(UI()->DoPickerLogic(&s_aButtons[i*3+2], &Bar, &X, 0)) @@ -1077,110 +1070,61 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) } } -void CMenus::RenderSettingsPlayer(CUIRect MainView) -{ - static int s_PlayerCountry = Config()->m_PlayerCountry; - static char s_aPlayerName[256] = {0}; - static char s_aPlayerClan[256] = {0}; - if(!s_aPlayerName[0]) - str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); - if(!s_aPlayerClan[0]) - str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); - - CUIRect Button, Left, Right, TopView, Label, Background; - - // render game menu backgrounds - float ButtonHeight = 20.0f; - float Spacing = 2.0f; - float BackgroundHeight = 2.0f*ButtonHeight+Spacing; - - MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings# - if(this->Client()->State() == IClient::STATE_ONLINE) - Background = MainView; - else - MainView.HSplitTop(20.0f, 0, &Background); - RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); - MainView.HSplitTop(20.0f, 0, &MainView); - MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); - RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - - // render game menu - TopView.HSplitTop(ButtonHeight, &Label, &TopView); - Label.y += 2.0f; - UI()->DoLabel(&Label, Localize("Personal"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - - // split menu - TopView.HSplitTop(Spacing, 0, &TopView); - TopView.VSplitMid(&Left, &Right, 3.0f); - - // left menu - Left.HSplitTop(ButtonHeight, &Button, &Left); - static float s_OffsetName = 0.0f; - DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); - - // right menu - Right.HSplitTop(ButtonHeight, &Button, &Right); - static float s_OffsetClan = 0.0f; - DoEditBoxOption(Config()->m_PlayerClan, Config()->m_PlayerClan, sizeof(Config()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); - - // country flag selector - MainView.HSplitTop(10.0f, 0, &MainView); - static CListBox s_ListBox; - int OldSelected = -1; - s_ListBox.DoHeader(&MainView, Localize("Country"), GetListHeaderHeight()); - s_ListBox.DoStart(40.0f, m_pClient->m_pCountryFlags->Num(), 18, 1, OldSelected); - - for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) - { - const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->GetByIndex(i); - if(pEntry->m_Blocked) - continue; - if(pEntry->m_CountryCode == Config()->m_PlayerCountry) - OldSelected = i; - - CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected == i); - if(Item.m_Visible) - { - CUIRect Label; - Item.m_Rect.Margin(5.0f, &Item.m_Rect); - Item.m_Rect.HSplitBottom(10.0f, &Item.m_Rect, &Label); - 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(); - - if(Item.m_Selected) - { - TextRender()->TextColor(CUI::ms_HighlightTextColor); - TextRender()->TextOutlineColor(CUI::ms_HighlightTextOutlineColor); - } - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, CUI::ALIGN_CENTER); - if(Item.m_Selected) - { - TextRender()->TextColor(CUI::ms_DefaultTextColor); - TextRender()->TextOutlineColor(CUI::ms_DefaultTextOutlineColor); - } - } - } - - const int NewSelected = s_ListBox.DoEnd(); - if(OldSelected != NewSelected) - Config()->m_PlayerCountry = m_pClient->m_pCountryFlags->GetByIndex(NewSelected, true)->m_CountryCode; - - - // check if the new settings require a server reload - m_NeedRestartPlayer = !( - s_PlayerCountry == Config()->m_PlayerCountry && - !str_comp(s_aPlayerClan, Config()->m_PlayerClan) && - !str_comp(s_aPlayerName, Config()->m_PlayerName) - ); -} +// void CMenus::RenderSettingsPlayer(CUIRect MainView) +// { +// static int s_PlayerCountry = Config()->m_PlayerCountry; +// static char s_aPlayerName[256] = {0}; +// static char s_aPlayerClan[256] = {0}; +// if(!s_aPlayerName[0]) +// str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); +// if(!s_aPlayerClan[0]) +// str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); + +// CUIRect Button, Left, Right, TopView, Label, Background; + +// // render game menu backgrounds +// float ButtonHeight = 20.0f; +// float Spacing = 2.0f; +// float BackgroundHeight = 2.0f*ButtonHeight+Spacing; + +// MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings# +// if(this->Client()->State() == IClient::STATE_ONLINE) +// Background = MainView; +// else +// MainView.HSplitTop(20.0f, 0, &Background); +// RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); +// MainView.HSplitTop(20.0f, 0, &MainView); +// MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); +// RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + +// // render game menu +// TopView.HSplitTop(ButtonHeight, &Label, &TopView); +// Label.y += 2.0f; +// UI()->DoLabel(&Label, Localize("Personal"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + +// // split menu +// TopView.HSplitTop(Spacing, 0, &TopView); +// TopView.VSplitMid(&Left, &Right, 3.0f); + + // // left menu + // Left.HSplitTop(ButtonHeight, &Button, &Left); + // static float s_OffsetName = 0.0f; + // DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); + + // // right menu + // Right.HSplitTop(ButtonHeight, &Button, &Right); + // static float s_OffsetClan = 0.0f; + // DoEditBoxOption(Config()->m_PlayerClan, Config()->m_PlayerClan, sizeof(Config()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); + +// // country flag selector + +// // check if the new settings require a server reload +// m_NeedRestartPlayer = !( +// s_PlayerCountry == Config()->m_PlayerCountry && +// !str_comp(s_aPlayerClan, Config()->m_PlayerClan) && +// !str_comp(s_aPlayerName, Config()->m_PlayerName) +// ); +// } void CMenus::RenderSettingsTeeBasic(CUIRect MainView) { @@ -1189,7 +1133,7 @@ void CMenus::RenderSettingsTeeBasic(CUIRect MainView) void CMenus::RenderSettingsTeeCustom(CUIRect MainView) { - CUIRect Label, Patterns, Button, Left, Right; + CUIRect Label, Patterns, Button, Left, Right, Picker, Palette; // render skin preview background float SpacingH = 2.0f; @@ -1226,19 +1170,40 @@ void CMenus::RenderSettingsTeeCustom(CUIRect MainView) // part selection RenderSkinPartSelection(Left); + // use custom color checkbox + Right.HSplitTop(ButtonHeight, &Button, &Right); + static bool s_CustomColors; + s_CustomColors = *CSkins::ms_apUCCVariables[m_TeePartSelected] == 1; + if(DoButton_CheckBox(&s_CustomColors, Localize("Custom colors"), s_CustomColors, &Button)) + { + *CSkins::ms_apUCCVariables[m_TeePartSelected] = s_CustomColors ? 0 : 1; + m_SkinModified = true; + } + // HSL picker - RenderHSLPicker(Right); - RenderSkinPartPalette(Right); + Right.HSplitBottom(45.0f, &Picker, &Palette); + if(s_CustomColors) + { + RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderHSLPicker(Picker); + RenderSkinPartPalette(Palette); + } } -void CMenus::RenderSettingsTee(CUIRect MainView) +void CMenus::RenderSettingsPlayer(CUIRect MainView) { static bool s_CustomSkinMenu = false; + static char s_aPlayerName[256] = {0}; + static char s_aPlayerClan[256] = {0}; static char s_aPlayerSkin[256] = {0}; + if(!s_aPlayerName[0]) + str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); + if(!s_aPlayerClan[0]) + str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); if(!s_aPlayerSkin[0]) str_copy(s_aPlayerSkin, Config()->m_PlayerSkin, sizeof(s_aPlayerSkin)); - CUIRect Button, Label, BottomView, Preview, Background; + CUIRect Button, Label, TopView, BottomView, Background, Left, Right; // cut view MainView.HSplitBottom(80.0f, &MainView, &BottomView); @@ -1249,7 +1214,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) const float SpacingW = 3.0f; const float ButtonHeight = 20.0f; const float SkinHeight = 50.0f; - const float BackgroundHeight = (ButtonHeight+SpacingH)*(s_CustomSkinMenu ? 1.0f : 2.0f) + SkinHeight; + const float BackgroundHeight = (ButtonHeight+SpacingH) + SkinHeight*2; if(this->Client()->State() == IClient::STATE_ONLINE) Background = MainView; @@ -1257,21 +1222,23 @@ void CMenus::RenderSettingsTee(CUIRect MainView) MainView.HSplitTop(20.0f, 0, &Background); RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); MainView.HSplitTop(20.0f, 0, &MainView); - MainView.HSplitTop(BackgroundHeight, &Preview, &MainView); - RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); + TopView.VSplitMid(&Left, &Right, 3.0f); + RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Preview.HSplitTop(ButtonHeight, &Label, &Preview); + Left.HSplitTop(ButtonHeight, &Label, &Left); Label.y += 2.0f; - UI()->DoLabel(&Label, Localize("Skin"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + UI()->DoLabel(&Label, Localize("Tee"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); // Preview { - CUIRect Left, Right; - Preview.HSplitTop(SpacingH, 0, &Preview); - Preview.HSplitTop(SkinHeight, &Left, &Preview); + CUIRect Top, Bottom, TeeLeft, TeeRight; + Left.HSplitTop(SpacingH, 0, &Left); + Left.HSplitTop(SkinHeight * 2, &Top, &Left); // split the menu in 2 parts - Left.VSplitMid(&Left, &Right, SpacingW); + Top.HSplitMid(&Top, &Bottom, SpacingH); // handle left @@ -1310,16 +1277,15 @@ void CMenus::RenderSettingsTee(CUIRect MainView) } // draw preview - RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&Top, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Left.VSplitMid(&Label, &Left); + Top.VSplitLeft(Top.w/3.0f+SpacingW/2.0f, &Label, &Top); Label.y += 17.0f; UI()->DoLabel(&Label, Localize("Normal:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - - RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Left.x+Left.w/2.0f, Left.y+Left.h/2.0f+2.0f)); + RenderTools()->DrawUIRect(&Top, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Top.x+Top.w/2.0f, Top.y+Top.h/2.0f+6.0f)); // handle right (team skins) @@ -1353,40 +1319,72 @@ void CMenus::RenderSettingsTee(CUIRect MainView) } // draw preview - RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&Bottom, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Right.VSplitLeft(Right.w/3.0f+SpacingW/2.0f, &Label, &Right); + Bottom.VSplitLeft(Bottom.w/3.0f+SpacingW/2.0f, &Label, &Bottom); Label.y += 17.0f; UI()->DoLabel(&Label, Localize("Team:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - Right.VSplitMid(&Left, &Right, SpacingW); + Bottom.VSplitMid(&TeeLeft, &TeeRight, SpacingW); - RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&TeeLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); for(int p = 0; p < NUM_SKINPARTS; p++) { int TeamColor = m_pClient->m_pSkins->GetTeamColor(aUCCVars[p], aColorVars[p], TEAM_RED, p); TeamSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_MARKING); } - RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(1, 0), vec2(Left.x+Left.w/2.0f, Left.y+Left.h/2.0f+2.0f)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(1, 0), vec2(TeeLeft.x+TeeLeft.w/2.0f, TeeLeft.y+TeeLeft.h/2.0f+6.0f)); - RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&TeeRight, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); for(int p = 0; p < NUM_SKINPARTS; p++) { int TeamColor = m_pClient->m_pSkins->GetTeamColor(aUCCVars[p], aColorVars[p], TEAM_BLUE, p); TeamSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_MARKING); } - RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(1, 0), vec2(Right.x+Right.w/2.0f, Right.y+Right.h/2.0f+2.0f)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(1, 0), vec2(TeeRight.x+TeeRight.w/2.0f, TeeRight.y+TeeRight.h/2.0f+6.0f)); } - if(!s_CustomSkinMenu) + Right.HSplitTop(ButtonHeight, &Label, &Right); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Personal"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + + // Personal { - Preview.HSplitTop(SpacingH, 0, &Preview); - RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Top, Bottom, Name, Clan, Flag; + Right.HSplitTop(SpacingH, 0, &Right); + Right.HSplitMid(&Top, &Bottom, SpacingH); + Top.HSplitMid(&Name, &Clan, SpacingH); - Preview.y += 2.0f; - UI()->DoLabel(&Preview, Config()->m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + // player name + Name.HSplitTop(ButtonHeight, &Button, &Name); + static float s_OffsetName = 0.0f; + DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); + + // player clan + Clan.HSplitTop(ButtonHeight, &Button, &Clan); + static float s_OffsetClan = 0.0f; + DoEditBoxOption(Config()->m_PlayerClan, Config()->m_PlayerClan, sizeof(Config()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); + + // country selector + RenderTools()->DrawUIRect(&Bottom, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Bottom.VSplitLeft(100.0f, &Label, &Button); + Label.y += 17.0f; + UI()->DoLabel(&Label, Localize("Country:"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); + + Button.w = (SkinHeight - 20.0f) * 2 + 20.0f; + RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + if(UI()->MouseHovered(&Button)) + RenderTools()->DrawUIRect(&Button, vec4(0.5f, 0.5f, 0.5f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Button.Margin(10.0f, &Flag); + vec4 Color = vec4(1,1,1,1); + m_pClient->m_pCountryFlags->Render(Config()->m_PlayerCountry, &Color, Flag.x, Flag.y, Flag.w, Flag.h); + + if(UI()->DoButtonLogic(&Config()->m_PlayerCountry, &Button)) + PopupCountry(Config()->m_PlayerCountry, &CMenus::PopupConfirmPlayerCountry); } MainView.HSplitTop(10.0f, 0, &MainView); @@ -2116,6 +2114,12 @@ void CMenus::ResetSettingsSound() UpdateMusicState(); } +void CMenus::PopupConfirmPlayerCountry() +{ + if(m_PopupSelection != -2) + Config()->m_PlayerCountry = m_PopupSelection; +} + void CMenus::RenderSettings(CUIRect MainView) { // handle which page should be rendered @@ -2123,8 +2127,8 @@ void CMenus::RenderSettings(CUIRect MainView) RenderSettingsGeneral(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_PLAYER) RenderSettingsPlayer(MainView); - else if(Config()->m_UiSettingsPage == SETTINGS_TEE) - RenderSettingsTee(MainView); + else if(Config()->m_UiSettingsPage == SETTINGS_TBD) {} + // RenderSettingsTee(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_CONTROLS) RenderSettingsControls(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_GRAPHICS) From aa816a315c9b79b10b0f9e8e4693fe66c4547ea2 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Mon, 21 Sep 2020 00:01:34 +0100 Subject: [PATCH 437/479] remove a unused variable --- src/game/client/components/menus_settings.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 938866ca..d343cd97 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -69,7 +69,6 @@ void CMenus::RenderHSLPicker(CUIRect MainView) // background float Spacing = 2.0f; - float ButtonHeight = 20.0f; if(!(*CSkins::ms_apUCCVariables[m_TeePartSelected])) return; From 0130b888ead01ee669a80ecc045619663bd0adff Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Mon, 21 Sep 2020 14:45:37 +0100 Subject: [PATCH 438/479] interactive elements --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_settings.cpp | 104 +++++++----------- src/game/client/gameclient.cpp | 1 + src/game/client/gameclient.h | 1 + 4 files changed, 41 insertions(+), 67 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 6d8ac396..517a4535 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -827,7 +827,7 @@ class CMenus : public CComponent void RenderSkinPartPalette(CUIRect MainView); void RenderSettingsGeneral(CUIRect MainView); void RenderSettingsPlayer(CUIRect MainView); - // void RenderSettingsTee(CUIRect MainView); + // void RenderSettingsTBD(CUIRect MainView); // TODO: change removed tee page to something else void RenderSettingsTeeBasic(CUIRect MainView); void RenderSettingsTeeCustom(CUIRect MainView); void PopupConfirmDeleteSkin(); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d343cd97..9476178c 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -311,6 +311,7 @@ void CMenus::RenderHSLPicker(CUIRect MainView) void CMenus::RenderSkinSelection(CUIRect MainView) { + static float s_LastSelectionTime = -10.0f; static sorted_array s_paSkinList; static CListBox s_ListBox; if(m_RefreshSkinSelector) @@ -365,7 +366,12 @@ void CMenus::RenderSkinSelection(CUIRect MainView) Info.m_Size = 50.0f; Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top - RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); + + { + // interactive tee: tee is happy to be selected + int TeeEmote = (Item.m_Selected && s_LastSelectionTime + 0.75f > Client()->LocalTime()) ? EMOTE_HAPPY : EMOTE_NORMAL; + RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, TeeEmote, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); + } CUIRect Label; Item.m_Rect.Margin(5.0f, &Item.m_Rect); @@ -388,6 +394,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) const int NewSelected = s_ListBox.DoEnd(); if(NewSelected != -1 && NewSelected != OldSelected) { + s_LastSelectionTime = Client()->LocalTime(); m_pSelectedSkin = s_paSkinList[NewSelected]; mem_copy(Config()->m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(Config()->m_PlayerSkin)); for(int p = 0; p < NUM_SKINPARTS; p++) @@ -1069,62 +1076,6 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) } } -// void CMenus::RenderSettingsPlayer(CUIRect MainView) -// { -// static int s_PlayerCountry = Config()->m_PlayerCountry; -// static char s_aPlayerName[256] = {0}; -// static char s_aPlayerClan[256] = {0}; -// if(!s_aPlayerName[0]) -// str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); -// if(!s_aPlayerClan[0]) -// str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); - -// CUIRect Button, Left, Right, TopView, Label, Background; - -// // render game menu backgrounds -// float ButtonHeight = 20.0f; -// float Spacing = 2.0f; -// float BackgroundHeight = 2.0f*ButtonHeight+Spacing; - -// MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings# -// if(this->Client()->State() == IClient::STATE_ONLINE) -// Background = MainView; -// else -// MainView.HSplitTop(20.0f, 0, &Background); -// RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, Config()->m_ClMenuAlpha/100.0f), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f); -// MainView.HSplitTop(20.0f, 0, &MainView); -// MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); -// RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - -// // render game menu -// TopView.HSplitTop(ButtonHeight, &Label, &TopView); -// Label.y += 2.0f; -// UI()->DoLabel(&Label, Localize("Personal"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER); - -// // split menu -// TopView.HSplitTop(Spacing, 0, &TopView); -// TopView.VSplitMid(&Left, &Right, 3.0f); - - // // left menu - // Left.HSplitTop(ButtonHeight, &Button, &Left); - // static float s_OffsetName = 0.0f; - // DoEditBoxOption(Config()->m_PlayerName, Config()->m_PlayerName, sizeof(Config()->m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); - - // // right menu - // Right.HSplitTop(ButtonHeight, &Button, &Right); - // static float s_OffsetClan = 0.0f; - // DoEditBoxOption(Config()->m_PlayerClan, Config()->m_PlayerClan, sizeof(Config()->m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); - -// // country flag selector - -// // check if the new settings require a server reload -// m_NeedRestartPlayer = !( -// s_PlayerCountry == Config()->m_PlayerCountry && -// !str_comp(s_aPlayerClan, Config()->m_PlayerClan) && -// !str_comp(s_aPlayerName, Config()->m_PlayerName) -// ); -// } - void CMenus::RenderSettingsTeeBasic(CUIRect MainView) { RenderSkinSelection(MainView); // yes thats all here ^^ @@ -1192,15 +1143,17 @@ void CMenus::RenderSettingsTeeCustom(CUIRect MainView) void CMenus::RenderSettingsPlayer(CUIRect MainView) { static bool s_CustomSkinMenu = false; + static int s_PlayerCountry = 0; static char s_aPlayerName[256] = {0}; static char s_aPlayerClan[256] = {0}; - static char s_aPlayerSkin[256] = {0}; - if(!s_aPlayerName[0]) + + if(m_pClient->m_IdentityState < 0) + { + s_PlayerCountry = Config()->m_PlayerCountry; str_copy(s_aPlayerName, Config()->m_PlayerName, sizeof(s_aPlayerName)); - if(!s_aPlayerClan[0]) str_copy(s_aPlayerClan, Config()->m_PlayerClan, sizeof(s_aPlayerClan)); - if(!s_aPlayerSkin[0]) - str_copy(s_aPlayerSkin, Config()->m_PlayerSkin, sizeof(s_aPlayerSkin)); + m_pClient->m_IdentityState = 0; + } CUIRect Button, Label, TopView, BottomView, Background, Left, Right; @@ -1214,6 +1167,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) const float ButtonHeight = 20.0f; const float SkinHeight = 50.0f; const float BackgroundHeight = (ButtonHeight+SpacingH) + SkinHeight*2; + const vec2 MousePosition = vec2(UI()->MouseX(), UI()->MouseY()); if(this->Client()->State() == IClient::STATE_ONLINE) Background = MainView; @@ -1284,7 +1238,17 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) RenderTools()->DrawUIRect(&Top, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Top.x+Top.w/2.0f, Top.y+Top.h/2.0f+6.0f)); + { + // interactive tee: tee looking towards cursor, and it is happy when you touch it + vec2 TeePosition = vec2(Top.x+Top.w/2.0f, Top.y+Top.h/2.0f+6.0f); + vec2 DeltaPosition = MousePosition - TeePosition; + float Distance = length(DeltaPosition); + vec2 TeeDirection = Distance < 20.0f ? normalize(vec2(DeltaPosition.x, max(DeltaPosition.y, 0.5f))) : normalize(DeltaPosition); + int TeeEmote = Distance < 20.0f ? EMOTE_HAPPY : EMOTE_NORMAL; + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, TeeEmote, TeeDirection, TeePosition); + if(Distance < 20.0f && UI()->MouseButtonClicked(0)) + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_PLAYER_SPAWN, 0); + } // handle right (team skins) @@ -1342,7 +1306,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) int TeamColor = m_pClient->m_pSkins->GetTeamColor(aUCCVars[p], aColorVars[p], TEAM_BLUE, p); TeamSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_MARKING); } - RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(1, 0), vec2(TeeRight.x+TeeRight.w/2.0f, TeeRight.y+TeeRight.h/2.0f+6.0f)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &TeamSkinInfo, 0, vec2(-1, 0), vec2(TeeRight.x+TeeRight.w/2.0f, TeeRight.y+TeeRight.h/2.0f+6.0f)); } Right.HSplitTop(ButtonHeight, &Label, &Right); @@ -1428,6 +1392,14 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) { s_CustomSkinMenu = !s_CustomSkinMenu; } + + // check if the new settings require a server reload + m_NeedRestartPlayer = !( + s_PlayerCountry == Config()->m_PlayerCountry && + !str_comp(s_aPlayerClan, Config()->m_PlayerClan) && + !str_comp(s_aPlayerName, Config()->m_PlayerName) + ); + m_pClient->m_IdentityState = m_NeedRestartPlayer ? 1 : 0; } void CMenus::PopupConfirmDeleteSkin() @@ -2126,8 +2098,8 @@ void CMenus::RenderSettings(CUIRect MainView) RenderSettingsGeneral(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_PLAYER) RenderSettingsPlayer(MainView); - else if(Config()->m_UiSettingsPage == SETTINGS_TBD) {} - // RenderSettingsTee(MainView); + else if(Config()->m_UiSettingsPage == SETTINGS_TBD) {} // TODO: replace removed tee page to something else + // RenderSettingsTBD(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_CONTROLS) RenderSettingsControls(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_GRAPHICS) diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 31172ee5..ee35184b 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -490,6 +490,7 @@ void CGameClient::OnReset() m_TeamCooldownTick = 0; m_TeamChangeTime = 0.0f; m_LastSkinChangeTime = Client()->LocalTime(); + m_IdentityState = -1; mem_zero(&m_GameInfo, sizeof(m_GameInfo)); m_DemoSpecMode = SPEC_FREEVIEW; m_DemoSpecID = -1; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index d3ee597e..4d78e062 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -232,6 +232,7 @@ class CGameClient : public IGameClient float m_TeamChangeTime; bool m_IsXmasDay; float m_LastSkinChangeTime; + int m_IdentityState; bool m_IsEasterDay; bool m_InitComplete; From 301fcad076bbca1f95b3414b178e635c0f2d6d26 Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Mon, 21 Sep 2020 15:18:29 +0100 Subject: [PATCH 439/479] remove tbd tab --- src/game/client/components/menus.cpp | 29 ++++++++++--------- src/game/client/components/menus_settings.cpp | 4 +-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 90257833..9d8084bc 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -901,8 +901,9 @@ void CMenus::RenderMenubar(CUIRect Rect) if(Client()->State() == IClient::STATE_ONLINE) { + int NumButtons = 6; float Spacing = 3.0f; - float ButtonWidth = (Box.w / 6.0f) - (Spacing*5.0) / 6.0f; + float ButtonWidth = (Box.w / NumButtons) - (Spacing*5.0) / NumButtons; float Alpha = 1.0f; if(m_GamePage == PAGE_SETTINGS) Alpha = InactiveAlpha; @@ -960,8 +961,9 @@ void CMenus::RenderMenubar(CUIRect Rect) if((Client()->State() == IClient::STATE_OFFLINE && m_MenuPage == PAGE_SETTINGS) || (Client()->State() == IClient::STATE_ONLINE && m_GamePage == PAGE_SETTINGS)) { + int NumButtons = 5; float Spacing = 3.0f; - float ButtonWidth = (Box.w/6.0f)-(Spacing*5.0)/6.0f; + float ButtonWidth = (Box.w/NumButtons)-(Spacing*5.0)/NumButtons; float NotActiveAlpha = Client()->State() == IClient::STATE_ONLINE ? 0.5f : 1.0f; int Corners = Client()->State() == IClient::STATE_ONLINE ? CUI::CORNER_T : CUI::CORNER_ALL; @@ -994,18 +996,17 @@ void CMenus::RenderMenubar(CUIRect Rect) // TODO: replace tee page to something else - Box.VSplitLeft(Spacing, 0, &Box); // little space - Box.VSplitLeft(ButtonWidth, &Button, &Box); - { - static CButtonContainer s_TeeButton; - if(DoButton_MenuTabTop(&s_TeeButton, Localize("TBD"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_TBD, &Button, - Config()->m_UiSettingsPage == SETTINGS_TBD ? 1.0f : NotActiveAlpha, 1.0f, Corners)) - { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TBD); - Config()->m_UiSettingsPage = SETTINGS_TBD; - } - } - + // Box.VSplitLeft(Spacing, 0, &Box); // little space + // Box.VSplitLeft(ButtonWidth, &Button, &Box); + // { + // static CButtonContainer s_TeeButton; + // if(DoButton_MenuTabTop(&s_TeeButton, Localize("TBD"), Client()->State() == IClient::STATE_OFFLINE && Config()->m_UiSettingsPage == SETTINGS_TBD, &Button, + // Config()->m_UiSettingsPage == SETTINGS_TBD ? 1.0f : NotActiveAlpha, 1.0f, Corners)) + // { + // m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TBD); + // Config()->m_UiSettingsPage = SETTINGS_TBD; + // } + // } Box.VSplitLeft(Spacing, 0, &Box); // little space Box.VSplitLeft(ButtonWidth, &Button, &Box); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 9476178c..02fb2738 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -2098,8 +2098,8 @@ void CMenus::RenderSettings(CUIRect MainView) RenderSettingsGeneral(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_PLAYER) RenderSettingsPlayer(MainView); - else if(Config()->m_UiSettingsPage == SETTINGS_TBD) {} // TODO: replace removed tee page to something else - // RenderSettingsTBD(MainView); + else if(Config()->m_UiSettingsPage == SETTINGS_TBD) // TODO: replace removed tee page to something else + Config()->m_UiSettingsPage = SETTINGS_PLAYER; // TODO: remove this else if(Config()->m_UiSettingsPage == SETTINGS_CONTROLS) RenderSettingsControls(MainView); else if(Config()->m_UiSettingsPage == SETTINGS_GRAPHICS) From 8f6d85a61ad896c076ef379bf80f3c0167c00e8c Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 25 Mar 2020 18:54:16 +0300 Subject: [PATCH 440/479] cherrypick: Add the dates in --- src/base/system.c | 79 +++++++------------ src/base/system.h | 20 ++++- src/engine/server/server.cpp | 2 +- src/engine/server/server.h | 2 +- src/engine/shared/filecollection.cpp | 2 +- src/engine/shared/filecollection.h | 2 +- src/engine/shared/storage.cpp | 10 ++- src/engine/storage.h | 1 + src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 10 +-- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 2 +- src/game/client/components/menus_settings.cpp | 4 +- src/game/client/components/skins.cpp | 4 +- src/game/client/components/skins.h | 6 +- src/game/editor/editor.cpp | 2 +- 16 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index baccf47b..8a019c9d 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1474,59 +1474,21 @@ int net_init() return 0; } - -int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user) +#if defined (CONF_FAMILY_WINDOWS) +static inline time_t filetime_to_unixtime(LPFILETIME filetime) { -#if defined(CONF_FAMILY_WINDOWS) - WIN32_FIND_DATA finddata; - HANDLE handle; - char buffer[1024*2]; - int length; - str_format(buffer, sizeof(buffer), "%s/*", dir); - - handle = FindFirstFileA(buffer, &finddata); - - if(handle == INVALID_HANDLE_VALUE) - return 0; - - str_format(buffer, sizeof(buffer), "%s/", dir); - length = str_length(buffer); - - /* add all the entries */ - do - { - str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); - if(cb(finddata.cFileName, fs_getmtime(buffer), fs_is_dir(buffer), type, user)) - break; - } - while (FindNextFileA(handle, &finddata)); - - FindClose(handle); - return 0; -#else - struct dirent *entry; - char buffer[1024*2]; - int length; - DIR *d = opendir(dir); - - if(!d) - return 0; - - str_format(buffer, sizeof(buffer), "%s/", dir); - length = str_length(buffer); + time_t t; + ULARGE_INTEGER li; + li.LowPart = filetime.dwLowDateTime; + li.HighPart = filetime.dwHighDateTime; - while((entry = readdir(d)) != NULL) - { - str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); - if(cb(entry->d_name, fs_getmtime(buffer), fs_is_dir(buffer), type, user)) - break; - } + li.QuadPart /= 10000000; // 100ns to 1s + li.QuadPart -= 11644473600LL; // Windows epoch is in the past - /* close the directory and return */ - closedir(d); - return 0; -#endif + t = li.QuadPart; + return t == li.QuadPart ? t : (time_t)-1; } +#endif void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) { @@ -1549,7 +1511,8 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) do { str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); - if(cb(finddata.cFileName, fs_is_dir(buffer), type, user)) + if(cb(finddata.cFileName, fs_is_dir(buffer), type, filetime_to_unixtime(finddata.ftCreationTime), + filetime_to_unixtime(ftLastWriteTime), user)) break; } while (FindNextFileA(handle, &finddata)); @@ -1558,6 +1521,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) return; #else struct dirent *entry; + time_t created, modified; char buffer[1024*2]; int length; DIR *d = opendir(dir); @@ -1571,7 +1535,8 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) while((entry = readdir(d)) != NULL) { str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); - if(cb(entry->d_name, fs_is_dir(buffer), type, user)) + fs_file_time(buffer, &created, &modified); + if(cb(entry->d_name, fs_is_dir(buffer), type, created, modified, user)) break; } @@ -1795,6 +1760,18 @@ char *fs_read_str(const char *name) return result; } +int fs_file_time(const char *name, time_t *created, time_t *modified) +{ + struct stat sb; + if(stat(name, &sb)) + return 1; + + *created = sb.st_ctime; + *modified = sb.st_mtime; + + return 0; +} + void swap_endian(void *data, unsigned elem_size, unsigned num) { char *src = (char*) data; diff --git a/src/base/system.h b/src/base/system.h index e27dcbf7..b685fc23 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1333,7 +1333,8 @@ int str_span(const char *str, const char *set); type - Type of the directory user - Pointer to give to the callback */ -typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, void *user); +typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, + time_t created, time_t modified, void *user); void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user); @@ -1500,6 +1501,23 @@ int fs_read(const char *name, void **result, unsigned *result_len); */ char *fs_read_str(const char *name); +/* + Function: fs_file_time + Gets the creation and the last modification date of a file. + + Parameters: + name - The filename. + created - Pointer to time_t + modified - Pointer to time_t + + Returns: + 0 on success non-zero on failure + + Remarks: + - Returned time is in seconds since UNIX Epoch +*/ +int fs_file_time(const char *name, time_t *created, time_t *modified); + /* Group: Undocumented */ diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 99d9d8ef..29819e9e 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1491,7 +1491,7 @@ int CServer::Run() return 0; } -int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser) +int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, time_t, time_t, void *pUser) { CSubdirCallbackUserdata *pUserdata = (CSubdirCallbackUserdata *)pUser; CServer *pThis = pUserdata->m_pServer; diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 2f7c82f3..a017f8f9 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -259,7 +259,7 @@ class CServer : public IServer void InitInterfaces(CConfig *pConfig, IConsole *pConsole, IGameServer *pGameServer, IEngineMap *pMap, IStorage *pStorage); int Run(); - static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser); + static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, time_t, time_t, void *pUser); static void ConKick(IConsole::IResult *pResult, void *pUser); static void ConStatus(IConsole::IResult *pResult, void *pUser); diff --git a/src/engine/shared/filecollection.cpp b/src/engine/shared/filecollection.cpp index 9a0ed2ca..6efed62e 100644 --- a/src/engine/shared/filecollection.cpp +++ b/src/engine/shared/filecollection.cpp @@ -168,7 +168,7 @@ void CFileCollection::AddEntry(int64 Timestamp) } } -int CFileCollection::FilelistCallback(const char *pFilename, int IsDir, int StorageType, void *pUser) +int CFileCollection::FilelistCallback(const char *pFilename, int IsDir, int StorageType, time_t, time_t, void *pUser) { CFileCollection *pThis = static_cast(pUser); diff --git a/src/engine/shared/filecollection.h b/src/engine/shared/filecollection.h index 47206c24..d5b6907f 100644 --- a/src/engine/shared/filecollection.h +++ b/src/engine/shared/filecollection.h @@ -29,7 +29,7 @@ class CFileCollection void Init(IStorage *pStorage, const char *pPath, const char *pFileDesc, const char *pFileExt, int MaxEntries); void AddEntry(int64 Timestamp); - static int FilelistCallback(const char *pFilename, int IsDir, int StorageType, void *pUser); + static int FilelistCallback(const char *pFilename, int IsDir, int StorageType, time_t, time_t, void *pUser); }; #endif diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 0e437d85..8abdc842 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -432,7 +432,7 @@ class CStorage : public IStorage bool m_CheckHashAndSize; }; - static int FindFileCallback(const char *pName, int IsDir, int Type, void *pUser) + static int FindFileCallback(const char *pName, int IsDir, int Type, time_t, time_t, void *pUser) { CFindCBData Data = *static_cast(pUser); if(IsDir) @@ -600,6 +600,14 @@ class CStorage : public IStorage return true; } + virtual bool GetFileTime(const char *pFilename, int StorageType, time_t *pCreated, time_t *pModified) + { + char aBuf[MAX_PATH_LENGTH]; + GetCompletePath(StorageType, pFilename, aBuf, sizeof(aBuf)); + + return !fs_file_time(aBuf, pCreated, pModified); + } + static IStorage *Create(const char *pApplicationName, int StorageType, int NumArgs, const char **ppArguments) { CStorage *p = new CStorage(); diff --git a/src/engine/storage.h b/src/engine/storage.h index 6f2baf14..6d5bf578 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -34,6 +34,7 @@ class IStorage : public IInterface virtual bool CreateFolder(const char *pFoldername, int Type) = 0; virtual void GetCompletePath(int Type, const char *pDir, char *pBuffer, unsigned BufferSize) = 0; virtual bool GetHashAndSize(const char *pFilename, int StorageType, SHA256_DIGEST *pSha256, unsigned *pCrc, unsigned *pSize) = 0; + virtual bool GetFileTime(const char *pFilename, int StorageType, time_t *pCreated, time_t *pModified) = 0; }; IStorage *CreateStorage(const char *pApplicationName, int StorageType, int NumArgs, const char **ppArguments); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index b104d79e..a28d2263 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1225,7 +1225,7 @@ void CMenus::RenderBackButton(CUIRect MainView) } } -int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(IsDir || !str_endswith(pName, ".png")) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index be5eee68..4f137e89 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -373,7 +373,7 @@ class CMenus : public CComponent }; array m_lMenuImages; - static int MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser); + static int MenuImageScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); const CMenuImage *FindMenuImage(const char* pName); @@ -392,8 +392,8 @@ class CMenus : public CComponent }; sorted_array m_lThemes; - static int ThemeScan(const char *pName, int IsDir, int DirType, void *pUser); - static int ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser); + static int ThemeScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int ThemeIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); // gametype icons class CGameIcon @@ -413,7 +413,7 @@ class CMenus : public CComponent array m_lGameIcons; IGraphics::CTextureHandle m_GameIconDefault; void DoGameIcon(const char *pName, const CUIRect *pRect); - static int GameIconScan(const char *pName, int IsDir, int DirType, void *pUser); + static int GameIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); int64 m_LastInput; @@ -551,7 +551,7 @@ class CMenus : public CComponent void DemolistOnUpdate(bool Reset); void DemolistPopulate(); - static int DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser); + static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser); // friends class CFriendItem diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 751af075..d8419731 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2312,7 +2312,7 @@ void CMenus::DoGameIcon(const char *pName, const CUIRect *pRect) Graphics()->QuadsEnd(); } -int CMenus::GameIconScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::GameIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".png"); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 8ce01db8..4c8e6a19 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -349,7 +349,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } -int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser) +int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(str_comp(pName, ".") == 0 diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 08d0a941..71f83577 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -556,7 +556,7 @@ class CLanguage }; -int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".map"); @@ -607,7 +607,7 @@ int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser) return 0; } -int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser) +int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".png"); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index fc3b08ac..1d2ea731 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -25,7 +25,7 @@ int *CSkins::ms_apColorVariables[NUM_SKINPARTS] = {0}; const float MIN_EYE_BODY_COLOR_DIST = 80.f; // between body and eyes (LAB color space) -int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) +int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { CSkins *pSelf = (CSkins *)pUser; if(IsDir || !str_endswith(pName, ".png")) @@ -103,7 +103,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) return 0; } -int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) +int CSkins::SkinScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) { if(IsDir || !str_endswith(pName, ".json")) return 0; diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index c28ebf41..956cac4c 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -16,7 +16,7 @@ class CSkins : public CComponent SKINFLAG_STANDARD=1<<1, DARKEST_COLOR_LGT=61, - + NUM_COLOR_COMPONENTS=4, HAT_NUM=2, @@ -83,8 +83,8 @@ class CSkins : public CComponent sorted_array m_aSkins; CSkin m_DummySkin; - static int SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser); - static int SkinScan(const char *pName, int IsDir, int DirType, void *pUser); + static int SkinPartScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int SkinScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); }; #endif diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 31725f48..bb2c8827 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3008,7 +3008,7 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) } -static int EditorListdirCallback(const char *pName, int IsDir, int StorageType, void *pUser) +static int EditorListdirCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser) { CEditor *pEditor = (CEditor*)pUser; const char *pExt = 0; From dbba12cba2d7baf41b99a44471e84e84aa9f347c Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 25 Mar 2020 19:26:52 +0300 Subject: [PATCH 441/479] Fix windows build --- src/base/system.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 8a019c9d..24032964 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1479,8 +1479,8 @@ static inline time_t filetime_to_unixtime(LPFILETIME filetime) { time_t t; ULARGE_INTEGER li; - li.LowPart = filetime.dwLowDateTime; - li.HighPart = filetime.dwHighDateTime; + li.LowPart = filetime->dwLowDateTime; + li.HighPart = filetime->dwHighDateTime; li.QuadPart /= 10000000; // 100ns to 1s li.QuadPart -= 11644473600LL; // Windows epoch is in the past @@ -1511,8 +1511,8 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) do { str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); - if(cb(finddata.cFileName, fs_is_dir(buffer), type, filetime_to_unixtime(finddata.ftCreationTime), - filetime_to_unixtime(ftLastWriteTime), user)) + if(cb(finddata.cFileName, fs_is_dir(buffer), type, filetime_to_unixtime(&finddata.ftCreationTime), + filetime_to_unixtime(&ftLastWriteTime), user)) break; } while (FindNextFileA(handle, &finddata)); @@ -1762,12 +1762,24 @@ char *fs_read_str(const char *name) int fs_file_time(const char *name, time_t *created, time_t *modified) { +#if defined(CONF_FAMILY_WINDOWS) + WIN32_FIND_DATA finddata; + HANDLE handle = FindFirstFile(name, finddata); + if(handle == INVALID_HANDLE_VALUE) + return 1; + + *created = filetime_to_unixtime(&finddata.ftCreationTime); + *modified = filetime_to_unixtime(&finddata.ftWriteTime); +#elif defined(CONF_FAMILY_UNIX) struct stat sb; if(stat(name, &sb)) return 1; *created = sb.st_ctime; *modified = sb.st_mtime; +#else + #error not implemented +#endif return 0; } From 008747f60792d93e1263343d453a097e95349510 Mon Sep 17 00:00:00 2001 From: LordSk Date: Sat, 28 Mar 2020 17:07:34 +0100 Subject: [PATCH 442/479] cherrypick: Added a separate file listing function since we use the additional info only in the editor --- src/base/system.c | 74 +++++++++++++++++-- src/base/system.h | 25 ++++++- src/engine/server/server.cpp | 2 +- src/engine/server/server.h | 2 +- src/engine/shared/filecollection.cpp | 2 +- src/engine/shared/filecollection.h | 2 +- src/engine/shared/storage.cpp | 10 +-- src/engine/storage.h | 2 +- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus.h | 10 +-- src/game/client/components/menus_browser.cpp | 2 +- src/game/client/components/menus_demo.cpp | 7 +- src/game/client/components/menus_settings.cpp | 4 +- src/game/client/components/skins.cpp | 4 +- src/game/client/components/skins.h | 4 +- src/game/editor/editor.cpp | 2 +- 16 files changed, 118 insertions(+), 36 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 24032964..5bc16612 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1511,8 +1511,66 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) do { str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); - if(cb(finddata.cFileName, fs_is_dir(buffer), type, filetime_to_unixtime(&finddata.ftCreationTime), - filetime_to_unixtime(&ftLastWriteTime), user)) + if(cb(finddata.cFileName, fs_is_dir(buffer), type, user)) + break; + } + while (FindNextFileA(handle, &finddata)); + + FindClose(handle); + return; +#else + struct dirent *entry; + char buffer[1024*2]; + int length; + DIR *d = opendir(dir); + + if(!d) + return; + + str_format(buffer, sizeof(buffer), "%s/", dir); + length = str_length(buffer); + + while((entry = readdir(d)) != NULL) + { + str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); + if(cb(entry->d_name, fs_is_dir(buffer), type, user)) + break; + } + + /* close the directory and return */ + closedir(d); + return; +#endif +} + +void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void* user) +{ +#if defined(CONF_FAMILY_WINDOWS) + WIN32_FIND_DATA finddata; + HANDLE handle; + char buffer[1024*2]; + int length; + str_format(buffer, sizeof(buffer), "%s/*", dir); + + handle = FindFirstFileA(buffer, &finddata); + + if (handle == INVALID_HANDLE_VALUE) + return; + + str_format(buffer, sizeof(buffer), "%s/", dir); + length = str_length(buffer); + + /* add all the entries */ + do + { + str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length); + + CFsFileInfo info; + info.m_pName = finddata.cFileName; + info.m_TimeCreated = filetime_to_unixtime(&finddata.ftCreationTime); + info.m_TimeModified = filetime_to_unixtime(&finddata.ftLastWriteTime); + + if(cb(&info, fs_is_dir(buffer), type, user)) break; } while (FindNextFileA(handle, &finddata)); @@ -1536,7 +1594,13 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) { str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); fs_file_time(buffer, &created, &modified); - if(cb(entry->d_name, fs_is_dir(buffer), type, created, modified, user)) + + CFsFileInfo info; + info.m_pName = finddata.cFileName; + info.m_TimeCreated = created; + info.m_TimeModified = modified; + + if(cb(&info, fs_is_dir(buffer), type, user)) break; } @@ -1764,12 +1828,12 @@ int fs_file_time(const char *name, time_t *created, time_t *modified) { #if defined(CONF_FAMILY_WINDOWS) WIN32_FIND_DATA finddata; - HANDLE handle = FindFirstFile(name, finddata); + HANDLE handle = FindFirstFile(name, &finddata); if(handle == INVALID_HANDLE_VALUE) return 1; *created = filetime_to_unixtime(&finddata.ftCreationTime); - *modified = filetime_to_unixtime(&finddata.ftWriteTime); + *modified = filetime_to_unixtime(&finddata.ftLastWriteTime); #elif defined(CONF_FAMILY_UNIX) struct stat sb; if(stat(name, &sb)) diff --git a/src/base/system.h b/src/base/system.h index b685fc23..66631768 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1333,13 +1333,30 @@ int str_span(const char *str, const char *set); type - Type of the directory user - Pointer to give to the callback */ -typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, - time_t created, time_t modified, void *user); +typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, void *user); void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user); +typedef struct +{ + const char* m_pName; + time_t m_TimeCreated; // seconds since UNIX Epoch + time_t m_TimeModified; // seconds since UNIX Epoch +} CFsFileInfo; + +/* Group: Filesystem */ + +/* + Function: fs_listdir_fileinfo + Lists the files in a directory and gets additional file information -typedef int (*FS_LISTDIR_INFO_CALLBACK)(const char *name, time_t date, int is_dir, int dir_type, void *user); -int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user); + Parameters: + dir - Directory to list + cb - Callback function to call for each entry + type - Type of the directory + user - Pointer to give to the callback +*/ +typedef int (*FS_LISTDIR_CALLBACK_FILEINFO)(const CFsFileInfo* info, int is_dir, int dir_type, void *user); +void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user); /* Function: fs_makedir diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 29819e9e..99d9d8ef 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1491,7 +1491,7 @@ int CServer::Run() return 0; } -int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, time_t, time_t, void *pUser) +int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser) { CSubdirCallbackUserdata *pUserdata = (CSubdirCallbackUserdata *)pUser; CServer *pThis = pUserdata->m_pServer; diff --git a/src/engine/server/server.h b/src/engine/server/server.h index a017f8f9..2f7c82f3 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -259,7 +259,7 @@ class CServer : public IServer void InitInterfaces(CConfig *pConfig, IConsole *pConsole, IGameServer *pGameServer, IEngineMap *pMap, IStorage *pStorage); int Run(); - static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, time_t, time_t, void *pUser); + static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser); static void ConKick(IConsole::IResult *pResult, void *pUser); static void ConStatus(IConsole::IResult *pResult, void *pUser); diff --git a/src/engine/shared/filecollection.cpp b/src/engine/shared/filecollection.cpp index 6efed62e..9a0ed2ca 100644 --- a/src/engine/shared/filecollection.cpp +++ b/src/engine/shared/filecollection.cpp @@ -168,7 +168,7 @@ void CFileCollection::AddEntry(int64 Timestamp) } } -int CFileCollection::FilelistCallback(const char *pFilename, int IsDir, int StorageType, time_t, time_t, void *pUser) +int CFileCollection::FilelistCallback(const char *pFilename, int IsDir, int StorageType, void *pUser) { CFileCollection *pThis = static_cast(pUser); diff --git a/src/engine/shared/filecollection.h b/src/engine/shared/filecollection.h index d5b6907f..47206c24 100644 --- a/src/engine/shared/filecollection.h +++ b/src/engine/shared/filecollection.h @@ -29,7 +29,7 @@ class CFileCollection void Init(IStorage *pStorage, const char *pPath, const char *pFileDesc, const char *pFileExt, int MaxEntries); void AddEntry(int64 Timestamp); - static int FilelistCallback(const char *pFilename, int IsDir, int StorageType, time_t, time_t, void *pUser); + static int FilelistCallback(const char *pFilename, int IsDir, int StorageType, void *pUser); }; #endif diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 8abdc842..c271c407 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -307,19 +307,19 @@ class CStorage : public IStorage } } - virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser) + virtual void ListDirectoryFileInfo(int Type, const char *pPath, FS_LISTDIR_CALLBACK_FILEINFO pfnCallback, void *pUser) { char aBuffer[IO_MAX_PATH_LENGTH]; if(Type == TYPE_ALL) { // list all available directories for(int i = 0; i < m_NumPaths; ++i) - fs_listdir_info(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser); + fs_listdir_fileinfo(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser); } else if(Type >= 0 && Type < m_NumPaths) { // list wanted directory - fs_listdir_info(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser); + fs_listdir_fileinfo(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser); } } @@ -432,7 +432,7 @@ class CStorage : public IStorage bool m_CheckHashAndSize; }; - static int FindFileCallback(const char *pName, int IsDir, int Type, time_t, time_t, void *pUser) + static int FindFileCallback(const char *pName, int IsDir, int Type, void *pUser) { CFindCBData Data = *static_cast(pUser); if(IsDir) @@ -602,7 +602,7 @@ class CStorage : public IStorage virtual bool GetFileTime(const char *pFilename, int StorageType, time_t *pCreated, time_t *pModified) { - char aBuf[MAX_PATH_LENGTH]; + char aBuf[IO_MAX_PATH_LENGTH]; GetCompletePath(StorageType, pFilename, aBuf, sizeof(aBuf)); return !fs_file_time(aBuf, pCreated, pModified); diff --git a/src/engine/storage.h b/src/engine/storage.h index 6d5bf578..1d764127 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -23,7 +23,7 @@ class IStorage : public IInterface typedef bool(*FCheckCallback)(IOHANDLE Handle, const void *pUserData); virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0; - virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser) = 0; + virtual void ListDirectoryFileInfo(int Type, const char *pPath, FS_LISTDIR_CALLBACK_FILEINFO pfnCallback, void *pUser) = 0; virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0, FCheckCallback pfnCheckCB = 0, const void *pCheckCBData = 0) = 0; virtual bool ReadFile(const char *pFilename, int Type, void **ppResult, unsigned *pResultLen) = 0; virtual char *ReadFileStr(const char *pFilename, int Type) = 0; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index a28d2263..b104d79e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1225,7 +1225,7 @@ void CMenus::RenderBackButton(CUIRect MainView) } } -int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; if(IsDir || !str_endswith(pName, ".png")) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 4f137e89..297762d9 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -373,7 +373,7 @@ class CMenus : public CComponent }; array m_lMenuImages; - static int MenuImageScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser); const CMenuImage *FindMenuImage(const char* pName); @@ -392,8 +392,8 @@ class CMenus : public CComponent }; sorted_array m_lThemes; - static int ThemeScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); - static int ThemeIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int ThemeScan(const char *pName, int IsDir, int DirType, void *pUser); + static int ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser); // gametype icons class CGameIcon @@ -413,7 +413,7 @@ class CMenus : public CComponent array m_lGameIcons; IGraphics::CTextureHandle m_GameIconDefault; void DoGameIcon(const char *pName, const CUIRect *pRect); - static int GameIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int GameIconScan(const char *pName, int IsDir, int DirType, void *pUser); int64 m_LastInput; @@ -551,7 +551,7 @@ class CMenus : public CComponent void DemolistOnUpdate(bool Reset); void DemolistPopulate(); - static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser); + static int DemolistFetchCallback(const CFsFileInfo* pFileInfo, int IsDir, int StorageType, void *pUser); // friends class CFriendItem diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index d8419731..751af075 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2312,7 +2312,7 @@ void CMenus::DoGameIcon(const char *pName, const CUIRect *pRect) Graphics()->QuadsEnd(); } -int CMenus::GameIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CMenus::GameIconScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".png"); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 4c8e6a19..5fb4560a 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -349,9 +349,10 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } -int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser) +int CMenus::DemolistFetchCallback(const CFsFileInfo* pFileInfo, int IsDir, int StorageType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; + const char *pName = pFileInfo->m_pName; if(str_comp(pName, ".") == 0 || (str_comp(pName, "..") == 0 && str_comp(pSelf->m_aCurrentDemoFolder, "demos") == 0) || (!IsDir && !str_endswith(pName, ".demo"))) @@ -370,7 +371,7 @@ int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, { str_truncate(Item.m_aName, sizeof(Item.m_aName), pName, str_length(pName) - 5); Item.m_InfosLoaded = false; - Item.m_Date = Date; + Item.m_Date = pFileInfo->m_TimeModified; } Item.m_IsDir = IsDir != 0; Item.m_StorageType = StorageType; @@ -384,7 +385,7 @@ void CMenus::DemolistPopulate() m_lDemos.clear(); if(!str_comp(m_aCurrentDemoFolder, "demos")) m_DemolistStorageType = IStorage::TYPE_ALL; - Storage()->ListDirectoryInfo(m_DemolistStorageType, m_aCurrentDemoFolder, DemolistFetchCallback, this); + Storage()->ListDirectoryFileInfo(m_DemolistStorageType, m_aCurrentDemoFolder, DemolistFetchCallback, this); m_lDemos.sort_range_by(CDemoComparator( Config()->m_BrDemoSort, Config()->m_BrDemoSortOrder )); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 71f83577..08d0a941 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -556,7 +556,7 @@ class CLanguage }; -int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".map"); @@ -607,7 +607,7 @@ int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, time_t, time_t, return 0; } -int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; const char *pSuffix = str_endswith(pName, ".png"); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 1d2ea731..fc3b08ac 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -25,7 +25,7 @@ int *CSkins::ms_apColorVariables[NUM_SKINPARTS] = {0}; const float MIN_EYE_BODY_COLOR_DIST = 80.f; // between body and eyes (LAB color space) -int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) { CSkins *pSelf = (CSkins *)pUser; if(IsDir || !str_endswith(pName, ".png")) @@ -103,7 +103,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, time_t, time return 0; } -int CSkins::SkinScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser) +int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) { if(IsDir || !str_endswith(pName, ".json")) return 0; diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index 956cac4c..030e1905 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -83,8 +83,8 @@ class CSkins : public CComponent sorted_array m_aSkins; CSkin m_DummySkin; - static int SkinPartScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); - static int SkinScan(const char *pName, int IsDir, int DirType, time_t, time_t, void *pUser); + static int SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser); + static int SkinScan(const char *pName, int IsDir, int DirType, void *pUser); }; #endif diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index bb2c8827..31725f48 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3008,7 +3008,7 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) } -static int EditorListdirCallback(const char *pName, int IsDir, int StorageType, time_t, time_t, void *pUser) +static int EditorListdirCallback(const char *pName, int IsDir, int StorageType, void *pUser) { CEditor *pEditor = (CEditor*)pUser; const char *pExt = 0; From a689aea59e6df36e4235c1bebca927d451536bef Mon Sep 17 00:00:00 2001 From: LordSk Date: Sat, 28 Mar 2020 17:19:51 +0100 Subject: [PATCH 443/479] Fixed linux --- src/base/system.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 5bc16612..70bc0629 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1592,11 +1592,12 @@ void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t while((entry = readdir(d)) != NULL) { + CFsFileInfo info; + str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length); fs_file_time(buffer, &created, &modified); - CFsFileInfo info; - info.m_pName = finddata.cFileName; + info.m_pName = entry->d_name; info.m_TimeCreated = created; info.m_TimeModified = modified; From f973c8689ffcc669f4fe8d90cb2f168a978ab4ca Mon Sep 17 00:00:00 2001 From: Learath Date: Wed, 25 Mar 2020 19:03:08 +0300 Subject: [PATCH 444/479] Initialize variables --- src/base/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index 70bc0629..ff97725f 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1579,7 +1579,7 @@ void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t return; #else struct dirent *entry; - time_t created, modified; + time_t created = -1, modified = -1; char buffer[1024*2]; int length; DIR *d = opendir(dir); From 23621fcf2d2f8bc670e4f3ec32d5d281460794f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 24 Sep 2020 18:45:50 +0200 Subject: [PATCH 445/479] fix animation smoothness of envelopes in demos of long running servers --- src/game/client/components/maplayers.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 83160aac..a5370264 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -242,9 +242,9 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void } s_Time = mix( - pThis->m_LastLocalTick / TickSpeed, - pThis->m_CurrentLocalTick / TickSpeed, - pThis->Client()->IntraGameTick()); + pThis->m_LastLocalTick - pInfo->m_FirstTick, + pThis->m_CurrentLocalTick - pInfo->m_FirstTick, + pThis->Client()->IntraGameTick()) / TickSpeed; } else if(pThis->Client()->State() == IClient::STATE_ONLINE) { @@ -253,9 +253,9 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void if(pItem->m_Version < 2 || pItem->m_Synchronized) { s_Time = mix( - (pThis->Client()->PrevGameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / TickSpeed, - (pThis->Client()->GameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / TickSpeed, - pThis->Client()->IntraGameTick()); + pThis->Client()->PrevGameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick, + pThis->Client()->GameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick, + pThis->Client()->IntraGameTick()) / TickSpeed; } else s_Time = pThis->Client()->LocalTime() - pThis->m_OnlineStartTime; @@ -265,7 +265,7 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void { s_Time = pThis->Client()->LocalTime(); } - pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); + CRenderTools::RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); } void CMapLayers::OnRender() From 5aebb3061f807c00d4051bc439e48029ed40e902 Mon Sep 17 00:00:00 2001 From: "Tom_Adams@web.de" Date: Fri, 25 Sep 2020 20:39:56 +0200 Subject: [PATCH 446/479] limit name/clan by the number of characters not by the memory size. closes #2741 --- src/base/system.c | 16 ++++++++++++++++ src/base/system.h | 20 ++++++++++++++++++++ src/engine/client/client.cpp | 4 ++-- src/engine/client/contacts.cpp | 4 ++-- src/engine/contacts.h | 4 ++-- src/engine/server/server.cpp | 8 ++++---- src/engine/server/server.h | 4 ++-- src/engine/serverbrowser.h | 4 ++-- src/game/client/components/chat.h | 2 +- src/game/client/components/infomessages.h | 4 ++-- src/game/client/components/menus.h | 4 ++-- src/game/client/components/menus_browser.cpp | 4 ++-- src/game/client/gameclient.cpp | 4 ++-- src/game/client/gameclient.h | 4 ++-- 14 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index baccf47b..203f38b5 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2646,6 +2646,22 @@ int str_utf8_check(const char *str) return 1; } +void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num) +{ + int new_cursor; + int cursor = 0; + + while(src[cursor]) + { + new_cursor = str_utf8_forward(src, cursor); + if(new_cursor >= dst_size) // reserve 1 byte for the null termination + break; + else + cursor = new_cursor; + } + + str_copy(dst, src, min(cursor+1, dst_size)); +} unsigned str_quickhash(const char *str) { diff --git a/src/base/system.h b/src/base/system.h index e27dcbf7..f203642e 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1575,6 +1575,10 @@ int str_isspace(char c); char str_uppercase(char c); unsigned str_quickhash(const char *str); +enum +{ + UTF8_BYTE_LENGTH = 4 +}; /* Function: str_utf8_is_whitespace Check if the unicode is an utf8 whitespace. @@ -1693,6 +1697,22 @@ int str_utf8_encode(char *ptr, int chr); */ int str_utf8_check(const char *str); +/* + Function: str_utf8_copy_num + Copies a number of utf8 characters from one string to another. + + Parameters: + dst - Pointer to a buffer that shall receive the string. + src - String to be copied. + dst_size - Size of the buffer dst. + num - maximum number of utf8 characters to be copied. + + Remarks: + - The strings are treated as zero-terminated strings. + - Garantees that dst string will contain zero-termination. +*/ +void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num); + /* Function: secure_random_init Initializes the secure random module. diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 6ea231ae..964a7b25 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -964,8 +964,8 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo int NumClients = 0; for(int i = 0; i < pInfo->m_NumClients; i++) { - str_copy(pInfo->m_aClients[i].m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aName)); - str_copy(pInfo->m_aClients[i].m_aClan, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aClan)); + str_utf8_copy_num(pInfo->m_aClients[i].m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aName), MAX_NAME_LENGTH); + str_utf8_copy_num(pInfo->m_aClients[i].m_aClan, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aClan), MAX_CLAN_LENGTH); pInfo->m_aClients[i].m_Country = pUnpacker->GetInt(); pInfo->m_aClients[i].m_Score = pUnpacker->GetInt(); pInfo->m_aClients[i].m_PlayerType = pUnpacker->GetInt()&CServerInfo::CClient::PLAYERFLAG_MASK; diff --git a/src/engine/client/contacts.cpp b/src/engine/client/contacts.cpp index fa3fed0f..7c30800b 100644 --- a/src/engine/client/contacts.cpp +++ b/src/engine/client/contacts.cpp @@ -67,8 +67,8 @@ void IContactList::AddContact(const char *pName, const char *pClan) return; } - str_copy(m_aContacts[m_NumContacts].m_aName, pName, sizeof(m_aContacts[m_NumContacts].m_aName)); - str_copy(m_aContacts[m_NumContacts].m_aClan, pClan, sizeof(m_aContacts[m_NumContacts].m_aClan)); + str_utf8_copy_num(m_aContacts[m_NumContacts].m_aName, pName, sizeof(m_aContacts[m_NumContacts].m_aName), MAX_NAME_LENGTH); + str_utf8_copy_num(m_aContacts[m_NumContacts].m_aClan, pClan, sizeof(m_aContacts[m_NumContacts].m_aClan), MAX_CLAN_LENGTH); m_aContacts[m_NumContacts].m_NameHash = NameHash; m_aContacts[m_NumContacts].m_ClanHash = ClanHash; ++m_NumContacts; diff --git a/src/engine/contacts.h b/src/engine/contacts.h index 07b8dc70..ae961d65 100644 --- a/src/engine/contacts.h +++ b/src/engine/contacts.h @@ -9,8 +9,8 @@ struct CContactInfo { - char m_aName[MAX_NAME_LENGTH]; - char m_aClan[MAX_CLAN_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; unsigned m_NameHash; unsigned m_ClanHash; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 99d9d8ef..0089d925 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -304,7 +304,7 @@ void CServer::SetClientName(int ClientID, const char *pName) const char *pDefaultName = "(1)"; pName = str_utf8_skip_whitespaces(pName); - str_copy(m_aClients[ClientID].m_aName, *pName ? pName : pDefaultName, MAX_NAME_LENGTH); + str_utf8_copy_num(m_aClients[ClientID].m_aName, *pName ? pName : pDefaultName, sizeof(m_aClients[ClientID].m_aName), MAX_NAME_LENGTH); } void CServer::SetClientClan(int ClientID, const char *pClan) @@ -312,7 +312,7 @@ void CServer::SetClientClan(int ClientID, const char *pClan) if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY || !pClan) return; - str_copy(m_aClients[ClientID].m_aClan, pClan, MAX_CLAN_LENGTH); + str_utf8_copy_num(m_aClients[ClientID].m_aClan, pClan, sizeof(m_aClients[ClientID].m_aClan), MAX_CLAN_LENGTH); } void CServer::SetClientCountry(int ClientID, int Country) @@ -1161,8 +1161,8 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token) { if(m_aClients[i].m_State != CClient::STATE_EMPTY) { - pPacker->AddString(ClientName(i), MAX_NAME_LENGTH); // client name - pPacker->AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan + pPacker->AddString(ClientName(i), 0); // client name + pPacker->AddString(ClientClan(i), 0); // client clan pPacker->AddInt(m_aClients[i].m_Country); // client country pPacker->AddInt(m_aClients[i].m_Score); // client score pPacker->AddInt(GameServer()->IsClientPlayer(i)?0:1); // flag spectator=1, bot=2 (player=0) diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 2f7c82f3..81c6ac5e 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -123,8 +123,8 @@ class CServer : public IServer CInput m_aInputs[200]; // TODO: handle input better int m_CurrentInput; - char m_aName[MAX_NAME_LENGTH]; - char m_aClan[MAX_CLAN_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; int m_Version; int m_Country; int m_Score; diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 695220d7..b2ec6be2 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -19,8 +19,8 @@ class CServerInfo class CClient { public: - char m_aName[MAX_NAME_LENGTH]; - char m_aClan[MAX_CLAN_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; int m_Country; int m_Score; int m_PlayerType; diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 29ba858b..3b1e35ae 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -28,7 +28,7 @@ class CChat : public CComponent int m_TargetID; int m_Mode; int m_NameColor; - char m_aName[MAX_NAME_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; char m_aText[MAX_LINE_LENGTH]; bool m_Highlighted; }; diff --git a/src/game/client/components/infomessages.h b/src/game/client/components/infomessages.h index 319a87fc..7c0b9a4e 100644 --- a/src/game/client/components/infomessages.h +++ b/src/game/client/components/infomessages.h @@ -14,12 +14,12 @@ class CInfoMessages : public CComponent // victim / finishing player int m_Player1ID; - char m_aPlayer1Name[MAX_NAME_LENGTH]; + char m_aPlayer1Name[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; CTeeRenderInfo m_Player1RenderInfo; // killer int m_Player2ID; - char m_aPlayer2Name[MAX_NAME_LENGTH]; + char m_aPlayer2Name[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; CTeeRenderInfo m_Player2RenderInfo; // kill msg diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index be5eee68..b81460cf 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -558,8 +558,8 @@ class CMenus : public CComponent { public: const CServerInfo *m_pServerInfo; - char m_aName[MAX_NAME_LENGTH]; - char m_aClan[MAX_CLAN_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; int m_FriendState; bool m_IsPlayer; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 751af075..ecd93d4f 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1650,7 +1650,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) BottomArea.HSplitTop(SpacingH, 0, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Name"), FontSize, CUI::ALIGN_LEFT); - static char s_aName[MAX_NAME_LENGTH] = { 0 }; + static char s_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH] = { 0 }; static float s_OffsetName = 0.0f; DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), Button.h*ms_FontmodHeight*0.8f, &s_OffsetName); @@ -1658,7 +1658,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View) BottomArea.HSplitTop(SpacingH, 0, &BottomArea); Button.VSplitLeft(50.0f, &Label, &Button); UI()->DoLabel(&Label, Localize("Clan"), FontSize, CUI::ALIGN_LEFT); - static char s_aClan[MAX_CLAN_LENGTH] = { 0 }; + static char s_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH] = { 0 }; static float s_OffsetClan = 0.0f; DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), Button.h*ms_FontmodHeight*0.8f, &s_OffsetClan); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index ee35184b..c194cd2c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -857,8 +857,8 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) m_aClients[pMsg->m_ClientID].m_Active = true; m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; - str_copy(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_pName, sizeof(m_aClients[pMsg->m_ClientID].m_aName)); - str_copy(m_aClients[pMsg->m_ClientID].m_aClan, pMsg->m_pClan, sizeof(m_aClients[pMsg->m_ClientID].m_aClan)); + str_utf8_copy_num(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_pName, sizeof(m_aClients[pMsg->m_ClientID].m_aName), MAX_NAME_LENGTH); + str_utf8_copy_num(m_aClients[pMsg->m_ClientID].m_aClan, pMsg->m_pClan, sizeof(m_aClients[pMsg->m_ClientID].m_aClan), MAX_CLAN_LENGTH); m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; for(int i = 0; i < NUM_SKINPARTS; i++) { diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 4d78e062..0301ffa5 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -197,8 +197,8 @@ class CGameClient : public IGameClient // client data struct CClientData { - char m_aName[MAX_NAME_LENGTH]; - char m_aClan[MAX_CLAN_LENGTH]; + char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; int m_Country; char m_aaSkinPartNames[NUM_SKINPARTS][24]; int m_aUseCustomColors[NUM_SKINPARTS]; From 9fccc2b55a594ae0e73686a9c6c981a55fdf3d6d Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 25 Sep 2020 23:49:28 +0200 Subject: [PATCH 447/479] fixed a warning --- src/base/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/system.c b/src/base/system.c index 203f38b5..819e6eca 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -2660,7 +2660,7 @@ void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num) cursor = new_cursor; } - str_copy(dst, src, min(cursor+1, dst_size)); + str_copy(dst, src, cursor < dst_size ? cursor+1 : dst_size); } unsigned str_quickhash(const char *str) From bca3bfb3a7f98ccbb83ae6aa89f23bacd503020c Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 26 Sep 2020 00:44:38 +0200 Subject: [PATCH 448/479] removed magic values --- src/engine/shared/config.h | 1 + src/engine/shared/protocol.h | 1 + src/game/client/components/menus.h | 2 +- src/game/client/components/menus_settings.cpp | 10 +++++----- src/game/client/components/skins.cpp | 4 ++-- src/game/client/components/skins.h | 4 ++-- src/game/client/gameclient.cpp | 4 ++-- src/game/client/gameclient.h | 2 +- src/game/server/gamecontext.cpp | 4 ++-- src/game/server/player.h | 2 +- src/game/variables.h | 14 +++++++------- 11 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index b2b70a84..86b42e40 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -4,6 +4,7 @@ #define ENGINE_SHARED_CONFIG_H #include +#include "protocol.h" class CConfig { diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index bfdec29e..e6524d6b 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -92,6 +92,7 @@ enum MAX_NAME_LENGTH=16, MAX_CLAN_LENGTH=12, + MAX_SKIN_LENGTH=24, // message packing MSGFLAG_VITAL=1, diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index b81460cf..99983944 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -427,7 +427,7 @@ class CMenus : public CComponent bool m_NeedRestartGraphics; bool m_NeedRestartSound; int m_TeePartSelected; - char m_aSaveSkinName[24]; + char m_aSaveSkinName[MAX_SKIN_LENGTH]; bool m_RefreshSkinSelector; const CSkins::CSkin *m_pSelectedSkin; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 08d0a941..fda8cc29 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -399,7 +399,7 @@ void CMenus::RenderSkinSelection(CUIRect MainView) mem_copy(Config()->m_PlayerSkin, m_pSelectedSkin->m_aName, sizeof(Config()->m_PlayerSkin)); for(int p = 0; p < NUM_SKINPARTS; p++) { - mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, 24); + mem_copy(CSkins::ms_apSkinVariables[p], m_pSelectedSkin->m_apParts[p]->m_aName, MAX_SKIN_LENGTH); *CSkins::ms_apUCCVariables[p] = m_pSelectedSkin->m_aUseCustomColors[p]; *CSkins::ms_apColorVariables[p] = m_pSelectedSkin->m_aPartColors[p]; } @@ -485,7 +485,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) if(NewSelected != -1 && NewSelected != OldSelected) { const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; - mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, 24); + mem_copy(CSkins::ms_apSkinVariables[m_TeePartSelected], s->m_aName, MAX_SKIN_LENGTH); Config()->m_PlayerSkin[0] = 0; m_SkinModified = true; } @@ -1199,13 +1199,13 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) CTeeRenderInfo OwnSkinInfo; OwnSkinInfo.m_Size = 50.0f; - char aSkinParts[NUM_SKINPARTS][24]; + char aSkinParts[NUM_SKINPARTS][MAX_SKIN_LENGTH]; char* apSkinPartsPtr[NUM_SKINPARTS]; int aUCCVars[NUM_SKINPARTS]; int aColorVars[NUM_SKINPARTS]; for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(aSkinParts[p], CSkins::ms_apSkinVariables[p], 24); + str_copy(aSkinParts[p], CSkins::ms_apSkinVariables[p], MAX_SKIN_LENGTH); apSkinPartsPtr[p] = aSkinParts[p]; aUCCVars[p] = *CSkins::ms_apUCCVariables[p]; aColorVars[p] = *CSkins::ms_apColorVariables[p]; @@ -1257,7 +1257,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(aSkinParts[p], CSkins::ms_apSkinVariables[p], 24); + str_copy(aSkinParts[p], CSkins::ms_apSkinVariables[p], MAX_SKIN_LENGTH); apSkinPartsPtr[p] = aSkinParts[p]; aUCCVars[p] = *CSkins::ms_apUCCVariables[p]; aColorVars[p] = *CSkins::ms_apColorVariables[p]; diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index fc3b08ac..fb823a67 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -454,7 +454,7 @@ bool CSkins::ValidateSkinParts(char* aPartNames[NUM_SKINPARTS], int* aUseCustomC // TODO: adjust eye color here as well? if(str_comp(aPartNames[SKINPART_EYES], "colorable") == 0 || str_comp(aPartNames[SKINPART_EYES], "negative") == 0) { - str_copy(aPartNames[SKINPART_EYES], "standard", 24); + str_copy(aPartNames[SKINPART_EYES], "standard", MAX_SKIN_LENGTH); return false; } } @@ -490,7 +490,7 @@ bool CSkins::ValidateSkinParts(char* aPartNames[NUM_SKINPARTS], int* aUseCustomC // white eye can't go to black because of our DARKEST_COLOR_LGT restriction, so switch to standard (black) eyes if(OrgEyeHsl.l < DARKEST_COLOR_LGT/255.f) - str_copy(aPartNames[SKINPART_EYES], "standard", 24); // black + str_copy(aPartNames[SKINPART_EYES], "standard", MAX_SKIN_LENGTH); // black else { aUseCustomColors[SKINPART_EYES] = 1; diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index c28ebf41..954353dd 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -26,7 +26,7 @@ class CSkins : public CComponent struct CSkinPart { int m_Flags; - char m_aName[24]; + char m_aName[MAX_SKIN_LENGTH]; IGraphics::CTextureHandle m_OrgTexture; IGraphics::CTextureHandle m_ColorTexture; vec3 m_BloodColor; @@ -37,7 +37,7 @@ class CSkins : public CComponent struct CSkin { int m_Flags; - char m_aName[24]; + char m_aName[MAX_SKIN_LENGTH]; const CSkinPart *m_apParts[NUM_SKINPARTS]; int m_aPartColors[NUM_SKINPARTS]; int m_aUseCustomColors[NUM_SKINPARTS]; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index c194cd2c..c948dbfa 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -862,7 +862,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; for(int i = 0; i < NUM_SKINPARTS; i++) { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); + str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], MAX_SKIN_LENGTH); m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; } @@ -934,7 +934,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) for(int i = 0; i < NUM_SKINPARTS; i++) { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); + str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], MAX_SKIN_LENGTH); m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 0301ffa5..ad868022 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -200,7 +200,7 @@ class CGameClient : public IGameClient char m_aName[MAX_NAME_LENGTH*UTF8_BYTE_LENGTH]; char m_aClan[MAX_CLAN_LENGTH*UTF8_BYTE_LENGTH]; int m_Country; - char m_aaSkinPartNames[NUM_SKINPARTS][24]; + char m_aaSkinPartNames[NUM_SKINPARTS][MAX_SKIN_LENGTH]; int m_aUseCustomColors[NUM_SKINPARTS]; int m_aSkinPartColors[NUM_SKINPARTS]; int m_SkinPartIDs[NUM_SKINPARTS]; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index f767d467..253601c8 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1080,7 +1080,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], 24); + str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], MAX_SKIN_LENGTH); pPlayer->m_TeeInfos.m_aUseCustomColors[p] = pMsg->m_aUseCustomColors[p]; pPlayer->m_TeeInfos.m_aSkinPartColors[p] = pMsg->m_aSkinPartColors[p]; } @@ -1119,7 +1119,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], 24); + str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], MAX_SKIN_LENGTH); pPlayer->m_TeeInfos.m_aUseCustomColors[p] = pMsg->m_aUseCustomColors[p]; pPlayer->m_TeeInfos.m_aSkinPartColors[p] = pMsg->m_aSkinPartColors[p]; } diff --git a/src/game/server/player.h b/src/game/server/player.h index 0f8cbc30..c739ed58 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -81,7 +81,7 @@ class CPlayer // TODO: clean this up struct { - char m_aaSkinPartNames[NUM_SKINPARTS][24]; + char m_aaSkinPartNames[NUM_SKINPARTS][MAX_SKIN_LENGTH]; int m_aUseCustomColors[NUM_SKINPARTS]; int m_aSkinPartColors[NUM_SKINPARTS]; } m_TeeInfos; diff --git a/src/game/variables.h b/src/game/variables.h index 17cc3c89..a3d1fbbe 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -73,13 +73,13 @@ MACRO_CONFIG_INT(PlayerUseCustomColorDecoration, player_use_custom_color_decorat MACRO_CONFIG_INT(PlayerUseCustomColorHands, player_use_custom_color_hands, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors for hands") MACRO_CONFIG_INT(PlayerUseCustomColorFeet, player_use_custom_color_feet, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors for feet") MACRO_CONFIG_INT(PlayerUseCustomColorEyes, player_use_custom_color_eyes, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors for eyes") -MACRO_CONFIG_STR(PlayerSkin, player_skin, 24, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") -MACRO_CONFIG_STR(PlayerSkinBody, player_skin_body, 24, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin body") -MACRO_CONFIG_STR(PlayerSkinMarking, player_skin_marking, 24, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin marking") -MACRO_CONFIG_STR(PlayerSkinDecoration, player_skin_decoration, 24, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin decoration") -MACRO_CONFIG_STR(PlayerSkinHands, player_skin_hands, 24, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin hands") -MACRO_CONFIG_STR(PlayerSkinFeet, player_skin_feet, 24, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin feet") -MACRO_CONFIG_STR(PlayerSkinEyes, player_skin_eyes, 24, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin eyes") +MACRO_CONFIG_STR(PlayerSkin, player_skin, MAX_SKIN_LENGTH, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") +MACRO_CONFIG_STR(PlayerSkinBody, player_skin_body, MAX_SKIN_LENGTH, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin body") +MACRO_CONFIG_STR(PlayerSkinMarking, player_skin_marking, MAX_SKIN_LENGTH, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin marking") +MACRO_CONFIG_STR(PlayerSkinDecoration, player_skin_decoration, MAX_SKIN_LENGTH, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin decoration") +MACRO_CONFIG_STR(PlayerSkinHands, player_skin_hands, MAX_SKIN_LENGTH, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin hands") +MACRO_CONFIG_STR(PlayerSkinFeet, player_skin_feet, MAX_SKIN_LENGTH, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin feet") +MACRO_CONFIG_STR(PlayerSkinEyes, player_skin_eyes, MAX_SKIN_LENGTH, "standard", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin eyes") MACRO_CONFIG_INT(UiBrowserPage, ui_browser_page, 5, 5, 8, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface serverbrowser page") MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 5, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface settings page") From 3b9233bbb1c1e3fcbffbce7c8de66755622018e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 21:46:06 +0200 Subject: [PATCH 449/479] change m_Binder to be non-static --- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_settings.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 99983944..bfcaa26e 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -887,7 +887,7 @@ class CMenus : public CComponent }; void GetSwitchTeamInfo(CSwitchTeamInfo *pInfo); - static CMenusKeyBinder m_Binder; + CMenusKeyBinder m_Binder; CMenus(); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index fda8cc29..b7657c19 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -27,8 +27,6 @@ #include "countryflags.h" #include "menus.h" -CMenusKeyBinder CMenus::m_Binder; - CMenusKeyBinder::CMenusKeyBinder() { m_TakeKey = false; From ebe16893f8d4f5ea91fc3303fb9ee1d8e42f916d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 21:53:06 +0200 Subject: [PATCH 450/479] remove unused variable m_SwitchButton --- src/game/client/components/menus.h | 2 -- src/game/client/components/menus_browser.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index bfcaa26e..199daa5c 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -614,8 +614,6 @@ class CMenus : public CComponent FILTER_FAVORITES, }; - // buttons var - int m_SwitchButton; CButtonContainer m_DeleteButtonContainer; CButtonContainer m_UpButtonContainer; CButtonContainer m_DownButtonContainer; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index ecd93d4f..4d3674db 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -58,9 +58,6 @@ CMenus::CBrowserFilter::CBrowserFilter(int Custom, const char* pName, IServerBro default: m_Filter = m_pServerBrowser->AddFilter(&ms_FilterAll); } - - // init buttons - m_SwitchButton = 0; } void CMenus::CBrowserFilter::Reset() From 420a4040b8549ffbc0c43364b662f418306cbd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:02:33 +0200 Subject: [PATCH 451/479] use bytes_be_to_uint for demoitems --- src/game/client/components/menus.h | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 199daa5c..d7c697a7 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -481,18 +481,12 @@ class CMenus : public CComponent { if(!m_Valid || !m_InfosLoaded) return -1; - return ((m_Info.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | - ((m_Info.m_aNumTimelineMarkers[1]<<16)&0xFF0000) | - ((m_Info.m_aNumTimelineMarkers[2]<<8)&0xFF00) | - (m_Info.m_aNumTimelineMarkers[3]&0xFF); + return bytes_be_to_uint(m_Info.m_aNumTimelineMarkers); } int Length() const { - return ((m_Info.m_aLength[0]<<24)&0xFF000000) | - ((m_Info.m_aLength[1]<<16)&0xFF0000) | - ((m_Info.m_aLength[2]<<8)&0xFF00) | - (m_Info.m_aLength[3]&0xFF); + return bytes_be_to_uint(m_Info.m_aLength); } bool operator<(const CDemoItem &Other) const @@ -509,7 +503,8 @@ class CMenus : public CComponent { int m_Type; int m_Order; - public: + + public: CDemoComparator(int Type, int Order) { m_Type = Type; From 2fb9941e72a9fa34490e6730472e383ecb80c8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:11:38 +0200 Subject: [PATCH 452/479] remove unused return value and dead code --- src/game/client/components/menus.cpp | 18 +++--------------- src/game/client/components/menus.h | 2 +- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index b104d79e..86e91cf3 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1439,7 +1439,7 @@ void CMenus::PopupCountry(int Selection, FPopupButtonCallback pfnOkButtonCallbac } -int CMenus::Render() +void CMenus::Render() { CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); @@ -1466,11 +1466,6 @@ int CMenus::Render() if(IsBackgroundNeeded()) RenderBackground(Client()->LocalTime()); - CUIRect TabBar, MainView; - - // some margin around the screen - //Screen.Margin(10.0f, &Screen); - static bool s_SoundCheck = false; if(!s_SoundCheck && m_Popup == POPUP_NONE) { @@ -1495,17 +1490,12 @@ int CMenus::Render() if(Config()->m_UiWideview) VMargin = min(VMargin, 60.0f); + CUIRect TabBar, MainView; Screen.VMargin(VMargin, &MainView); MainView.HSplitTop(BarHeight, &TabBar, &MainView); RenderMenubar(TabBar); - // news is not implemented yet - /*if(m_MenuPage <= PAGE_NEWS || m_MenuPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_GAME && m_MenuPage <= PAGE_CALLVOTE)) - { - ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); - m_MenuPage = PAGE_INTERNET; - }*/ - + // render top buttons { // quit button CUIRect Button, Row; @@ -2026,8 +2016,6 @@ int CMenus::Render() if(m_Popup == POPUP_NONE) UI()->SetActiveItem(0); } - - return 0; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index d7c697a7..c764a0a8 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -756,7 +756,7 @@ class CMenus : public CComponent void UpdateVideoModeSettings(); // found in menus.cpp - int Render(); + void Render(); void RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); void RenderBackButton(CUIRect MainView); From 9aac4f59f1b11c44d2e6d66d4894e9fa5bfbbb0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:15:49 +0200 Subject: [PATCH 453/479] fix names of static variables in DoKeyReader --- src/game/client/components/menus.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 86e91cf3..9c8ccf66 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -810,15 +810,16 @@ void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier) { // process - static const void *pGrabbedID = 0; - static bool MouseReleased = true; - static int ButtonUsed = 0; + static const void *s_pGrabbedID = 0; + static bool s_MouseReleased = true; + static int s_ButtonUsed = 0; + const bool Hovered = UI()->MouseHovered(pRect); int NewKey = Key; *NewModifier = Modifier; - if(!UI()->MouseButton(0) && !UI()->MouseButton(1) && pGrabbedID == pBC->GetID()) - MouseReleased = true; + if(!UI()->MouseButton(0) && !UI()->MouseButton(1) && s_pGrabbedID == pBC->GetID()) + s_MouseReleased = true; if(UI()->CheckActiveItem(pBC->GetID())) { @@ -832,11 +833,11 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in } m_Binder.m_GotKey = false; UI()->SetActiveItem(0); - MouseReleased = false; - pGrabbedID = pBC->GetID(); + s_MouseReleased = false; + s_pGrabbedID = pBC->GetID(); } - if(ButtonUsed == 1 && !UI()->MouseButton(1)) + if(s_ButtonUsed == 1 && !UI()->MouseButton(1)) { if(Hovered) NewKey = 0; @@ -845,20 +846,20 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in } else if(UI()->HotItem() == pBC->GetID()) { - if(MouseReleased) + if(s_MouseReleased) { if(UI()->MouseButton(0)) { m_Binder.m_TakeKey = true; m_Binder.m_GotKey = false; UI()->SetActiveItem(pBC->GetID()); - ButtonUsed = 0; + s_ButtonUsed = 0; } if(UI()->MouseButton(1)) { UI()->SetActiveItem(pBC->GetID()); - ButtonUsed = 1; + s_ButtonUsed = 1; } } } @@ -867,7 +868,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in UI()->SetHotItem(pBC->GetID()); // draw - if(UI()->CheckActiveItem(pBC->GetID()) && ButtonUsed == 0) + if(UI()->CheckActiveItem(pBC->GetID()) && s_ButtonUsed == 0) { DoButton_KeySelect(pBC, "???", pRect); m_KeyReaderIsActive = true; From d1c40c737e89f3439e05c74e2e4aeee9d61583e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:21:10 +0200 Subject: [PATCH 454/479] extract value into constant --- src/game/client/components/menus_settings.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index b7657c19..48e2e9fd 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1511,53 +1511,54 @@ void CMenus::RenderSettingsControls(CUIRect MainView) float CMenus::RenderSettingsControlsStats(CUIRect View) { + const float RowHeight = 20.0f; CUIRect Button; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos, Localize("Frags"), Config()->m_ClStatboardInfos & TC_STATS_FRAGS, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_FRAGS; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+1, Localize("Deaths"), Config()->m_ClStatboardInfos & TC_STATS_DEATHS, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_DEATHS; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+2, Localize("Suicides"), Config()->m_ClStatboardInfos & TC_STATS_SUICIDES, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_SUICIDES; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+3, Localize("Ratio"), Config()->m_ClStatboardInfos & TC_STATS_RATIO, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_RATIO; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+4, Localize("Net score"), Config()->m_ClStatboardInfos & TC_STATS_NET, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_NET; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+5, Localize("Frags per minute"), Config()->m_ClStatboardInfos & TC_STATS_FPM, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_FPM; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+6, Localize("Current spree"), Config()->m_ClStatboardInfos & TC_STATS_SPREE, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_SPREE; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+7, Localize("Best spree"), Config()->m_ClStatboardInfos & TC_STATS_BESTSPREE, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_BESTSPREE; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+9, Localize("Weapons stats"), Config()->m_ClStatboardInfos & TC_STATS_WEAPS, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_WEAPS; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+8, Localize("Flag grabs"), Config()->m_ClStatboardInfos & TC_STATS_FLAGGRABS, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_FLAGGRABS; - View.HSplitTop(20.0f, &Button, &View); + View.HSplitTop(RowHeight, &Button, &View); if(DoButton_CheckBox(&Config()->m_ClStatboardInfos+10, Localize("Flag captures"), Config()->m_ClStatboardInfos & TC_STATS_FLAGCAPTURES, &Button)) Config()->m_ClStatboardInfos ^= TC_STATS_FLAGCAPTURES; - return 11*20.0f; + return 11 * RowHeight; } bool CMenus::DoResolutionList(CUIRect* pRect, CListBox* pListBox, From 1e60acf5cb68183aab54d117c5491c0586ece25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:28:54 +0200 Subject: [PATCH 455/479] fix variable naming --- src/game/client/components/menus.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 9c8ccf66..eb0048b3 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -807,7 +807,7 @@ void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, RenderTools()->DrawUIRect(&Slider, SliderColor, CUI::CORNER_ALL, Slider.h/2.0f); } -int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, int Modifier, int* NewModifier) +int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, int Modifier, int* pNewModifier) { // process static const void *s_pGrabbedID = 0; @@ -816,7 +816,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in const bool Hovered = UI()->MouseHovered(pRect); int NewKey = Key; - *NewModifier = Modifier; + *pNewModifier = Modifier; if(!UI()->MouseButton(0) && !UI()->MouseButton(1) && s_pGrabbedID == pBC->GetID()) s_MouseReleased = true; @@ -829,7 +829,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in if(m_Binder.m_Key.m_Key != KEY_ESCAPE) { NewKey = m_Binder.m_Key.m_Key; - *NewModifier = m_Binder.m_Modifier; + *pNewModifier = m_Binder.m_Modifier; } m_Binder.m_GotKey = false; UI()->SetActiveItem(0); @@ -873,16 +873,15 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in DoButton_KeySelect(pBC, "???", pRect); m_KeyReaderIsActive = true; } + else if(Key == 0) + { + DoButton_KeySelect(pBC, "", pRect); + } else { - if(Key == 0) - DoButton_KeySelect(pBC, "", pRect); - else - { - char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s%s", CBinds::GetModifierName(*NewModifier), Input()->KeyName(Key)); - DoButton_KeySelect(pBC, aBuf, pRect); - } + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s%s", CBinds::GetModifierName(*pNewModifier), Input()->KeyName(Key)); + DoButton_KeySelect(pBC, aBuf, pRect); } return NewKey; } From 00cbbba4b15c4881fec6a0356ee5e3d51cd4f1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 22:52:59 +0200 Subject: [PATCH 456/479] extract method, rename variables in CLayers --- src/game/layers.cpp | 29 +++++++++++++++-------------- src/game/layers.h | 2 ++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/game/layers.cpp b/src/game/layers.cpp index a3cca222..bf1bac66 100644 --- a/src/game/layers.cpp +++ b/src/game/layers.cpp @@ -19,13 +19,18 @@ void CLayers::Init(class IKernel *pKernel, IMap *pMap) m_pMap->GetType(MAPITEMTYPE_GROUP, &m_GroupsStart, &m_GroupsNum); m_pMap->GetType(MAPITEMTYPE_LAYER, &m_LayersStart, &m_LayersNum); + InitGameLayer(); + InitTilemapSkip(); +} + +void CLayers::InitGameLayer() +{ for(int g = 0; g < NumGroups(); g++) { CMapItemGroup *pGroup = GetGroup(g); for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l); - if(pLayer->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilemap = reinterpret_cast(pLayer); @@ -54,8 +59,6 @@ void CLayers::Init(class IKernel *pKernel, IMap *pMap) } } } - - InitTilemapSkip(); } void CLayers::InitTilemapSkip() @@ -63,28 +66,26 @@ void CLayers::InitTilemapSkip() for(int g = 0; g < NumGroups(); g++) { CMapItemGroup *pGroup = GetGroup(g); - for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l); - if(pLayer->m_Type == LAYERTYPE_TILES) { - CMapItemLayerTilemap *pTmap = (CMapItemLayerTilemap *)pLayer; - CTile *pTiles = (CTile *)Map()->GetData(pTmap->m_Data); - for(int y = 0; y < pTmap->m_Height; y++) + CMapItemLayerTilemap *pTilemap = (CMapItemLayerTilemap *)pLayer; + CTile *pTiles = (CTile *)Map()->GetData(pTilemap->m_Data); + for(int y = 0; y < pTilemap->m_Height; y++) { - for(int x = 1; x < pTmap->m_Width;) + for(int x = 1; x < pTilemap->m_Width;) { - int sx; - for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++) + int SkippedX; + for(SkippedX = 1; x+SkippedX < pTilemap->m_Width && SkippedX < 255; SkippedX++) { - if(pTiles[y*pTmap->m_Width+x+sx].m_Index) + if(pTiles[y*pTilemap->m_Width+x+SkippedX].m_Index) break; } - pTiles[y*pTmap->m_Width+x].m_Skip = sx-1; - x += sx; + pTiles[y*pTilemap->m_Width+x].m_Skip = SkippedX-1; + x += SkippedX; } } } diff --git a/src/game/layers.h b/src/game/layers.h index 465cbbf8..a6982b9a 100644 --- a/src/game/layers.h +++ b/src/game/layers.h @@ -15,6 +15,8 @@ class CLayers CMapItemGroup *m_pGameGroup; CMapItemLayerTilemap *m_pGameLayer; class IMap *m_pMap; + + void InitGameLayer(); void InitTilemapSkip(); public: From 2ccb293d16c4346b0facefef7ef44b164b7c5873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 26 Sep 2020 23:03:44 +0200 Subject: [PATCH 457/479] multiply instead of dividing multiple times in CCollision --- src/game/collision.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/game/collision.cpp b/src/game/collision.cpp index 5949b2b6..5a0a361f 100644 --- a/src/game/collision.cpp +++ b/src/game/collision.cpp @@ -67,14 +67,13 @@ bool CCollision::IsTile(int x, int y, int Flag) const // TODO: rewrite this smarter! int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) const { - float Distance = distance(Pos0, Pos1); - int End(Distance+1); + const int End = distance(Pos0, Pos1)+1; + const float InverseEnd = 1.0f/End; vec2 Last = Pos0; for(int i = 0; i <= End; i++) { - float a = i/float(End); - vec2 Pos = mix(Pos0, Pos1, a); + vec2 Pos = mix(Pos0, Pos1, i*InverseEnd); if(CheckPoint(Pos.x, Pos.y)) { if(pOutCollision) @@ -151,22 +150,17 @@ void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elas vec2 Pos = *pInoutPos; vec2 Vel = *pInoutVel; - float Distance = length(Vel); - int Max = (int)Distance; + const float Distance = length(Vel); + const int Max = (int)Distance; if(pDeath) *pDeath = false; if(Distance > 0.00001f) { - //vec2 old_pos = pos; - float Fraction = 1.0f/(float)(Max+1); + const float Fraction = 1.0f/(Max+1); for(int i = 0; i <= Max; i++) { - //float amount = i/(float)max; - //if(max == 0) - //amount = 0; - vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice //You hit a deathtile, congrats to that :) From c3ee510342c2ca73f61ca116a28294bd97d3d59f Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 3 Oct 2020 10:23:15 +0200 Subject: [PATCH 458/479] fixed adding multi-command votes via the menu f.e. sv_map ctf1;reload just added the first command and restarted the server --- src/game/client/components/voting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index af8582d5..855ce4d5 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -81,7 +81,7 @@ void CVoting::RemovevoteOption(int OptionID) void CVoting::AddvoteOption(const char *pDescription, const char *pCommand) { char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "add_vote \"%s\" %s", pDescription, pCommand); + str_format(aBuf, sizeof(aBuf), "add_vote \"%s\" \"%s\"", pDescription, pCommand); Client()->Rcon(aBuf); } From ce8d1e5d84c48c7ab6028f6436a2780b44b01f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 5 Oct 2020 22:24:48 +0200 Subject: [PATCH 459/479] fix damageind when world in demo is paused --- src/game/client/components/damageind.cpp | 41 ++++++++++++------------ src/game/client/components/damageind.h | 5 +-- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index 19151833..fdacaf4e 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -14,32 +14,32 @@ CDamageInd::CDamageInd() m_NumItems = 0; } -CDamageInd::CItem *CDamageInd::CreateI() +CDamageInd::CItem *CDamageInd::CreateItem() { - if (m_NumItems < MAX_ITEMS) + if(m_NumItems < MAX_ITEMS) { - CItem *p = &m_aItems[m_NumItems]; + CItem *pItem = &m_aItems[m_NumItems]; m_NumItems++; - return p; + return pItem; } return 0; } -void CDamageInd::DestroyI(CDamageInd::CItem *i) +void CDamageInd::DestroyItem(CDamageInd::CItem *pItem) { m_NumItems--; - *i = m_aItems[m_NumItems]; + *pItem = m_aItems[m_NumItems]; } void CDamageInd::Create(vec2 Pos, vec2 Dir) { - CItem *i = CreateI(); - if (i) + CItem *pItem = CreateItem(); + if(pItem) { - i->m_Pos = Pos; - i->m_StartTime = Client()->LocalTime(); - i->m_Dir = Dir*-1; - i->m_StartAngle = (frandom() - 1.0f) * 2.0f * pi; + pItem->m_Pos = Pos; + pItem->m_StartTime = Client()->LocalTime(); + pItem->m_Dir = Dir*-1; + pItem->m_StartAngle = (frandom() - 1.0f) * 2.0f * pi; } } @@ -47,26 +47,27 @@ void CDamageInd::OnRender() { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - static float s_LastLocalTime = Client()->LocalTime(); + const float Now = Client()->LocalTime(); + static float s_LastLocalTime = Now; 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; + if(pInfo->m_Paused || m_pClient->IsWorldPaused()) + m_aItems[i].m_StartTime += Now-s_LastLocalTime; else - m_aItems[i].m_StartTime += (Client()->LocalTime()-s_LastLocalTime)*(1.0f-pInfo->m_Speed); + m_aItems[i].m_StartTime += (Now-s_LastLocalTime)*(1.0f-pInfo->m_Speed); } else { if(m_pClient->IsWorldPaused()) - m_aItems[i].m_StartTime += Client()->LocalTime()-s_LastLocalTime; + m_aItems[i].m_StartTime += Now-s_LastLocalTime; } - float Life = 0.75f - (Client()->LocalTime() - m_aItems[i].m_StartTime); + float Life = 0.75f - (Now - m_aItems[i].m_StartTime); if(Life < 0.0f) - DestroyI(&m_aItems[i]); + DestroyItem(&m_aItems[i]); else { 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)); @@ -78,8 +79,8 @@ void CDamageInd::OnRender() i++; } } - s_LastLocalTime = Client()->LocalTime(); Graphics()->QuadsEnd(); + s_LastLocalTime = Now; } void CDamageInd::OnReset() diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h index 457acb55..d41f3430 100644 --- a/src/game/client/components/damageind.h +++ b/src/game/client/components/damageind.h @@ -23,13 +23,14 @@ class CDamageInd : public CComponent CItem m_aItems[MAX_ITEMS]; int m_NumItems; - CItem *CreateI(); - void DestroyI(CItem *i); + CItem *CreateItem(); + void DestroyItem(CItem *pItem); public: CDamageInd(); void Create(vec2 Pos, vec2 Dir); + virtual void OnRender(); virtual void OnReset(); }; From a5d29a302edbfd05c72f2dab8eb8350ee6c6ad0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 5 Oct 2020 22:25:11 +0200 Subject: [PATCH 460/479] fix items when world in demo is paused --- src/game/client/components/items.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 5afcce4a..ab6ded9d 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -67,23 +67,24 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); + const float Now = Client()->LocalTime(); static float s_Time = 0.0f; - static float s_LastLocalTime = Client()->LocalTime(); + static float s_LastLocalTime = Now; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused) - s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed; + if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) + s_Time += (Now-s_LastLocalTime)*pInfo->m_Speed; } else { if(!m_pClient->IsWorldPaused()) - s_Time += Client()->LocalTime()-s_LastLocalTime; + s_Time += Now-s_LastLocalTime; } Graphics()->QuadsSetRotation(s_Time*pi*2*2 + ItemID); - s_LastLocalTime = Client()->LocalTime(); + s_LastLocalTime = Now; } else { @@ -148,23 +149,24 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu Graphics()->QuadsSetRotation(Angle); + const float Now = Client()->LocalTime(); static float s_Time = 0.0f; - static float s_LastLocalTime = Client()->LocalTime(); + static float s_LastLocalTime = Now; float Offset = Pos.y/32.0f + Pos.x/32.0f; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused) - s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed; + if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) + s_Time += (Now-s_LastLocalTime)*pInfo->m_Speed; } else { if(!m_pClient->IsWorldPaused()) - s_Time += Client()->LocalTime()-s_LastLocalTime; + s_Time += Now-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(); + s_LastLocalTime = Now; RenderTools()->DrawSprite(Pos.x, Pos.y, Size); Graphics()->QuadsEnd(); } From 9538bafb2e080a927e7acbcde4a3d8fc367b2129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 5 Oct 2020 22:26:45 +0200 Subject: [PATCH 461/479] fix particles when world in demo is paused --- src/game/client/components/particles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index 2c2e2450..5dfe08ec 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -40,7 +40,7 @@ void CParticles::Add(int Group, CParticle *pPart) if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(pInfo->m_Paused) + if(pInfo->m_Paused || m_pClient->IsWorldPaused()) return; } else @@ -143,7 +143,7 @@ void CParticles::OnRender() if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused) + if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) Update((float)((Now-s_LastTime)/(double)time_freq())*pInfo->m_Speed); } else From 74e2b724f8eaabb86ca24b62d5bbb145efbe9713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 6 Oct 2020 18:21:05 +0200 Subject: [PATCH 462/479] fix envelopes when world in demo is paused --- src/game/client/components/maplayers.cpp | 33 +++-------------------- src/game/client/components/maplayers.h | 4 --- src/game/client/components/menus_demo.cpp | 2 -- 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index a5370264..dc14bc20 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -22,8 +22,6 @@ CMapLayers::CMapLayers(int Type) { m_Type = Type; - m_CurrentLocalTick = 0; - m_LastLocalTick = 0; m_pMenuMap = 0; m_pMenuLayers = 0; m_OnlineStartTime = 0; @@ -192,16 +190,6 @@ void CMapLayers::LoadEnvPoints(const CLayers *pLayers, array& lEnvPoi } } -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; - } -} - void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) { CMapLayers *pThis = (CMapLayers *)pUser; @@ -230,23 +218,8 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void return; const CMapItemEnvelope *pItem = (CMapItemEnvelope *)pLayers->Map()->GetItem(Start+Env, 0, 0); - const float TickSpeed = (float)pThis->Client()->GameTickSpeed(); static float s_Time = 0.0f; - if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); - if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick) - { - pThis->m_LastLocalTick = pThis->m_CurrentLocalTick; - pThis->m_CurrentLocalTick = pInfo->m_CurrentTick; - } - - s_Time = mix( - pThis->m_LastLocalTick - pInfo->m_FirstTick, - pThis->m_CurrentLocalTick - pInfo->m_FirstTick, - pThis->Client()->IntraGameTick()) / TickSpeed; - } - else if(pThis->Client()->State() == IClient::STATE_ONLINE) + if(pThis->Client()->State() == IClient::STATE_ONLINE || pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { if(pThis->m_pClient->m_Snap.m_pGameData && !pThis->m_pClient->IsWorldPaused()) { @@ -255,7 +228,7 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void s_Time = mix( pThis->Client()->PrevGameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick, pThis->Client()->GameTick() - pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick, - pThis->Client()->IntraGameTick()) / TickSpeed; + pThis->Client()->IntraGameTick()) / (float)pThis->Client()->GameTickSpeed(); } else s_Time = pThis->Client()->LocalTime() - pThis->m_OnlineStartTime; @@ -265,7 +238,7 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void { s_Time = pThis->Client()->LocalTime(); } - CRenderTools::RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); + CRenderTools::RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + TimeOffset, pChannels); } void CMapLayers::OnRender() diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 5ec94862..aec9f126 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -11,8 +11,6 @@ class CMapLayers : public CComponent IEngineMap *m_pMenuMap; int m_Type; - int m_CurrentLocalTick; - int m_LastLocalTick; float m_OnlineStartTime; array m_lEnvPoints; @@ -44,8 +42,6 @@ class CMapLayers : public CComponent virtual void OnRender(); virtual void OnMapLoad(); - void EnvelopeUpdate(); - static void ConchainBackgroundMap(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); virtual void OnConsoleInit(); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 5fb4560a..9f7d225e 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -344,8 +344,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) m_pClient->m_SuppressEvents = true; DemoPlayer()->SetPos(PositionToSeek); m_pClient->m_SuppressEvents = false; - m_pClient->m_pMapLayersBackGround->EnvelopeUpdate(); - m_pClient->m_pMapLayersForeGround->EnvelopeUpdate(); } } From d2d68f306cd6e9caf4acf4487772ad28094b6cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 6 Oct 2020 19:09:38 +0200 Subject: [PATCH 463/479] refactoring: add IsDemoPlaybackPaused and GetAnimationPlaybackSpeed --- src/game/client/components/damageind.cpp | 26 ++++---------- src/game/client/components/damageind.h | 2 +- src/game/client/components/items.cpp | 30 +++------------- src/game/client/components/particles.cpp | 45 +++++++----------------- src/game/client/components/players.cpp | 40 +++++---------------- src/game/client/gameclient.cpp | 10 ++++++ src/game/client/gameclient.h | 2 ++ 7 files changed, 45 insertions(+), 110 deletions(-) diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index fdacaf4e..648a3ec3 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -37,7 +37,7 @@ void CDamageInd::Create(vec2 Pos, vec2 Dir) if(pItem) { pItem->m_Pos = Pos; - pItem->m_StartTime = Client()->LocalTime(); + pItem->m_LifeTime = 0.75f; pItem->m_Dir = Dir*-1; pItem->m_StartAngle = (frandom() - 1.0f) * 2.0f * pi; } @@ -51,29 +51,15 @@ void CDamageInd::OnRender() static float s_LastLocalTime = Now; for(int i = 0; i < m_NumItems;) { - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(pInfo->m_Paused || m_pClient->IsWorldPaused()) - m_aItems[i].m_StartTime += Now-s_LastLocalTime; - else - m_aItems[i].m_StartTime += (Now-s_LastLocalTime)*(1.0f-pInfo->m_Speed); - } - else - { - if(m_pClient->IsWorldPaused()) - m_aItems[i].m_StartTime += Now-s_LastLocalTime; - } - - float Life = 0.75f - (Now - m_aItems[i].m_StartTime); - if(Life < 0.0f) + m_aItems[i].m_LifeTime -= (Now - s_LastLocalTime) * m_pClient->GetAnimationPlaybackSpeed(); + if(m_aItems[i].m_LifeTime < 0.0f) DestroyItem(&m_aItems[i]); else { - 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)); - const float Alpha = clamp(Life * 10.0f, 0.0f, 1.0f); // 0.1 -> 0.0 == 1.0 -> 0.0 + 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_LifeTime-0.60f)/0.15f, 0.0f, 1.0f)); + const float Alpha = clamp(m_aItems[i].m_LifeTime * 10.0f, 0.0f, 1.0f); // 0.1 -> 0.0 == 1.0 -> 0.0 Graphics()->SetColor(1.0f*Alpha, 1.0f*Alpha, 1.0f*Alpha, Alpha); - Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + Life * 2.0f); + Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + m_aItems[i].m_LifeTime * 2.0f); RenderTools()->SelectSprite(SPRITE_STAR1); RenderTools()->DrawSprite(Pos.x, Pos.y, 48.0f); i++; diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h index d41f3430..376bbf1a 100644 --- a/src/game/client/components/damageind.h +++ b/src/game/client/components/damageind.h @@ -11,7 +11,7 @@ class CDamageInd : public CComponent { vec2 m_Pos; vec2 m_Dir; - float m_StartTime; + float m_LifeTime; float m_StartAngle; }; diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index ab6ded9d..8d2ac224 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -38,7 +38,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) } static float s_LastGameTickTime = Client()->GameTickTime(); - if(!m_pClient->IsWorldPaused()) + if(!m_pClient->IsWorldPaused() && !m_pClient->IsDemoPlaybackPaused()) s_LastGameTickTime = Client()->GameTickTime(); float Ct; @@ -70,19 +70,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) const float Now = Client()->LocalTime(); static float s_Time = 0.0f; static float s_LastLocalTime = Now; - - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) - s_Time += (Now-s_LastLocalTime)*pInfo->m_Speed; - } - else - { - if(!m_pClient->IsWorldPaused()) - s_Time += Now-s_LastLocalTime; - } - + s_Time += (Now - s_LastLocalTime) * m_pClient->GetAnimationPlaybackSpeed(); Graphics()->QuadsSetRotation(s_Time*pi*2*2 + ItemID); s_LastLocalTime = Now; } @@ -152,18 +140,8 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu const float Now = Client()->LocalTime(); static float s_Time = 0.0f; static float s_LastLocalTime = Now; - float Offset = Pos.y/32.0f + Pos.x/32.0f; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) - s_Time += (Now-s_LastLocalTime)*pInfo->m_Speed; - } - else - { - if(!m_pClient->IsWorldPaused()) - s_Time += Now-s_LastLocalTime; - } + s_Time += (Now - s_LastLocalTime) * m_pClient->GetAnimationPlaybackSpeed(); + const float Offset = Pos.y/32.0f + Pos.x/32.0f; Pos.x += cosf(s_Time*2.0f+Offset)*2.5f; Pos.y += sinf(s_Time*2.0f+Offset)*2.5f; s_LastLocalTime = Now; diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index 5dfe08ec..d7556a93 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -37,18 +37,8 @@ void CParticles::OnReset() void CParticles::Add(int Group, CParticle *pPart) { - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(pInfo->m_Paused || m_pClient->IsWorldPaused()) - return; - } - else - { - if(m_pClient->IsWorldPaused()) - return; - } - + if(m_pClient->IsWorldPaused() || m_pClient->IsDemoPlaybackPaused()) + return; if (m_FirstFree == -1) return; @@ -74,17 +64,20 @@ void CParticles::Add(int Group, CParticle *pPart) void CParticles::Update(float TimePassed) { - static float FrictionFraction = 0; - FrictionFraction += TimePassed; + if(TimePassed <= 0.0f) + return; - if(FrictionFraction > 2.0f) // safty messure - FrictionFraction = 0; + static float s_FrictionFraction = 0.0f; + s_FrictionFraction += TimePassed; + + if(s_FrictionFraction > 2.0f) // safety messure + s_FrictionFraction = 0.0f; int FrictionCount = 0; - while(FrictionFraction > 0.05f) + while(s_FrictionFraction > 0.05f) { FrictionCount++; - FrictionFraction -= 0.05f; + s_FrictionFraction -= 0.05f; } for(int g = 0; g < NUM_GROUPS; g++) @@ -137,21 +130,9 @@ void CParticles::OnRender() if(Client()->State() < IClient::STATE_ONLINE) return; - static int64 s_LastTime = 0; int64 Now = time_get(); - - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(!pInfo->m_Paused && !m_pClient->IsWorldPaused()) - Update((float)((Now-s_LastTime)/(double)time_freq())*pInfo->m_Speed); - } - else - { - if(!m_pClient->IsWorldPaused()) - Update((float)((Now-s_LastTime)/(double)time_freq())); - } - + static int64 s_LastTime = Now; + Update((float)((Now-s_LastTime)/(double)time_freq()) * m_pClient->GetAnimationPlaybackSpeed()); s_LastTime = Now; } diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 6cd39d05..2f68aae1 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -169,7 +169,7 @@ void CPlayers::RenderPlayer( { m_pClient->UsePredictedChar(&Prev, &Player, &IntraTick, ClientID); } - const bool WorldPaused = m_pClient->IsWorldPaused(); + const bool Paused = m_pClient->IsWorldPaused() || m_pClient->IsDemoPlaybackPaused(); vec2 Direction = direction(Angle); vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); @@ -201,7 +201,7 @@ void CPlayers::RenderPlayer( State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f); static float s_LastGameTickTime = Client()->GameTickTime(); - if(!WorldPaused) + if(!Paused) s_LastGameTickTime = Client()->GameTickTime(); if (Player.m_Weapon == WEAPON_HAMMER) { @@ -283,21 +283,10 @@ void CPlayers::RenderPlayer( { int IteX = random_int() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; static int s_LastIteX = IteX; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(pInfo->m_Paused) - IteX = s_LastIteX; - else - s_LastIteX = IteX; - } + if(Paused) + IteX = s_LastIteX; else - { - if(WorldPaused) - IteX = s_LastIteX; - else - s_LastIteX = IteX; - } + 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); @@ -319,7 +308,7 @@ void CPlayers::RenderPlayer( // TODO: should be an animation Recoil = 0; static float s_LastIntraTick = IntraTick; - if(!WorldPaused) + if(!Paused) s_LastIntraTick = IntraTick; float a = (Client()->GameTick()-Player.m_AttackTick+s_LastIntraTick)/5.0f; @@ -345,21 +334,10 @@ void CPlayers::RenderPlayer( int IteX = random_int() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; static int s_LastIteX = IteX; - if(Client()->State() == IClient::STATE_DEMOPLAYBACK) - { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - if(pInfo->m_Paused) - IteX = s_LastIteX; - else - s_LastIteX = IteX; - } + if(Paused) + IteX = s_LastIteX; else - { - if(WorldPaused) - IteX = s_LastIteX; - else - s_LastIteX = IteX; - } + 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/client/gameclient.cpp b/src/game/client/gameclient.cpp index c948dbfa..1dfd3410 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -134,6 +134,16 @@ const char *CGameClient::GetItemName(int Type) const { return m_NetObjHandler.Ge bool CGameClient::IsXmas() const { return Config()->m_ClShowXmasHats == 2 || (Config()->m_ClShowXmasHats == 1 && m_IsXmasDay); } bool CGameClient::IsEaster() const { return Config()->m_ClShowEasterEggs == 2 || (Config()->m_ClShowEasterEggs == 1 && m_IsEasterDay); } +bool CGameClient::IsDemoPlaybackPaused() const { return Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->BaseInfo()->m_Paused; } +float CGameClient::GetAnimationPlaybackSpeed() const +{ + if(IsWorldPaused() || IsDemoPlaybackPaused()) + return 0.0f; + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + return DemoPlayer()->BaseInfo()->m_Speed; + return 1.0f; +} + enum { STR_TEAM_GAME, diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index ad868022..9eff8cc1 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -297,6 +297,8 @@ class CGameClient : public IGameClient bool IsEaster() const; int RacePrecision() const { return m_Snap.m_pGameDataRace ? m_Snap.m_pGameDataRace->m_Precision : 3; } bool IsWorldPaused() const { return m_Snap.m_pGameData && (m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)); } + bool IsDemoPlaybackPaused() const; + float GetAnimationPlaybackSpeed() const; // void DoEnterMessage(const char *pName, int ClientID, int Team); From 0c102a047eaf971de86f2ad2b4f49712447b31fc Mon Sep 17 00:00:00 2001 From: TsFreddie Date: Wed, 7 Oct 2020 10:37:55 +0800 Subject: [PATCH 464/479] fix menu tab width --- src/game/client/components/menus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index eb0048b3..fc683759 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -903,7 +903,7 @@ void CMenus::RenderMenubar(CUIRect Rect) { int NumButtons = 6; float Spacing = 3.0f; - float ButtonWidth = (Box.w / NumButtons) - (Spacing*5.0) / NumButtons; + float ButtonWidth = (Box.w/NumButtons)-(Spacing*(NumButtons-1))/NumButtons; float Alpha = 1.0f; if(m_GamePage == PAGE_SETTINGS) Alpha = InactiveAlpha; @@ -963,7 +963,7 @@ void CMenus::RenderMenubar(CUIRect Rect) { int NumButtons = 5; float Spacing = 3.0f; - float ButtonWidth = (Box.w/NumButtons)-(Spacing*5.0)/NumButtons; + float ButtonWidth = (Box.w/NumButtons)-(Spacing*(NumButtons-1))/NumButtons; float NotActiveAlpha = Client()->State() == IClient::STATE_ONLINE ? 0.5f : 1.0f; int Corners = Client()->State() == IClient::STATE_ONLINE ? CUI::CORNER_T : CUI::CORNER_ALL; From e0976ecb241bc74d8db77e05944e31137021d908 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 9 Oct 2020 10:08:08 +0200 Subject: [PATCH 465/479] skip self-assignment --- src/game/client/components/damageind.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index 648a3ec3..2c6789bb 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -28,7 +28,8 @@ CDamageInd::CItem *CDamageInd::CreateItem() void CDamageInd::DestroyItem(CDamageInd::CItem *pItem) { m_NumItems--; - *pItem = m_aItems[m_NumItems]; + if(pItem != &m_aItems[m_NumItems]) + *pItem = m_aItems[m_NumItems]; } void CDamageInd::Create(vec2 Pos, vec2 Dir) From 740555190a7f98ba94862e8cd01bde1a19ee6d31 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 9 Oct 2020 10:15:33 +0200 Subject: [PATCH 466/479] show client address on auth. closes #2767 --- src/engine/server/server.cpp | 8 ++++++-- src/engine/shared/econ.cpp | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 0089d925..bab85c69 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1037,8 +1037,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if(m_aClients[ClientID].m_Version >= MIN_MAPLIST_CLIENTVERSION) m_aClients[ClientID].m_pMapListEntryToSend = m_pFirstMapEntry; SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted."); + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); + str_format(aBuf, sizeof(aBuf), "ClientID=%d addr=%s authed (admin)", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(Config()->m_SvRconModPassword[0] && str_comp(pPw, Config()->m_SvRconModPassword) == 0) @@ -1052,8 +1054,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) const IConsole::CCommandInfo *pInfo = Console()->GetCommandInfo("sv_map", CFGFLAG_SERVER, false); if(pInfo && pInfo->GetAccessLevel() == IConsole::ACCESS_LEVEL_MOD && m_aClients[ClientID].m_Version >= MIN_MAPLIST_CLIENTVERSION) m_aClients[ClientID].m_pMapListEntryToSend = m_pFirstMapEntry; + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); + str_format(aBuf, sizeof(aBuf), "ClientID=%d addr=%s authed (moderator)", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(Config()->m_SvRconMaxTries && m_ServerBan.IsBannable(m_NetServer.ClientAddr(ClientID))) diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp index 0aff8720..6a62c381 100644 --- a/src/engine/shared/econ.cpp +++ b/src/engine/shared/econ.cpp @@ -124,7 +124,9 @@ void CEcon::Update() m_aClients[ClientID].m_State = CClient::STATE_AUTHED; m_NetConsole.Send(ClientID, "Authentication successful. External console access granted."); - str_format(aBuf, sizeof(aBuf), "cid=%d authed", ClientID); + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); + str_format(aBuf, sizeof(aBuf), "cid=%d addr=%s authed", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf); } else From ec59e654c357c683e91a3f31bdc817591bb187d9 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 9 Oct 2020 10:21:12 +0200 Subject: [PATCH 467/479] limit skin (part) names by number of characters and not the memory size --- src/game/client/components/skins.cpp | 8 ++++---- src/game/client/components/skins.h | 4 ++-- src/game/client/gameclient.cpp | 4 ++-- src/game/server/gamecontext.cpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index fb823a67..0d625721 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -92,7 +92,7 @@ int CSkins::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser) Part.m_Flags |= SKINFLAG_SPECIAL; if(DirType != IStorage::TYPE_SAVE) Part.m_Flags |= SKINFLAG_STANDARD; - str_truncate(Part.m_aName, sizeof(Part.m_aName), pName, str_length(pName) - 4); + str_utf8_copy_num(Part.m_aName, pName, min(str_length(pName) - 3, int(sizeof(Part.m_aName))), MAX_SKIN_LENGTH); if(pSelf->Config()->m_Debug) { str_format(aBuf, sizeof(aBuf), "load skin part %s", Part.m_aName); @@ -123,7 +123,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) // init CSkin Skin = pSelf->m_DummySkin; - str_truncate(Skin.m_aName, sizeof(Skin.m_aName), pName, str_length(pName) - 5); + str_utf8_copy_num(Skin.m_aName, pName, min(str_length(pName) - 4, int(sizeof(Skin.m_aName))), MAX_SKIN_LENGTH); if(pSelf->Find(Skin.m_aName, true) != -1) return 0; bool SpecialSkin = pName[0] == 'x' && pName[1] == '_'; @@ -341,7 +341,7 @@ void CSkins::AddSkin(const char *pSkinName) { CSkin Skin = m_DummySkin; Skin.m_Flags = 0; - str_copy(Skin.m_aName, pSkinName, sizeof(Skin.m_aName)); + str_utf8_copy_num(Skin.m_aName, pSkinName, sizeof(Skin.m_aName), MAX_SKIN_LENGTH); for(int PartIndex = 0; PartIndex < NUM_SKINPARTS; ++PartIndex) { int SkinPart = FindSkinPart(PartIndex, ms_apSkinVariables[PartIndex], false); @@ -350,7 +350,7 @@ void CSkins::AddSkin(const char *pSkinName) Skin.m_aUseCustomColors[PartIndex] = *ms_apUCCVariables[PartIndex]; Skin.m_aPartColors[PartIndex] = *ms_apColorVariables[PartIndex]; } - int SkinIndex = Find(pSkinName, false); + int SkinIndex = Find(Skin.m_aName, false); if(SkinIndex != -1) m_aSkins[SkinIndex] = Skin; else diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index ca660e00..54e84993 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -26,7 +26,7 @@ class CSkins : public CComponent struct CSkinPart { int m_Flags; - char m_aName[MAX_SKIN_LENGTH]; + char m_aName[MAX_SKIN_LENGTH*UTF8_BYTE_LENGTH]; IGraphics::CTextureHandle m_OrgTexture; IGraphics::CTextureHandle m_ColorTexture; vec3 m_BloodColor; @@ -37,7 +37,7 @@ class CSkins : public CComponent struct CSkin { int m_Flags; - char m_aName[MAX_SKIN_LENGTH]; + char m_aName[MAX_SKIN_LENGTH*UTF8_BYTE_LENGTH]; const CSkinPart *m_apParts[NUM_SKINPARTS]; int m_aPartColors[NUM_SKINPARTS]; int m_aUseCustomColors[NUM_SKINPARTS]; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1dfd3410..eafca181 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -872,7 +872,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; for(int i = 0; i < NUM_SKINPARTS; i++) { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], MAX_SKIN_LENGTH); + str_utf8_copy_num(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], sizeof(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i]), MAX_SKIN_LENGTH); m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; } @@ -944,7 +944,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) for(int i = 0; i < NUM_SKINPARTS; i++) { - str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], MAX_SKIN_LENGTH); + str_utf8_copy_num(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], sizeof(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i]), MAX_SKIN_LENGTH); m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index b6718b91..ac9609dc 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1080,7 +1080,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], MAX_SKIN_LENGTH); + str_utf8_copy_num(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], sizeof(pPlayer->m_TeeInfos.m_aaSkinPartNames[p]), MAX_SKIN_LENGTH); pPlayer->m_TeeInfos.m_aUseCustomColors[p] = pMsg->m_aUseCustomColors[p]; pPlayer->m_TeeInfos.m_aSkinPartColors[p] = pMsg->m_aSkinPartColors[p]; } @@ -1119,7 +1119,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) for(int p = 0; p < NUM_SKINPARTS; p++) { - str_copy(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], MAX_SKIN_LENGTH); + str_utf8_copy_num(pPlayer->m_TeeInfos.m_aaSkinPartNames[p], pMsg->m_apSkinPartNames[p], sizeof(pPlayer->m_TeeInfos.m_aaSkinPartNames[p]), MAX_SKIN_LENGTH); pPlayer->m_TeeInfos.m_aUseCustomColors[p] = pMsg->m_aUseCustomColors[p]; pPlayer->m_TeeInfos.m_aSkinPartColors[p] = pMsg->m_aSkinPartColors[p]; } From c397fdf5a8bb8451f9a5ed5ef5571a000007792c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 10 Oct 2020 11:40:35 +0200 Subject: [PATCH 468/479] implement absolute joystick ingame input mode --- src/engine/client/input.cpp | 18 +++++++++- src/engine/client/input.h | 1 + src/engine/input.h | 5 +-- src/engine/shared/config_variables.h | 1 + src/game/client/components/controls.cpp | 34 +++++++++++++------ src/game/client/components/controls.h | 1 + src/game/client/components/menus_callback.cpp | 28 +++++++++++---- 7 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 2ae03469..e0911109 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -222,6 +222,22 @@ bool CInput::JoystickRelative(float *pX, float *pY) return false; } +bool CInput::JoystickAbsolute(float *pX, float *pY) +{ + if(m_pConfig->m_JoystickEnable && GetActiveJoystick()) + { + const vec2 RawJoystickPos = vec2(GetJoystickAxisValue(m_pConfig->m_JoystickX), GetJoystickAxisValue(m_pConfig->m_JoystickY)); + const float DeadZone = m_pConfig->m_JoystickTolerance/50.0f; + if(length(RawJoystickPos) > DeadZone) + { + *pX = RawJoystickPos.x; + *pY = RawJoystickPos.y; + return true; + } + } + return false; +} + bool CInput::MouseRelative(float *pX, float *pY) { if(!m_MouseInputRelative) @@ -229,7 +245,7 @@ bool CInput::MouseRelative(float *pX, float *pY) int MouseX = 0, MouseY = 0; SDL_GetRelativeMouseState(&MouseX, &MouseY); - if (MouseX || MouseY) + if(MouseX || MouseY) { *pX = MouseX; *pY = MouseY; diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 929d53aa..64a16241 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -56,6 +56,7 @@ class CInput : public IEngineInput int GetJoystickNumAxes(); float GetJoystickAxisValue(int Axis); bool JoystickRelative(float *pX, float *pY); + bool JoystickAbsolute(float *pX, float *pY); void MouseModeRelative(); void MouseModeAbsolute(); diff --git a/src/engine/input.h b/src/engine/input.h index bfa9bdb2..9ba9223c 100644 --- a/src/engine/input.h +++ b/src/engine/input.h @@ -72,6 +72,7 @@ class IInput : public IInterface virtual int GetJoystickNumAxes() = 0; virtual float GetJoystickAxisValue(int Axis) = 0; virtual bool JoystickRelative(float *pX, float *pY) = 0; + virtual bool JoystickAbsolute(float *pX, float *pY) = 0; // mouse virtual void MouseModeRelative() = 0; @@ -85,9 +86,9 @@ class IInput : public IInterface int CursorRelative(float *pX, float *pY) { - if (MouseRelative(pX, pY)) + if(MouseRelative(pX, pY)) return CURSOR_MOUSE; - if (JoystickRelative(pX, pY)) + if(JoystickRelative(pX, pY)) return CURSOR_JOYSTICK; return CURSOR_NONE; } diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 00467cdc..a1ae26c7 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -75,6 +75,7 @@ MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 1, 100000, CFGFLAG_SAVE|CFGFL MACRO_CONFIG_INT(JoystickEnable , joystick_enable, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable joystick") MACRO_CONFIG_STR(JoystickGUID, joystick_guid, 34, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick GUID which uniquely identifies the active joystick") +MACRO_CONFIG_INT(JoystickAbsolute, joystick_absolute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable absolute joystick aiming ingame") MACRO_CONFIG_INT(JoystickSens, joystick_sens, 100, 1, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick sensitivity") MACRO_CONFIG_INT(JoystickX, joystick_x, 0, 0, 12, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls X axis of cursor") MACRO_CONFIG_INT(JoystickY, joystick_y, 1, 0, 12, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Joystick axis that controls Y axis of cursor") diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 02644816..c154ac93 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -212,6 +212,17 @@ bool CControls::OnCursorMove(float x, float y, int CursorType) if(m_pClient->IsWorldPaused() || (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) return false; + if(CursorType == IInput::CURSOR_JOYSTICK + && Config()->m_JoystickAbsolute + && m_pClient->m_Snap.m_pGameData + && !m_pClient->m_Snap.m_SpecInfo.m_Active) + { + float absX = 0.0f, absY = 0.0f; + if(Input()->JoystickAbsolute(&absX, &absY)) + m_MousePos = vec2(absX, absY) * GetMaxMouseDistance(); + return true; + } + float Factor = 1.0f; switch(CursorType) { @@ -236,17 +247,20 @@ void CControls::ClampMousePos() } else { - float MouseMax; - if(Config()->m_ClDynamicCamera) - { - float CameraMaxDistance = 200.0f; - float FollowFactor = Config()->m_ClMouseFollowfactor/100.0f; - MouseMax = min(CameraMaxDistance/FollowFactor + Config()->m_ClMouseDeadzone, (float)Config()->m_ClMouseMaxDistanceDynamic); - } - else - MouseMax = (float)Config()->m_ClMouseMaxDistanceStatic; - + const float MouseMax = GetMaxMouseDistance(); if(length(m_MousePos) > MouseMax) m_MousePos = normalize(m_MousePos)*MouseMax; } } + +float CControls::GetMaxMouseDistance() const +{ + if(Config()->m_ClDynamicCamera) + { + float CameraMaxDistance = 200.0f; + float FollowFactor = Config()->m_ClMouseFollowfactor/100.0f; + return min(CameraMaxDistance/FollowFactor + Config()->m_ClMouseDeadzone, (float)Config()->m_ClMouseMaxDistanceDynamic); + } + else + return (float)Config()->m_ClMouseMaxDistanceStatic; +} diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h index 172403b2..9155f67c 100644 --- a/src/game/client/components/controls.h +++ b/src/game/client/components/controls.h @@ -28,5 +28,6 @@ class CControls : public CComponent int SnapInput(int *pData); void ClampMousePos(); + float GetMaxMouseDistance() const; }; #endif diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index 7cb8f280..2851f203 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -168,7 +168,11 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) { NumOptions++; // joystick selection } - NumOptions += 3; // ingame sens, ui sens, tolerance + NumOptions += 3; // mode, ui sens, tolerance + if(!Config()->m_JoystickAbsolute) + { + NumOptions++; // ingame sens + } NumOptions += m_pClient->Input()->GetJoystickNumAxes(); // axis selection } const float ButtonHeight = 20.0f; @@ -181,8 +185,7 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) CUIRect Button; View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - static int s_ButtonJoystickEnable = 0; - if(DoButton_CheckBox(&s_ButtonJoystickEnable, Localize("Enable joystick"), Config()->m_JoystickEnable, &Button)) + if(DoButton_CheckBox(&Config()->m_JoystickEnable, Localize("Enable joystick"), Config()->m_JoystickEnable, &Button)) { Config()->m_JoystickEnable ^= 1; } @@ -204,13 +207,24 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View) } } - View.HSplitTop(Spacing, 0, &View); - View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->m_JoystickSens, &Config()->m_JoystickSens, &Button, Localize("Ingame joystick sens."), 1, 500, &LogarithmicScrollbarScale); + { + View.HSplitTop(Spacing, 0, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + const int NumLabels = 2; + const char *aLabels[NumLabels] = { Localize("Relative", "Ingame joystick mode"), Localize("Absolute", "Ingame joystick mode")}; + DoScrollbarOptionLabeled(&Config()->m_JoystickAbsolute, &Config()->m_JoystickAbsolute, &Button, Localize("Ingame joystick mode"), aLabels, NumLabels); + } + + if(!Config()->m_JoystickAbsolute) + { + View.HSplitTop(Spacing, 0, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + DoScrollbarOption(&Config()->m_JoystickSens, &Config()->m_JoystickSens, &Button, Localize("Ingame joystick sensitivity"), 1, 500, &LogarithmicScrollbarScale); + } View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); - DoScrollbarOption(&Config()->m_UiJoystickSens, &Config()->m_UiJoystickSens, &Button, Localize("Menu/Editor joystick sens."), 1, 500, &LogarithmicScrollbarScale); + DoScrollbarOption(&Config()->m_UiJoystickSens, &Config()->m_UiJoystickSens, &Button, Localize("Menu/Editor joystick sensitivity"), 1, 500, &LogarithmicScrollbarScale); View.HSplitTop(Spacing, 0, &View); View.HSplitTop(ButtonHeight, &Button, &View); From 150eef9ce526c632e83a583021709ba084822a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 10 Oct 2020 11:45:51 +0200 Subject: [PATCH 469/479] allow clicking on labeled scrollbar option to toggle --- src/game/client/components/menus.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index fc683759..8e1bbecd 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -583,6 +583,9 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR ScrollBar.VMargin(4.0f, &ScrollBar); Value = pScale->ToAbsolute(DoScrollbarH(pID, &ScrollBar, pScale->ToRelative(Value, 0, Max)), 0, Max); + if(UI()->HotItem() != pID && UI()->MouseHovered(pRect) && UI()->MouseButtonClicked(0)) + Value = (Value + 1) % Num; + *pOption = clamp(Value, 0, Max); } From eba75c094e2fa31150060d703374a1967db83d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 10 Oct 2020 12:05:39 +0200 Subject: [PATCH 470/479] fix inconsistent left padding of labeled scrollbar option --- src/game/client/components/menus.cpp | 3 +-- src/game/client/components/menus_settings.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8e1bbecd..cc04bfe2 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -574,9 +574,8 @@ void CMenus::DoScrollbarOptionLabeled(void *pID, int *pOption, const CUIRect *pR RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Label, ScrollBar; - pRect->VSplitLeft(5.0f, 0, &Label); + pRect->VSplitLeft(pRect->h+5.0f, 0, &Label); Label.VSplitRight(60.0f, &Label, &ScrollBar); - Label.y += 2.0f; UI()->DoLabel(&Label, aBuf, FontSize, CUI::ALIGN_LEFT); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 48e2e9fd..1a26c51a 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -966,7 +966,6 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) { GameRight.HSplitTop(Spacing, 0, &GameRight); GameRight.HSplitTop(ButtonHeight, &Button, &GameRight); - Button.VSplitLeft(ButtonHeight, 0, &Button); /*RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); CUIRect Text; Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button); From c10d0617b50aa8aaf003b268dd7cbd9523e9b0ca Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 11 Oct 2020 17:30:02 +0200 Subject: [PATCH 471/479] Fix uninitialized variable --- src/game/client/components/voting.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index 855ce4d5..8aed5581 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -124,8 +124,7 @@ void CVoting::AddOption(const char *pDescription) for(;*pDescription == '#'; pDescription++, Depth++); pOption->m_Depth = Depth ? Depth : pOption->m_pPrev ? pOption->m_pPrev->m_Depth : 0; - if(Depth) - pOption->m_IsSubheader = true; + pOption->m_IsSubheader = Depth; if(!*pDescription) pOption->m_Depth = 0; From dafaf824d798c7e2f52ab1df0213f3cdf4ab0b59 Mon Sep 17 00:00:00 2001 From: Learath2 Date: Sun, 11 Oct 2020 17:38:42 +0200 Subject: [PATCH 472/479] Fix uninitialized variable in CButtonContainer --- src/game/client/components/menus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index f5de4a58..975cd891 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -102,7 +102,7 @@ class CMenus : public CComponent bool m_CleanBackground; float m_FadeStartTime; public: - CButtonContainer(bool CleanBackground = false) { m_CleanBackground = CleanBackground; } + CButtonContainer(bool CleanBackground = false) : m_FadeStartTime(0.0f) { m_CleanBackground = CleanBackground; } const void *GetID() const { return &m_FadeStartTime; } float GetFade(bool Checked = false, float Seconds = 0.6f); bool IsCleanBackground() const { return m_CleanBackground; } From 46c84a6c0befa61d5de5cc36812cc7396f60e086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 11 Oct 2020 20:44:16 +0200 Subject: [PATCH 473/479] fix vertical alignment of browser entries with wide view --- src/game/client/components/menus_browser.cpp | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 4d3674db..e478d833 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -528,13 +528,13 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn { TextRender()->TextColor(TextBaseColor); TextRender()->TextOutlineColor(TextBaseOutlineColor); - Button.y += 2.0f; + Button.y += (Button.h - FontSize/ms_FontmodHeight)/2.0f; UI()->DoLabelHighlighted(&Button, pEntry->m_aName, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } else if(ID == COL_BROWSER_MAP) { TextRender()->TextColor(TextBaseColor); - Button.y += 2.0f; + Button.y += (Button.h - FontSize/ms_FontmodHeight)/2.0f; UI()->DoLabelHighlighted(&Button, pEntry->m_aMap, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_MAPNAME) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } else if(ID == COL_BROWSER_PLAYERS) @@ -563,19 +563,19 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } } - static float RenderOffset = 0.0f; - if(RenderOffset == 0.0f) - RenderOffset = TextRender()->TextWidth(0, FontSize, "0", -1, -1.0f); + static float s_RenderOffset = 0.0f; + if(s_RenderOffset == 0.0f) + s_RenderOffset = TextRender()->TextWidth(0, FontSize, "0", -1, -1.0f); str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max); if(Config()->m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER)) TextRender()->TextColor(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextAlpha); - Button.y += 2.0f; + Button.y += (Button.h - FontSize/ms_FontmodHeight)/2.0f; if(Num < 100) - Button.x += RenderOffset; + Button.x += s_RenderOffset; if(Num < 10) - Button.x += RenderOffset; + Button.x += s_RenderOffset; if(!Num) TextRender()->TextColor(CUI::ms_TransparentTextColor); UI()->DoLabel(&Button, aTemp, FontSize, CUI::ALIGN_LEFT); @@ -583,7 +583,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn } else if(ID == COL_BROWSER_PING) { - int Ping = pEntry->m_Latency; + const int Ping = pEntry->m_Latency; vec4 Color; if(Selected || Highlighted) @@ -612,10 +612,10 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn Color = mix(StartColor, EndColor, MixVal); } - str_format(aTemp, sizeof(aTemp), "%d", pEntry->m_Latency); + str_format(aTemp, sizeof(aTemp), "%d", Ping); TextRender()->TextColor(Color); TextRender()->TextOutlineColor(TextBaseOutlineColor); - Button.y += 2.0f; + Button.y += (Button.h - FontSize/ms_FontmodHeight)/2.0f; Button.w -= 4.0f; UI()->DoLabel(&Button, aTemp, FontSize, CUI::ALIGN_RIGHT); } @@ -630,7 +630,7 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn // gametype text TextRender()->TextColor(TextBaseColor); TextRender()->TextOutlineColor(TextBaseOutlineColor); - Button.y += 2.0f; + Button.y += (Button.h - FontSize/ms_FontmodHeight)/2.0f; UI()->DoLabelHighlighted(&Button, pEntry->m_aGameType, (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_GAMETYPE) ? Config()->m_BrFilterString : 0, FontSize, TextBaseColor, HighlightColor); } } @@ -2127,7 +2127,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int s_pLastInfo = pInfo; const float RowWidth = (RowCount == 0) ? View.w : (View.w * 0.25f); - const float FontSize = 8.0f; + const float FontSize = Config()->m_UiWideview ? 8.0f : 7.0f; const vec4 HighlightColor = vec4(TextHighlightColor.r, TextHighlightColor.g, TextHighlightColor.b, TextColor.a); float LineHeight = 20.0f; @@ -2207,7 +2207,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int // score if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)) { - Score.y += 4.0f; + Score.y += (Score.h - FontSize/ms_FontmodHeight)/2.0f; char aTemp[16]; FormatScore(aTemp, sizeof(aTemp), pInfo->m_Flags&IServerBrowser::FLAG_TIMESCORE, &pInfo->m_aClients[i]); UI()->DoLabel(&Score, aTemp, FontSize, CUI::ALIGN_LEFT); From b656a89a72499933594a7009782eb6afc0cd8f59 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Thu, 15 Oct 2020 16:47:49 +0200 Subject: [PATCH 474/479] Remove whitespace in release script #hacktoberfest future employee pls don't fire me for shitty prs i did today --- scripts/make_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/make_release.py b/scripts/make_release.py index 59b13049..23a13ad8 100644 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -142,7 +142,7 @@ def shell(cmd): if include_exe and not use_bundle: shutil.copy(source_package_dir+name+exe_ext, package_dir) shutil.copy(source_package_dir+name+"_srv"+exe_ext, package_dir) - + if include_src: for p in ["src", "scripts", "datasrc", "other", "objs"]: os.mkdir(os.path.join(package_dir, p)) From b969541498722d1240d7b4af383ee278cc0b34a6 Mon Sep 17 00:00:00 2001 From: Marvin Winkens Date: Sun, 18 Oct 2020 15:54:42 +0200 Subject: [PATCH 475/479] merged --- src/game/server/entities/character.cpp | 2 +- src/game/server/entities/pickup.cpp | 4 ++-- src/game/server/gamecontext.cpp | 8 +++++--- src/game/server/gamecontroller.cpp | 5 +---- src/game/server/gamecontroller.h | 6 +++++- src/game/version.h | 1 - 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 0c64c473..919deed6 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -751,7 +751,7 @@ bool CCharacter::TakeDamage(vec2 Force, vec2 Source, int Dmg, int From, int Weap OR Weapon is Grenade and Damage is too small (prevents Explosions beeing to strong)*/ if((GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetTeamID() == m_pPlayer->GetTeamID() && From != m_pPlayer->GetCID()) || (From == m_pPlayer->GetCID() && Weapon >= WEAPON_HAMMER) - || (Weapon == WEAPON_GRENADE && Dmg < g_Config.m_SvMinGrenadeDmg)) + || (Weapon == WEAPON_GRENADE && Dmg < Config()->m_SvMinGrenadeDmg)) { return false; } diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index e00ecd04..bf386254 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -30,7 +30,7 @@ void CPickup::Reset() void CPickup::Tick() { // wait for respawn - if((!g_Config.m_SvAllowPickups && (m_Type == PICKUP_HEALTH || PICKUP_ARMOR)) || (!g_Config.m_SvAllowWeaponPickups && m_Type != PICKUP_HEALTH && m_Type != PICKUP_ARMOR)) + if((!Config()->m_SvAllowPickups && (m_Type == PICKUP_HEALTH || PICKUP_ARMOR)) || (!Config()->m_SvAllowWeaponPickups && m_Type != PICKUP_HEALTH && m_Type != PICKUP_ARMOR)) return; if(m_SpawnTick > 0) { @@ -140,7 +140,7 @@ void CPickup::TickPaused() void CPickup::Snap(int SnappingClient) { - if(m_SpawnTick != -1 || NetworkClipped(SnappingClient) || ((!g_Config.m_SvAllowPickups && (m_Type == PICKUP_HEALTH || PICKUP_ARMOR)) || (!g_Config.m_SvAllowWeaponPickups && m_Type != PICKUP_HEALTH && m_Type != PICKUP_ARMOR))) + if(m_SpawnTick != -1 || NetworkClipped(SnappingClient) || ((!Config()->m_SvAllowPickups && (m_Type == PICKUP_HEALTH || PICKUP_ARMOR)) || (!Config()->m_SvAllowWeaponPickups && m_Type != PICKUP_HEALTH && m_Type != PICKUP_ARMOR))) return; CNetObj_Pickup *pP = static_cast(Server()->SnapNewItem(NETOBJTYPE_PICKUP, GetID(), sizeof(CNetObj_Pickup))); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index c8663eab..e691d5a8 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1344,11 +1344,11 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; else if(pPlayer->m_LastKillRequest+Server()->TickSpeed()*1 > Server()->Tick()) return;//don't send a message - else if(pPlayer->m_LastKill && pPlayer->m_LastKill+Server()->TickSpeed()*g_Config.m_SvSelfkillCooldown > Server()->Tick()) + else if(pPlayer->m_LastKill && pPlayer->m_LastKill+Server()->TickSpeed()*Config()->m_SvSelfkillCooldown > Server()->Tick()) { pPlayer->m_LastKillRequest = Server()->Tick(); char aSelfkill[128]; - float seconds = (pPlayer->m_LastKill+Server()->TickSpeed()*g_Config.m_SvSelfkillCooldown-Server()->Tick()*1.0f)/Server()->TickSpeed(); + float seconds = (pPlayer->m_LastKill+Server()->TickSpeed()*Config()->m_SvSelfkillCooldown-Server()->Tick()*1.0f)/Server()->TickSpeed(); str_format(aSelfkill, sizeof(aSelfkill), "You can't kill yourself for %.2f second(s)", seconds); SendServerInfo(aSelfkill, ClientID); return; @@ -1877,9 +1877,11 @@ void CGameContext::OnInit() m_Collision.Init(&m_Layers); // select gametype + m_pController = new CGameControllerCatch64(this); - m_pController->RegisterChatCommands(CommandManager()); + // IDK how this works now + //m_pController->RegisterChatCommands(CommandManager()); // create all entities from the game layer CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer(); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index a1f2ee9c..1c82eca0 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -57,9 +57,6 @@ IGameController::IGameController(CGameContext *pGameServer) m_TopTeam = -1; m_StartWeapon = 4;//Weapon laser; - - // commands - CommandsManager()->OnInit(); } //activity @@ -657,7 +654,7 @@ void IGameController::SetGameState(EGameState GameState, int Timer) GameServer()->m_World.m_Paused = true; if(m_TopTeam >= 0 && m_TopTeam < MAX_PLAYERS && GameServer()->m_apPlayers[m_TopTeam]) { char aBuf[256]; - GameServer()->m_apPlayers[m_TopTeam]->m_Score+=g_Config.m_SvWinBonus; + GameServer()->m_apPlayers[m_TopTeam]->m_Score+=Config()->m_SvWinBonus; char colorbuf[5]; TeamHandler::getInstance().HSLtoRGBString(m_TopTeam, colorbuf); str_format(aBuf, sizeof(aBuf), "%s■■■^999 Team '%s' of player '%s' won the round! %s■■■", colorbuf, TeamHandler::getInstance().GetTeamName(m_TopTeam), Server()->ClientName(m_TopTeam), colorbuf); diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index f89d5f2e..810f11a1 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -132,6 +132,10 @@ class IGameController int m_TopscoreCount; + void ComSendMessageList(std::vector& messageList, const int ClientID); + void ComHelp(class IGameController* pGameController, class CPlayer *pPlayer, const char *pArgs); + void ComInfo(class IGameController* pGameController, class CPlayer *pPlayer, const char *pArgs); + public: IGameController(class CGameContext *pGameServer); @@ -243,7 +247,7 @@ class IGameController int GetStartWeapon(){ return m_StartWeapon;} //static void Com_Example(IConsole::IResult *pResult, void *pContext); - virtual void RegisterChatCommands(CCommandManager *pManager); + //virtual void RegisterChatCommands(CCommandManager *pManager); }; #endif diff --git a/src/game/version.h b/src/game/version.h index 0f52d471..cdd5c22f 100644 --- a/src/game/version.h +++ b/src/game/version.h @@ -9,7 +9,6 @@ #define CLIENT_VERSION 0x0705 #define PREV_CLIENT_VERSION 0x0704 #define SETTINGS_FILENAME "settings07" -<<<<<<< HEAD static const char GAME_RELEASE_VERSION[8] = "0.7.5"; #define CATCH_VERSION "1.2.0" #endif From b5aec8b33173b8741fe031888dedea176a71500c Mon Sep 17 00:00:00 2001 From: Marvin Winkens Date: Sun, 18 Oct 2020 16:31:59 +0200 Subject: [PATCH 476/479] added random spawns and laserjump --- src/game/server/entities/laser.cpp | 7 ++++ src/game/server/gamecontroller.cpp | 55 ++++++++++++++++++++++++++++-- src/game/server/gamecontroller.h | 1 + src/game/variables.h | 6 ++++ 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 8bc9194c..09580e2b 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.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 @@ -68,6 +70,11 @@ void CLaser::DoBounce() m_Energy = -1; GameServer()->CreateSound(m_Pos, SOUND_LASER_BOUNCE); + + if(Config()->m_SvLaserJump) + { + GameServer()->CreateExplosion(m_Pos, m_Owner, WEAPON_LASER, Config()->m_SvLaserExplosionDamage); + } } } else diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 1c82eca0..0e831c48 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -1059,9 +1059,16 @@ bool IGameController::CanSpawn(int Team, vec2 *pOutPos) const } else { - EvaluateSpawnType(&Eval, 0); - EvaluateSpawnType(&Eval, 1); - EvaluateSpawnType(&Eval, 2); + if(Config()->m_SvRandomSpawn)//random spawning + { + EvaluateSpawnRandom(&Eval); + } + else//classical spawning + { + EvaluateSpawnType(&Eval, 0); + EvaluateSpawnType(&Eval, 1); + EvaluateSpawnType(&Eval, 2); + } } *pOutPos = Eval.m_Pos; @@ -1121,6 +1128,48 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type) const } } +void IGameController::EvaluateSpawnRandom(CSpawnEval *pEval) const +{ + int spawn_tries = Config()->m_SvRandomSpawnTries; + while(spawn_tries--) + { + int spawn_type = rand()%3; + if(m_aNumSpawnPoints[spawn_type]) + { + int spawn_id = rand()%m_aNumSpawnPoints[spawn_type]; + + // check if the position is occupado (occupied) + CCharacter *aEnts[MAX_CLIENTS]; + int Num = GameServer()->m_World.FindEntities(m_aaSpawnPoints[spawn_type][spawn_id], 64, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); + vec2 Positions[5] = { vec2(0.0f, 0.0f), vec2(-32.0f, 0.0f), vec2(0.0f, -32.0f), vec2(32.0f, 0.0f), vec2(0.0f, 32.0f) }; // start, left, up, right, down + int Result = -1; + for(int Index = 0; Index < 5 && Result == -1; ++Index) + { + Result = Index; + for(int c = 0; c < Num; ++c) + if(GameServer()->Collision()->CheckPoint(m_aaSpawnPoints[spawn_type][spawn_id]+Positions[Index]) || + distance(aEnts[c]->GetPos(), m_aaSpawnPoints[spawn_type][spawn_id]+Positions[Index]) <= aEnts[c]->GetProximityRadius()) + { + Result = -1; + break; + } + } + if(Result == -1) + continue; // try next spawn point + + vec2 P = m_aaSpawnPoints[spawn_type][spawn_id]+Positions[Result]; + float S = pEval->m_RandomSpawn ? random_int() : EvaluateSpawnPos(pEval, P); + if(!pEval->m_Got || pEval->m_Score > S) + { + pEval->m_Got = true; + pEval->m_Score = S; + pEval->m_Pos = P; + break;//Found Spawn, I don't care about the score, maybe future Assa will + } + } + } +} + bool IGameController::GetStartRespawnState() const { if(m_GameFlags&GAMEFLAG_SURVIVAL) diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 810f11a1..c034d309 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -94,6 +94,7 @@ class IGameController float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) const; void EvaluateSpawnType(CSpawnEval *pEval, int Type) const; + void EvaluateSpawnRandom(CSpawnEval *pEval) const; // team int ClampTeam(int Team) const; diff --git a/src/game/variables.h b/src/game/variables.h index 4d09ca87..b226bc2b 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -147,6 +147,12 @@ MACRO_CONFIG_INT(SvSelfkillCooldown, sv_selfkill_cooldown, 15, 3, 9999, CFGFLAG_ MACRO_CONFIG_INT(SvWinBonus, sv_win_bonus, 5, 0, 9999, CFGFLAG_SAVE|CFGFLAG_SERVER, "Bonus for Winning Team leader"); MACRO_CONFIG_INT(SvMinGrenadeDmg, sv_min_grenade_dmg, 4, 0, 6, CFGFLAG_SAVE|CFGFLAG_SERVER, "Minium damage for players to switch team"); +MACRO_CONFIG_INT(SvLaserJump, sv_laser_jump, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVER, "Laser Explosions"); +MACRO_CONFIG_INT(SvLaserExplosionDamage, sv_laser_explosion_damage, 4, 0, 6, CFGFLAG_SAVE|CFGFLAG_SERVER, "Laser Explosion Damage"); + +MACRO_CONFIG_INT(SvRandomSpawn, sv_random_spawn, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVER, "Activate Random Spawning"); +MACRO_CONFIG_INT(SvRandomSpawnTries, sv_random_spawn, 100, 1, 9999, CFGFLAG_SAVE|CFGFLAG_SERVER, "Tries for random spawn per player per tick"); + // debug #ifdef CONF_DEBUG // this one can crash the server if not used correctly MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "") From 18362adcd7357a8ca95b1703c1373bd570144965 Mon Sep 17 00:00:00 2001 From: Marvin Winkens Date: Sun, 18 Oct 2020 16:41:49 +0200 Subject: [PATCH 477/479] updated readme and variables --- README.md | 80 ++++++++++++++++++++++++++++++++++++++++++++ src/game/variables.h | 2 +- 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..672275ee --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# catch64 +[![Actions Status](https://github.com/AssassinTee/catch64/workflows/All%20OS/badge.svg)](https://github.com/AssassinTee/catch64/actions) +[![CircleCI](https://circleci.com/gh/AssassinTee/catch64.svg?style=shield)](https://circleci.com/gh/AssassinTee/catch64) +[![Build status](https://ci.appveyor.com/api/projects/status/uai64nkyvc8tgc36/branch/master?svg=true)](hhttps://ci.appveyor.com/project/AssassinTee/catch64) +[![release version](https://img.shields.io/badge/releases-Unix%20%7C%20Windows%20%7C%20MacOS-brightgreen)](https://github.com/AssassinTee/catch64/releases) +![Teeworlds version](https://img.shields.io/badge/Teeworlds-0.7.5-brightgreen.svg) +[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/AssassinTee/catch64/issues) + +![Nice](https://i.imgur.com/nhr0NEl.png) +![haha](https://i.imgur.com/PNYZgvm.png) + +## Description +catch64 is a -Mod for the retro-multiplayergame [Teeworlds](www.teeworlds.com). +It is written for Teeworlds 0.7 and supports 64 players. +If you hit someone, he is in your team and gets your colors and skin. +If he hits someone, the hit player is in your team, too. +Colorcatch is easy to understand. + +## Installing + +You need the dependencies for hosting AND/OR compiling the server + +``` +# Debian/Ubuntu +sudo apt install build-essential cmake git libfreetype6-dev libsdl2-dev libpnglite-dev libwavpack-dev python3 + +# Fedora +sudo dnf install @development-tools cmake gcc-c++ git freetype-devel mesa-libGLU-devel pnglite-devel python3 SDL2-devel wavpack-devel + +# Arch Linux (doesn't have pnglite in its repositories) +sudo pacman -S --needed base-devel cmake freetype2 git glu python sdl2 wavpack + +# macOS +sudo brew install cmake freetype sdl2 +``` + +## Getting Started + +* clone this repository + +* compile the game the same way, you [compile default Teeworlds](https://www.teeworlds.com/?page=docs&wiki=compiling_everything). Remember, that this mod is written for **Teeworlds 0.7.x**. You only need the server, so use the command `/bam conf=release server` for compiling + +* start the server with + + * Linux: `./teeworlds_srv` (It may be found under /build) + + * Windows: doubleclick `teeworlds_srv.exe` + +* you may have to call the restart command in the admin console (of teeworlds) + +* Have Fun! + +## Variables + +| command | default | min | max | description | +| ------------------------- | ------- | --- | ---- | ----------------------------------- | +| sv_allow_pickups | 0 | 0 | 1 | Spawn hearts and shields | +| sv_allow_weapon_pickups | 0 | 0 | 1 | Spawn weapons | +| sv_selfkill_cooldown | 15 | 3 | 9999 | Cooldown after selfkill | +| sv_win_bonus | 5 | 0 | 9999 | Bonus for winning a round | +| sv_min_grenade_damage | 4 | 0 | 6 | Minimum damage required for a kill | +| sv_laser_jump | 1 | 0 | 1 | Activate laser jumping | +| sv_laser_explosion_damage | 4 | 0 | 6 | Explosion damage of laser jump | +| sv_random_spawn | 1 | 0 | 1 | Activates random spawns | +| sv_random_spawn_tries | 100 | 0 | 9999 | Tries for players to spawn randomly | + +## Contributing + +Feel free to contribute! In the current project state every feedback is usefull + +## Authors + +* **AssassinTee** - Everything + +## License +This project is licensed under the default Teeworlds license - see [license.txt](https://github.com/AssassinTee/Teeworlds-Zod2/blob/master/license.txt) file for details + +## Great Thanks to + +* CircleCI integration is awesome, thank you Teeworlds devs! diff --git a/src/game/variables.h b/src/game/variables.h index b226bc2b..00ab4dd0 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -151,7 +151,7 @@ MACRO_CONFIG_INT(SvLaserJump, sv_laser_jump, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVE MACRO_CONFIG_INT(SvLaserExplosionDamage, sv_laser_explosion_damage, 4, 0, 6, CFGFLAG_SAVE|CFGFLAG_SERVER, "Laser Explosion Damage"); MACRO_CONFIG_INT(SvRandomSpawn, sv_random_spawn, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_SERVER, "Activate Random Spawning"); -MACRO_CONFIG_INT(SvRandomSpawnTries, sv_random_spawn, 100, 1, 9999, CFGFLAG_SAVE|CFGFLAG_SERVER, "Tries for random spawn per player per tick"); +MACRO_CONFIG_INT(SvRandomSpawnTries, sv_random_spawn_tries, 100, 1, 9999, CFGFLAG_SAVE|CFGFLAG_SERVER, "Tries for random spawn per player per tick"); // debug #ifdef CONF_DEBUG // this one can crash the server if not used correctly From efd35b2fc9e6555c7fa1970db1d06d5424e39b08 Mon Sep 17 00:00:00 2001 From: Marvin Winkens Date: Sun, 18 Oct 2020 16:53:29 +0200 Subject: [PATCH 478/479] added nice screenshots --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 672275ee..96cad5a0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # catch64 [![Actions Status](https://github.com/AssassinTee/catch64/workflows/All%20OS/badge.svg)](https://github.com/AssassinTee/catch64/actions) -[![CircleCI](https://circleci.com/gh/AssassinTee/catch64.svg?style=shield)](https://circleci.com/gh/AssassinTee/catch64) -[![Build status](https://ci.appveyor.com/api/projects/status/uai64nkyvc8tgc36/branch/master?svg=true)](hhttps://ci.appveyor.com/project/AssassinTee/catch64) [![release version](https://img.shields.io/badge/releases-Unix%20%7C%20Windows%20%7C%20MacOS-brightgreen)](https://github.com/AssassinTee/catch64/releases) ![Teeworlds version](https://img.shields.io/badge/Teeworlds-0.7.5-brightgreen.svg) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/AssassinTee/catch64/issues) From 93f986592fe879208d9b8847afa8785df2c66550 Mon Sep 17 00:00:00 2001 From: Marvin Winkens Date: Sun, 18 Oct 2020 16:53:44 +0200 Subject: [PATCH 479/479] fixed scorelimit and scoring behaviour reset --- src/game/server/gamecontroller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 0e831c48..c66fd99d 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -408,7 +408,8 @@ void IGameController::OnReset() GameServer()->m_apPlayers[i]->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2; if(m_TopscoreCount == 1) { - GameServer()->m_apPlayers[i]->m_Score = 0; + if(m_GameInfo.m_ScoreLimit)//only reset scores when a scorelimit is set + GameServer()->m_apPlayers[i]->m_Score = 0; GameServer()->m_apPlayers[i]->m_ScoreStartTick = Server()->Tick(); } GameServer()->m_apPlayers[i]->m_IsReadyToPlay = true;