Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for netplay input delay. #819

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/api/frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
if (ParamInt < 1 || ParamPtr == NULL)
return M64ERR_INPUT_INVALID;
return netplay_start(ParamPtr, ParamInt);
case M64CMD_NETPLAY_SET_INPUT_DELAY:
if (ParamInt < 0)
return M64ERR_INPUT_INVALID;
return netplay_set_input_delay(ParamInt);
case M64CMD_NETPLAY_CONTROL_PLAYER:
if (ParamInt < 1 || ParamInt > 4 || ParamPtr == NULL)
return M64ERR_INPUT_INVALID;
Expand Down
3 changes: 2 additions & 1 deletion src/api/m64p_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ typedef enum {
M64CMD_NETPLAY_CONTROL_PLAYER,
M64CMD_NETPLAY_GET_VERSION,
M64CMD_NETPLAY_CLOSE,
M64CMD_PIF_OPEN
M64CMD_PIF_OPEN,
M64CMD_NETPLAY_SET_INPUT_DELAY
} m64p_command;

typedef struct {
Expand Down
55 changes: 48 additions & 7 deletions src/main/netplay.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ static struct controller_input_compat *l_cin_compats;
static uint8_t l_plugin[4];
static uint8_t l_buffer_target;
static uint8_t l_player_lag[4];
static int input_delay;
static int controlled_player;

//UDP packet formats
#define UDP_SEND_KEY_INFO 0
Expand Down Expand Up @@ -127,6 +129,7 @@ m64p_error netplay_start(const char* host, int port)
l_vi_counter = 0;
l_status = 0;
l_reg_id = 0;
input_delay = -1;

return M64ERR_SUCCESS;
}
Expand Down Expand Up @@ -278,13 +281,15 @@ static void netplay_process()
plugin = packet->data[curr];
curr += 1;

//insert new event at beginning of linked list
struct netplay_event* new_event = (struct netplay_event*)malloc(sizeof(struct netplay_event));
new_event->count = count;
new_event->buttons = keys;
new_event->plugin = plugin;
new_event->next = l_cin_compats[player].event_first;
l_cin_compats[player].event_first = new_event;
if (input_delay < 0 || player != controlled_player) {
// Ignore inputs from the network for locally controlled players when using input delay.
struct netplay_event* new_event = (struct netplay_event*)malloc(sizeof(struct netplay_event));
new_event->count = count;
new_event->buttons = keys;
new_event->plugin = plugin;
new_event->next = l_cin_compats[player].event_first;
l_cin_compats[player].event_first = new_event;
}
}
break;
default:
Expand Down Expand Up @@ -379,6 +384,35 @@ static uint32_t netplay_get_input(uint8_t control_id)

static void netplay_send_input(uint8_t control_id, uint32_t keys)
{
if (input_delay > 0 && control_id == controlled_player)
{
// Store the input in the linked list in addition to sending it to the server.
// This lets us avoid waiting on a local input to arrive from the server before
// it can be used, which can improve performance.
struct netplay_event* new_event = (struct netplay_event*)malloc(sizeof(struct netplay_event));
new_event->count = l_cin_compats[control_id].netplay_count + input_delay;
new_event->buttons = keys;
new_event->plugin = l_plugin[control_id];
new_event->next = l_cin_compats[control_id].event_first;
l_cin_compats[control_id].event_first = new_event;

if (l_cin_compats[control_id].netplay_count == 0)
{
// Duplicate the first inputs to cover the initial input delay
// during startup of the game. Otherwise the inputs for frame zero
// would never be in the linked list
for (int i = 0; i < input_delay; i++)
{
struct netplay_event* new_event = (struct netplay_event*)malloc(sizeof(struct netplay_event));
new_event->count = i;
new_event->buttons = keys;
new_event->plugin = l_plugin[control_id];
new_event->next = l_cin_compats[control_id].event_first;
l_cin_compats[control_id].event_first = new_event;
}
}
}

UDPpacket *packet = SDLNet_AllocPacket(11);
packet->data[0] = UDP_SEND_KEY_INFO;
packet->data[1] = control_id; //player number
Expand All @@ -393,6 +427,7 @@ static void netplay_send_input(uint8_t control_id, uint32_t keys)
uint8_t netplay_register_player(uint8_t player, uint8_t plugin, uint8_t rawdata, uint32_t reg_id)
{
l_reg_id = reg_id;
controlled_player = player;
char output_data[8];
output_data[0] = TCP_REGISTER_PLAYER;
output_data[1] = player; //player number we'd like to register
Expand All @@ -415,6 +450,12 @@ int netplay_lag()
return l_canFF;
}

m64p_error netplay_set_input_delay(int _input_delay)
{
input_delay = _input_delay;
return M64ERR_SUCCESS;
}

int netplay_next_controller()
{
return l_netplay_controller;
Expand Down
1 change: 1 addition & 0 deletions src/main/netplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct controller_input_compat;

m64p_error netplay_start(const char* host, int port);
m64p_error netplay_stop();
m64p_error netplay_set_input_delay(int input_delay);
uint8_t netplay_register_player(uint8_t player, uint8_t plugin, uint8_t rawdata, uint32_t reg_id);
int netplay_lag();
void netplay_set_controller(uint8_t player);
Expand Down