Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add auto desync kick #3318

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/netplay/netplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,7 @@ static bool swapPlayerIndexes(uint32_t playerIndexA, uint32_t playerIndexB)
// Swap certain ingame player-associated entries
std::swap(ingame.PingTimes[playerIndexA], ingame.PingTimes[playerIndexB]);
std::swap(ingame.LagCounter[playerIndexA], ingame.LagCounter[playerIndexB]);
std::swap(ingame.DesyncCounter[playerIndexA], ingame.DesyncCounter[playerIndexB]);
std::swap(ingame.VerifiedIdentity[playerIndexA], ingame.VerifiedIdentity[playerIndexB]);
std::swap(ingame.JoiningInProgress[playerIndexA], ingame.JoiningInProgress[playerIndexB]);
std::swap(ingame.PendingDisconnect[playerIndexA], ingame.PendingDisconnect[playerIndexB]);
Expand Down
2 changes: 2 additions & 0 deletions src/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ bool loadConfig()
pie_EnableFog(false);
}
war_setAutoLagKickSeconds(iniGetInteger("hostAutoLagKickSeconds", war_getAutoLagKickSeconds()).value());
war_setAutoDesyncKickSeconds(iniGetInteger("hostAutoDesyncKickSeconds", war_getAutoDesyncKickSeconds()).value());
war_setDisableReplayRecording(iniGetBool("disableReplayRecord", war_getDisableReplayRecording()).value());
war_setMaxReplaysSaved(iniGetInteger("maxReplaysSaved", war_getMaxReplaysSaved()).value());
war_setOldLogsLimit(iniGetInteger("oldLogsLimit", war_getOldLogsLimit()).value());
Expand Down Expand Up @@ -769,6 +770,7 @@ bool saveConfig()
iniSetBool("autosaveEnabled", autosaveEnabled);
iniSetBool("fog", pie_GetFogEnabled());
iniSetInteger("hostAutoLagKickSeconds", war_getAutoLagKickSeconds());
iniSetInteger("hostAutoDesyncKickSeconds", war_getAutoDesyncKickSeconds());
iniSetBool("disableReplayRecord", war_getDisableReplayRecording());
iniSetInteger("maxReplaysSaved", war_getMaxReplaysSaved());
iniSetInteger("oldLogsLimit", war_getOldLogsLimit());
Expand Down
2 changes: 2 additions & 0 deletions src/multibot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "mapgrid.h"
#include "multirecv.h"
#include "transporter.h"
#include "warzoneconfig.h"
#include "multiint.h"

#include <vector>
#include <algorithm>
Expand Down
1 change: 1 addition & 0 deletions src/multiint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6267,6 +6267,7 @@ bool WzMultiplayerOptionsTitleUI::startHost()
ingame.PingTimes[i] = 0;
ingame.VerifiedIdentity[i] = false;
ingame.LagCounter[i] = 0;
ingame.DesyncCounter[i] = 0;
ingame.lastSentPlayerDataCheck2[i].reset();
ingame.muteChat[i] = false;
}
Expand Down
3 changes: 3 additions & 0 deletions src/multijoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ void clearPlayer(UDWORD player, bool quietly)
debug(LOG_NET, "R.I.P. %s (%u). quietly is %s", getPlayerName(player), player, quietly ? "true" : "false");

ingame.LagCounter[player] = 0;
ingame.DesyncCounter[player] = 0;
ingame.JoiningInProgress[player] = false; // if they never joined, reset the flag
ingame.DataIntegrity[player] = false;
ingame.hostChatPermissions[player] = false;
Expand Down Expand Up @@ -332,6 +333,7 @@ void handlePlayerLeftInGame(UDWORD player)
debug(LOG_NET, "R.I.P. %s (%u).", getPlayerName(player), player);

ingame.LagCounter[player] = 0;
ingame.DesyncCounter[player] = 0;
ingame.JoiningInProgress[player] = false; // if they never joined, reset the flag
ingame.PendingDisconnect[player] = false;
ingame.DataIntegrity[player] = false;
Expand Down Expand Up @@ -667,6 +669,7 @@ void setupNewPlayer(UDWORD player)

ingame.PingTimes[player] = 0; // Reset ping time
ingame.LagCounter[player] = 0;
ingame.DesyncCounter[player] = 0;
ingame.VerifiedIdentity[player] = false;
ingame.JoiningInProgress[player] = true; // Note that player is now joining
ingame.PendingDisconnect[player] = false;
Expand Down
72 changes: 69 additions & 3 deletions src/multiplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ static bool sendDataCheck2();
void startMultiplayerGame();

// ////////////////////////////////////////////////////////////////////////////
// Auto Lag Kick Handling
// Auto Kick Handling

#define LAG_INITIAL_LOAD_GRACEPERIOD 60
#define LAG_CHECK_INTERVAL 1000
Expand Down Expand Up @@ -184,12 +184,77 @@ static void autoLagKickRoutine()
ingame.LagCounter[i] = 0;
}
else if (ingame.LagCounter[i] >= (LagAutoKickSeconds - 3)) {
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds.", i, getPlayerName(i), (LagAutoKickSeconds - ingame.LagCounter[i]));
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds. (lag)", i, getPlayerName(i), (LagAutoKickSeconds - ingame.LagCounter[i]));
debug(LOG_INFO, "%s", msg.c_str());
sendTextMessage(msg.c_str());
}
else if (ingame.LagCounter[i] % 15 == 0) { // every 15 seconds
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds.", i, getPlayerName(i), (LagAutoKickSeconds - ingame.LagCounter[i]));
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds. (lag)", i, getPlayerName(i), (LagAutoKickSeconds - ingame.LagCounter[i]));
debug(LOG_INFO, "%s", msg.c_str());
sendTextMessage(msg.c_str());
}
}
}

#define DESYNC_CHECK_INTERVAL 1000
const std::chrono::milliseconds DesyncCheckInterval(DESYNC_CHECK_INTERVAL);

static void autoDesyncKickRoutine()
{
if (!NetPlay.isHost)
{
return;
}

int DesyncAutoKickSeconds = war_getAutoDesyncKickSeconds();
if (DesyncAutoKickSeconds <= 0)
{
return;
}

const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - ingame.lastDesyncCheck) < DesyncCheckInterval)
{
return;
}

ingame.lastDesyncCheck = now;
uint32_t playerCheckLimit = (!ingame.TimeEveryoneIsInGame.has_value()) ? MAX_CONNECTED_PLAYERS : MAX_PLAYERS;
for (uint32_t i = 0; i < playerCheckLimit; ++i)
{
if (!isHumanPlayer(i))
{
continue;
}
if (i > MAX_PLAYERS && !gtimeShouldWaitForPlayer(i))
{
continue;
}
if (NETcheckPlayerConnectionStatus(CONNECTIONSTATUS_DESYNC, i))
{
ingame.DesyncCounter[i]++;
}
else
{
ingame.DesyncCounter[i] = 0;
continue;
}
debug(LOG_INFO, "Player %d Status %d Counter %d", i, NETcheckPlayerConnectionStatus(CONNECTIONSTATUS_DESYNC, i), ingame.DesyncCounter[i]);
if (ingame.DesyncCounter[i] >= DesyncAutoKickSeconds) {
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") because of desync. (Timeout: %u seconds)", i, getPlayerName(i), DesyncAutoKickSeconds);
debug(LOG_INFO, "%s", msg.c_str());
sendTextMessage(msg.c_str());
wz_command_interface_output("WZEVENT: desync-kick: %u %s\n", i, NetPlay.players[i].IPtextAddress);
kickPlayer(i, "Your timeline diviated too far.", ERROR_CONNECTION, false);
ingame.DesyncCounter[i] = 0;
}
else if (ingame.DesyncCounter[i] >= (DesyncAutoKickSeconds - 3)) {
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds. (desync)", i, getPlayerName(i), (DesyncAutoKickSeconds - ingame.DesyncCounter[i]));
debug(LOG_INFO, "%s", msg.c_str());
sendTextMessage(msg.c_str());
}
else if (ingame.DesyncCounter[i] % 2 == 0) { // every 2 seconds
std::string msg = astringf("Auto-kicking player %" PRIu32 " (\"%s\") in %u seconds. (desync)", i, getPlayerName(i), (DesyncAutoKickSeconds - ingame.DesyncCounter[i]));
debug(LOG_INFO, "%s", msg.c_str());
sendTextMessage(msg.c_str());
}
Expand Down Expand Up @@ -371,6 +436,7 @@ bool multiPlayerLoop()
if (NetPlay.isHost)
{
autoLagKickRoutine();
autoDesyncKickRoutine();
processPendingKickVotes();
}

Expand Down
2 changes: 2 additions & 0 deletions src/multiplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct MULTIPLAYERINGAME
{
UDWORD PingTimes[MAX_CONNECTED_PLAYERS]; // store for pings.
int LagCounter[MAX_CONNECTED_PLAYERS];
int DesyncCounter[MAX_CONNECTED_PLAYERS];
bool VerifiedIdentity[MAX_CONNECTED_PLAYERS]; // if the multistats identity has been verified.
bool localOptionsReceived; // used to show if we have game options yet..
bool localJoiningInProgress; // used before we know our player number.
Expand All @@ -119,6 +120,7 @@ struct MULTIPLAYERINGAME
std::chrono::steady_clock::time_point startTime;
optional<std::chrono::steady_clock::time_point> endTime;
std::chrono::steady_clock::time_point lastLagCheck;
std::chrono::steady_clock::time_point lastDesyncCheck;
optional<std::chrono::steady_clock::time_point> lastSentPlayerDataCheck2[MAX_CONNECTED_PLAYERS] = {};
std::chrono::steady_clock::time_point lastPlayerDataCheck2;
bool muteChat[MAX_CONNECTED_PLAYERS] = {false}; // the local client-set mute status for this player
Expand Down
16 changes: 16 additions & 0 deletions src/warzoneconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct WARZONE_GLOBALS
JS_BACKEND jsBackend = (JS_BACKEND)0;
bool autoAdjustDisplayScale = true;
int autoLagKickSeconds = 60;
int autoDesyncKickSeconds = 10;
bool disableReplayRecording = false;
int maxReplaysSaved = MAX_REPLAY_FILES;
int oldLogsLimit = MAX_OLD_LOGS;
Expand Down Expand Up @@ -486,6 +487,21 @@ void war_setAutoLagKickSeconds(int seconds)
warGlobs.autoLagKickSeconds = seconds;
}

int war_getAutoDesyncKickSeconds()
{
return warGlobs.autoDesyncKickSeconds;
}

void war_setAutoDesyncKickSeconds(int seconds)
{
seconds = std::max(seconds, 0);
if (seconds > 0)
{
seconds = std::max(seconds, 10);
}
warGlobs.autoDesyncKickSeconds = seconds;
}

bool war_getDisableReplayRecording()
{
return warGlobs.disableReplayRecording;
Expand Down
2 changes: 2 additions & 0 deletions src/warzoneconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ bool war_getAutoAdjustDisplayScale();
void war_setAutoAdjustDisplayScale(bool autoAdjustDisplayScale);
int war_getAutoLagKickSeconds();
void war_setAutoLagKickSeconds(int seconds);
int war_getAutoDesyncKickSeconds();
void war_setAutoDesyncKickSeconds(int seconds);
bool war_getDisableReplayRecording();
void war_setDisableReplayRecording(bool disable);
int war_getMaxReplaysSaved();
Expand Down
Loading