Add cl_confirm_disconnect_quit_time (fixes #1530)

Number of minutes of active racing time before being asked to confirm
disconnecting, disconnecting dummy or quitting through GUI. Defaults to
20 minutes, -1 to disable, 0 to always enable.

Also removed confirmation to quit when in main menu, except when having
an unsaved map in editor.

Spectate and kill should already be safe thanks to server-side kill
protection.
This commit is contained in:
def 2019-03-25 20:02:50 +01:00
parent c559fa3201
commit 8908102536
10 changed files with 61 additions and 12 deletions

View file

@ -179,6 +179,8 @@ public:
virtual const char *GetCurrentMapPath() = 0; virtual const char *GetCurrentMapPath() = 0;
virtual unsigned GetMapCrc() = 0; virtual unsigned GetMapCrc() = 0;
virtual int GetCurrentRaceTime() = 0;
virtual void RaceRecord_Start(const char *pFilename) = 0; virtual void RaceRecord_Start(const char *pFilename) = 0;
virtual void RaceRecord_Stop() = 0; virtual void RaceRecord_Stop() = 0;
virtual bool RaceRecord_IsRecording() = 0; virtual bool RaceRecord_IsRecording() = 0;
@ -220,6 +222,7 @@ public:
virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0; virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0;
virtual void OnDummySwap() = 0; virtual void OnDummySwap() = 0;
virtual void SendDummyInfo(bool Start) = 0; virtual void SendDummyInfo(bool Start) = 0;
virtual int GetLastRaceTick() = 0;
virtual const char *GetItemName(int Type) = 0; virtual const char *GetItemName(int Type) = 0;
virtual const char *Version() = 0; virtual const char *Version() = 0;

View file

@ -824,6 +824,13 @@ void CClient::DummyDisconnect(const char *pReason)
GameClient()->OnDummyDisconnect(); GameClient()->OnDummyDisconnect();
} }
int CClient::GetCurrentRaceTime()
{
if(GameClient()->GetLastRaceTick() < 0)
return 0;
return (GameTick() - GameClient()->GetLastRaceTick()) / 50;
}
int CClient::SendMsgExY(CMsgPacker *pMsg, int Flags, bool System, int NetClient) int CClient::SendMsgExY(CMsgPacker *pMsg, int Flags, bool System, int NetClient)
{ {
CNetChunk Packet; CNetChunk Packet;

View file

@ -397,6 +397,8 @@ public:
void GenerateTimeoutSeed(); void GenerateTimeoutSeed();
void GenerateTimeoutCodes(); void GenerateTimeoutCodes();
virtual int GetCurrentRaceTime();
const char *GetCurrentMap(); const char *GetCurrentMap();
const char *GetCurrentMapPath(); const char *GetCurrentMapPath();
unsigned GetMapCrc(); unsigned GetMapCrc();

View file

@ -384,7 +384,7 @@ MACRO_CONFIG_INT(ClChatReset, cl_chat_reset, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAV
MACRO_CONFIG_INT(ClShowDirection, cl_show_direction, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show tee direction") MACRO_CONFIG_INT(ClShowDirection, cl_show_direction, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show tee direction")
MACRO_CONFIG_INT(ClHttpMapDownload, cl_http_map_download, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try fast HTTP map download first") MACRO_CONFIG_INT(ClHttpMapDownload, cl_http_map_download, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try fast HTTP map download first")
MACRO_CONFIG_INT(ClOldGunPosition, cl_old_gun_position, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Tees hold gun a bit higher like in TW 0.6.1 and older") MACRO_CONFIG_INT(ClOldGunPosition, cl_old_gun_position, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Tees hold gun a bit higher like in TW 0.6.1 and older")
MACRO_CONFIG_INT(ClConfirmDisconnect, cl_confirm_disconnect, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Confirmation popup before disconnecting") MACRO_CONFIG_INT(ClConfirmDisconnectQuitTime, cl_confirm_disconnect_quit_time, 20, -1, 1440, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Confirmation popup before disconnecting/quitting after game time (in minutes, -1 to turn off, 0 to always turn on)")
MACRO_CONFIG_STR(ClTimeoutCode, cl_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout code to use") MACRO_CONFIG_STR(ClTimeoutCode, cl_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout code to use")
MACRO_CONFIG_STR(ClDummyTimeoutCode, cl_dummy_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Dummy Timeout code to use") MACRO_CONFIG_STR(ClDummyTimeoutCode, cl_dummy_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Dummy Timeout code to use")
MACRO_CONFIG_STR(ClTimeoutSeed, cl_timeout_seed, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout seed") MACRO_CONFIG_STR(ClTimeoutSeed, cl_timeout_seed, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout seed")

View file

@ -263,7 +263,7 @@ void CGhost::OnNewSnapshot()
{ {
CServerInfo ServerInfo; CServerInfo ServerInfo;
Client()->GetServerInfo(&ServerInfo); Client()->GetServerInfo(&ServerInfo);
if(!IsRace(&ServerInfo) || !g_Config.m_ClRaceGhost || Client()->State() != IClient::STATE_ONLINE) if(!IsRace(&ServerInfo) || Client()->State() != IClient::STATE_ONLINE)
return; return;
if(!m_pClient->m_Snap.m_pGameInfoObj || m_pClient->m_Snap.m_SpecInfo.m_Active || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) if(!m_pClient->m_Snap.m_pGameInfoObj || m_pClient->m_Snap.m_SpecInfo.m_Active || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter)
return; return;
@ -271,14 +271,18 @@ void CGhost::OnNewSnapshot()
bool RaceFlag = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_RACETIME; bool RaceFlag = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_RACETIME;
bool ServerControl = RaceFlag && g_Config.m_ClRaceGhostServerControl; bool ServerControl = RaceFlag && g_Config.m_ClRaceGhostServerControl;
if(!ServerControl) if(g_Config.m_ClRaceGhost)
CheckStartLocal(false); {
else if(!ServerControl)
CheckStart(); CheckStartLocal(false);
else
CheckStart();
if(m_Recording) if(m_Recording)
AddInfos(m_pClient->m_Snap.m_pLocalCharacter); AddInfos(m_pClient->m_Snap.m_pLocalCharacter);
}
// Record m_LastRaceTick for g_Config.m_ClConfirmDisconnectQuitTime anyway
int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer; int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer;
m_LastRaceTick = RaceFlag ? RaceTick : -1; m_LastRaceTick = RaceFlag ? RaceTick : -1;
} }
@ -622,3 +626,8 @@ void CGhost::OnMapLoad()
m_pClient->m_pMenus->GhostlistPopulate(); m_pClient->m_pMenus->GhostlistPopulate();
m_AllowRestart = false; m_AllowRestart = false;
} }
int CGhost::GetLastRaceTick()
{
return m_LastRaceTick;
}

View file

@ -165,6 +165,8 @@ public:
class IGhostLoader *GhostLoader() const { return m_pGhostLoader; } class IGhostLoader *GhostLoader() const { return m_pGhostLoader; }
class IGhostRecorder *GhostRecorder() const { return m_pGhostRecorder; } class IGhostRecorder *GhostRecorder() const { return m_pGhostRecorder; }
int GetLastRaceTick();
}; };
#endif #endif

View file

@ -806,7 +806,16 @@ int CMenus::RenderMenubar(CUIRect r)
Box.VSplitRight(33.0f, &Box, &Button); Box.VSplitRight(33.0f, &Box, &Button);
static int s_QuitButton=0; static int s_QuitButton=0;
if(DoButton_MenuTab(&s_QuitButton, "\xEE\x97\x8D", 0, &Button, CUI::CORNER_T)) if(DoButton_MenuTab(&s_QuitButton, "\xEE\x97\x8D", 0, &Button, CUI::CORNER_T))
m_Popup = POPUP_QUIT; {
if(m_pClient->Editor()->HasUnsavedData() || Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime)
{
m_Popup = POPUP_QUIT;
}
else
{
Client()->Quit();
}
}
Box.VSplitRight(10.0f, &Box, &Button); Box.VSplitRight(10.0f, &Box, &Button);
Box.VSplitRight(33.0f, &Box, &Button); Box.VSplitRight(33.0f, &Box, &Button);
@ -1201,7 +1210,6 @@ int CMenus::Render()
#endif #endif
// additional info // additional info
Box.HSplitTop(10.0f, 0, &Box);
Box.VMargin(20.f/UI()->Scale(), &Box); Box.VMargin(20.f/UI()->Scale(), &Box);
if(m_pClient->Editor()->HasUnsavedData()) if(m_pClient->Editor()->HasUnsavedData())
{ {

View file

@ -54,10 +54,14 @@ void CMenus::RenderGame(CUIRect MainView)
static int s_DisconnectButton = 0; static int s_DisconnectButton = 0;
if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button)) if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button))
{ {
if(g_Config.m_ClConfirmDisconnect) if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime)
{
m_Popup = POPUP_DISCONNECT; m_Popup = POPUP_DISCONNECT;
}
else else
{
Client()->Disconnect(); Client()->Disconnect();
}
} }
static int s_SpectateButton = 0; static int s_SpectateButton = 0;
@ -149,7 +153,14 @@ void CMenus::RenderGame(CUIRect MainView)
} }
else else
{ {
Client()->DummyDisconnect(0); if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime)
{
m_Popup = POPUP_DISCONNECT;
}
else
{
Client()->DummyDisconnect(0);
}
} }
} }
} }

View file

@ -689,6 +689,11 @@ void CGameClient::OnDummyDisconnect()
m_LastNewPredictedTick[1] = -1; m_LastNewPredictedTick[1] = -1;
} }
int CGameClient::GetLastRaceTick()
{
return m_pGhost->GetLastRaceTick();
}
void CGameClient::OnRelease() void CGameClient::OnRelease()
{ {
// release all systems // release all systems

View file

@ -382,6 +382,8 @@ public:
CWeaponData *GetWeaponData(int Tick) { return &m_aWeaponData[((Tick%150)+150)%150]; } CWeaponData *GetWeaponData(int Tick) { return &m_aWeaponData[((Tick%150)+150)%150]; }
CWeaponData *FindWeaponData(int TargetTick); CWeaponData *FindWeaponData(int TargetTick);
virtual int GetLastRaceTick();
void FindWeaker(bool IsWeaker[2][MAX_CLIENTS]); void FindWeaker(bool IsWeaker[2][MAX_CLIENTS]);
bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && (m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking); } bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && (m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking); }