diff --git a/datasrc/network.py b/datasrc/network.py index bd76de9cf..1108905bf 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -578,4 +578,8 @@ Messages = [ NetMessageEx("Sv_CommandInfoGroupStart", "sv-commandinfo-group-start@netmsg.ddnet.org", []), NetMessageEx("Sv_CommandInfoGroupEnd", "sv-commandinfo-group-end@netmsg.ddnet.org", []), + + NetMessageEx("Sv_ChangeInfoCooldown", "change-info-cooldown@netmsg.ddnet.org", [ + NetTick("m_WaitUntil") + ]), ] diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 1d1774959..3f8ad0c31 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -263,9 +263,9 @@ void CMenus::SetNeedSendInfo() void CMenus::RenderSettingsPlayer(CUIRect MainView) { - CUIRect TabBar, PlayerTab, DummyTab, QuickSearch, QuickSearchClearButton; + CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo, QuickSearch, QuickSearchClearButton; MainView.HSplitTop(20.0f, &TabBar, &MainView); - TabBar.VSplitMid(&TabBar, nullptr); + TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f); TabBar.VSplitMid(&PlayerTab, &DummyTab); MainView.HSplitTop(10.0f, nullptr, &MainView); @@ -281,6 +281,14 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) m_Dummy = true; } + if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_NextChangeInfo && m_pClient->m_NextChangeInfo > Client()->GameTick(g_Config.m_ClDummy)) + { + char aChangeInfo[128], aTimeLeft[32]; + str_format(aTimeLeft, sizeof(aTimeLeft), Localize("%ds left"), (m_pClient->m_NextChangeInfo - Client()->GameTick(g_Config.m_ClDummy) + Client()->GameTickSpeed() - 1) / Client()->GameTickSpeed()); + str_format(aChangeInfo, sizeof(aChangeInfo), "%s: %s", Localize("Player info change cooldown"), aTimeLeft); + UI()->DoLabel(&ChangeInfo, aChangeInfo, 10.f, TEXTALIGN_ML); + } + static CLineInput s_NameInput; static CLineInput s_ClanInput; @@ -510,9 +518,9 @@ void CMenus::OnConfigSave(IConfigManager *pConfigManager) void CMenus::RenderSettingsTee(CUIRect MainView) { - CUIRect TabBar, PlayerTab, DummyTab; + CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo; MainView.HSplitTop(20.0f, &TabBar, &MainView); - TabBar.VSplitMid(&TabBar, nullptr); + TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f); TabBar.VSplitMid(&PlayerTab, &DummyTab); MainView.HSplitTop(10.0f, nullptr, &MainView); @@ -528,6 +536,14 @@ void CMenus::RenderSettingsTee(CUIRect MainView) m_Dummy = true; } + if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_NextChangeInfo && m_pClient->m_NextChangeInfo > Client()->GameTick(g_Config.m_ClDummy)) + { + char aChangeInfo[128], aTimeLeft[32]; + str_format(aTimeLeft, sizeof(aTimeLeft), Localize("%ds left"), (m_pClient->m_NextChangeInfo - Client()->GameTick(g_Config.m_ClDummy) + Client()->GameTickSpeed() - 1) / Client()->GameTickSpeed()); + str_format(aChangeInfo, sizeof(aChangeInfo), "%s: %s", Localize("Player info change cooldown"), aTimeLeft); + UI()->DoLabel(&ChangeInfo, aChangeInfo, 10.f, TEXTALIGN_ML); + } + char *pSkinName; size_t SkinNameSize; int *pUseCustomColor; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 87e0fd7bc..4f735c5b4 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -574,6 +574,8 @@ void CGameClient::OnReset() m_LastFlagCarrierBlue = -4; m_aTuning[g_Config.m_ClDummy] = CTuningParams(); + m_NextChangeInfo = 0; + m_Teams.Reset(); m_aDDRaceMsgSent[0] = false; m_aDDRaceMsgSent[1] = false; @@ -964,6 +966,11 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dumm m_CharOrder.GiveWeak(ID.first); } } + else if(MsgId == NETMSGTYPE_SV_CHANGEINFOCOOLDOWN) + { + CNetMsg_Sv_ChangeInfoCooldown *pMsg = (CNetMsg_Sv_ChangeInfoCooldown *)pRawMsg; + m_NextChangeInfo = pMsg->m_WaitUntil; + } } void CGameClient::OnStateChange(int NewState, int OldState) diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 48b52eef5..c56a63ae0 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -517,6 +517,8 @@ public: void SendDummyInfo(bool Start) override; void SendKill(int ClientID) const; + int m_NextChangeInfo; + // DDRace int m_aLocalIDs[NUM_DUMMIES]; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 66361a524..6c55177e2 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2554,6 +2554,13 @@ void CGameContext::OnChangeInfoNetMessage(const CNetMsg_Cl_ChangeInfo *pMsg, int pPlayer->m_LastChangeInfo = Server()->Tick(); pPlayer->UpdatePlaytime(); + if(g_Config.m_SvSpamprotection) + { + CNetMsg_Sv_ChangeInfoCooldown ChangeInfoCooldownMsg; + ChangeInfoCooldownMsg.m_WaitUntil = Server()->Tick() + Server()->TickSpeed() * g_Config.m_SvInfoChangeDelay; + Server()->SendPackMsg(&ChangeInfoCooldownMsg, MSGFLAG_VITAL | MSGFLAG_NORECORD, ClientID); + } + // set infos if(Server()->WouldClientNameChange(ClientID, pMsg->m_pName) && !ProcessSpamProtection(ClientID)) {