diff --git a/config.def.h b/config.def.h index 63fe9d67a8..e00827f52a 100644 --- a/config.def.h +++ b/config.def.h @@ -1154,6 +1154,9 @@ static const bool audio_enable_menu_bgm = false; /* Start netplay in spectator mode */ static const bool netplay_start_as_spectator = false; +/* Allow players (other than the host) to pause */ +static const bool netplay_allow_pausing = false; + /* Allow connections in slave mode */ static const bool netplay_allow_slaves = true; diff --git a/configuration.c b/configuration.c index faf0f05836..29ee793c28 100644 --- a/configuration.c +++ b/configuration.c @@ -1600,6 +1600,7 @@ static struct config_bool_setting *populate_settings_bool( #ifdef HAVE_NETWORKING SETTING_BOOL("netplay_public_announce", &settings->bools.netplay_public_announce, true, DEFAULT_NETPLAY_PUBLIC_ANNOUNCE, false); SETTING_BOOL("netplay_start_as_spectator", &settings->bools.netplay_start_as_spectator, false, netplay_start_as_spectator, false); + SETTING_BOOL("netplay_allow_pausing", &settings->bools.netplay_allow_pausing, true, netplay_allow_pausing, false); SETTING_BOOL("netplay_allow_slaves", &settings->bools.netplay_allow_slaves, true, netplay_allow_slaves, false); SETTING_BOOL("netplay_require_slaves", &settings->bools.netplay_require_slaves, true, netplay_require_slaves, false); SETTING_BOOL("netplay_stateless_mode", &settings->bools.netplay_stateless_mode, true, netplay_stateless_mode, false); @@ -2208,8 +2209,8 @@ static struct config_uint_setting *populate_settings_uint( #endif #ifdef HAVE_NETWORKING SETTING_UINT("netplay_ip_port", &settings->uints.netplay_port, true, RARCH_DEFAULT_PORT, false); - SETTING_UINT("netplay_max_connections", &settings->uints.netplay_max_connections, true, netplay_max_connections, false); SETTING_OVERRIDE(RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT); + SETTING_UINT("netplay_max_connections", &settings->uints.netplay_max_connections, true, netplay_max_connections, false); SETTING_UINT("netplay_input_latency_frames_min",&settings->uints.netplay_input_latency_frames_min, true, 0, false); SETTING_UINT("netplay_input_latency_frames_range",&settings->uints.netplay_input_latency_frames_range, true, 0, false); SETTING_UINT("netplay_share_digital", &settings->uints.netplay_share_digital, true, netplay_share_digital, false); diff --git a/configuration.h b/configuration.h index 35ff7ebae7..8fffe09c5d 100644 --- a/configuration.h +++ b/configuration.h @@ -757,6 +757,7 @@ typedef struct settings /* Netplay */ bool netplay_public_announce; bool netplay_start_as_spectator; + bool netplay_allow_pausing; bool netplay_allow_slaves; bool netplay_require_slaves; bool netplay_stateless_mode; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 954a2090fe..f0b5ea5451 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1972,6 +1972,10 @@ MSG_HASH( MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR, "netplay_start_as_spectator" ) +MSG_HASH( + MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING, + "netplay_allow_pausing" + ) MSG_HASH( MENU_ENUM_LABEL_NETPLAY_STATELESS_MODE, "netplay_stateless_mode" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 3493e8df45..bd36e4def5 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -5246,6 +5246,10 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_MAX_CONNECTIONS, "Max Simultaneous Connections" ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_MAX_CONNECTIONS, + "The maximum number of active connections that the host will accept before refusing new ones." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Server Password" @@ -5270,6 +5274,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_START_AS_SPECTATOR, "Start netplay in spectator mode." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_NETPLAY_ALLOW_PAUSING, + "Allow Pausing" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_ALLOW_PAUSING, + "Allow players to pause during netplay. The host can always pause regardless of this setting." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_ALLOW_SLAVES, "Allow Slave-Mode Clients" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index e356a1acb9..3c92d18897 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -611,9 +611,11 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_layout_path, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_public_announce, MENU_ENUM_SUBLABEL_NETPLAY_PUBLIC_ANNOUNCE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_ip_address, MENU_ENUM_SUBLABEL_NETPLAY_IP_ADDRESS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_tcp_udp_port, MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_max_connections, MENU_ENUM_SUBLABEL_NETPLAY_MAX_CONNECTIONS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_password, MENU_ENUM_SUBLABEL_NETPLAY_PASSWORD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_spectate_password, MENU_ENUM_SUBLABEL_NETPLAY_SPECTATE_PASSWORD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_start_as_spectator, MENU_ENUM_SUBLABEL_NETPLAY_START_AS_SPECTATOR) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_allow_pausing, MENU_ENUM_SUBLABEL_NETPLAY_ALLOW_PAUSING) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_allow_slaves, MENU_ENUM_SUBLABEL_NETPLAY_ALLOW_SLAVES) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_require_slaves, MENU_ENUM_SUBLABEL_NETPLAY_REQUIRE_SLAVES) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_stateless_mode, MENU_ENUM_SUBLABEL_NETPLAY_STATELESS_MODE) @@ -2985,6 +2987,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_start_as_spectator); break; + case MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_allow_pausing); + break; case MENU_ENUM_LABEL_NETPLAY_ALLOW_SLAVES: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_allow_slaves); break; @@ -3000,6 +3005,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_spectate_password); break; + case MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_max_connections); + break; case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_tcp_udp_port); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 421cbf010b..982db8df89 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -7305,6 +7305,7 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_NETPLAY_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR, PARSE_ONLY_BOOL, true}, + {MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_ALLOW_SLAVES, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_NETPLAY_STATELESS_MODE, PARSE_ONLY_BOOL, true}, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 232223281b..21d8eb8274 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -19195,6 +19195,21 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); + CONFIG_BOOL( + list, list_info, + &settings->bools.netplay_allow_pausing, + MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING, + MENU_ENUM_LABEL_VALUE_NETPLAY_ALLOW_PAUSING, + netplay_allow_pausing, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + CONFIG_BOOL( list, list_info, &settings->bools.netplay_allow_slaves, diff --git a/msg_hash.h b/msg_hash.h index 9cbad1ea6d..74c7bb8b74 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1902,6 +1902,7 @@ enum msg_hash_enums MENU_LABEL(NETPLAY_DELAY_FRAMES), MENU_LABEL(NETPLAY_PUBLIC_ANNOUNCE), MENU_LABEL(NETPLAY_START_AS_SPECTATOR), + MENU_LABEL(NETPLAY_ALLOW_PAUSING), MENU_LABEL(NETPLAY_ALLOW_SLAVES), MENU_LABEL(NETPLAY_REQUIRE_SLAVES), MENU_LABEL(NETPLAY_STATELESS_MODE), diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 7ab1b9fdcf..85f64f08b7 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -5281,17 +5281,18 @@ static bool netplay_get_cmd(netplay_t *netplay, RECV(nick, sizeof(nick)) return false; - nick[sizeof(nick)-1] = '\0'; - /* We outright ignore pausing from spectators and slaves */ - if (connection->mode != NETPLAY_CONNECTION_PLAYING) - break; - - connection->paused = true; - netplay->remote_paused = true; if (netplay->is_server) { + settings_t *settings = config_get_ptr(); + if (!settings->bools.netplay_allow_pausing) + break; + + /* We outright ignore pausing from spectators and slaves */ + if (connection->mode != NETPLAY_CONNECTION_PLAYING) + break; + /* Inform peers */ snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), @@ -5306,6 +5307,10 @@ static bool netplay_get_cmd(netplay_t *netplay, else snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), nick); + + connection->paused = true; + netplay->remote_paused = true; + RARCH_LOG("%s\n", msg); runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); break; @@ -6033,17 +6038,9 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, ? nick : RARCH_DEFAULT_NICK, sizeof(netplay->nick)); - if (!init_socket(netplay, direct_host, server, port)) - { - free(netplay); - return NULL; - } - - if (!netplay_init_buffers(netplay)) - { - free(netplay); - return NULL; - } + if (!init_socket(netplay, direct_host, server, port) || + !netplay_init_buffers(netplay)) + goto failure; if (netplay->is_server) { @@ -6076,24 +6073,18 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, if (netplay->is_server) { if (!socket_nonblock(netplay->listen_fd)) - goto error; + goto failure; } else { if (!socket_nonblock(netplay->connections[0].fd)) - goto error; + goto failure; } return netplay; -error: - if (netplay->listen_fd >= 0) - socket_close(netplay->listen_fd); - - if (netplay->connections && netplay->connections[0].fd >= 0) - socket_close(netplay->connections[0].fd); - - free(netplay); +failure: + netplay_free(netplay); return NULL; } @@ -7209,16 +7200,12 @@ static void netplay_announce(void) task_push_http_post_transfer(url, buf, true, NULL, netplay_announce_cb, NULL); - if (username) - free(username); - if (corename) - free(corename); - if (gamename) - free(gamename); - if (coreversion) - free(coreversion); - if (frontend_ident) - free(frontend_ident); + free(username); + free(corename); + free(gamename); + free(subsystemname); + free(coreversion); + free(frontend_ident); } int16_t input_state_net(unsigned port, unsigned device, diff --git a/ui/drivers/qt/qt_options.cpp b/ui/drivers/qt/qt_options.cpp index e6d17a28c8..b545acd49d 100644 --- a/ui/drivers/qt/qt_options.cpp +++ b/ui/drivers/qt/qt_options.cpp @@ -412,6 +412,7 @@ QWidget *NetplayPage::widget() checksLayout->add(MENU_ENUM_LABEL_NETPLAY_PUBLIC_ANNOUNCE); checksLayout->add(MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR); + checksLayout->add(MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING); checksLayout->add(MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS); serverForm->add(MENU_ENUM_LABEL_NETPLAY_IP_ADDRESS);