mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-19 09:12:19 +00:00
Compare commits
10 commits
67504ebebd
...
5a6e644184
Author | SHA1 | Date | |
---|---|---|---|
5a6e644184 | |||
66fb5d5d7f | |||
d3f0c2a156 | |||
d5e81ca78d | |||
128ffd2313 | |||
af1b32d296 | |||
0ad1c08c22 | |||
9f278979e5 | |||
32e9240634 | |||
53be2625ef |
|
@ -2929,6 +2929,24 @@ void CClient::Run()
|
||||||
g_UuidManager.DebugDump();
|
g_UuidManager.DebugDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONF_WEBASM
|
||||||
|
char aNetworkError[256];
|
||||||
|
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
|
||||||
|
{
|
||||||
|
log_error("client", "%s", aNetworkError);
|
||||||
|
ShowMessageBox("Network Error", aNetworkError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!m_Http.Init(std::chrono::seconds{1}))
|
||||||
|
{
|
||||||
|
const char *pErrorMessage = "Failed to initialize the HTTP client.";
|
||||||
|
log_error("client", "%s", pErrorMessage);
|
||||||
|
ShowMessageBox("HTTP Error", pErrorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// init graphics
|
// init graphics
|
||||||
m_pGraphics = CreateEngineGraphicsThreaded();
|
m_pGraphics = CreateEngineGraphicsThreaded();
|
||||||
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
|
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
|
||||||
|
@ -2952,24 +2970,6 @@ void CClient::Run()
|
||||||
CVideo::Init();
|
CVideo::Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONF_WEBASM
|
|
||||||
char aNetworkError[256];
|
|
||||||
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
|
|
||||||
{
|
|
||||||
log_error("client", "%s", aNetworkError);
|
|
||||||
ShowMessageBox("Network Error", aNetworkError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!m_Http.Init(std::chrono::seconds{1}))
|
|
||||||
{
|
|
||||||
const char *pErrorMessage = "Failed to initialize the HTTP client.";
|
|
||||||
log_error("client", "%s", pErrorMessage);
|
|
||||||
ShowMessageBox("HTTP Error", pErrorMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init text render
|
// init text render
|
||||||
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
||||||
m_pTextRender->Init();
|
m_pTextRender->Init();
|
||||||
|
|
|
@ -300,7 +300,7 @@ void CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex)
|
||||||
FreeTextureIndex(pIndex);
|
FreeTextureIndex(pIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage)
|
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage)
|
||||||
{
|
{
|
||||||
if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA)
|
if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,6 +124,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Structure: CVideoMode
|
Structure: CVideoMode
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -489,7 +489,7 @@ MACRO_CONFIG_INT(SvSpecFrequency, sv_pause_frequency, 1, 0, 9999, CFGFLAG_SERVER
|
||||||
MACRO_CONFIG_INT(SvInvite, sv_invite, 1, 0, 1, CFGFLAG_SERVER, "Whether players can invite other players to teams")
|
MACRO_CONFIG_INT(SvInvite, sv_invite, 1, 0, 1, CFGFLAG_SERVER, "Whether players can invite other players to teams")
|
||||||
MACRO_CONFIG_INT(SvInviteFrequency, sv_invite_frequency, 1, 0, 9999, CFGFLAG_SERVER, "The minimum allowed delay between invites")
|
MACRO_CONFIG_INT(SvInviteFrequency, sv_invite_frequency, 1, 0, 9999, CFGFLAG_SERVER, "The minimum allowed delay between invites")
|
||||||
MACRO_CONFIG_INT(SvTeleOthersAuthLevel, sv_tele_others_auth_level, 1, 1, 3, CFGFLAG_SERVER, "The auth level you need to tele others")
|
MACRO_CONFIG_INT(SvTeleOthersAuthLevel, sv_tele_others_auth_level, 1, 1, 3, CFGFLAG_SERVER, "The auth level you need to tele others")
|
||||||
MACRO_CONFIG_INT(SvRegionalRankings, sv_regional_rankings, 1, 0, 1, CFGFLAG_SERVER, "Display regional rankings in /rank and /top5")
|
MACRO_CONFIG_INT(SvRegionalRankings, sv_regional_rankings, 1, 0, 1, CFGFLAG_SERVER, "Display regional rankings in /rank, /top5 and /top5team")
|
||||||
|
|
||||||
MACRO_CONFIG_INT(SvEmotionalTees, sv_emotional_tees, 1, -1, 1, CFGFLAG_SERVER, "Whether eye change of tees is enabled with emoticons = 1, not = 0, -1 not at all")
|
MACRO_CONFIG_INT(SvEmotionalTees, sv_emotional_tees, 1, -1, 1, CFGFLAG_SERVER, "Whether eye change of tees is enabled with emoticons = 1, not = 0, -1 not at all")
|
||||||
MACRO_CONFIG_INT(SvEmoticonMsDelay, sv_emoticon_ms_delay, 3000, 20, 999999999, CFGFLAG_SERVER, "The time in ms a player has to wait before allowing the next over-head emoticons")
|
MACRO_CONFIG_INT(SvEmoticonMsDelay, sv_emoticon_ms_delay, 3000, 20, 999999999, CFGFLAG_SERVER, "The time in ms a player has to wait before allowing the next over-head emoticons")
|
||||||
|
|
|
@ -70,18 +70,18 @@ void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan)
|
||||||
}
|
}
|
||||||
|
|
||||||
NETADDR BindAddr;
|
NETADDR BindAddr;
|
||||||
if(g_Config.m_EcBindaddr[0] == '\0')
|
if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
|
||||||
{
|
{
|
||||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
// got bindaddr
|
||||||
|
BindAddr.port = g_Config.m_EcPort;
|
||||||
}
|
}
|
||||||
else if(net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) != 0)
|
else
|
||||||
{
|
{
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_Bindaddr);
|
str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_EcBindaddr);
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
BindAddr.type = NETTYPE_ALL;
|
|
||||||
BindAddr.port = g_Config.m_EcPort;
|
|
||||||
|
|
||||||
if(m_NetConsole.Open(BindAddr, pNetBan))
|
if(m_NetConsole.Open(BindAddr, pNetBan))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1397,22 +1397,10 @@ void CMenus::RenderDemoBrowserButtons(CUIRect ButtonsView, bool WasListboxItemAc
|
||||||
|
|
||||||
// quick search
|
// quick search
|
||||||
{
|
{
|
||||||
SetIconMode(true);
|
CUIRect DemoSearch;
|
||||||
CUIRect DemoSearch, SearchIcon;
|
|
||||||
ButtonBarTop.VSplitLeft(ButtonBarBottom.h * 21.0f, &DemoSearch, &ButtonBarTop);
|
ButtonBarTop.VSplitLeft(ButtonBarBottom.h * 21.0f, &DemoSearch, &ButtonBarTop);
|
||||||
ButtonBarTop.VSplitLeft(ButtonBarTop.h / 2.0f, nullptr, &ButtonBarTop);
|
ButtonBarTop.VSplitLeft(ButtonBarTop.h / 2.0f, nullptr, &ButtonBarTop);
|
||||||
DemoSearch.VSplitLeft(TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS), &SearchIcon, &DemoSearch);
|
if(Ui()->DoEditBox_Search(&m_DemoSearchInput, &DemoSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
|
||||||
DemoSearch.VSplitLeft(5.0f, nullptr, &DemoSearch);
|
|
||||||
Ui()->DoLabel(&SearchIcon, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
SetIconMode(false);
|
|
||||||
m_DemoSearchInput.SetEmptyText(Localize("Search"));
|
|
||||||
|
|
||||||
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
|
|
||||||
{
|
|
||||||
Ui()->SetActiveItem(&m_DemoSearchInput);
|
|
||||||
m_DemoSearchInput.SelectAll();
|
|
||||||
}
|
|
||||||
if(Ui()->DoClearableEditBox(&m_DemoSearchInput, &DemoSearch, 12.0f))
|
|
||||||
{
|
{
|
||||||
RefreshFilteredDemos();
|
RefreshFilteredDemos();
|
||||||
DemolistOnUpdate(false);
|
DemolistOnUpdate(false);
|
||||||
|
|
|
@ -683,26 +683,15 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
||||||
|
|
||||||
// render quick search
|
// render quick search
|
||||||
CUIRect QuickSearch;
|
CUIRect QuickSearch;
|
||||||
Bottom.VSplitLeft(5.0f, 0, &Bottom);
|
Bottom.VSplitLeft(5.0f, nullptr, &Bottom);
|
||||||
Bottom.VSplitLeft(250.0f, &QuickSearch, &Bottom);
|
Bottom.VSplitLeft(250.0f, &QuickSearch, &Bottom);
|
||||||
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
if(m_ControlPageOpening)
|
||||||
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
|
||||||
|
|
||||||
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
QuickSearch.VSplitLeft(SearchWidth, 0, &QuickSearch);
|
|
||||||
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
|
|
||||||
|
|
||||||
if(m_ControlPageOpening || (Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed()))
|
|
||||||
{
|
{
|
||||||
Ui()->SetActiveItem(&m_FilterInput);
|
|
||||||
m_ControlPageOpening = false;
|
m_ControlPageOpening = false;
|
||||||
|
Ui()->SetActiveItem(&m_FilterInput);
|
||||||
m_FilterInput.SelectAll();
|
m_FilterInput.SelectAll();
|
||||||
}
|
}
|
||||||
m_FilterInput.SetEmptyText(Localize("Search"));
|
Ui()->DoEditBox_Search(&m_FilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed());
|
||||||
Ui()->DoClearableEditBox(&m_FilterInput, &QuickSearch, 14.0f);
|
|
||||||
|
|
||||||
// call vote
|
// call vote
|
||||||
Bottom.VSplitRight(10.0f, &Bottom, 0);
|
Bottom.VSplitRight(10.0f, &Bottom, 0);
|
||||||
|
|
|
@ -257,7 +257,7 @@ void CMenus::SetNeedSendInfo()
|
||||||
|
|
||||||
void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
||||||
{
|
{
|
||||||
CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo, QuickSearch, QuickSearchClearButton;
|
CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo, QuickSearch;
|
||||||
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
||||||
TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f);
|
TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f);
|
||||||
TabBar.VSplitMid(&PlayerTab, &DummyTab);
|
TabBar.VSplitMid(&PlayerTab, &DummyTab);
|
||||||
|
@ -340,7 +340,10 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
||||||
}
|
}
|
||||||
|
|
||||||
MainView.HSplitTop(10.0f, nullptr, &MainView);
|
MainView.HSplitTop(10.0f, nullptr, &MainView);
|
||||||
MainView.HSplitBottom(25.0f, &MainView, &QuickSearch);
|
MainView.HSplitBottom(20.0f, &MainView, &QuickSearch);
|
||||||
|
MainView.HSplitBottom(5.0f, &MainView, nullptr);
|
||||||
|
QuickSearch.VSplitLeft(220.0f, &QuickSearch, nullptr);
|
||||||
|
|
||||||
int OldSelected = -1;
|
int OldSelected = -1;
|
||||||
static CListBox s_ListBox;
|
static CListBox s_ListBox;
|
||||||
s_ListBox.DoStart(48.0f, vpFilteredFlags.size(), 10, 3, OldSelected, &MainView);
|
s_ListBox.DoStart(48.0f, vpFilteredFlags.size(), 10, 3, OldSelected, &MainView);
|
||||||
|
@ -378,30 +381,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
||||||
SetNeedSendInfo();
|
SetNeedSendInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// render quick search
|
Ui()->DoEditBox_Search(&s_FlagFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed());
|
||||||
QuickSearch.VSplitLeft(240.0f, &QuickSearch, nullptr);
|
|
||||||
QuickSearch.HSplitTop(5.0f, nullptr, &QuickSearch);
|
|
||||||
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
|
||||||
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
|
||||||
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
|
|
||||||
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
|
|
||||||
QuickSearch.VSplitLeft(SearchWidth - 1.5f, nullptr, &QuickSearch);
|
|
||||||
QuickSearch.VSplitLeft(5.0f, nullptr, &QuickSearch);
|
|
||||||
QuickSearch.VSplitLeft(QuickSearch.w - 10.0f, &QuickSearch, &QuickSearchClearButton);
|
|
||||||
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
|
|
||||||
{
|
|
||||||
Ui()->SetActiveItem(&s_FlagFilterInput);
|
|
||||||
s_FlagFilterInput.SelectAll();
|
|
||||||
}
|
|
||||||
s_FlagFilterInput.SetEmptyText(Localize("Search"));
|
|
||||||
Ui()->DoClearableEditBox(&s_FlagFilterInput, &QuickSearch, 14.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CUISkin
|
struct CUISkin
|
||||||
|
@ -770,8 +750,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
||||||
CUIRect QuickSearch, DatabaseButton, DirectoryButton, RefreshButton;
|
CUIRect QuickSearch, DatabaseButton, DirectoryButton, RefreshButton;
|
||||||
MainView.HSplitBottom(20.0f, &MainView, &QuickSearch);
|
MainView.HSplitBottom(20.0f, &MainView, &QuickSearch);
|
||||||
MainView.HSplitBottom(5.0f, &MainView, nullptr);
|
MainView.HSplitBottom(5.0f, &MainView, nullptr);
|
||||||
QuickSearch.VSplitLeft(240.0f, &QuickSearch, &DatabaseButton);
|
QuickSearch.VSplitLeft(220.0f, &QuickSearch, &DatabaseButton);
|
||||||
QuickSearch.VSplitRight(10.0f, &QuickSearch, nullptr);
|
DatabaseButton.VSplitLeft(10.0f, nullptr, &DatabaseButton);
|
||||||
DatabaseButton.VSplitLeft(150.0f, &DatabaseButton, &DirectoryButton);
|
DatabaseButton.VSplitLeft(150.0f, &DatabaseButton, &DirectoryButton);
|
||||||
DirectoryButton.VSplitRight(175.0f, nullptr, &DirectoryButton);
|
DirectoryButton.VSplitRight(175.0f, nullptr, &DirectoryButton);
|
||||||
DirectoryButton.VSplitRight(25.0f, &DirectoryButton, &RefreshButton);
|
DirectoryButton.VSplitRight(25.0f, &DirectoryButton, &RefreshButton);
|
||||||
|
@ -904,24 +884,10 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
||||||
SetNeedSendInfo();
|
SetNeedSendInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick search
|
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
|
||||||
|
if(Ui()->DoEditBox_Search(&s_SkinFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
|
||||||
{
|
{
|
||||||
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
m_SkinListNeedsUpdate = true;
|
||||||
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
|
||||||
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
|
|
||||||
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
|
|
||||||
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
|
|
||||||
{
|
|
||||||
Ui()->SetActiveItem(&s_SkinFilterInput);
|
|
||||||
s_SkinFilterInput.SelectAll();
|
|
||||||
}
|
|
||||||
s_SkinFilterInput.SetEmptyText(Localize("Search"));
|
|
||||||
if(Ui()->DoClearableEditBox(&s_SkinFilterInput, &QuickSearch, 14.0f))
|
|
||||||
m_SkinListNeedsUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CButtonContainer s_SkinDatabaseButton;
|
static CButtonContainer s_SkinDatabaseButton;
|
||||||
|
|
|
@ -282,24 +282,10 @@ void CMenus::RenderSettingsTee7(CUIRect MainView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick search
|
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
|
||||||
|
if(Ui()->DoEditBox_Search(&s_SkinFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
|
||||||
{
|
{
|
||||||
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
m_SkinListNeedsUpdate = true;
|
||||||
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
|
||||||
Ui()->DoLabel(&QuickSearch, FontIcons::FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
float SearchWidth = TextRender()->TextWidth(14.0f, FontIcons::FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
|
|
||||||
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
|
|
||||||
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
|
|
||||||
{
|
|
||||||
Ui()->SetActiveItem(&s_SkinFilterInput);
|
|
||||||
s_SkinFilterInput.SelectAll();
|
|
||||||
}
|
|
||||||
s_SkinFilterInput.SetEmptyText(Localize("Search"));
|
|
||||||
if(Ui()->DoClearableEditBox(&s_SkinFilterInput, &QuickSearch, 14.0f))
|
|
||||||
m_SkinListNeedsUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CButtonContainer s_DirectoryButton;
|
static CButtonContainer s_DirectoryButton;
|
||||||
|
|
|
@ -352,7 +352,7 @@ int InitSearchList(std::vector<const TName *> &vpSearchList, std::vector<TName>
|
||||||
|
|
||||||
void CMenus::RenderSettingsCustom(CUIRect MainView)
|
void CMenus::RenderSettingsCustom(CUIRect MainView)
|
||||||
{
|
{
|
||||||
CUIRect TabBar, CustomList, QuickSearch, QuickSearchClearButton, DirectoryButton, ReloadButton;
|
CUIRect TabBar, CustomList, QuickSearch, DirectoryButton, ReloadButton;
|
||||||
|
|
||||||
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
||||||
const float TabWidth = TabBar.w / NUMBER_OF_ASSETS_TABS;
|
const float TabWidth = TabBar.w / NUMBER_OF_ASSETS_TABS;
|
||||||
|
@ -599,29 +599,13 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// render quick search
|
// Quick search
|
||||||
|
MainView.HSplitBottom(ms_ButtonHeight, &MainView, &QuickSearch);
|
||||||
|
QuickSearch.VSplitLeft(220.0f, &QuickSearch, &DirectoryButton);
|
||||||
|
QuickSearch.HSplitTop(5.0f, nullptr, &QuickSearch);
|
||||||
|
if(Ui()->DoEditBox_Search(&s_aFilterInputs[s_CurCustomTab], &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
|
||||||
{
|
{
|
||||||
MainView.HSplitBottom(ms_ButtonHeight, &MainView, &QuickSearch);
|
gs_aInitCustomList[s_CurCustomTab] = true;
|
||||||
QuickSearch.VSplitLeft(240.0f, &QuickSearch, &DirectoryButton);
|
|
||||||
QuickSearch.HSplitTop(5.0f, 0, &QuickSearch);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
|
||||||
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
|
||||||
|
|
||||||
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
|
|
||||||
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
|
|
||||||
TextRender()->SetRenderFlags(0);
|
|
||||||
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
|
||||||
QuickSearch.VSplitLeft(SearchWidth, 0, &QuickSearch);
|
|
||||||
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
|
|
||||||
QuickSearch.VSplitLeft(QuickSearch.w - 10.0f, &QuickSearch, &QuickSearchClearButton);
|
|
||||||
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
|
|
||||||
{
|
|
||||||
Ui()->SetActiveItem(&s_aFilterInputs[s_CurCustomTab]);
|
|
||||||
s_aFilterInputs[s_CurCustomTab].SelectAll();
|
|
||||||
}
|
|
||||||
s_aFilterInputs[s_CurCustomTab].SetEmptyText(Localize("Search"));
|
|
||||||
if(Ui()->DoClearableEditBox(&s_aFilterInputs[s_CurCustomTab], &QuickSearch, 14.0f))
|
|
||||||
gs_aInitCustomList[s_CurCustomTab] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryButton.HSplitTop(5.0f, 0, &DirectoryButton);
|
DirectoryButton.HSplitTop(5.0f, 0, &DirectoryButton);
|
||||||
|
|
|
@ -1004,6 +1004,25 @@ bool CUi::DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float
|
||||||
return ReturnValue;
|
return ReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CUi::DoEditBox_Search(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, bool HotkeyEnabled)
|
||||||
|
{
|
||||||
|
CUIRect QuickSearch = *pRect;
|
||||||
|
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
||||||
|
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
||||||
|
DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, FontSize, TEXTALIGN_ML);
|
||||||
|
const float SearchWidth = TextRender()->TextWidth(FontSize, FONT_ICON_MAGNIFYING_GLASS);
|
||||||
|
TextRender()->SetRenderFlags(0);
|
||||||
|
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
||||||
|
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
|
||||||
|
if(HotkeyEnabled && Input()->ModifierIsPressed() && Input()->KeyPress(KEY_F))
|
||||||
|
{
|
||||||
|
SetActiveItem(pLineInput);
|
||||||
|
pLineInput->SelectAll();
|
||||||
|
}
|
||||||
|
pLineInput->SetEmptyText(Localize("Search"));
|
||||||
|
return DoClearableEditBox(pLineInput, &QuickSearch, FontSize);
|
||||||
|
}
|
||||||
|
|
||||||
int CUi::DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props)
|
int CUi::DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props)
|
||||||
{
|
{
|
||||||
CUIRect Text = *pRect, DropDownIcon;
|
CUIRect Text = *pRect, DropDownIcon;
|
||||||
|
|
|
@ -603,6 +603,24 @@ public:
|
||||||
*/
|
*/
|
||||||
bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {});
|
bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an input field with a search icon and a clear [x] button attached to it.
|
||||||
|
* The input will have default text "Search" and the hotkey Ctrl+F can be used to activate the input.
|
||||||
|
*
|
||||||
|
* @see DoEditBox
|
||||||
|
*
|
||||||
|
* @param pLineInput This pointer will be stored and written to on next user input.
|
||||||
|
* So you can not pass in a pointer that goes out of scope such as a local variable.
|
||||||
|
* Pass in either a member variable of the current class or a static variable.
|
||||||
|
* For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;```
|
||||||
|
* @param pRect the UI rect it will attach to
|
||||||
|
* @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here)
|
||||||
|
* @param HotkeyEnabled Whether the hotkey to enable this editbox is currently enabled.
|
||||||
|
*
|
||||||
|
* @return true if the value of the input field changed since the last call.
|
||||||
|
*/
|
||||||
|
bool DoEditBox_Search(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, bool HotkeyEnabled);
|
||||||
|
|
||||||
int DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {});
|
int DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {});
|
||||||
// only used for popup menus
|
// only used for popup menus
|
||||||
int DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true);
|
int DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true);
|
||||||
|
|
|
@ -4384,7 +4384,7 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CEditorImage ImgInfo(this);
|
CImageInfo ImgInfo;
|
||||||
if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
||||||
{
|
{
|
||||||
ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
||||||
|
@ -4394,21 +4394,33 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
|
||||||
std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage];
|
std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage];
|
||||||
Graphics()->UnloadTexture(&(pImg->m_Texture));
|
Graphics()->UnloadTexture(&(pImg->m_Texture));
|
||||||
pImg->Free();
|
pImg->Free();
|
||||||
*pImg = ImgInfo;
|
pImg->m_Width = ImgInfo.m_Width;
|
||||||
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
str_copy(pImg->m_aName, aBuf);
|
str_copy(pImg->m_aName, aBuf);
|
||||||
pImg->m_External = IsVanillaImage(pImg->m_aName);
|
pImg->m_External = IsVanillaImage(pImg->m_aName);
|
||||||
|
|
||||||
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA)
|
if(!pImg->m_External && pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height);
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
|
||||||
|
{
|
||||||
|
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||||
int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
pImg->m_Texture = Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
pImg->m_Texture = Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||||
ImgInfo.m_pData = nullptr;
|
|
||||||
SortImages();
|
SortImages();
|
||||||
for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i)
|
for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -4447,7 +4459,7 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CEditorImage ImgInfo(pEditor);
|
CImageInfo ImgInfo;
|
||||||
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
||||||
{
|
{
|
||||||
pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
||||||
|
@ -4455,19 +4467,30 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor);
|
std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor);
|
||||||
*pImg = ImgInfo;
|
pImg->m_Width = ImgInfo.m_Width;
|
||||||
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
pImg->m_External = IsVanillaImage(aBuf);
|
pImg->m_External = IsVanillaImage(aBuf);
|
||||||
|
|
||||||
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA)
|
if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height);
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
|
||||||
|
{
|
||||||
|
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||||
ImgInfo.m_pData = nullptr;
|
|
||||||
str_copy(pImg->m_aName, aBuf);
|
str_copy(pImg->m_aName, aBuf);
|
||||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||||
pEditor->m_Map.m_vpImages.push_back(pImg);
|
pEditor->m_Map.m_vpImages.push_back(pImg);
|
||||||
|
|
|
@ -509,6 +509,15 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
|
||||||
pImg->m_Height = ImgInfo.m_Height;
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
pImg->m_Format = ImgInfo.m_Format;
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
pImg->m_pData = ImgInfo.m_pData;
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
|
if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
|
{
|
||||||
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
|
|
|
@ -99,6 +99,48 @@ bool CTeamrank::SamePlayers(const std::vector<std::string> *pvSortedNames)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CTeamrank::GetSqlTop5Team(IDbConnection *pSqlServer, bool *pEnd, char *pError, int ErrorSize, char (*paMessages)[512], int *Line, int Count)
|
||||||
|
{
|
||||||
|
char aTime[32];
|
||||||
|
int StartLine = *Line;
|
||||||
|
for(*Line = StartLine; *Line < StartLine + Count; (*Line)++)
|
||||||
|
{
|
||||||
|
bool Last = false;
|
||||||
|
float Time = pSqlServer->GetFloat(2);
|
||||||
|
str_time_float(Time, TIME_HOURS_CENTISECS, aTime, sizeof(aTime));
|
||||||
|
int Rank = pSqlServer->GetInt(3);
|
||||||
|
int TeamSize = pSqlServer->GetInt(4);
|
||||||
|
|
||||||
|
char aNames[2300] = {0};
|
||||||
|
for(int i = 0; i < TeamSize; i++)
|
||||||
|
{
|
||||||
|
char aName[MAX_NAME_LENGTH];
|
||||||
|
pSqlServer->GetString(1, aName, sizeof(aName));
|
||||||
|
str_append(aNames, aName);
|
||||||
|
if(i < TeamSize - 2)
|
||||||
|
str_append(aNames, ", ");
|
||||||
|
else if(i == TeamSize - 2)
|
||||||
|
str_append(aNames, " & ");
|
||||||
|
if(pSqlServer->Step(&Last, pError, ErrorSize))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(Last)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str_format(paMessages[*Line], sizeof(paMessages[*Line]), "%d. %s Team Time: %s",
|
||||||
|
Rank, aNames, aTime);
|
||||||
|
if(Last)
|
||||||
|
{
|
||||||
|
(*Line)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CScoreWorker::LoadBestTime(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize)
|
bool CScoreWorker::LoadBestTime(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize)
|
||||||
{
|
{
|
||||||
const auto *pData = dynamic_cast<const CSqlLoadBestTimeData *>(pGameData);
|
const auto *pData = dynamic_cast<const CSqlLoadBestTimeData *>(pGameData);
|
||||||
|
@ -1071,34 +1113,40 @@ bool CScoreWorker::ShowTeamTop5(IDbConnection *pSqlServer, const ISqlData *pGame
|
||||||
|
|
||||||
int LimitStart = maximum(absolute(pData->m_Offset) - 1, 0);
|
int LimitStart = maximum(absolute(pData->m_Offset) - 1, 0);
|
||||||
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
|
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
|
||||||
|
const char *pAny = "%";
|
||||||
|
|
||||||
// check sort method
|
// check sort method
|
||||||
char aBuf[1024];
|
char aBuf[1024];
|
||||||
|
|
||||||
str_format(aBuf, sizeof(aBuf),
|
str_format(aBuf, sizeof(aBuf),
|
||||||
"SELECT Name, Time, Ranking, TeamSize "
|
"SELECT Name, Time, Ranking, TeamSize "
|
||||||
"FROM (" // limit to 5
|
"FROM ("
|
||||||
" SELECT TeamSize, Ranking, Id "
|
" SELECT TeamSize, Ranking, Id, Server "
|
||||||
" FROM (" // teamrank score board
|
" FROM (" // teamrank score board
|
||||||
" SELECT RANK() OVER w AS Ranking, COUNT(*) AS Teamsize, Id "
|
" SELECT RANK() OVER w AS Ranking, COUNT(*) AS Teamsize, Id, Server "
|
||||||
" FROM %s_teamrace "
|
" FROM ("
|
||||||
|
" SELECT * FROM %s_teamrace as tr "
|
||||||
|
" INNER JOIN %s_race as rr ON tr.Map = rr.Map AND tr.Name = rr.Name AND tr.Time = rr.Time AND tr.Timestamp = rr.Timestamp"
|
||||||
|
" ) "
|
||||||
" WHERE Map = ? "
|
" WHERE Map = ? "
|
||||||
" GROUP BY ID "
|
" GROUP BY ID "
|
||||||
" WINDOW w AS (ORDER BY Min(Time))"
|
" WINDOW w AS (ORDER BY Min(Time))"
|
||||||
" ) as l1 "
|
" ) as l1 "
|
||||||
|
" WHERE Server LIKE ? "
|
||||||
" ORDER BY Ranking %s "
|
" ORDER BY Ranking %s "
|
||||||
" LIMIT %d, 5"
|
" LIMIT %d, ?"
|
||||||
") as l2 "
|
") as l2 "
|
||||||
"INNER JOIN %s_teamrace as r ON l2.Id = r.Id "
|
"INNER JOIN %s_teamrace as r ON l2.Id = r.Id "
|
||||||
"ORDER BY Ranking %s, r.Id, Name ASC",
|
"ORDER BY Ranking %s, r.Id, Name ASC",
|
||||||
pSqlServer->GetPrefix(), pOrder, LimitStart, pSqlServer->GetPrefix(), pOrder);
|
pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pOrder, LimitStart, pSqlServer->GetPrefix(), pOrder);
|
||||||
if(pSqlServer->PrepareStatement(aBuf, pError, ErrorSize))
|
if(pSqlServer->PrepareStatement(aBuf, pError, ErrorSize))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pSqlServer->BindString(1, pData->m_aMap);
|
pSqlServer->BindString(1, pData->m_aMap);
|
||||||
|
pSqlServer->BindString(2, pAny);
|
||||||
|
pSqlServer->BindInt(3, 5);
|
||||||
|
|
||||||
// show teamtop5
|
|
||||||
int Line = 0;
|
int Line = 0;
|
||||||
str_copy(paMessages[Line++], "------- Team Top 5 -------", sizeof(paMessages[Line]));
|
str_copy(paMessages[Line++], "------- Team Top 5 -------", sizeof(paMessages[Line]));
|
||||||
|
|
||||||
|
@ -1109,44 +1157,45 @@ bool CScoreWorker::ShowTeamTop5(IDbConnection *pSqlServer, const ISqlData *pGame
|
||||||
}
|
}
|
||||||
if(!End)
|
if(!End)
|
||||||
{
|
{
|
||||||
for(Line = 1; Line < 6; Line++) // print
|
if(CTeamrank::GetSqlTop5Team(pSqlServer, &End, pError, ErrorSize, paMessages, &Line, 5))
|
||||||
{
|
{
|
||||||
bool Last = false;
|
return true;
|
||||||
float Time = pSqlServer->GetFloat(2);
|
}
|
||||||
str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf));
|
}
|
||||||
int Rank = pSqlServer->GetInt(3);
|
|
||||||
int TeamSize = pSqlServer->GetInt(4);
|
if(!g_Config.m_SvRegionalRankings)
|
||||||
|
{
|
||||||
char aNames[2300] = {0};
|
str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line]));
|
||||||
for(int i = 0; i < TeamSize; i++)
|
return false;
|
||||||
{
|
}
|
||||||
char aName[MAX_NAME_LENGTH];
|
|
||||||
pSqlServer->GetString(1, aName, sizeof(aName));
|
char aServerLike[16];
|
||||||
str_append(aNames, aName);
|
str_format(aServerLike, sizeof(aServerLike), "%%%s%%", pData->m_aServer);
|
||||||
if(i < TeamSize - 2)
|
|
||||||
str_append(aNames, ", ");
|
if(pSqlServer->PrepareStatement(aBuf, pError, ErrorSize))
|
||||||
else if(i == TeamSize - 2)
|
{
|
||||||
str_append(aNames, " & ");
|
return true;
|
||||||
if(pSqlServer->Step(&Last, pError, ErrorSize))
|
}
|
||||||
{
|
pSqlServer->BindString(1, pData->m_aMap);
|
||||||
return true;
|
pSqlServer->BindString(2, aServerLike);
|
||||||
}
|
pSqlServer->BindInt(3, 3);
|
||||||
if(Last)
|
|
||||||
{
|
str_format(pResult->m_Data.m_aaMessages[Line], sizeof(pResult->m_Data.m_aaMessages[Line]),
|
||||||
break;
|
"----- %s Team Top -----", pData->m_aServer);
|
||||||
}
|
Line++;
|
||||||
}
|
|
||||||
str_format(paMessages[Line], sizeof(paMessages[Line]), "%d. %s Team Time: %s",
|
if(pSqlServer->Step(&End, pError, ErrorSize))
|
||||||
Rank, aNames, aBuf);
|
{
|
||||||
if(Last)
|
return true;
|
||||||
{
|
}
|
||||||
Line++;
|
if(!End)
|
||||||
break;
|
{
|
||||||
}
|
if(CTeamrank::GetSqlTop5Team(pSqlServer, &End, pError, ErrorSize, paMessages, &Line, 3))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line]));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,8 @@ struct CTeamrank
|
||||||
bool NextSqlResult(IDbConnection *pSqlServer, bool *pEnd, char *pError, int ErrorSize);
|
bool NextSqlResult(IDbConnection *pSqlServer, bool *pEnd, char *pError, int ErrorSize);
|
||||||
|
|
||||||
bool SamePlayers(const std::vector<std::string> *pvSortedNames);
|
bool SamePlayers(const std::vector<std::string> *pvSortedNames);
|
||||||
|
|
||||||
|
static bool GetSqlTop5Team(IDbConnection *pSqlServer, bool *pEnd, char *pError, int ErrorSize, char (*paMessages)[512], int *StartLine, int Count);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CScoreWorker
|
struct CScoreWorker
|
||||||
|
|
|
@ -282,41 +282,46 @@ struct TeamScore : public Score
|
||||||
{
|
{
|
||||||
void SetUp() override
|
void SetUp() override
|
||||||
{
|
{
|
||||||
CSqlTeamScoreData teamScoreData;
|
InsertTeamRank(100.0);
|
||||||
str_copy(teamScoreData.m_aMap, "Kobra 3", sizeof(teamScoreData.m_aMap));
|
|
||||||
str_copy(teamScoreData.m_aGameUuid, "8d300ecf-5873-4297-bee5-95668fdff320", sizeof(teamScoreData.m_aGameUuid));
|
|
||||||
teamScoreData.m_Size = 2;
|
|
||||||
str_copy(teamScoreData.m_aaNames[0], "nameless tee", sizeof(teamScoreData.m_aaNames[0]));
|
|
||||||
str_copy(teamScoreData.m_aaNames[1], "brainless tee", sizeof(teamScoreData.m_aaNames[1]));
|
|
||||||
teamScoreData.m_Time = 100.0;
|
|
||||||
str_copy(teamScoreData.m_aTimestamp, "2021-11-24 19:24:08", sizeof(teamScoreData.m_aTimestamp));
|
|
||||||
ASSERT_FALSE(CScoreWorker::SaveTeamScore(m_pConn, &teamScoreData, Write::NORMAL, m_aError, sizeof(m_aError))) << m_aError;
|
|
||||||
|
|
||||||
str_copy(m_PlayerRequest.m_aMap, "Kobra 3", sizeof(m_PlayerRequest.m_aMap));
|
|
||||||
str_copy(m_PlayerRequest.m_aRequestingPlayer, "brainless tee", sizeof(m_PlayerRequest.m_aRequestingPlayer));
|
|
||||||
m_PlayerRequest.m_Offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertTeamRank(float Time = 100.0)
|
void InsertTeamRank(float Time = 100.0)
|
||||||
{
|
{
|
||||||
|
str_copy(g_Config.m_SvSqlServerName, "USA", sizeof(g_Config.m_SvSqlServerName));
|
||||||
CSqlTeamScoreData teamScoreData;
|
CSqlTeamScoreData teamScoreData;
|
||||||
|
CSqlScoreData ScoreData(std::make_shared<CScorePlayerResult>());
|
||||||
str_copy(teamScoreData.m_aMap, "Kobra 3", sizeof(teamScoreData.m_aMap));
|
str_copy(teamScoreData.m_aMap, "Kobra 3", sizeof(teamScoreData.m_aMap));
|
||||||
|
str_copy(ScoreData.m_aMap, "Kobra 3", sizeof(ScoreData.m_aMap));
|
||||||
str_copy(teamScoreData.m_aGameUuid, "8d300ecf-5873-4297-bee5-95668fdff320", sizeof(teamScoreData.m_aGameUuid));
|
str_copy(teamScoreData.m_aGameUuid, "8d300ecf-5873-4297-bee5-95668fdff320", sizeof(teamScoreData.m_aGameUuid));
|
||||||
|
str_copy(ScoreData.m_aGameUuid, "8d300ecf-5873-4297-bee5-95668fdff320", sizeof(ScoreData.m_aGameUuid));
|
||||||
teamScoreData.m_Size = 2;
|
teamScoreData.m_Size = 2;
|
||||||
str_copy(teamScoreData.m_aaNames[0], "nameless tee", sizeof(teamScoreData.m_aaNames[0]));
|
str_copy(teamScoreData.m_aaNames[0], "nameless tee", sizeof(teamScoreData.m_aaNames[0]));
|
||||||
str_copy(teamScoreData.m_aaNames[1], "brainless tee", sizeof(teamScoreData.m_aaNames[1]));
|
str_copy(teamScoreData.m_aaNames[1], "brainless tee", sizeof(teamScoreData.m_aaNames[1]));
|
||||||
teamScoreData.m_Time = Time;
|
teamScoreData.m_Time = Time;
|
||||||
|
ScoreData.m_Time = Time;
|
||||||
str_copy(teamScoreData.m_aTimestamp, "2021-11-24 19:24:08", sizeof(teamScoreData.m_aTimestamp));
|
str_copy(teamScoreData.m_aTimestamp, "2021-11-24 19:24:08", sizeof(teamScoreData.m_aTimestamp));
|
||||||
|
str_copy(ScoreData.m_aTimestamp, "2021-11-24 19:24:08", sizeof(ScoreData.m_aTimestamp));
|
||||||
|
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
||||||
|
ScoreData.m_aCurrentTimeCp[i] = 0;
|
||||||
ASSERT_FALSE(CScoreWorker::SaveTeamScore(m_pConn, &teamScoreData, Write::NORMAL, m_aError, sizeof(m_aError))) << m_aError;
|
ASSERT_FALSE(CScoreWorker::SaveTeamScore(m_pConn, &teamScoreData, Write::NORMAL, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
|
|
||||||
str_copy(m_PlayerRequest.m_aMap, "Kobra 3", sizeof(m_PlayerRequest.m_aMap));
|
str_copy(m_PlayerRequest.m_aMap, "Kobra 3", sizeof(m_PlayerRequest.m_aMap));
|
||||||
str_copy(m_PlayerRequest.m_aRequestingPlayer, "brainless tee", sizeof(m_PlayerRequest.m_aRequestingPlayer));
|
str_copy(m_PlayerRequest.m_aRequestingPlayer, "brainless tee", sizeof(m_PlayerRequest.m_aRequestingPlayer));
|
||||||
|
str_copy(ScoreData.m_aRequestingPlayer, "brainless tee", sizeof(ScoreData.m_aRequestingPlayer));
|
||||||
|
|
||||||
|
str_copy(ScoreData.m_aName, "nameless tee", sizeof(ScoreData.m_aName));
|
||||||
|
ScoreData.m_ClientId = 0;
|
||||||
|
ASSERT_FALSE(CScoreWorker::SaveScore(m_pConn, &ScoreData, Write::NORMAL, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
|
str_copy(ScoreData.m_aName, "brainless tee", sizeof(ScoreData.m_aName));
|
||||||
|
ScoreData.m_ClientId = 1;
|
||||||
|
ASSERT_FALSE(CScoreWorker::SaveScore(m_pConn, &ScoreData, Write::NORMAL, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
m_PlayerRequest.m_Offset = 0;
|
m_PlayerRequest.m_Offset = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_P(TeamScore, All)
|
TEST_P(TeamScore, All)
|
||||||
{
|
{
|
||||||
|
g_Config.m_SvRegionalRankings = false;
|
||||||
ASSERT_FALSE(CScoreWorker::ShowTeamTop5(m_pConn, &m_PlayerRequest, m_aError, sizeof(m_aError))) << m_aError;
|
ASSERT_FALSE(CScoreWorker::ShowTeamTop5(m_pConn, &m_PlayerRequest, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
ExpectLines(m_pPlayerResult,
|
ExpectLines(m_pPlayerResult,
|
||||||
{"------- Team Top 5 -------",
|
{"------- Team Top 5 -------",
|
||||||
|
@ -324,6 +329,18 @@ TEST_P(TeamScore, All)
|
||||||
"-------------------------------"});
|
"-------------------------------"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(TeamScore, TeamTop5Regional)
|
||||||
|
{
|
||||||
|
g_Config.m_SvRegionalRankings = true;
|
||||||
|
str_copy(m_PlayerRequest.m_aServer, "USA", sizeof(m_PlayerRequest.m_aServer));
|
||||||
|
ASSERT_FALSE(CScoreWorker::ShowTeamTop5(m_pConn, &m_PlayerRequest, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
|
ExpectLines(m_pPlayerResult,
|
||||||
|
{"------- Team Top 5 -------",
|
||||||
|
"1. brainless tee & nameless tee Team Time: 01:40.00",
|
||||||
|
"----- USA Team Top -----",
|
||||||
|
"1. brainless tee & nameless tee Team Time: 01:40.00"});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(TeamScore, PlayerExists)
|
TEST_P(TeamScore, PlayerExists)
|
||||||
{
|
{
|
||||||
str_copy(m_PlayerRequest.m_aName, "brainless tee", sizeof(m_PlayerRequest.m_aName));
|
str_copy(m_PlayerRequest.m_aName, "brainless tee", sizeof(m_PlayerRequest.m_aName));
|
||||||
|
|
Loading…
Reference in a new issue