From a947699d9b7caea022b73655476c266bac8b20f0 Mon Sep 17 00:00:00 2001 From: MrS-ibra Date: Mon, 2 Mar 2026 03:40:42 +0300 Subject: [PATCH] Prevent dc vote abuse in 2 player games by adding grace period to vote button state --- .../Include/GameNetwork/DisconnectManager.h | 3 +++ .../Source/GameNetwork/DisconnectManager.cpp | 3 +++ .../Include/GameClient/DisconnectMenu.h | 3 +++ .../GUI/DisconnectMenu/DisconnectMenu.cpp | 16 ++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/Core/GameEngine/Include/GameNetwork/DisconnectManager.h b/Core/GameEngine/Include/GameNetwork/DisconnectManager.h index ccbb183881f..2cc1ffbcdfa 100644 --- a/Core/GameEngine/Include/GameNetwork/DisconnectManager.h +++ b/Core/GameEngine/Include/GameNetwork/DisconnectManager.h @@ -49,6 +49,9 @@ class DisconnectManager void init(); void update(ConnectionManager *conMgr); +#if defined(GENERALS_ONLINE) + time_t getTimeOfDisconnectScreenOn() const { return m_timeOfDisconnectScreenOn; } +#endif void processDisconnectCommand(NetCommandRef *ref, ConnectionManager *conMgr); void allCommandsReady(UnsignedInt frame, ConnectionManager *conMgr, Bool waitForPacketRouter = TRUE); diff --git a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp index 0ba17322677..2fc72b3382c 100644 --- a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp +++ b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp @@ -198,6 +198,9 @@ Int DisconnectManager::getPingsReceived() void DisconnectManager::updateDisconnectStatus(ConnectionManager *conMgr) { +#if defined(GENERALS_ONLINE) + TheDisconnectMenu->updateTwoPlayerVoteButtonState(conMgr); +#endif for (Int i = 0; i < MAX_SLOTS; ++i) { if (conMgr->isPlayerConnected(i)) { Int slot = translatedSlotPosition(i, conMgr->getLocalPlayerID()); diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/DisconnectMenu.h b/GeneralsMD/Code/GameEngine/Include/GameClient/DisconnectMenu.h index 7cbcde1bac1..d80a029a988 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/DisconnectMenu.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/DisconnectMenu.h @@ -60,6 +60,9 @@ class DisconnectMenu { void removePlayer(Int slot, UnicodeString playerName); void voteForPlayer(Int slot); void updateVotes(Int slot, Int votes); +#if defined(GENERALS_ONLINE) + void updateTwoPlayerVoteButtonState(ConnectionManager* conMgr); +#endif protected: DisconnectManager *m_disconnectManager; ///< For retrieving status updates from the disconnect manager. diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp index a2c241e5ada..2019624ed5b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp @@ -313,3 +313,19 @@ void DisconnectMenu::updateVotes(Int slot, Int votes) { GadgetStaticTextSetText(control, unistr); } } + +#if defined(GENERALS_ONLINE) +// Wait 10 seconds after the disconnect screen comes up before allowing the vote buttons to be enabled in 2 player situations +void DisconnectMenu::updateTwoPlayerVoteButtonState(ConnectionManager* conMgr) { + if (m_disconnectManager == nullptr || conMgr->getNumPlayers() != 2) + return; + + Bool allowed = (timeGetTime() - m_disconnectManager->getTimeOfDisconnectScreenOn()) >= 10000; + for (Int i = 0; m_playerVoteButtonControlNames[i] != nullptr; ++i) { + NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerVoteButtonControlNames[i]); + GameWindow* control = TheWindowManager->winGetWindowFromId(nullptr, id); + if (control != nullptr && control->winIsHidden() == FALSE) + control->winEnable(allowed); + } +} +#endif