diff options
-rw-r--r-- | src/d_net.c | 48 | ||||
-rw-r--r-- | src/net_client.c | 96 | ||||
-rw-r--r-- | src/net_defs.h | 5 | ||||
-rw-r--r-- | src/net_server.c | 125 | ||||
-rw-r--r-- | src/net_structrw.c | 13 |
5 files changed, 135 insertions, 152 deletions
diff --git a/src/d_net.c b/src/d_net.c index df66e693..ea39ace1 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: d_net.c 388 2006-02-24 19:14:22Z fraggle $ +// $Id: d_net.c 394 2006-02-27 16:31:08Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -117,7 +117,7 @@ //----------------------------------------------------------------------------- -static const char rcsid[] = "$Id: d_net.c 388 2006-02-24 19:14:22Z fraggle $"; +static const char rcsid[] = "$Id: d_net.c 394 2006-02-27 16:31:08Z fraggle $"; #include "d_main.h" @@ -137,6 +137,8 @@ static const char rcsid[] = "$Id: d_net.c 388 2006-02-24 19:14:22Z fraggle $"; #include "net_loop.h" +#define FPS 35 + // // NETWORKING // @@ -155,6 +157,7 @@ int maketic; int lastnettic; int ticdup; int extratics; +fixed_t offsetms; void D_ProcessEvents (void); @@ -162,12 +165,23 @@ void G_BuildTiccmd (ticcmd_t *cmd); void D_DoAdvanceDemo (void); +// 35 fps clock adjusted by offsetms milliseconds + +static int GetAdjustedTime(void) +{ + int time_ms; + + time_ms = I_GetTimeMS() + (offsetms / FRACUNIT); + + return (time_ms * FPS) / 1000; +} + // // NetUpdate // Builds ticcmds for console player, // sends out a packet // -int gametime; +int lasttime; void NetUpdate (void) { @@ -183,9 +197,9 @@ void NetUpdate (void) NET_SV_Run(); // check time - nowtime = I_GetTime ()/ticdup; - newtics = nowtime - gametime; - gametime = nowtime; + nowtime = GetAdjustedTime()/ticdup; + newtics = nowtime - lasttime; + lasttime = nowtime; if (newtics <= 0) // nothing new to update return; @@ -196,7 +210,14 @@ void NetUpdate (void) for (i=0 ; i<newtics ; i++) { ticcmd_t cmd; - + + I_StartTic (); + D_ProcessEvents (); + + // Always run the menu + + M_Ticker (); + // If playing single player, do not allow tics to buffer // up very far @@ -208,9 +229,6 @@ void NetUpdate (void) if (maketic - gameticdiv > 35) break; - I_StartTic (); - D_ProcessEvents (); - //printf ("mk:%i ",maketic); G_BuildTiccmd(&cmd); @@ -247,6 +265,7 @@ void D_CheckNetGame (void) ticdup = 1; extratics = 1; lowres_turn = false; + offsetms = 0; for (i=0; i<MAXPLAYERS; i++) { @@ -384,6 +403,8 @@ void TryRunTics (void) else counts = availabletics; + counts = availabletics; + if (counts < 1) counts = 1; @@ -402,10 +423,11 @@ void TryRunTics (void) if (lowtic < gametic/ticdup) I_Error ("TryRunTics: lowtic < gametic"); - // don't stay in here forever -- give the menu a chance to work - if (I_GetTime ()/ticdup - entertic >= 20) + // Don't stay in this loop forever. The menu is still running, + // so return to update the screen + + if (I_GetTime ()/ticdup - entertic > 0) { - M_Ticker (); return; } diff --git a/src/net_client.c b/src/net_client.c index 4a52c62b..110c458f 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.c 389 2006-02-24 19:14:59Z fraggle $ +// $Id: net_client.c 394 2006-02-27 16:31:08Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -213,6 +213,8 @@ typedef struct net_ticdiff_t cmd; } net_server_send_t; +extern fixed_t offsetms; + static net_connection_t client_connection; static net_clientstate_t client_state; static net_addr_t *server_addr; @@ -261,6 +263,10 @@ static ticcmd_t recvwindow_cmd_base[MAXPLAYERS]; static int recvwindow_start; static net_server_recv_t recvwindow[BACKUPTICS]; +// Average time between sending our ticcmd and receiving from the server + +static fixed_t average_latency; + #define NET_CL_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) // Called when a player leaves the game @@ -308,10 +314,66 @@ static void NET_CL_Disconnected(void) // the d_net.c structures (netcmds/nettics) and save the new ticcmd // back into recvwindow_cmd_base. -static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd) +static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd, int seq) { + int latency; + fixed_t adjustment; int i; + // Update average_latency + + if (seq == send_queue[seq % NET_TICCMD_QUEUE_SIZE].seq) + { + latency = I_GetTimeMS() - send_queue[seq % NET_TICCMD_QUEUE_SIZE].time; + } + else if (seq > send_queue[seq % NET_TICCMD_QUEUE_SIZE].seq) + { + // We have received the ticcmd from the server before we have + // even sent ours + + latency = 0; + } + else + { + latency = -1; + } + + if (latency >= 0) + { + if (seq <= 20) + { + average_latency = latency * FRACUNIT; + } + else + { + // Low level filter + + average_latency = (average_latency * 0.9) + + (latency * FRACUNIT * 0.1); + } + } + + //printf("latency: %i\tremote:%i\n", average_latency / FRACUNIT, + // cmd->latency); + + // Possibly adjust offsetms in d_net.c, try to make players all have + // the same lag. Don't adjust in the first few tics of play, as + // we don't have an accurate value for average_latency yet. + + if (seq > 35) + { + adjustment = (cmd->latency * FRACUNIT) - average_latency; + + // Only adjust very slightly; the cumulative effect over + // multiple tics will sort it out. + + adjustment = adjustment / 100; + + offsetms += adjustment; + } + + // Expand tic diffs for all players + for (i=0; i<MAXPLAYERS; ++i) { if (i == consoleplayer) @@ -358,7 +420,7 @@ static void NET_CL_AdvanceWindow(void) { // Expand tic diff data into d_net.c structures - NET_CL_ExpandFullTiccmd(&recvwindow[0].cmd); + NET_CL_ExpandFullTiccmd(&recvwindow[0].cmd, recvwindow_start); // Advance the window @@ -454,7 +516,7 @@ static void NET_CL_SendTics(int start, int end) sendobj = &send_queue[i % NET_TICCMD_QUEUE_SIZE]; - NET_WriteInt16(packet, sendobj->time); + NET_WriteInt16(packet, average_latency / FRACUNIT); NET_WriteTiccmdDiff(packet, &sendobj->cmd, lowres_turn); } @@ -800,28 +862,6 @@ static void NET_CL_ParseGameData(net_packet_t *packet) } } -static void NET_CL_ParseTimeRequest(net_packet_t *packet) -{ - net_packet_t *reply; - unsigned int seq; - - // Received a request from the server for our current time. - - if (!NET_ReadInt32(packet, &seq)) - { - return; - } - - // Send a response with our current time. - - reply = NET_NewPacket(10); - NET_WriteInt16(reply, NET_PACKET_TYPE_TIME_RESP); - NET_WriteInt32(reply, seq); - NET_WriteInt32(reply, I_GetTimeMS()); - NET_Conn_SendPacket(&client_connection, reply); - NET_FreePacket(reply); -} - // Parse a resend request from the server due to a dropped packet static void NET_CL_ParseResendRequest(net_packet_t *packet) @@ -873,10 +913,6 @@ static void NET_CL_ParsePacket(net_packet_t *packet) NET_CL_ParseGameData(packet); break; - case NET_PACKET_TYPE_TIME_REQ: - NET_CL_ParseTimeRequest(packet); - break; - case NET_PACKET_TYPE_GAMEDATA_RESEND: NET_CL_ParseResendRequest(packet); break; diff --git a/src/net_defs.h b/src/net_defs.h index ee6c790d..8854317c 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_defs.h 376 2006-02-23 18:19:05Z fraggle $ +// $Id: net_defs.h 394 2006-02-27 16:31:08Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -165,8 +165,6 @@ typedef enum NET_PACKET_TYPE_DISCONNECT, NET_PACKET_TYPE_DISCONNECT_ACK, NET_PACKET_TYPE_RELIABLE_ACK, - NET_PACKET_TYPE_TIME_REQ, - NET_PACKET_TYPE_TIME_RESP, NET_PACKET_TYPE_GAMEDATA_RESEND, } net_packet_type_t; @@ -199,6 +197,7 @@ typedef struct typedef struct { + signed int latency; unsigned int seq; boolean playeringame[MAXPLAYERS]; net_ticdiff_t cmds[MAXPLAYERS]; diff --git a/src/net_server.c b/src/net_server.c index ba64422d..02ac1926 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_server.c 389 2006-02-24 19:14:59Z fraggle $ +// $Id: net_server.c 394 2006-02-27 16:31:08Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -200,12 +200,6 @@ typedef struct boolean recording_lowres; - // time query variables - - int last_time_req_time; - int time_req_seq; - signed int time_offset; - // send queue: items to send to the client // this is a circular buffer @@ -222,10 +216,9 @@ typedef struct boolean active; - // Time this tic was generated (adjusted for time offset between - // client and server - - unsigned int time; + // Latency value received from the client + + signed int latency; // Last time we sent a resend request for this tic @@ -470,9 +463,6 @@ static void NET_SV_InitNewClient(net_client_t *client, client->addr = addr; client->last_send_time = -1; client->name = strdup(player_name); - client->last_time_req_time = -1; - client->time_req_seq = 0; - client->time_offset = 0; // init the ticcmd send queue @@ -700,60 +690,6 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) recvwindow_start = 0; } -static void NET_SV_ParseTimeResponse(net_packet_t *packet, net_client_t *client) -{ - unsigned int seq; - unsigned int remote_time; - unsigned int rtt; - unsigned int nowtime; - signed int time_offset; - - if (!NET_ReadInt32(packet, &seq) - || !NET_ReadInt32(packet, &remote_time)) - { - return; - } - - if (seq != client->time_req_seq) - { - // Not the time response we are expecting - - return; - } - - // Calculate the round trip time - - nowtime = I_GetTimeMS(); - rtt = nowtime - client->last_time_req_time; - - // Adjust the remote time based on the round trip time - - remote_time += rtt / 2; - - // Calculate the offset to our own time - - time_offset = remote_time - nowtime; - - // Update the time offset - - if (client->time_req_seq == 1) - { - // This is the first reply, so this is the only sample we have - // so far - - client->time_offset = time_offset; - } - else - { - // Apply a low level filter to the time offset adjustments - - client->time_offset = ((client->time_offset * 3) / 4) - + (time_offset / 4); - } - - //printf("SV: client %p time offset: %i(%i)->%i\n", client, time_offset, rtt, client->time_offset); -} - // Send a resend request to a client static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) @@ -900,9 +836,9 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) for (i=0; i<num_tics; ++i) { net_ticdiff_t diff; - unsigned int time; + signed int latency; - if (!NET_ReadInt16(packet, &time) + if (!NET_ReadSInt16(packet, &latency) || !NET_ReadTiccmdDiff(packet, &diff, sv_settings.lowres_turn)) { return; @@ -920,6 +856,7 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) recvobj = &recvwindow[index][player]; recvobj->active = true; recvobj->diff = diff; + recvobj->latency = latency; } // Has this been received out of sequence, ie. have we not received @@ -1082,9 +1019,6 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) case NET_PACKET_TYPE_GAMEDATA_RESEND: NET_SV_ParseResendRequest(packet, client); break; - case NET_PACKET_TYPE_TIME_RESP: - NET_SV_ParseTimeResponse(packet, client); - break; default: // unknown packet type @@ -1150,25 +1084,6 @@ static void NET_SV_SendWaitingData(net_client_t *client) NET_FreePacket(packet); } -static void NET_SV_SendTimeRequest(net_client_t *client) -{ - net_packet_t *packet; - - ++client->time_req_seq; - - // Transmit the request packet - - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_TIME_REQ); - NET_WriteInt32(packet, client->time_req_seq); - NET_Conn_SendPacket(&client->connection, packet); - NET_FreePacket(packet); - - // Save the time we send the request - - client->last_time_req_time = I_GetTimeMS(); -} - static void NET_SV_PumpSendQueue(net_client_t *client) { net_full_ticcmd_t cmd; @@ -1217,8 +1132,12 @@ static void NET_SV_PumpSendQueue(net_client_t *client) // Add ticcmds from all players + cmd.latency = 0; + for (i=0; i<MAXPLAYERS; ++i) { + net_client_recv_t *recvobj; + if (sv_players[i] == client) { // Not the player we are sending to @@ -1234,9 +1153,17 @@ static void NET_SV_PumpSendQueue(net_client_t *client) } cmd.playeringame[i] = true; - cmd.cmds[i] = recvwindow[recv_index][i].diff; + + recvobj = &recvwindow[recv_index][i]; + + cmd.cmds[i] = recvobj->diff; + + if (recvobj->latency > cmd.latency) + cmd.latency = recvobj->latency; } + //printf("SV: %i: latency %i\n", client->player_number, cmd.latency); + // Add into the queue client->sendqueue[client->sendseq % BACKUPTICS] = cmd; @@ -1294,18 +1221,6 @@ static void NET_SV_RunClient(net_client_t *client) } } - if (client->last_time_req_time < 0) - { - client->last_time_req_time = I_GetTimeMS() - 5000; - } - - if (I_GetTimeMS() - client->last_time_req_time > 10000) - { - // Query the clients' times once every ten seconds. - - NET_SV_SendTimeRequest(client); - } - if (server_state == SERVER_IN_GAME) { NET_SV_PumpSendQueue(client); diff --git a/src/net_structrw.c b/src/net_structrw.c index 6567c01c..0fdf0245 100644 --- a/src/net_structrw.c +++ b/src/net_structrw.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_structrw.c 378 2006-02-23 19:12:02Z fraggle $ +// $Id: net_structrw.c 394 2006-02-27 16:31:08Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -242,6 +242,13 @@ boolean NET_ReadFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean unsigned int bitfield; int i; + // Latency + + if (!NET_ReadSInt16(packet, &cmd->latency)) + { + return false; + } + // Regenerate playeringame from the "header" bitfield if (!NET_ReadInt8(packet, &bitfield)) @@ -275,6 +282,10 @@ void NET_WriteFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean l unsigned int bitfield; int i; + // Write the latency + + NET_WriteInt16(packet, cmd->latency); + // Write "header" byte indicating which players are active // in this ticcmd |