ref: 48b1728d9145baf1912aa6566d8e64abea65f83b
parent: 609e5d2928561b35fc16749e063dbfd61c9a17e1
author: Simon Howard <[email protected]>
date: Tue Apr 2 16:44:26 EDT 2013
Split game start sequence into two-stage process. This is the first stage in refactoring the way that network startup works. Subversion-branch: /branches/v2-branch Subversion-revision: 2580
--- a/src/d_loop.c
+++ b/src/d_loop.c
@@ -309,6 +309,24 @@
lasttime = GetAdjustedTime() / ticdup;
}
+//
+// Block until the game start message is received from the server.
+//
+
+void D_BlockUntilStart(net_gamesettings_t *settings)
+{
+ while (!NET_CL_GetSettings(settings))
+ {
+ NET_CL_Run();
+ NET_SV_Run();
+
+ if (!net_client_connected)
+ {
+ I_Error("Lost connection to server");
+ }
+ }
+}
+
boolean D_InitNetGame(net_connect_data_t *connect_data,
net_gamesettings_t *settings)
{
@@ -440,9 +458,15 @@
printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
- // Wait for game start message received from server.
+ // Wait for launch message received from server.
- NET_WaitForStart(settings);
+ NET_WaitForLaunch();
+
+ // Send our game settings and block until game start is received
+ // from the server.
+
+ NET_CL_StartGame(settings);
+ D_BlockUntilStart(settings);
// Read the game settings that were received.
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -51,6 +51,10 @@
typedef enum
{
+ // waiting for the game to launch
+
+ CLIENT_STATE_WAITING_LAUNCH,
+
// waiting for the game to start
CLIENT_STATE_WAITING_START,
@@ -73,10 +77,10 @@
unsigned int resend_time;
- // Tic data from server
+ // Tic data from server
net_full_ticcmd_t cmd;
-
+
} net_server_recv_t;
// Type of structure used in the send window
@@ -115,15 +119,15 @@
boolean net_client_connected;
-// true if we have received waiting data from the server
+// true if we have received waiting data from the server,
+// and the wait data that was received.
boolean net_client_received_wait_data;
-
net_waitdata_t net_client_wait_data;
-// Waiting for the game to start?
+// Waiting at the initial wait screen for the game to be launched?
-boolean net_waiting_for_start = false;
+boolean net_waiting_for_launch = false;
// Name that we send to the server
@@ -306,6 +310,11 @@
}
}
+void NET_CL_LaunchGame(void)
+{
+ NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_LAUNCH);
+}
+
void NET_CL_StartGame(net_gamesettings_t *settings)
{
net_packet_t *packet;
@@ -457,6 +466,16 @@
net_client_received_wait_data = true;
}
+static void NET_CL_ParseLaunch(net_packet_t *packet)
+{
+ if (client_state != CLIENT_STATE_WAITING_LAUNCH)
+ {
+ return;
+ }
+
+ client_state = CLIENT_STATE_WAITING_START;
+}
+
static void NET_CL_ParseGameStart(net_packet_t *packet)
{
if (!NET_ReadSettings(packet, &settings))
@@ -805,6 +824,10 @@
NET_CL_ParseWaitingData(packet);
break;
+ case NET_PACKET_TYPE_LAUNCH:
+ NET_CL_ParseLaunch(packet);
+ break;
+
case NET_PACKET_TYPE_GAMESTART:
NET_CL_ParseGameStart(packet);
break;
@@ -864,13 +887,14 @@
|| client_connection.state == NET_CONN_STATE_DISCONNECTED_SLEEP)
{
NET_CL_Disconnected();
-
+
NET_CL_Shutdown();
}
-
- net_waiting_for_start = client_connection.state == NET_CONN_STATE_CONNECTED
- && client_state == CLIENT_STATE_WAITING_START;
+ net_waiting_for_launch =
+ client_connection.state == NET_CONN_STATE_CONNECTED
+ && client_state == CLIENT_STATE_WAITING_LAUNCH;
+
if (client_state == CLIENT_STATE_IN_GAME)
{
// Possibly advance the receive window
@@ -932,7 +956,7 @@
NET_Conn_InitClient(&client_connection, addr);
// try to connect
-
+
start_time = I_GetTimeMS();
last_send_time = -1;
@@ -947,9 +971,9 @@
NET_CL_SendSYN(data);
last_send_time = nowtime;
}
-
- // time out after 5 seconds
+ // time out after 5 seconds
+
if (nowtime - start_time > 5000)
{
break;
@@ -973,7 +997,7 @@
{
// connected ok!
- client_state = CLIENT_STATE_WAITING_START;
+ client_state = CLIENT_STATE_WAITING_LAUNCH;
drone = data->drone;
return true;
--- a/src/net_client.h
+++ b/src/net_client.h
@@ -33,6 +33,7 @@
void NET_CL_Disconnect(void);
void NET_CL_Run(void);
void NET_CL_Init(void);
+void NET_CL_LaunchGame(void);
void NET_CL_StartGame(net_gamesettings_t *settings);
void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic);
boolean NET_CL_GetSettings(net_gamesettings_t *_settings);
@@ -43,7 +44,7 @@
extern boolean net_client_connected;
extern boolean net_client_received_wait_data;
extern net_waitdata_t net_client_wait_data;
-extern boolean net_waiting_for_start;
+extern boolean net_waiting_for_launch;
extern char *net_player_name;
extern sha1_digest_t net_server_wad_sha1sum;
--- a/src/net_defs.h
+++ b/src/net_defs.h
@@ -116,7 +116,7 @@
// packet types
-typedef enum
+typedef enum
{
NET_PACKET_TYPE_SYN,
NET_PACKET_TYPE_ACK,
@@ -133,6 +133,7 @@
NET_PACKET_TYPE_CONSOLE_MESSAGE,
NET_PACKET_TYPE_QUERY,
NET_PACKET_TYPE_QUERY_RESPONSE,
+ NET_PACKET_TYPE_LAUNCH,
} net_packet_type_t;
typedef enum
--- a/src/net_gui.c
+++ b/src/net_gui.c
@@ -54,11 +54,9 @@
I_Quit();
}
-static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(settings))
+static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
{
- TXT_CAST_ARG(net_gamesettings_t, settings);
-
- NET_CL_StartGame(settings);
+ NET_CL_LaunchGame();
}
static void OpenWaitDialog(void)
@@ -112,7 +110,7 @@
TXT_AddWidget(window, drone_label);
}
-static void UpdateGUI(net_gamesettings_t *settings)
+static void UpdateGUI(void)
{
txt_window_action_t *startgame;
char buf[50];
@@ -174,7 +172,7 @@
if (net_client_wait_data.is_controller)
{
startgame = TXT_NewWindowAction(' ', "Start game");
- TXT_SignalConnect(startgame, "pressed", StartGame, settings);
+ TXT_SignalConnect(startgame, "pressed", StartGame, NULL);
}
else
{
@@ -287,11 +285,11 @@
TXT_AddWidget(window, TXT_NewLabel
("If you continue, this may cause your game to desync."));
-
+
had_warning = true;
}
-void NET_WaitForStart(net_gamesettings_t *settings)
+void NET_WaitForLaunch(void)
{
if (!TXT_Init())
{
@@ -305,9 +303,9 @@
OpenWaitDialog();
had_warning = false;
- while (net_waiting_for_start)
+ while (net_waiting_for_launch)
{
- UpdateGUI(settings);
+ UpdateGUI();
CheckSHA1Sums();
TXT_DispatchEvents();
@@ -323,6 +321,6 @@
TXT_Sleep(100);
}
-
+
TXT_Shutdown();
}
--- a/src/net_gui.h
+++ b/src/net_gui.h
@@ -22,15 +22,15 @@
//
// * The client waiting screen when we are waiting for the server to
// start the game.
-//
+//
-#ifndef NET_GUI_H
+#ifndef NET_GUI_H
#define NET_GUI_H
#include "doomtype.h"
-extern void NET_WaitForStart(net_gamesettings_t *settings);
+extern void NET_WaitForLaunch(void);
#endif /* #ifndef NET_GUI_H */
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -56,8 +56,14 @@
typedef enum
{
- // waiting for the game to start
+ // waiting for the game to be "launched" (key player to press the start
+ // button)
+ SERVER_WAITING_LAUNCH,
+
+ // game has been launched, we are waiting for all players to be ready
+ // so the game can start.
+
SERVER_WAITING_START,
// in a game
@@ -65,7 +71,7 @@
SERVER_IN_GAME,
} net_server_state_t;
-typedef struct
+typedef struct
{
boolean active;
int player_number;
@@ -80,7 +86,7 @@
unsigned int connect_time;
// Last time new gamedata was received from this client
-
+
int last_gamedata_time;
// recording a demo without -longtics
@@ -542,7 +548,7 @@
// will simply not function at all.
//
- if (M_CheckParm("-ignoreversion") == 0)
+ if (M_CheckParm("-ignoreversion") == 0)
{
NET_SV_SendReject(addr,
"Version mismatch: server version is: "
@@ -578,17 +584,17 @@
{
return;
}
-
+
// received a valid SYN
// not accepting new connections?
-
- if (server_state != SERVER_WAITING_START)
+
+ if (server_state != SERVER_WAITING_LAUNCH)
{
NET_SV_SendReject(addr, "Server is not currently accepting connections");
return;
}
-
+
// allocate a client slot if there isn't one already
if (client == NULL)
@@ -683,6 +689,43 @@
}
}
+// Parse a launch packet. This is sent by the key player when the "start"
+// button is pressed, and causes the startup process to continue.
+
+static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client)
+{
+ unsigned int i;
+
+ // Only the controller can launch the game.
+
+ if (client != NET_SV_Controller())
+ {
+ return;
+ }
+
+ // Can only launch when we are in the waiting state.
+
+ if (server_state != SERVER_WAITING_LAUNCH)
+ {
+ return;
+ }
+
+ // Forward launch on to all clients.
+
+ for (i=0; i<MAXNETNODES; ++i)
+ {
+ if (!ClientConnected(&clients[i]))
+ continue;
+
+ NET_Conn_NewReliable(&clients[i].connection,
+ NET_PACKET_TYPE_LAUNCH);
+ }
+
+ // Now in launch state.
+
+ server_state = SERVER_WAITING_START;
+}
+
// Parse a game start packet
static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client)
@@ -691,7 +734,7 @@
net_packet_t *startpacket;
int nowtime;
int i;
-
+
if (client != NET_SV_Controller())
{
// Only the controller can start a new game
@@ -713,10 +756,10 @@
return;
}
+ // Can only start a game if we are in the waiting start state.
+
if (server_state != SERVER_WAITING_START)
{
- // Can only start a game if we are in the waiting start state.
-
return;
}
@@ -1232,7 +1275,7 @@
// Packet was eaten by the common connection code
}
else
- {
+ {
//printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type);
switch (packet_type)
@@ -1240,6 +1283,9 @@
case NET_PACKET_TYPE_GAMESTART:
NET_SV_ParseGameStart(packet, client);
break;
+ case NET_PACKET_TYPE_LAUNCH:
+ NET_SV_ParseLaunch(packet, client);
+ break;
case NET_PACKET_TYPE_GAMEDATA:
NET_SV_ParseGameData(packet, client);
break;
@@ -1502,7 +1548,7 @@
{
int i;
- server_state = SERVER_WAITING_START;
+ server_state = SERVER_WAITING_LAUNCH;
sv_gamemode = indetermined;
for (i=0; i<MAXNETNODES; ++i)
@@ -1557,7 +1603,7 @@
return;
}
- if (server_state == SERVER_WAITING_START)
+ if (server_state == SERVER_WAITING_LAUNCH)
{
// Waiting for the game to start
@@ -1605,7 +1651,7 @@
NET_SV_AssignPlayers();
- server_state = SERVER_WAITING_START;
+ server_state = SERVER_WAITING_LAUNCH;
sv_gamemode = indetermined;
server_initialized = true;
}