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.
This commit is contained in:
Gregor Richards 2017-09-11 07:29:44 -04:00
parent 39243a8d40
commit ed320fd914
4 changed files with 60 additions and 34 deletions

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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<<simstate->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<<client))) continue;
client_count++;
simstate = netplay_device_client_state(resstate, simframe, device, client);
simstate = netplay_device_client_state(netplay, simframe, device, client);
if (!simstate) continue;
client_count++;
for (word = 0; word < 3 /* FIXME */; word++)
{
@ -166,7 +174,7 @@ static void netplay_merge_digital(netplay_t *netplay,
for (client = 0; client < MAX_CLIENTS; client++)
{
if (!(clients & (1<<client))) continue;
simstate = netplay_device_client_state(resstate, simframe, device, client);
simstate = netplay_device_client_state(netplay, simframe, device, client);
if (!simstate) continue;
for (word = 0; word < 3 /* FIXME */; word++)
{
@ -220,12 +228,19 @@ static void merge_analog_part(netplay_t *netplay,
uint8_t share_mode = netplay->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<<simstate->client_num;
}
for (client = 0; client < MAX_CLIENTS; client++)
{
if (!(clients & (1<<client))) continue;
client_count++;
simstate = netplay_device_client_state(resstate, simframe, device, client);
simstate = netplay_device_client_state(netplay, simframe, device, client);
if (!simstate) continue;
client_count++;
new_value = (int16_t) ((simstate->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<<simstate->client_num;
}
for (client = 0; client < MAX_CLIENTS; client++)
{
if (!(clients & (1<<client))) continue;
client_count++;
/* Resolve this client-device */
simulated = false;
simstate = netplay_input_state_for(&simframe->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);