From 2130fd81a5c65c4b706f300eacf0a2e5cd4adb6c Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Mon, 12 Dec 2016 17:23:21 -0500 Subject: [PATCH] Fixed simulation for >2 players --- network/netplay/netplay.c | 82 +++++++++++++++++-------------- network/netplay/netplay_net.c | 5 +- network/netplay/netplay_private.h | 2 +- 3 files changed, 49 insertions(+), 40 deletions(-) diff --git a/network/netplay/netplay.c b/network/netplay/netplay.c index 50a4d5eaec..65036aef38 100644 --- a/network/netplay/netplay.c +++ b/network/netplay/netplay.c @@ -1318,45 +1318,56 @@ static int poll_input(netplay_t *netplay, bool block) * * "Simulate" input by assuming it hasn't changed since the last read input. */ -void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr, bool resim) +void netplay_simulate_input(netplay_t *netplay, size_t sim_ptr, bool resim) { - size_t prev = PREV_PTR(netplay->unread_ptr); - struct delta_frame *pframe = &netplay->buffer[prev], - *simframe = &netplay->buffer[sim_ptr]; - if (resim) + uint32_t player; + size_t prev; + struct delta_frame *simframe, *pframe; + + simframe = &netplay->buffer[sim_ptr]; + + for (player = 0; player < MAX_USERS; player++) { - /* In resimulation mode, we only copy the buttons. The reason for this - * is nonobvious: - * - * If we resimulated nothing, then the /duration/ with which any input - * was pressed would be approximately correct, since the original - * simulation came in as the input came in, but the /number of times/ - * the input was pressed would be wrong, as there would be an - * advancing wavefront of real data overtaking the simulated data - * (which is really just real data offset by some frames). - * - * That's acceptable for arrows in most situations, since the amount - * you move is tied to the duration, but unacceptable for buttons, - * which will seem to jerkily be pressed numerous times with those - * wavefronts. - */ - const uint32_t keep = (1U<simulated_input_state[0][0] & keep; - sim_state |= pframe->real_input_state[0][0] & ~keep; - simframe->simulated_input_state[0][0] = sim_state; - } - else - { - memcpy(simframe->simulated_input_state, - pframe->real_input_state, - sizeof(pframe->real_input_state)); + if (!(netplay->connected_players & (1<have_real[player]) continue; + + prev = PREV_PTR(netplay->read_ptr[player]); + pframe = &netplay->buffer[prev]; + + if (resim) + { + /* In resimulation mode, we only copy the buttons. The reason for this + * is nonobvious: + * + * If we resimulated nothing, then the /duration/ with which any input + * was pressed would be approximately correct, since the original + * simulation came in as the input came in, but the /number of times/ + * the input was pressed would be wrong, as there would be an + * advancing wavefront of real data overtaking the simulated data + * (which is really just real data offset by some frames). + * + * That's acceptable for arrows in most situations, since the amount + * you move is tied to the duration, but unacceptable for buttons, + * which will seem to jerkily be pressed numerous times with those + * wavefronts. + */ + const uint32_t keep = (1U<simulated_input_state[player][0] & keep; + sim_state |= pframe->real_input_state[player][0] & ~keep; + simframe->simulated_input_state[player][0] = sim_state; + } + else + { + memcpy(simframe->simulated_input_state[player], + pframe->real_input_state[player], + WORDS_PER_INPUT * sizeof(uint32_t)); + } } } - /** * netplay_poll: * @netplay : pointer to netplay object @@ -1392,8 +1403,7 @@ static bool netplay_poll(void) } /* Simulate the input if we don't have real input */ - if (!netplay_data->buffer[netplay_data->self_ptr].have_real) - netplay_simulate_input(netplay_data, netplay_data->self_ptr, false); + netplay_simulate_input(netplay_data, netplay_data->self_ptr, false); /* Consider stalling */ switch (netplay_data->stall) diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index 889a451f77..72830f4ff2 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -318,9 +318,8 @@ void netplay_sync_post_frame(netplay_t *netplay) if (netplay->replay_frame_count < netplay->unread_frame_count) netplay_handle_frame_hash(netplay, ptr); - /* Simulate this frame's input */ - if (netplay->replay_frame_count >= netplay->unread_frame_count) - netplay_simulate_input(netplay, netplay->replay_ptr, true); + /* Re-simulate this frame's input */ + netplay_simulate_input(netplay, netplay->replay_ptr, true); autosave_lock(); core_run(); diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 8e0dee2775..3bcb53056d 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -482,7 +482,7 @@ bool netplay_init_serialization(netplay_t *netplay); /* Force serialization to be ready by fast-forwarding the core */ bool netplay_wait_and_init_serialization(netplay_t *netplay); -void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr, bool resim); +void netplay_simulate_input(netplay_t *netplay, size_t sim_ptr, bool resim); void netplay_log_connection(const struct sockaddr_storage *their_addr, unsigned slot, const char *nick);