From 2840213616978c2d806c35b586ff1c4beff0f187 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Wed, 3 Apr 2013 23:47:43 +0000 Subject: Don't start the game until all players are ready. Send waiting data to players that are ready for startup progress screens. Subversion-branch: /branches/v2-branch Subversion-revision: 2581 --- src/net_client.c | 13 ++ src/net_defs.h | 1 + src/net_server.c | 349 +++++++++++++++++++++++++++++++++-------------------- src/net_structrw.c | 2 + 4 files changed, 233 insertions(+), 132 deletions(-) diff --git a/src/net_client.c b/src/net_client.c index f258eb44..239691c8 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -446,6 +446,7 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet) } if (wait_data.num_players > wait_data.max_players + || wait_data.ready_players > wait_data.num_players || wait_data.max_players > NET_MAXPLAYERS) { // insane data @@ -468,11 +469,23 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet) static void NET_CL_ParseLaunch(net_packet_t *packet) { + unsigned int num_players; + if (client_state != CLIENT_STATE_WAITING_LAUNCH) { return; } + // The launch packet contains the number of players that will be + // in the game when it starts, so that we can do the startup + // progress indicator (the wait data is unreliable). + + if (!NET_ReadInt8(packet, &num_players)) + { + return; + } + + net_client_wait_data.num_players = num_players; client_state = CLIENT_STATE_WAITING_START; } diff --git a/src/net_defs.h b/src/net_defs.h index a5804e53..38114efc 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -241,6 +241,7 @@ typedef struct { int num_players; int num_drones; + int ready_players; int max_players; int is_controller; int consoleplayer; diff --git a/src/net_server.c b/src/net_server.c index 67f49236..ff91c71f 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -80,6 +80,11 @@ typedef struct int last_send_time; char *name; + // If true, the client has sent the NET_PACKET_TYPE_GAMESTART + // message indicating that it is ready for the game to start. + + boolean ready; + // Time that this client connected to the server. // This is used to determine the controller (oldest client). @@ -280,6 +285,25 @@ static int NET_SV_NumPlayers(void) return result; } +// Returns the number of players ready to start the game. + +static int NET_SV_NumReadyPlayers(void) +{ + int result = 0; + int i; + + for (i = 0; i < MAXNETNODES; ++i) + { + if (ClientConnected(&clients[i]) + && !clients[i].drone && clients[i].ready) + { + ++result; + } + } + + return result; +} + // Returns the maximum number of players that can play. static int NET_SV_MaxPlayers(void) @@ -337,6 +361,95 @@ static int NET_SV_NumClients(void) return count; } +// returns a pointer to the client which controls the server + +static net_client_t *NET_SV_Controller(void) +{ + net_client_t *best; + int i; + + // Find the oldest client (first to connect). + + best = NULL; + + for (i=0; iconnect_time) + { + best = &clients[i]; + } + } + + return best; +} + +static void NET_SV_SendWaitingData(net_client_t *client) +{ + net_waitdata_t wait_data; + net_packet_t *packet; + net_client_t *controller; + int i; + + NET_SV_AssignPlayers(); + + controller = NET_SV_Controller(); + + wait_data.num_players = NET_SV_NumPlayers(); + wait_data.num_drones = NET_SV_NumDrones(); + wait_data.ready_players = NET_SV_NumReadyPlayers(); + wait_data.max_players = NET_SV_MaxPlayers(); + wait_data.is_controller = (client == controller); + wait_data.consoleplayer = client->player_number; + + // Send the WAD and dehacked checksums of the controlling client. + // If no controller found (?), send the details that the client + // is expecting anyway. + + if (controller != NULL) + { + controller = client; + } + + memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, + sizeof(sha1_digest_t)); + memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, + sizeof(sha1_digest_t)); + wait_data.is_freedoom = controller->is_freedoom; + + // set name and address of each player: + + for (i = 0; i < wait_data.num_players; ++i) + { + strncpy(wait_data.player_names[i], + sv_players[i]->name, + MAXPLAYERNAME); + wait_data.player_names[i][MAXPLAYERNAME-1] = '\0'; + + strncpy(wait_data.player_addrs[i], + NET_AddrToString(sv_players[i]->addr), + MAXPLAYERNAME); + wait_data.player_addrs[i][MAXPLAYERNAME-1] = '\0'; + } + + // Construct packet: + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); + NET_WriteWaitData(packet, &wait_data); + + // Send packet to client and free + + NET_Conn_SendPacket(&client->connection, packet); + NET_FreePacket(packet); +} + // Find the latest tic which has been acknowledged as received by // all clients. @@ -419,35 +532,6 @@ static void NET_SV_AdvanceWindow(void) } } -// returns a pointer to the client which controls the server - -static net_client_t *NET_SV_Controller(void) -{ - net_client_t *best; - int i; - - // Find the oldest client (first to connect). - - best = NULL; - - for (i=0; iconnect_time) - { - best = &clients[i]; - } - } - - return best; -} - // Given an address, find the corresponding client static net_client_t *NET_SV_FindClient(net_addr_t *addr) @@ -496,6 +580,7 @@ static void NET_SV_InitNewClient(net_client_t *client, client->sendseq = 0; client->acknowledged = 0; client->drone = false; + client->ready = false; client->last_gamedata_time = 0; @@ -694,6 +779,8 @@ static void NET_SV_ParseSYN(net_packet_t *packet, static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client) { + net_packet_t *launchpacket; + int num_players; unsigned int i; // Only the controller can launch the game. @@ -712,13 +799,17 @@ static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client) // Forward launch on to all clients. + NET_SV_AssignPlayers(); + num_players = NET_SV_NumPlayers(); + for (i=0; irecording_lowres) { - settings.lowres_turn = true; + sv_settings.lowres_turn = true; } } - settings.num_players = NET_SV_NumPlayers(); + sv_settings.num_players = NET_SV_NumPlayers(); // Copy player classes: @@ -787,11 +851,11 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) { if (sv_players[i] != NULL) { - settings.player_classes[i] = sv_players[i]->player_class; + sv_settings.player_classes[i] = sv_players[i]->player_class; } else { - settings.player_classes[i] = 0; + sv_settings.player_classes[i] = 0; } } @@ -799,7 +863,7 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) // Send start packets to each connected node - for (i=0; iready = true; + + // Start the game once all clients are ready. + + if (AllNodesReady()) + { + StartGame(); + } + + // Update all ready clients with the current state (number of players + // ready, etc.). This is used by games that show startup progress + // (eg. Hexen's spinal loading) + + SendAllWaitingData(); +} + // Send a resend request to a client static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) @@ -1312,65 +1456,6 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) } -static void NET_SV_SendWaitingData(net_client_t *client) -{ - net_waitdata_t wait_data; - net_packet_t *packet; - net_client_t *controller; - int i; - - NET_SV_AssignPlayers(); - - controller = NET_SV_Controller(); - - wait_data.num_players = NET_SV_NumPlayers(); - wait_data.num_drones = NET_SV_NumDrones(); - wait_data.max_players = NET_SV_MaxPlayers(); - wait_data.is_controller = (client == controller); - wait_data.consoleplayer = client->player_number; - - // Send the WAD and dehacked checksums of the controlling client. - // If no controller found (?), send the details that the client - // is expecting anyway. - - if (controller != NULL) - { - controller = client; - } - - memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, - sizeof(sha1_digest_t)); - memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, - sizeof(sha1_digest_t)); - wait_data.is_freedoom = controller->is_freedoom; - - // set name and address of each player: - - for (i = 0; i < wait_data.num_players; ++i) - { - strncpy(wait_data.player_names[i], - sv_players[i]->name, - MAXPLAYERNAME); - wait_data.player_names[i][MAXPLAYERNAME-1] = '\0'; - - strncpy(wait_data.player_addrs[i], - NET_AddrToString(sv_players[i]->addr), - MAXPLAYERNAME); - wait_data.player_addrs[i][MAXPLAYERNAME-1] = '\0'; - } - - // Construct packet: - - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); - NET_WriteWaitData(packet, &wait_data); - - // Send packet to client and free - - NET_Conn_SendPacket(&client->connection, packet); - NET_FreePacket(packet); -} - static void NET_SV_PumpSendQueue(net_client_t *client) { net_full_ticcmd_t cmd; diff --git a/src/net_structrw.c b/src/net_structrw.c index 8f6f8d57..17556ccd 100644 --- a/src/net_structrw.c +++ b/src/net_structrw.c @@ -451,6 +451,7 @@ void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data) NET_WriteInt8(packet, data->num_players); NET_WriteInt8(packet, data->num_drones); + NET_WriteInt8(packet, data->ready_players); NET_WriteInt8(packet, data->max_players); NET_WriteInt8(packet, data->is_controller); NET_WriteInt8(packet, data->consoleplayer); @@ -473,6 +474,7 @@ boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) if (!NET_ReadInt8(packet, (unsigned int *) &data->num_players) || !NET_ReadInt8(packet, (unsigned int *) &data->num_drones) + || !NET_ReadInt8(packet, (unsigned int *) &data->ready_players) || !NET_ReadInt8(packet, (unsigned int *) &data->max_players) || !NET_ReadInt8(packet, (unsigned int *) &data->is_controller) || !NET_ReadSInt8(packet, &data->consoleplayer)) -- cgit v1.2.3