Very, very partial support for the server spectating

This commit is contained in:
Gregor Richards 2016-12-12 21:57:14 -05:00
parent 3d7f1f6575
commit 3631ff74ff
3 changed files with 102 additions and 36 deletions

View File

@ -60,6 +60,10 @@ static bool in_netplay = false;
static void announce_nat_traversal(netplay_t *netplay); static void announce_nat_traversal(netplay_t *netplay);
#endif #endif
static bool netplay_send_raw_cmd(netplay_t *netplay,
struct netplay_connection *connection, uint32_t cmd, const void *data,
size_t size);
static void netplay_send_raw_cmd_all(netplay_t *netplay, static void netplay_send_raw_cmd_all(netplay_t *netplay,
struct netplay_connection *except, uint32_t cmd, const void *data, struct netplay_connection *except, uint32_t cmd, const void *data,
size_t size); size_t size);
@ -430,30 +434,45 @@ static bool send_cur_input(netplay_t *netplay, struct netplay_connection *connec
struct delta_frame *dframe = &netplay->buffer[netplay->self_ptr]; struct delta_frame *dframe = &netplay->buffer[netplay->self_ptr];
uint32_t player; uint32_t player;
for (player = 0; player < MAX_USERS; player++) if (netplay->is_server)
{ {
if (connection->mode == NETPLAY_CONNECTION_PLAYING && /* Send the other players' input data */
connection->player == player) for (player = 0; player < MAX_USERS; player++)
continue;
if ((netplay->connected_players & (1<<player)))
{ {
if (dframe->have_real[player]) if (connection->mode == NETPLAY_CONNECTION_PLAYING &&
connection->player == player)
continue;
if ((netplay->connected_players & (1<<player)))
{ {
if (!send_input_frame(netplay, connection, NULL, if (dframe->have_real[player])
netplay->self_frame_count, player, {
dframe->real_input_state[player])) if (!send_input_frame(netplay, connection, NULL,
return false; netplay->self_frame_count, player,
dframe->real_input_state[player]))
return false;
}
} }
} }
else if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING &&
netplay->self_player == player) /* If we're not playing, send a NOINPUT */
if (netplay->self_mode != NETPLAY_CONNECTION_PLAYING)
{ {
if (!send_input_frame(netplay, connection, NULL, uint32_t payload = htonl(netplay->self_frame_count);
netplay->self_frame_count, if (!netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_NOINPUT,
(netplay->is_server ? NETPLAY_CMD_INPUT_BIT_SERVER : 0) | player, &payload, sizeof(payload)))
dframe->self_state))
return false; return false;
} }
}
/* Send our own data */
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING)
{
if (!send_input_frame(netplay, connection, NULL,
netplay->self_frame_count,
(netplay->is_server ? NETPLAY_CMD_INPUT_BIT_SERVER : 0) | netplay->self_player,
dframe->self_state))
return false;
} }
if (!netplay_send_flush(&connection->send_packet_buffer, connection->fd, if (!netplay_send_flush(&connection->send_packet_buffer, connection->fd,
@ -773,6 +792,25 @@ static bool netplay_get_cmd(netplay_t *netplay,
break; break;
} }
case NETPLAY_CMD_NOINPUT:
{
uint32_t frame;
if (netplay->is_server)
return netplay_cmd_nak(netplay, connection);
RECV(&frame, sizeof(frame))
return netplay_cmd_nak(netplay, connection);
frame = ntohl(frame);
if (frame != netplay->server_frame_count)
return netplay_cmd_nak(netplay, connection);
netplay->server_ptr = NEXT_PTR(netplay->server_ptr);
netplay->server_frame_count++;
break;
}
case NETPLAY_CMD_FLIP_PLAYERS: case NETPLAY_CMD_FLIP_PLAYERS:
if (cmd_size != sizeof(uint32_t)) if (cmd_size != sizeof(uint32_t))
{ {
@ -2046,29 +2084,54 @@ static void netplay_flip_users(netplay_t *netplay)
/* Toggle between play mode and spectate mode */ /* Toggle between play mode and spectate mode */
static void netplay_toggle_play_spectate(netplay_t *netplay) static void netplay_toggle_play_spectate(netplay_t *netplay)
{ {
uint32_t cmd;
size_t i;
if (netplay->is_server) if (netplay->is_server)
{ {
/* FIXME */ /* FIXME: Duplication */
return; uint32_t payload[2];
} payload[0] = htonl(netplay->self_frame_count+1);
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING)
{
/* Mark us as no longer playing */
payload[1] = htonl(netplay->self_player);
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING;
}
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
{
uint32_t player;
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING) /* Take a player number */
{ for (player = 0; player < MAX_USERS; player++)
/* Switch to spectator mode immediately */ if (!(netplay->connected_players & (1<<player))) break;
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING; if (player == MAX_USERS) return; /* Failure! */
cmd = NETPLAY_CMD_SPECTATE;
}
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
{
/* Switch only after getting permission */
cmd = NETPLAY_CMD_PLAY;
}
else return;
netplay_send_raw_cmd_all(netplay, NULL, cmd, NULL, 0); payload[1] = htonl(NETPLAY_CMD_MODE_BIT_PLAYING | player);
netplay->self_mode = NETPLAY_CONNECTION_PLAYING;
netplay->self_player = player;
}
netplay_send_raw_cmd_all(netplay, NULL, NETPLAY_CMD_MODE, payload, sizeof(payload));
}
else
{
uint32_t cmd;
size_t i;
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING)
{
/* Switch to spectator mode immediately */
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING;
cmd = NETPLAY_CMD_SPECTATE;
}
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
{
/* Switch only after getting permission */
cmd = NETPLAY_CMD_PLAY;
}
else return;
netplay_send_raw_cmd_all(netplay, NULL, cmd, NULL, 0);
}
} }

View File

@ -262,7 +262,7 @@ static void netplay_handshake_ready(netplay_t *netplay, struct netplay_connectio
if (netplay->is_server) if (netplay->is_server)
{ {
netplay_log_connection(&connection->addr, 0, connection->nick); netplay_log_connection(&connection->addr, connection - netplay->connections, connection->nick);
/* Send them the savestate */ /* Send them the savestate */
if (!(netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION))) if (!(netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION)))

View File

@ -95,6 +95,9 @@ enum netplay_cmd
/* Input data */ /* Input data */
NETPLAY_CMD_INPUT = 0x0003, NETPLAY_CMD_INPUT = 0x0003,
/* Non-input data */
NETPLAY_CMD_NOINPUT = 0x0004,
/* Initialization commands */ /* Initialization commands */
/* Inform the other side of our nick (must be first command) */ /* Inform the other side of our nick (must be first command) */