Improve dummy connecting button and error handling

Track whether the dummy is currently connecting separately so the dummy being disconnected due to errors can be detected. Show an error message as echo in the chat when the dummy could not be connected, e.g. when the server is full.

Use the global time for limiting the dummy connecting delay instead of using game ticks, so the delay also works correctly when having connection problems (i.e., when ticks do not advance). Handle the dummy connecting being delayed separately from the dummy currently connecting.

Add tooltips for the "Connect dummy"-button when it's disable due to dummy not being allow on the server or when connecting is delayed.

Add console error messages for `dummy_connect` command.
This commit is contained in:
Robert Müller 2024-07-27 22:34:53 +02:00
parent 78cbb45d49
commit b61005d3e7
4 changed files with 69 additions and 38 deletions

View file

@ -163,6 +163,7 @@ public:
virtual void DummyConnect() = 0;
virtual bool DummyConnected() const = 0;
virtual bool DummyConnecting() const = 0;
virtual bool DummyConnectingDelayed() const = 0;
virtual bool DummyAllowed() const = 0;
virtual void Restart() = 0;

View file

@ -260,7 +260,7 @@ void CClient::SendInput()
// fetch input
for(int Dummy = 0; Dummy < NUM_DUMMIES; Dummy++)
{
if(!m_DummyConnected && Dummy != 0)
if(!DummyConnected() && Dummy != 0)
{
break;
}
@ -396,7 +396,7 @@ void CClient::OnEnterGame(bool Dummy)
if(!Dummy)
{
m_LastDummyConnectTime = 0;
m_LastDummyConnectTime = 0.0f;
}
GameClient()->OnEnterGame();
@ -621,38 +621,51 @@ bool CClient::DummyConnected() const
bool CClient::DummyConnecting() const
{
return !m_DummyConnected && m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(g_Config.m_ClDummy);
return m_DummyConnecting;
}
bool CClient::DummyConnectingDelayed() const
{
return !DummyConnected() && !DummyConnecting() && m_LastDummyConnectTime > 0.0f && m_LastDummyConnectTime + 5.0f > GlobalTime();
}
void CClient::DummyConnect()
{
if(m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(g_Config.m_ClDummy))
return;
if(m_aNetClient[CONN_MAIN].State() != NETSTATE_ONLINE)
{
log_info("client", "Not online.");
return;
}
if(m_DummyConnected || !DummyAllowed())
if(!DummyAllowed())
{
log_info("client", "Dummy is not allowed on this server.");
return;
}
if(DummyConnected() || DummyConnecting())
{
log_info("client", "Dummy is already connected/connecting.");
return;
}
if(DummyConnectingDelayed())
{
log_info("client", "Wait before connecting dummy again.");
return;
}
m_LastDummyConnectTime = GameTick(g_Config.m_ClDummy);
m_LastDummyConnectTime = GlobalTime();
m_aRconAuthed[1] = 0;
m_DummySendConnInfo = true;
g_Config.m_ClDummyCopyMoves = 0;
g_Config.m_ClDummyHammer = 0;
// connect to the server
m_DummyConnecting = true;
m_aNetClient[CONN_DUMMY].Connect(m_aNetClient[CONN_MAIN].ServerAddress(), 1);
}
void CClient::DummyDisconnect(const char *pReason)
{
if(!m_DummyConnected)
return;
m_aNetClient[CONN_DUMMY].Disconnect(pReason);
g_Config.m_ClDummy = 0;
@ -666,6 +679,7 @@ void CClient::DummyDisconnect(const char *pReason)
m_aapSnapshots[1][SNAP_PREV] = 0;
m_aReceivedSnapshots[1] = 0;
m_DummyConnected = false;
m_DummyConnecting = false;
GameClient()->OnDummyDisconnect();
}
@ -1526,6 +1540,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
else if(Conn == CONN_DUMMY && Msg == NETMSG_CON_READY)
{
m_DummyConnected = true;
m_DummyConnecting = false;
g_Config.m_ClDummy = 1;
Rcon("crashmeplx");
if(m_aRconAuthed[0])
@ -2269,25 +2284,33 @@ void CClient::PumpNetwork()
if(State() != IClient::STATE_DEMOPLAYBACK)
{
// check for errors
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING && m_aNetClient[CONN_MAIN].State() == NETSTATE_OFFLINE)
// check for errors of main and dummy
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING)
{
if(m_aNetClient[CONN_MAIN].State() == NETSTATE_OFFLINE)
{
// This will also disconnect the dummy, so the branch below is an `else if`
Disconnect();
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "offline error='%s'", m_aNetClient[CONN_MAIN].ErrorString());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, gs_ClientNetworkErrPrintColor);
}
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING && m_DummyConnected &&
m_aNetClient[CONN_DUMMY].State() == NETSTATE_OFFLINE)
else if((DummyConnecting() || DummyConnected()) && m_aNetClient[CONN_DUMMY].State() == NETSTATE_OFFLINE)
{
DummyDisconnect(0);
const bool WasConnecting = DummyConnecting();
DummyDisconnect(nullptr);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "offline dummy error='%s'", m_aNetClient[CONN_DUMMY].ErrorString());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, gs_ClientNetworkErrPrintColor);
if(WasConnecting)
{
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Could not connect dummy"), m_aNetClient[CONN_DUMMY].ErrorString());
GameClient()->Echo(aBuf);
}
}
}
//
// check if main was connected
if(State() == IClient::STATE_CONNECTING && m_aNetClient[CONN_MAIN].State() == NETSTATE_ONLINE)
{
// we switched to online
@ -3164,7 +3187,7 @@ void CClient::Con_DummyConnect(IConsole::IResult *pResult, void *pUserData)
void CClient::Con_DummyDisconnect(IConsole::IResult *pResult, void *pUserData)
{
CClient *pSelf = (CClient *)pUserData;
pSelf->DummyDisconnect(0);
pSelf->DummyDisconnect(nullptr);
}
void CClient::Con_DummyResetInput(IConsole::IResult *pResult, void *pUserData)

View file

@ -178,8 +178,9 @@ class CClient : public IClient, public CDemoPlayer::IListener
int m_aCurrentInput[NUM_DUMMIES] = {0, 0};
bool m_LastDummy = false;
bool m_DummySendConnInfo = false;
bool m_DummyConnecting = false;
bool m_DummyConnected = false;
int m_LastDummyConnectTime = 0;
float m_LastDummyConnectTime = 0.0f;
// graphs
CGraph m_InputtimeMarginGraph;
@ -316,6 +317,7 @@ public:
void DummyConnect() override;
bool DummyConnected() const override;
bool DummyConnecting() const override;
bool DummyConnectingDelayed() const override;
bool DummyAllowed() const override;
void GetServerInfo(CServerInfo *pServerInfo) const override;

View file

@ -72,13 +72,18 @@ void CMenus::RenderGame(CUIRect MainView)
ButtonBar.VSplitRight(5.0f, &ButtonBar, 0);
ButtonBar.VSplitRight(170.0f, &ButtonBar, &Button);
bool DummyConnecting = Client()->DummyConnecting();
static CButtonContainer s_DummyButton;
if(!Client()->DummyAllowed())
{
DoButton_Menu(&s_DummyButton, Localize("Connect Dummy"), 1, &Button);
GameClient()->m_Tooltips.DoToolTip(&s_DummyButton, &Button, Localize("Dummy is not allowed on this server."));
}
else if(DummyConnecting)
else if(Client()->DummyConnectingDelayed())
{
DoButton_Menu(&s_DummyButton, Localize("Connect Dummy"), 1, &Button);
GameClient()->m_Tooltips.DoToolTip(&s_DummyButton, &Button, Localize("Please wait…"));
}
else if(Client()->DummyConnecting())
{
DoButton_Menu(&s_DummyButton, Localize("Connecting dummy"), 1, &Button);
}
@ -131,7 +136,7 @@ void CMenus::RenderGame(CUIRect MainView)
{
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
if(!DummyConnecting && DoButton_Menu(&s_SpectateButton, Localize("Spectate"), 0, &Button))
if(!Client()->DummyConnecting() && DoButton_Menu(&s_SpectateButton, Localize("Spectate"), 0, &Button))
{
if(g_Config.m_ClDummy == 0 || Client()->DummyConnected())
{
@ -148,7 +153,7 @@ void CMenus::RenderGame(CUIRect MainView)
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
static CButtonContainer s_JoinRedButton;
if(!DummyConnecting && DoButton_Menu(&s_JoinRedButton, Localize("Join red"), 0, &Button))
if(!Client()->DummyConnecting() && DoButton_Menu(&s_JoinRedButton, Localize("Join red"), 0, &Button))
{
m_pClient->SendSwitchTeam(TEAM_RED);
SetActive(false);
@ -160,7 +165,7 @@ void CMenus::RenderGame(CUIRect MainView)
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
static CButtonContainer s_JoinBlueButton;
if(!DummyConnecting && DoButton_Menu(&s_JoinBlueButton, Localize("Join blue"), 0, &Button))
if(!Client()->DummyConnecting() && DoButton_Menu(&s_JoinBlueButton, Localize("Join blue"), 0, &Button))
{
m_pClient->SendSwitchTeam(TEAM_BLUE);
SetActive(false);
@ -173,7 +178,7 @@ void CMenus::RenderGame(CUIRect MainView)
{
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
if(!DummyConnecting && DoButton_Menu(&s_SpectateButton, Localize("Join game"), 0, &Button))
if(!Client()->DummyConnecting() && DoButton_Menu(&s_SpectateButton, Localize("Join game"), 0, &Button))
{
m_pClient->SendSwitchTeam(0);
SetActive(false);