diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 213f5dde..88e018d1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -71,8 +71,6 @@ // firstticstosend is used to optimize a condition // Normally maketic >= gametic > 0 -#define PREDICTIONQUEUE BACKUPTICS -#define PREDICTIONMASK (PREDICTIONQUEUE-1) #define MAX_REASONLENGTH 30 #define FORCECLOSE 0x8000 @@ -109,7 +107,7 @@ static tic_t firstticstosend; // min of the nettics static tic_t tictoclear = 0; // optimize d_clearticcmd static tic_t maketic; -static INT16 consistancy[BACKUPTICS]; +static INT16 consistancy[TICQUEUE]; // Resynching shit! static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick @@ -163,7 +161,7 @@ typedef struct textcmdtic_s struct textcmdtic_s *next; } textcmdtic_t; -ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; +ticcmd_t netcmds[TICQUEUE][MAXPLAYERS]; static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; @@ -208,21 +206,22 @@ UINT16 software_MAXPACKETLENGTH; /** Guesses the value of a tic from its lowest byte and from maketic * * \param low The lowest byte of the tic value + * \param basetic The last full tic value to compare against * \return The full tic value * */ -tic_t ExpandTics(INT32 low) +tic_t ExpandTics(INT32 low, tic_t basetic) { INT32 delta; - delta = low - (maketic & UINT8_MAX); + delta = low - (basetic & UINT8_MAX); if (delta >= -64 && delta <= 64) - return (maketic & ~UINT8_MAX) + low; + return (basetic & ~UINT8_MAX) + low; else if (delta > 64) - return (maketic & ~UINT8_MAX) - 256 + low; + return (basetic & ~UINT8_MAX) - 256 + low; else //if (delta < -64) - return (maketic & ~UINT8_MAX) + 256 + low; + return (basetic & ~UINT8_MAX) + 256 + low; } // ----------------------------------------------------------------- @@ -467,9 +466,9 @@ static void D_Clearticcmd(tic_t tic) D_FreeTextcmd(tic); for (i = 0; i < MAXPLAYERS; i++) - netcmds[tic%BACKUPTICS][i].angleturn = 0; + netcmds[tic%TICQUEUE][i].angleturn = 0; - DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); + DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%TICQUEUE)); } void D_ResetTiccmds(void) @@ -1747,7 +1746,7 @@ static void CL_LoadReceivedSavegame(void) save_p = NULL; if (unlink(tmpsave) == -1) CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - consistancy[gametic%BACKUPTICS] = Consistancy(); + consistancy[gametic%TICQUEUE] = Consistancy(); CON_ToggleOff(); } #endif @@ -3666,7 +3665,7 @@ void SV_StopServer(void) localtextcmd3[0] = 0; localtextcmd4[0] = 0; - for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) + for (i = firstticstosend; i < firstticstosend + TICQUEUE; i++) D_Clearticcmd(i); consoleplayer = 0; @@ -4199,9 +4198,9 @@ static void HandlePacketFromAwayNode(SINT8 node) */ static boolean CheckForSpeedHacks(UINT8 p) { - if (netcmds[maketic%BACKUPTICS][p].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][p].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].sidemove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][p].driftturn > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].driftturn < -KART_FULLTURN) + if (netcmds[maketic%TICQUEUE][p].forwardmove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].forwardmove < -MAXPLMOVE + || netcmds[maketic%TICQUEUE][p].sidemove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].sidemove < -MAXPLMOVE + || netcmds[maketic%TICQUEUE][p].driftturn > KART_FULLTURN || netcmds[maketic%TICQUEUE][p].driftturn < -KART_FULLTURN) { XBOXSTATIC char buf[2]; CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]); @@ -4269,8 +4268,8 @@ FILESTAMP // To save bytes, only the low byte of tic numbers are sent // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom); + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, nettics[node]); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, nettics[node]); if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS || netbuffer->packettype == PT_CLIENT3MIS || netbuffer->packettype == PT_CLIENT4MIS @@ -4307,7 +4306,7 @@ FILESTAMP break; // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1); // Check ticcmd for "speed hacks" if (CheckForSpeedHacks((UINT8)netconsole)) @@ -4319,7 +4318,7 @@ FILESTAMP || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer2[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer2[node])) @@ -4330,7 +4329,7 @@ FILESTAMP || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer3[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer3[node]], &netbuffer->u.client3pak.cmd3, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer3[node])) @@ -4340,7 +4339,7 @@ FILESTAMP if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS) && (nodetoplayer4[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer4[node]], &netbuffer->u.client4pak.cmd4, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer4[node])) @@ -4355,8 +4354,8 @@ FILESTAMP break; } // Check player consistancy during the level - if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) + if (realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL + && consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)) { SV_RequireResynch(node); @@ -4365,10 +4364,10 @@ FILESTAMP if (cv_blamecfail.value) CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], + consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy)); DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], + netconsole, realstart, consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy))); break; } @@ -4380,7 +4379,7 @@ FILESTAMP buf[1] = KICK_MSG_CON_FAIL; SendNetXCmd(XD_KICK, &buf, 2); DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], + netconsole, realstart, consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy))); break; } @@ -4455,10 +4454,10 @@ FILESTAMP // search a tic that have enougth space in the ticcmd while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) + && tic < firstticstosend + TICQUEUE) tic++; - if (tic >= firstticstosend + BACKUPTICS) + if (tic >= firstticstosend + TICQUEUE) { DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), @@ -4566,7 +4565,7 @@ FILESTAMP break; } - realstart = ExpandTics(netbuffer->u.serverpak.starttic); + realstart = ExpandTics(netbuffer->u.serverpak.starttic, maketic); realend = realstart + netbuffer->u.serverpak.numtics; if (!txtpak) @@ -4588,7 +4587,7 @@ FILESTAMP D_Clearticcmd(i); // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + pak = G_ScpyTiccmd(netcmds[i%TICQUEUE], pak, netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); // copy the textcmds @@ -4943,7 +4942,7 @@ static void CL_SendClientCmd(void) { packetsize = sizeof (clientcmd_pak); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); - netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); + netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%TICQUEUE]); if (splitscreen || botingame) // Send a special packet with 2 cmd for splitscreen { @@ -5030,20 +5029,23 @@ static void SV_SendTics(void) for (n = 1; n < MAXNETNODES; n++) if (nodeingame[n]) { - lasttictosend = maketic; - // assert supposedtics[n]>=nettics[n] realfirsttic = supposedtics[n]; - if (realfirsttic >= maketic) + lasttictosend = maketic; + + if (lasttictosend - nettics[n] >= BACKUPTICS) + lasttictosend = nettics[n] + BACKUPTICS-1; + + if (realfirsttic >= lasttictosend) { // well we have sent all tics we will so use extrabandwidth // to resent packet that are supposed lost (this is necessary since lost // packet detection work when we have received packet with firsttic > neededtic // (getpacket servertics case) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, supposedtics[n], nettics[n])); + n, lasttictosend, supposedtics[n], nettics[n])); realfirsttic = nettics[n]; - if (realfirsttic >= maketic || (I_GetTime() + n)&3) + if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) // all tic are ok continue; DEBFILE(va("Sent %d anyway\n", realfirsttic)); @@ -5093,7 +5095,7 @@ static void SV_SendTics(void) for (i = realfirsttic; i < lasttictosend; i++) { - bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); + bufpos = G_DcpyTiccmd(bufpos, netcmds[i%TICQUEUE], doomcom->numslots * sizeof (ticcmd_t)); } // add textcmds @@ -5169,16 +5171,16 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) for (tic = server ? maketic : (neededtic - 1); tic >= gametic; tic--) { - if (numadjust++ == BACKUPTICS) + if (numadjust++ == TICQUEUE) { DEBFILE(va("SV_SpawnPlayer: All netcmds for player %d adjusted!\n", playernum)); // We already adjusted them all, waste of time doing the same thing over and over // This shouldn't happen normally though, either gametic was 0 (which is handled now anyway) - // or maketic >= gametic + BACKUPTICS + // or maketic >= gametic + TICQUEUE // -- Monster Iestyn 16/01/18 break; } - netcmds[tic%BACKUPTICS][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED); + netcmds[tic%TICQUEUE][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED); if (!tic) // failsafe for gametic == 0 -- Monster Iestyn 16/01/18 break; @@ -5194,7 +5196,7 @@ static void SV_Maketic(void) if (playerpernode[j]) { INT32 player = nodetoplayer[j]; - if ((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0) + if ((netcmds[maketic%TICQUEUE][player].angleturn & TICCMD_RECEIVED) == 0) { // we didn't receive this tic INT32 i; @@ -5209,8 +5211,8 @@ static void SV_Maketic(void) else if (i == 1) player = nodetoplayer2[j]; else if (i == 2) player = nodetoplayer3[j]; else if (i == 3) player = nodetoplayer4[j]; - netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player]; - netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED; + netcmds[maketic%TICQUEUE][player] = netcmds[(maketic-1)%TICQUEUE][player]; + netcmds[maketic%TICQUEUE][player].angleturn &= ~TICCMD_RECEIVED; } } } @@ -5288,7 +5290,7 @@ void TryRunTics(tic_t realtics) G_Ticker((gametic % NEWTICRATERATIO) == 0); ExtraDataTicker(); gametic++; - consistancy[gametic%BACKUPTICS] = Consistancy(); + consistancy[gametic%TICQUEUE] = Consistancy(); // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) @@ -5367,6 +5369,8 @@ static inline void PingUpdate(void) //make the ping packet and clear server data for next one for (i = 0; i < MAXPLAYERS; i++) { + CONS_Printf("player %d - total pings: %d\n", i, realpingtable[i]); + netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; //server takes a snapshot of the real ping for display. //otherwise, pings fluctuate a lot and would be odd to look at. @@ -5397,7 +5401,7 @@ static void UpdatePingTable(void) // 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])); + realpingtable[i] += (INT32)(GetLag(playernode[i]) * (1000.00f/TICRATE)); // TicsToMilliseconds can't handle pings over 1000ms lol pingmeasurecount++; } } @@ -5521,8 +5525,8 @@ FILESTAMP // Do not make tics while resynching if (counts != -666) { - if (maketic + counts >= firstticstosend + BACKUPTICS) - counts = firstticstosend+BACKUPTICS-maketic-1; + if (maketic + counts >= firstticstosend + TICQUEUE) + counts = firstticstosend+TICQUEUE-maketic-1; for (i = 0; i < counts; i++) SV_Maketic(); // Create missed tics and increment maketic diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 66d9e73e..a6ba3499 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -37,6 +37,7 @@ // Networking and tick handling related. #define BACKUPTICS 32 +#define TICQUEUE 512 // more than enough for most timeouts.... #define MAXTEXTCMD 256 // // Packet structure @@ -544,7 +545,7 @@ extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; // Used in d_net, the only dependence -tic_t ExpandTics(INT32 low); +tic_t ExpandTics(INT32 low, tic_t basetic); void D_ClientServerInit(void); // Initialise the other field diff --git a/src/d_net.c b/src/d_net.c index 94b11d51..8c9c3e95 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -842,7 +842,7 @@ static void DebugPrintpacket(const char *header) size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd; fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ", - (UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd)); + (UINT32)serverpak->starttic, serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd)); /// \todo Display more readable information about net commands fprintfstringnewline((char *)cmd, ntxtcmd); /*fprintfstring((char *)cmd, 3); @@ -865,8 +865,8 @@ static void DebugPrintpacket(const char *header) case PT_NODEKEEPALIVE: case PT_NODEKEEPALIVEMIS: fprintf(debugfile, " tic %4u resendfrom %u\n", - (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic), - (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom)); + (UINT32)netbuffer->u.clientpak.client_tic, + (UINT32)netbuffer->u.clientpak.resendfrom); break; case PT_BASICKEEPALIVE: fprintf(debugfile, " keep alive\n"); diff --git a/src/doomstat.h b/src/doomstat.h index 1f855da2..6b8a5ff5 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -549,7 +549,7 @@ extern consvar_t cv_downloading; // allow clients to downloading WADs. extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu extern consvar_t cv_jointimeout; extern consvar_t cv_maxping; -extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; +extern ticcmd_t netcmds[TICQUEUE][MAXPLAYERS]; extern INT32 serverplayer; extern INT32 adminplayers[MAXPLAYERS]; diff --git a/src/g_game.c b/src/g_game.c index b8a1a3bf..142eb1cd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2358,7 +2358,7 @@ void G_Ticker(boolean run) default: I_Error("gameaction = %d\n", gameaction); } - buf = gametic % BACKUPTICS; + buf = gametic % TICQUEUE; if (!demo.playback) // read/write demo and check turbo cheat diff --git a/src/p_setup.c b/src/p_setup.c index bf13971b..e07bc060 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3328,7 +3328,7 @@ boolean P_SetupLevel(boolean skipprecip) if (loadprecip) // uglier hack { // to make a newly loaded level start on the second frame. - INT32 buf = gametic % BACKUPTICS; + INT32 buf = gametic % TICQUEUE; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i])