From ed320fd914134a06720c6725580cf12cbdff401f Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Mon, 11 Sep 2017 07:29:44 -0400 Subject: [PATCH] Adding and removing players The new input handling makes adding and removing players more complicated, since data can be present that's not expected from the connected clients list, or absent that's expected in the list but actually shouldn't be there. --- network/netplay/netplay_delta.c | 3 -- network/netplay/netplay_frontend.c | 11 ++--- network/netplay/netplay_private.h | 3 -- network/netplay/netplay_sync.c | 77 ++++++++++++++++++++++-------- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/network/netplay/netplay_delta.c b/network/netplay/netplay_delta.c index a759d68f52..7828cb9f9a 100644 --- a/network/netplay/netplay_delta.c +++ b/network/netplay/netplay_delta.c @@ -65,10 +65,7 @@ bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta, } delta->have_local = false; for (i = 0; i < MAX_CLIENTS; i++) - { delta->have_real[i] = false; - delta->used_real[i] = false; - } return true; } diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index a731874eeb..d0058029ce 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -496,11 +496,8 @@ static int16_t netplay_input_state(netplay_t *netplay, return 0; } - /* FIXME: Mixing */ delta = &netplay->buffer[ptr]; istate = delta->resolved_input[port]; - if (istate && istate->used) - delta->used_real[port] = true; if (!istate) return 0; @@ -1253,23 +1250,23 @@ static void netplay_toggle_play_spectate(netplay_t *netplay) } else { - uint32_t cmd; + enum rarch_netplay_connection_mode mode; if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING || netplay->self_mode == NETPLAY_CONNECTION_SLAVE) { /* Switch to spectator mode immediately */ netplay->self_mode = NETPLAY_CONNECTION_SPECTATING; - cmd = NETPLAY_CMD_SPECTATE; + mode = NETPLAY_CONNECTION_SPECTATING; } else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING) { /* Switch only after getting permission */ - cmd = NETPLAY_CMD_PLAY; + mode = NETPLAY_CONNECTION_PLAYING; } else return; - netplay_send_raw_cmd_all(netplay, NULL, cmd, NULL, 0); + netplay_cmd_mode(netplay, &netplay->one_connection, mode); } } diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 446828d7eb..982ce5ddcf 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -318,9 +318,6 @@ struct delta_frame /* Have we read the real (remote) input? */ bool have_real[MAX_CLIENTS]; - - /* Is the current state as of self_frame_count using the real (remote) data? */ - bool used_real[MAX_CLIENTS]; }; struct socket_buffer diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c index 9d5608427f..f85312082e 100644 --- a/network/netplay/netplay_sync.c +++ b/network/netplay/netplay_sync.c @@ -88,21 +88,21 @@ struct vote_count { /** * netplay_device_client_state - * @resstate : state being resolved + * @netplay : pointer to netplay object * @simframe : frame in which merging is being performed * @device : device being merged * @client : client to find state for */ -netplay_input_state_t netplay_device_client_state( - netplay_input_state_t resstate, struct delta_frame *simframe, - uint32_t device, uint32_t client) +netplay_input_state_t netplay_device_client_state(netplay_t *netplay, + struct delta_frame *simframe, uint32_t device, uint32_t client) { netplay_input_state_t simstate = netplay_input_state_for( &simframe->real_input[device], client, 3 /* FIXME */, false, true); if (!simstate) { - resstate->used = false; + if (netplay->read_frame_count1[client] > simframe->frame) + return NULL; simstate = netplay_input_state_for(&simframe->simlated_input[device], client, 3 /* FIXME */, false, true); } @@ -125,6 +125,14 @@ static void netplay_merge_digital(netplay_t *netplay, netplay_input_state_t simstate; uint32_t word, bit, client; uint8_t share_mode = netplay->device_share_modes[device] & NETPLAY_SHARE_DIGITAL_BITS; + + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + if (share_mode == NETPLAY_SHARE_DIGITAL_VOTE) { /* Vote mode requires counting all the bits */ @@ -133,9 +141,9 @@ static void netplay_merge_digital(netplay_t *netplay, for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<device_share_modes[device] & NETPLAY_SHARE_ANALOG_BITS; int32_t value = 0, new_value; + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<data[word]>>bit) & 0xFFFF); switch (share_mode) { @@ -279,31 +294,36 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) { size_t prev; struct delta_frame *simframe, *pframe; - netplay_input_state_t simstate, resstate, oldresstate, pstate; + netplay_input_state_t simstate, client_state = NULL, resstate, oldresstate, pstate; uint32_t clients, client, client_count; uint32_t device; - bool ret = false, simulated; + bool ret = false; simframe = &netplay->buffer[sim_ptr]; for (device = 0; device < MAX_INPUT_DEVICES; device++) { clients = netplay->device_clients[device]; - if (!clients) continue; client_count = 0; + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<real_input[device], client, 3 /* FIXME */, false, true); if (!simstate) { - /* Don't already have this input, so must simulate */ - simulated = true; + /* Don't already have this input, so must simulate if we're supposed to have it at all */ + if (netplay->read_frame_count1[client] > simframe->frame) + continue; simstate = netplay_input_state_for(&simframe->simlated_input[device], client, 3 /* FIXME */, false, false); if (!simstate) continue; @@ -345,6 +365,9 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) simstate->size * sizeof(uint32_t)); } } + + client_state = simstate; + client_count++; } /* Now we copy the state, whether real or simulated, out into the resolved state */ @@ -355,12 +378,24 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) if (client_count == 1) { /* Trivial in the common 1-client case */ - resstate->used = !simulated; /* We reuse "used" to mean "real" */ - if (memcmp(resstate->data, simstate->data, resstate->size * sizeof(uint32_t))) + if (memcmp(resstate->data, client_state->data, resstate->size * sizeof(uint32_t))) ret = true; - memcpy(resstate->data, simstate->data, resstate->size * sizeof(uint32_t)); + memcpy(resstate->data, client_state->data, resstate->size * sizeof(uint32_t)); - } else { + } + else if (client_count == 0) + { + uint32_t word; + for (word = 0; word < resstate->size; word++) + { + if (resstate->data[word]) + ret = true; + resstate->data[word] = 0; + } + + } + else + { /* Merge them */ static const uint32_t digital[3] = {-1, 0, 0}; oldresstate = netplay_input_state_for(&simframe->resolved_input[device], 1, 3 /* FIXME */, false, false);