Index: source/network/NetClient.cpp =================================================================== --- source/network/NetClient.cpp +++ source/network/NetClient.cpp @@ -695,6 +695,9 @@ client->GetScriptInterface().Eval("({'type':'start'})", &msg); client->PushGuiMessage(msg); + // prevent player drops during loading + client->m_Session->SetLongTimeout(true); + return true; } @@ -709,6 +712,9 @@ shared_ptr(new CNetFileReceiveTask_ClientRejoin(*client)) ); + // prevent player drops during loading + client->m_Session->SetLongTimeout(true); + return true; } @@ -881,6 +887,9 @@ if (client->m_Rejoin) client->SendRejoinedMessage(); + // we allowed longer timeouts during loading, so now return them to normal + client->m_Session->SetLongTimeout(false); + return true; } Index: source/network/NetServer.cpp =================================================================== --- source/network/NetServer.cpp +++ source/network/NetServer.cpp @@ -1101,6 +1101,8 @@ ); session->SetNextState(NSS_JOIN_SYNCING); + // prevent player drops during loading + session->SetLongTimeout(true); } return true; @@ -1249,6 +1251,9 @@ if (session->GetGUID() == server.m_HostGUID) server.StartGame(); + // prevent player drops during game loading + session->SetLongTimeout(true); + return true; } @@ -1280,6 +1285,9 @@ loadedSession->SendMessage(&message); server.Broadcast(&message, { NSS_INGAME }); + // the client has loaded, so no longer needs a long timeout + loadedSession->SetLongTimeout(false); + return true; } @@ -1356,6 +1364,9 @@ session->SendMessage(&pausedMessage); } + // the client has loaded, so no longer needs a long timeout to prevent drops + session->SetLongTimeout(false); + return true; } Index: source/network/NetSession.h =================================================================== --- source/network/NetSession.h +++ source/network/NetSession.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -105,6 +105,11 @@ */ u32 GetMeanRTT() const; + /** + * Allows temporarily increasing the timeout to prevent drops during map generation + */ + void SetLongTimeout(bool longTimeout); + CNetFileTransferer& GetFileTransferer() { return m_FileTransferer; } private: @@ -182,6 +187,11 @@ void SetLocalClient(bool isLocalClient); /** + * Allows temporarily increasing the timeout to prevent drops during map generation + */ + void SetLongTimeout(bool longTimeout); + + /** * Send a message to the client. */ virtual bool SendMessage(const CNetMessage* message); Index: source/network/NetSession.cpp =================================================================== --- source/network/NetSession.cpp +++ source/network/NetSession.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -28,10 +28,22 @@ const u32 NETWORK_WARNING_TIMEOUT = 2000; +const u32 LONG_TIMEOUT = 40000; + const u32 MAXIMUM_HOST_TIMEOUT = std::numeric_limits::max(); static const int CHANNEL_COUNT = 1; +void LongTimeout(ENetPeer* peer, bool longTimeout) +{ +#if (ENET_VERSION >= ENET_VERSION_CREATE(1, 3, 4)) + if (longTimeout) + enet_peer_timeout(peer, 0, LONG_TIMEOUT, LONG_TIMEOUT); + else + enet_peer_timeout(peer, 0, 0, 0); +#endif +} + CNetClientSession::CNetClientSession(CNetClient& client) : m_Client(client), m_FileTransferer(this), m_Host(NULL), m_Server(NULL), m_Stats(NULL) { @@ -200,7 +212,10 @@ return m_Server->roundTripTime; } - +void CNetClientSession::SetLongTimeout(bool longTimeout) +{ + LongTimeout(m_Server, longTimeout); +} CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) : m_Server(server), m_FileTransferer(this), m_Peer(peer) @@ -262,3 +277,10 @@ enet_peer_timeout(m_Peer, 0, MAXIMUM_HOST_TIMEOUT, MAXIMUM_HOST_TIMEOUT); #endif } + +void CNetServerSession::SetLongTimeout(bool longTimeout) +{ + if (m_IsLocalClient) + return; // don't change the timeout if the client is local, since that is handled by SetLocalClient + LongTimeout(m_Peer, longTimeout); +}