From 440dd9fc2affb98ddd334e118f3a17657965e7be Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Fri, 29 Sep 2006 21:25:13 +0000 Subject: Working drone clients! Subversion-branch: /trunk/chocolate-doom Subversion-revision: 680 --- src/d_main.c | 6 +- src/d_net.c | 16 ++++- src/net_client.c | 94 +++++++++++++++++++++++++---- src/net_client.h | 3 +- src/net_defs.h | 3 +- src/net_server.c | 177 +++++++++++++++++++++++++++++++++++++------------------ 6 files changed, 224 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/d_main.c b/src/d_main.c index e2c88e45..f68113cb 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: d_main.c 666 2006-09-25 20:47:11Z fraggle $ +// $Id: d_main.c 680 2006-09-29 21:25:13Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -184,7 +184,7 @@ //----------------------------------------------------------------------------- -static const char rcsid[] = "$Id: d_main.c 666 2006-09-25 20:47:11Z fraggle $"; +static const char rcsid[] = "$Id: d_main.c 680 2006-09-29 21:25:13Z fraggle $"; #define BGCOLOR 7 #define FGCOLOR 8 @@ -278,8 +278,6 @@ boolean nomonsters; // checkparm of -nomonsters boolean respawnparm; // checkparm of -respawn boolean fastparm; // checkparm of -fast -boolean drone; - boolean singletics = false; // debug flag to cancel adaptiveness diff --git a/src/d_net.c b/src/d_net.c index 3fec28b5..76693b89 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: d_net.c 544 2006-05-29 20:55:20Z fraggle $ +// $Id: d_net.c 680 2006-09-29 21:25:13Z 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 544 2006-05-29 20:55:20Z fraggle $"; +static const char rcsid[] = "$Id: d_net.c 680 2006-09-29 21:25:13Z fraggle $"; #include "doomfeatures.h" @@ -249,6 +249,13 @@ void NetUpdate (void) // Always run the menu M_Ticker (); + + if (drone) + { + // In drone mode, do not generate any ticcmds. + + continue; + } if (net_cl_new_sync) { @@ -326,6 +333,11 @@ void D_CheckNetGame (void) nettics[i] = 0; } + if (M_CheckParm("-drone") > 0) + { + drone = true; + } + playeringame[0] = true; #ifdef FEATURE_MULTIPLAYER diff --git a/src/net_client.c b/src/net_client.c index 1c5b7a28..e13b8ea3 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.c 641 2006-09-21 11:13:28Z rtc_marine $ +// $Id: net_client.c 680 2006-09-29 21:25:13Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -265,6 +265,12 @@ static ticcmd_t recvwindow_cmd_base[MAXPLAYERS]; static int recvwindow_start; static net_server_recv_t recvwindow[BACKUPTICS]; +// Whether we need to send an acknowledgement and +// when gamedata was last received. + +static boolean need_to_acknowledge; +static unsigned int gamedata_recv_time; + // Average time between sending our ticcmd and receiving from the server static fixed_t average_latency; @@ -273,6 +279,9 @@ static fixed_t average_latency; boolean net_cl_new_sync = true; +// Connected but not participating in the game (observer) + +boolean drone = false; #define NET_CL_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) @@ -384,7 +393,7 @@ static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd, int seq) for (i=0; i MAXPLAYERS - || player_number >= num_players) + if (num_players > MAXPLAYERS) { // insane data return; } + + if ((player_number >= 0 && drone) + || (player_number < 0 && !drone) + || (player_number >= (signed int) num_players)) + { + // Invalid player number + + return; + } // Read the player names @@ -644,11 +682,12 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet) static void NET_CL_ParseGameStart(net_packet_t *packet) { net_gamesettings_t settings; - unsigned int player_number, num_players; + unsigned int num_players; + signed int player_number; int i; if (!NET_ReadInt8(packet, &num_players) - || !NET_ReadInt8(packet, &player_number) + || !NET_ReadSInt8(packet, &player_number) || !NET_ReadSettings(packet, &settings)) { return; @@ -659,15 +698,31 @@ static void NET_CL_ParseGameStart(net_packet_t *packet) return; } - if (num_players > MAXPLAYERS || player_number >= num_players) + if (num_players > MAXPLAYERS || player_number >= (signed int) num_players) { // insane values return; } + if ((drone && player_number >= 0) + || (!drone && player_number < 0)) + { + // Invalid player number: must be positive for real players, + // negative for drones + + return; + } + // Start the game - consoleplayer = player_number; + if (!drone) + { + consoleplayer = player_number; + } + else + { + consoleplayer = 0; + } for (i=0; i 200) + { + NET_CL_SendGameDataACK(); + } } @@ -817,6 +881,15 @@ static void NET_CL_ParseGameData(net_packet_t *packet) nowtime = I_GetTimeMS(); + // Whatever happens, we now need to send an acknowledgement of our + // current receive point. + + if (!need_to_acknowledge) + { + need_to_acknowledge = true; + gamedata_recv_time = nowtime; + } + // Expand byte value into the full tic number seq = NET_CL_ExpandTicNum(seq); @@ -1045,6 +1118,7 @@ static void NET_CL_SendSYN(void) NET_WriteInt16(packet, gamemode); NET_WriteInt16(packet, gamemission); NET_WriteInt8(packet, lowres_turn); + NET_WriteInt8(packet, drone); NET_WriteString(packet, net_player_name); NET_Conn_SendPacket(&client_connection, packet); NET_FreePacket(packet); diff --git a/src/net_client.h b/src/net_client.h index 7440e4f7..56c327c8 100644 --- a/src/net_client.h +++ b/src/net_client.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.h 470 2006-04-14 15:25:42Z fraggle $ +// $Id: net_client.h 680 2006-09-29 21:25:13Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -91,6 +91,7 @@ extern char net_player_addresses[MAXPLAYERS][MAXPLAYERNAME]; extern int net_player_number; extern char *net_player_name; extern boolean net_cl_new_sync; +extern boolean drone; #endif /* #ifndef NET_CLIENT_H */ diff --git a/src/net_defs.h b/src/net_defs.h index 978cfba5..f8bca1d8 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_defs.h 612 2006-09-17 20:37:26Z fraggle $ +// $Id: net_defs.h 680 2006-09-29 21:25:13Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -158,6 +158,7 @@ typedef enum NET_PACKET_TYPE_WAITING_DATA, NET_PACKET_TYPE_GAMESTART, NET_PACKET_TYPE_GAMEDATA, + NET_PACKET_TYPE_GAMEDATA_ACK, NET_PACKET_TYPE_DISCONNECT, NET_PACKET_TYPE_DISCONNECT_ACK, NET_PACKET_TYPE_RELIABLE_ACK, diff --git a/src/net_server.c b/src/net_server.c index 394dc6c2..af794d02 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_server.c 641 2006-09-21 11:13:28Z rtc_marine $ +// $Id: net_server.c 680 2006-09-29 21:25:13Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -209,6 +209,14 @@ typedef struct int sendseq; net_full_ticcmd_t sendqueue[BACKUPTICS]; + // Latest acknowledged by the client + + int acknowledged; + + // Observer: receives data but does not participate in the game. + + boolean drone; + } net_client_t; // structure used for the recv window @@ -320,9 +328,16 @@ static void NET_SV_AssignPlayers(void) { if (ClientConnected(&clients[i])) { - sv_players[pl] = &clients[i]; - sv_players[pl]->player_number = pl; - ++pl; + if (!clients[i].drone) + { + sv_players[pl] = &clients[i]; + sv_players[pl]->player_number = pl; + ++pl; + } + else + { + clients[i].player_number = -1; + } } } @@ -332,30 +347,29 @@ static void NET_SV_AssignPlayers(void) } } -// returns the number of clients connected +// Returns the number of players currently connected. -static int NET_SV_NumClients(void) +static int NET_SV_NumPlayers(void) { - int count; int i; + int result; - count = 0; + result = 0; - for (i=0; isendseq for all connected - // players + // Find the smallest value of client->acknowledged for all connected + // clients - for (i=0; isendseq < lowtic) + if (ClientConnected(&clients[i])) { - lowtic = sv_players[i]->sendseq; + if (lowtic < 0 || clients[i].acknowledged < lowtic) + { + lowtic = clients[i].acknowledged; + } } } @@ -460,7 +469,7 @@ static net_client_t *NET_SV_Controller(void) for (i=0; isendseq = 0; + client->acknowledged = 0; + client->drone = false; memset(client->sendqueue, 0xff, sizeof(client->sendqueue)); } @@ -526,6 +537,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, unsigned int magic; unsigned int cl_gamemode, cl_gamemission; unsigned int cl_recording_lowres; + unsigned int cl_drone; char *player_name; char *client_version; int i; @@ -545,7 +557,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, } // Check the client version is the same as the server - // + client_version = NET_ReadString(packet); if (client_version == NULL) @@ -563,7 +575,8 @@ static void NET_SV_ParseSYN(net_packet_t *packet, if (!NET_ReadInt16(packet, &cl_gamemode) || !NET_ReadInt16(packet, &cl_gamemission) - || !NET_ReadInt8(packet, &cl_recording_lowres)) + || !NET_ReadInt8(packet, &cl_recording_lowres) + || !NET_ReadInt8(packet, &cl_drone)) { return; } @@ -627,14 +640,15 @@ static void NET_SV_ParseSYN(net_packet_t *packet, if (!client->active) { - int num_clients; + int num_players; // Before accepting a new client, check that there is a slot // free - num_clients = NET_SV_NumClients(); + NET_SV_AssignPlayers(); + num_players = NET_SV_NumPlayers(); - if (num_clients >= MAXPLAYERS) + if (num_players >= MAXPLAYERS) { NET_SV_SendReject(addr, "Server is full!"); return; @@ -646,7 +660,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, // Adopt the game mode and mission of the first connecting client - if (num_clients == 0) + if (num_players == 0 && !cl_drone) { sv_gamemode = cl_gamemode; sv_gamemission = cl_gamemission; @@ -666,6 +680,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, NET_SV_InitNewClient(client, addr, player_name); client->recording_lowres = cl_recording_lowres; + client->drone = cl_drone; } if (client->connection.state == NET_CONN_STATE_WAITING_ACK) @@ -733,16 +748,16 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) // Send start packets to each connected node - for (i=0; iconnection, + startpacket = NET_Conn_NewReliable(&clients[i].connection, NET_PACKET_TYPE_GAMESTART); - NET_WriteInt8(startpacket, NET_SV_NumClients()); - NET_WriteInt8(startpacket, sv_players[i]->player_number); + NET_WriteInt8(startpacket, NET_SV_NumPlayers()); + NET_WriteInt8(startpacket, clients[i].player_number); NET_WriteSettings(startpacket, &settings); } @@ -867,6 +882,7 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) { net_client_recv_t *recvobj; unsigned int seq; + unsigned int ackseq; unsigned int num_tics; unsigned int nowtime; size_t i; @@ -879,21 +895,26 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) return; } - //if (rand() % 8 == 0) - // return; + if (client->drone) + { + // Drones do not contribute any game data. + return; + } player = client->player_number; // Read header - if (!NET_ReadInt8(packet, &seq) + if (!NET_ReadInt8(packet, &ackseq) + || !NET_ReadInt8(packet, &seq) || !NET_ReadInt8(packet, &num_tics)) { return; } - // Expand 8-bit value to the full sequence number + // Expand 8-bit values to the full sequence number + ackseq = NET_SV_ExpandTicNum(ackseq); seq = NET_SV_ExpandTicNum(seq); // Sanity checks @@ -924,6 +945,13 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) recvobj->latency = latency; } + // Higher acknowledgement point? + + if (ackseq > client->acknowledged) + { + client->acknowledged = ackseq; + } + // Has this been received out of sequence, ie. have we not received // all tics before the first tic in this packet? If so, send a // resend request. @@ -975,6 +1003,34 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) } } +static void NET_SV_ParseGameDataACK(net_packet_t *packet, net_client_t *client) +{ + unsigned int ackseq; + + if (server_state != SERVER_IN_GAME) + { + return; + } + + // Read header + + if (!NET_ReadInt8(packet, &ackseq)) + { + return; + } + + // Expand 8-bit values to the full sequence number + + ackseq = NET_SV_ExpandTicNum(ackseq); + + // Higher acknowledgement point than we already have? + + if (ackseq > client->acknowledged) + { + client->acknowledged = ackseq; + } +} + static void NET_SV_SendTics(net_client_t *client, int start, int end) { net_packet_t *packet; @@ -1075,7 +1131,7 @@ void NET_SV_SendQueryResponse(net_addr_t *addr) // Number of players/maximum players - querydata.num_players = NET_SV_NumClients(); + querydata.num_players = NET_SV_NumPlayers(); querydata.max_players = MAXPLAYERS; // Game mode/mission @@ -1144,6 +1200,9 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) case NET_PACKET_TYPE_GAMEDATA: NET_SV_ParseGameData(packet, client); break; + case NET_PACKET_TYPE_GAMEDATA_ACK: + NET_SV_ParseGameDataACK(packet, client); + break; case NET_PACKET_TYPE_GAMEDATA_RESEND: NET_SV_ParseResendRequest(packet, client); break; @@ -1167,41 +1226,43 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) static void NET_SV_SendWaitingData(net_client_t *client) { net_packet_t *packet; - int num_clients; + int num_players; int i; - num_clients = NET_SV_NumClients(); + NET_SV_AssignPlayers(); + + num_players = NET_SV_NumPlayers(); // time to send the client another status packet packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); - // include the number of clients waiting + // include the number of players waiting - NET_WriteInt8(packet, num_clients); + NET_WriteInt8(packet, num_players); // indicate whether the client is the controller NET_WriteInt8(packet, NET_SV_Controller() == client); - // send the index of the client + // send the player number of this client - NET_WriteInt8(packet, NET_SV_ClientIndex(client)); + NET_WriteInt8(packet, client->player_number); // send the address of all players - for (i=0; iname); // address - addr = NET_AddrToString(clients[i].addr); + addr = NET_AddrToString(sv_players[i]->addr); NET_WriteString(packet, addr); } @@ -1396,6 +1457,8 @@ void NET_SV_Init(void) clients[i].active = false; } + NET_SV_AssignPlayers(); + server_state = SERVER_WAITING_START; sv_gamemode = indetermined; server_initialised = true; -- cgit v1.2.3