diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c84faa72..961c1e59 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4083,6 +4083,21 @@ FILESTAMP else if (resynch_score[node]) --resynch_score[node]; break; + case PT_BASICKEEPALIVE: + if (client) + break; + + // This should probably still timeout though, as the node should always have a player 1 number + if (netconsole == -1) + break; + + // If a client sends this it should mean they are done receiving the savegame + sendingsavegame[node] = false; + + // As long as clients send keep alives, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + freezetimeout[node] = I_GetTime() + connectiontimeout; + break; case PT_TEXTCMD: case PT_TEXTCMD2: case PT_TEXTCMD3: @@ -4586,6 +4601,15 @@ static INT16 Consistancy(void) return (INT16)(ret & 0xFFFF); } +// confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE +// used during wipes to tell the server that a node is still connected +static void CL_SendClientKeepAlive(void) +{ + netbuffer->packettype = PT_BASICKEEPALIVE; + + HSendPacket(servernode, false, 0, 0); +} + // send the client packet to the server static void CL_SendClientCmd(void) { @@ -5032,9 +5056,77 @@ static inline void PingUpdate(void) } #endif +static tic_t gametime = 0; + +#ifdef NEWPING +static void UpdatePingTable(void) +{ + INT32 i; + if (server) + { + if (netgame && !(gametime % 255)) + PingUpdate(); + // update node latency values so we can take an average later. + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); + pingmeasurecount++; + } +} +#endif + +// Handle timeouts to prevent definitive freezes from happenning +static void HandleNodeTimeouts(void) +{ + INT32 i; + if (server) + for (i = 1; i < MAXNETNODES; i++) + if (nodeingame[i] && freezetimeout[i] < I_GetTime()) + Net_ConnectionTimeout(i); +} + +// Keep the network alive while not advancing tics! +void NetKeepAlive(void) +{ + tic_t nowtime; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + // return if there's no time passed since the last call + if (realtics <= 0) // nothing new to update + return; + +#ifdef NEWPING + UpdatePingTable(); +#endif + + if (server) + CL_SendClientKeepAlive(); + +// Sryder: What is FILESTAMP??? +FILESTAMP + GetPackets(); +FILESTAMP + + MasterClient_Ticker(); + + if (client) + { + // send keep alive + CL_SendClientKeepAlive(); + // No need to check for resynch because we aren't running any tics + } + // No else because no tics are being run and we can't resynch during this + + Net_AckTicker(); + HandleNodeTimeouts(); + SV_FileSendTicker(); +} + void NetUpdate(void) { - static tic_t gametime = 0; static tic_t resptime = 0; tic_t nowtime; INT32 i; @@ -5056,16 +5148,7 @@ void NetUpdate(void) gametime = nowtime; #ifdef NEWPING - if (server) - { - if (netgame && !(gametime % 255)) - PingUpdate(); - // update node latency values so we can take an average later. - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); - pingmeasurecount++; - } + UpdatePingTable(); #endif if (client) @@ -5133,12 +5216,7 @@ FILESTAMP } } Net_AckTicker(); - // Handle timeouts to prevent definitive freezes from happenning - if (server) - for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && freezetimeout[i] < I_GetTime()) - Net_ConnectionTimeout(i); - nowtime /= NEWTICRATERATIO; + HandleNodeTimeouts(); if (nowtime > resptime) { resptime = nowtime; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 39cb8c4d..62bd8bc1 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -71,6 +71,7 @@ typedef enum PT_CLIENT3MIS, PT_CLIENT4CMD, // 4P PT_CLIENT4MIS, + PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL // allows HSendPacket(*, true, *, *) to return false. @@ -538,6 +539,7 @@ void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam); // splitsreen void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player // Create any new ticcmds and broadcast to other players. +void NetKeepAlive(void); void NetUpdate(void); void SV_StartSinglePlayerServer(void); diff --git a/src/d_net.c b/src/d_net.c index 62301dc1..6702a60a 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -903,6 +903,9 @@ static void DebugPrintpacket(const char *header) (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic), (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom)); break; + case PT_BASICKEEPALIVE: + fprintf(debugfile, " keep alive\n"); + break; case PT_TEXTCMD: case PT_TEXTCMD2: case PT_TEXTCMD3: diff --git a/src/f_wipe.c b/src/f_wipe.c index f7a5992a..eaa5a013 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -26,6 +26,7 @@ #include "console.h" #include "d_main.h" #include "m_misc.h" // movie mode +#include "d_clisrv.h" // So the network state can be updated during the wipe #ifdef HWRENDER #include "hardware/hw_main.h" @@ -375,6 +376,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) if (moviemode) M_SaveFrame(); + + NetKeepAlive(); // Update the network so we don't cause timeouts } WipeInAction = false; #endif diff --git a/src/p_setup.c b/src/p_setup.c index 912791cf..58e13c2e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2857,6 +2857,9 @@ boolean P_SetupLevel(boolean skipprecip) lastwipetic = nowtime; if (moviemode) // make sure we save frames for the white hold too M_SaveFrame(); + + // Keep the network alive + NetKeepAlive(); } ranspecialwipe = 1; @@ -3435,7 +3438,7 @@ boolean P_AddWadFile(const char *wadfilename) // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] - // + // // edit music defs // S_LoadMusicDefs(wadnum);