From b6a116a2479eb62aece540633c41d0f54a481fd6 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 11 Jul 2021 21:57:05 +0200 Subject: Add: allow setting your server visibility to "invite-only" (#9434) In this mode you do register to the Game Coordinator, but your server will not show up in the public server listing. You can give your friends the invite code of the server with which they can join. --- src/console_cmds.cpp | 1 - src/lang/english.txt | 3 +++ src/network/network.cpp | 25 +++++++++++++++++++++- src/network/network_coordinator.cpp | 19 ++++++++++++----- src/network/network_func.h | 1 + src/network/network_gui.cpp | 38 +++++++++++++++++---------------- src/network/network_type.h | 1 + src/settings_type.h | 2 ++ src/table/settings/network_settings.ini | 16 +++++++++++--- 9 files changed, 78 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 0fcac4488..fd7f09e3c 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2420,7 +2420,6 @@ void IConsoleStdLibRegister() IConsole::AliasRegister("name", "setting client_name %+"); IConsole::AliasRegister("server_name", "setting server_name %+"); IConsole::AliasRegister("server_port", "setting server_port %+"); - IConsole::AliasRegister("server_advertise", "setting server_advertise %+"); IConsole::AliasRegister("max_clients", "setting max_clients %+"); IConsole::AliasRegister("max_companies", "setting max_companies %+"); IConsole::AliasRegister("max_spectators", "setting max_spectators %+"); diff --git a/src/lang/english.txt b/src/lang/english.txt index 813705958..baf94c2ee 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1995,8 +1995,11 @@ STR_FACE_TIE :Tie: STR_FACE_EARRING :Earring: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Change tie or earring +############ Next lines match ServerGameType STR_NETWORK_SERVER_VISIBILITY_LOCAL :Local STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Public +STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY :Invite only +############ End of leave-in-this-order # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer diff --git a/src/network/network.cpp b/src/network/network.cpp index f8138bbbc..d35fbe746 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -934,7 +934,7 @@ bool NetworkServerStart() NetworkInitGameInfo(); - if (_settings_client.network.server_advertise) { + if (_settings_client.network.server_game_type != SERVER_GAME_TYPE_LOCAL) { _network_coordinator_client.Register(); } @@ -999,6 +999,29 @@ void NetworkDisconnect(bool blocking, bool close_admins) NetworkUDPInitialize(); } +/** + * The setting server_game_type was updated; possibly we need to take some + * action. + */ +void NetworkUpdateServerGameType() +{ + if (!_networking) return; + + switch (_settings_client.network.server_game_type) { + case SERVER_GAME_TYPE_LOCAL: + _network_coordinator_client.CloseConnection(); + break; + + case SERVER_GAME_TYPE_INVITE_ONLY: + case SERVER_GAME_TYPE_PUBLIC: + _network_coordinator_client.Register(); + break; + + default: + NOT_REACHED(); + } +} + /** * Receives something from the network. * @return true if everything went fine, false when the connection got closed. diff --git a/src/network/network_coordinator.cpp b/src/network/network_coordinator.cpp index 8bd81b6f6..22b303f00 100644 --- a/src/network/network_coordinator.cpp +++ b/src/network/network_coordinator.cpp @@ -94,8 +94,8 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_ERROR(Packet *p) SetDParamStr(0, detail); ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED, STR_JUST_RAW_STRING, WL_ERROR); - /* To prevent that we constantly try to reconnect, switch to private game. */ - _settings_client.network.server_advertise = false; + /* To prevent that we constantly try to reconnect, switch to local game. */ + _settings_client.network.server_game_type = SERVER_GAME_TYPE_LOCAL; this->CloseConnection(); return false; @@ -153,9 +153,18 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p) default: connection_type = "Unknown"; break; // Should never happen, but don't fail if it does. } + std::string game_type; + switch (_settings_client.network.server_game_type) { + case SERVER_GAME_TYPE_INVITE_ONLY: game_type = "Invite only"; break; + case SERVER_GAME_TYPE_PUBLIC: game_type = "Public"; break; + + case SERVER_GAME_TYPE_LOCAL: // Impossible to register local servers. + default: game_type = "Unknown"; break; // Should never happen, but don't fail if it does. + } + Debug(net, 3, "----------------------------------------"); Debug(net, 3, "Your server is now registered with the Game Coordinator:"); - Debug(net, 3, " Game type: Public"); + Debug(net, 3, " Game type: {}", game_type); Debug(net, 3, " Connection type: {}", connection_type); Debug(net, 3, " Invite code: {}", _network_server_invite_code); Debug(net, 3, "----------------------------------------"); @@ -298,7 +307,7 @@ void ClientNetworkCoordinatorSocketHandler::Register() Packet *p = new Packet(PACKET_COORDINATOR_SERVER_REGISTER); p->Send_uint8(NETWORK_COORDINATOR_VERSION); - p->Send_uint8(SERVER_GAME_TYPE_PUBLIC); + p->Send_uint8(_settings_client.network.server_game_type); p->Send_uint16(_settings_client.network.server_port); if (_settings_client.network.server_invite_code.empty() || _settings_client.network.server_invite_code_secret.empty()) { p->Send_string(""); @@ -467,7 +476,7 @@ void ClientNetworkCoordinatorSocketHandler::CloseAllTokens() void ClientNetworkCoordinatorSocketHandler::SendReceive() { /* Private games are not listed via the Game Coordinator. */ - if (_network_server && !_settings_client.network.server_advertise) { + if (_network_server && _settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) { if (this->sock != INVALID_SOCKET) { this->CloseConnection(); } diff --git a/src/network/network_func.h b/src/network/network_func.h index 6da8fb5cc..c0f68f915 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -39,6 +39,7 @@ bool NetworkValidateOurClientName(); bool NetworkValidateClientName(std::string &client_name); bool NetworkValidateServerName(std::string &server_name); void NetworkUpdateClientName(const std::string &client_name); +void NetworkUpdateServerGameType(); bool NetworkCompanyHasClients(CompanyID company); std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password); void NetworkReboot(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index a0d2d47c8..d2fefb5cc 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -60,16 +60,6 @@ static const int NETWORK_LIST_REFRESH_DELAY = 30; ///< Time, in seconds, between static ClientID _admin_client_id = INVALID_CLIENT_ID; ///< For what client a confirmation window is open. static CompanyID _admin_company_id = INVALID_COMPANY; ///< For what company a confirmation window is open. -/** - * Visibility of the server. Public servers advertise, where private servers - * do not. - */ -static const StringID _server_visibility_dropdown[] = { - STR_NETWORK_SERVER_VISIBILITY_LOCAL, - STR_NETWORK_SERVER_VISIBILITY_PUBLIC, - INVALID_STRING_ID -}; - /** * Update the network new window because a new server is * found on the network. @@ -79,6 +69,17 @@ void UpdateNetworkGameWindow() InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME, 0); } +static DropDownList BuildVisibilityDropDownList() +{ + DropDownList list; + + list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_LOCAL, SERVER_GAME_TYPE_LOCAL, false)); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY, SERVER_GAME_TYPE_INVITE_ONLY, false)); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_PUBLIC, SERVER_GAME_TYPE_PUBLIC, false)); + + return list; +} + typedef GUIList GUIGameServerList; typedef int ServerListPosition; static const ServerListPosition SLP_INVALID = -1; @@ -1015,7 +1016,7 @@ struct NetworkStartServerWindow : public Window { { switch (widget) { case WID_NSS_CONNTYPE_BTN: - SetDParam(0, _server_visibility_dropdown[_settings_client.network.server_advertise]); + SetDParam(0, STR_NETWORK_SERVER_VISIBILITY_LOCAL + _settings_client.network.server_game_type); break; case WID_NSS_CLIENTS_TXT: @@ -1036,7 +1037,7 @@ struct NetworkStartServerWindow : public Window { { switch (widget) { case WID_NSS_CONNTYPE_BTN: - *size = maxdim(GetStringBoundingBox(_server_visibility_dropdown[0]), GetStringBoundingBox(_server_visibility_dropdown[1])); + *size = maxdim(maxdim(GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_LOCAL), GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_PUBLIC)), GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY)); size->width += padding.width; size->height += padding.height; break; @@ -1066,7 +1067,7 @@ struct NetworkStartServerWindow : public Window { break; case WID_NSS_CONNTYPE_BTN: // Connection type - ShowDropDownMenu(this, _server_visibility_dropdown, _settings_client.network.server_advertise, WID_NSS_CONNTYPE_BTN, 0, 0); // do it for widget WID_NSS_CONNTYPE_BTN + ShowDropDownList(this, BuildVisibilityDropDownList(), _settings_client.network.server_game_type, WID_NSS_CONNTYPE_BTN); break; case WID_NSS_CLIENTS_BTND: case WID_NSS_CLIENTS_BTNU: // Click on up/down button for number of clients @@ -1144,7 +1145,7 @@ struct NetworkStartServerWindow : public Window { { switch (widget) { case WID_NSS_CONNTYPE_BTN: - _settings_client.network.server_advertise = (index != 0); + _settings_client.network.server_game_type = (ServerGameType)index; break; default: NOT_REACHED(); @@ -2041,7 +2042,7 @@ public: { switch (widget) { case WID_CL_SERVER_VISIBILITY: - *size = maxdim(GetStringBoundingBox(_server_visibility_dropdown[0]), GetStringBoundingBox(_server_visibility_dropdown[1])); + *size = maxdim(maxdim(GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_LOCAL), GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_PUBLIC)), GetStringBoundingBox(STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY)); size->width += padding.width; size->height += padding.height; break; @@ -2073,7 +2074,7 @@ public: break; case WID_CL_SERVER_VISIBILITY: - SetDParam(0, _server_visibility_dropdown[_settings_client.network.server_advertise]); + SetDParam(0, STR_NETWORK_SERVER_VISIBILITY_LOCAL + _settings_client.network.server_game_type); break; case WID_CL_SERVER_INVITE_CODE: { @@ -2117,7 +2118,7 @@ public: case WID_CL_SERVER_VISIBILITY: if (!_network_server) break; - ShowDropDownMenu(this, _server_visibility_dropdown, _settings_client.network.server_advertise, WID_CL_SERVER_VISIBILITY, 0, 0); + ShowDropDownList(this, BuildVisibilityDropDownList(), _settings_client.network.server_game_type, WID_CL_SERVER_VISIBILITY); break; case WID_CL_MATRIX: { @@ -2183,7 +2184,8 @@ public: case WID_CL_SERVER_VISIBILITY: if (!_network_server) break; - _settings_client.network.server_advertise = (index != 0); + _settings_client.network.server_game_type = (ServerGameType)index; + NetworkUpdateServerGameType(); break; case WID_CL_MATRIX: { diff --git a/src/network/network_type.h b/src/network/network_type.h index 6e6fe33de..a3fb217fe 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -42,6 +42,7 @@ enum NetworkVehicleType { enum ServerGameType : uint8 { SERVER_GAME_TYPE_LOCAL = 0, SERVER_GAME_TYPE_PUBLIC, + SERVER_GAME_TYPE_INVITE_ONLY, }; /** 'Unique' identifier to be given to clients */ diff --git a/src/settings_type.h b/src/settings_type.h index 79e462c3e..93e2f049f 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -15,6 +15,7 @@ #include "town_type.h" #include "transport_type.h" #include "network/core/config.h" +#include "network/network_type.h" #include "company_type.h" #include "cargotype.h" #include "linkgraph/linkgraph_type.h" @@ -266,6 +267,7 @@ struct NetworkSettings { uint16 server_port; ///< port the server listens on uint16 server_admin_port; ///< port the server listens on for the admin network bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network + ServerGameType server_game_type; ///< Server type: local / public / invite-only. std::string server_invite_code; ///< Invite code to use when registering as server. std::string server_invite_code_secret; ///< Secret to proof we got this invite code from the Game Coordinator. std::string server_name; ///< name of the server diff --git a/src/table/settings/network_settings.ini b/src/table/settings/network_settings.ini index 45459b6e1..552f58823 100644 --- a/src/table/settings/network_settings.ini +++ b/src/table/settings/network_settings.ini @@ -9,14 +9,18 @@ [pre-amble] static void UpdateClientConfigValues(); +static std::initializer_list _server_game_type{"local", "public", "invite-only"}; + static const SettingVariant _network_settings_table[] = { [post-amble] }; [templates] SDTC_BOOL = SDTC_BOOL( $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDTC_VAR = SDTC_VAR( $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] +SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTC_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); [defaults] @@ -159,10 +163,16 @@ flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = true cat = SC_EXPERT -[SDTC_BOOL] -var = network.server_advertise +[SDTC_OMANY] +var = network.server_game_type +type = SLE_UINT8 flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY -def = false +def = SERVER_GAME_TYPE_LOCAL +min = SERVER_GAME_TYPE_LOCAL +max = SERVER_GAME_TYPE_INVITE_ONLY +full = _server_game_type +post_cb = [](auto) { NetworkUpdateServerGameType(); } +cat = SC_BASIC [SDTC_BOOL] var = network.autoclean_companies -- cgit v1.2.3-70-g09d2