Changeset - r25815:13efa809f0d9
[Not reviewed]
master
0 15 0
Patric Stout - 4 years ago 2021-04-29 13:37:02
truebrain@openttd.org
Feature: join servers based on their invite code

This removes the need to know a server IP to join it. Invite codes
are small (~7 characters) indentifiers for servers, which can be
exchanged with other players to join the servers.
15 files changed with 422 insertions and 29 deletions:
0 comments (0 inline, 0 general)
src/console_cmds.cpp
Show inline comments
 
@@ -699,12 +699,13 @@ DEF_CONSOLE_CMD(ConServerInfo)
 
	if (argc == 0) {
 
		IConsolePrint(CC_HELP, "List current and maximum client/company limits. Usage 'server_info'.");
 
		IConsolePrint(CC_HELP, "You can change these values by modifying settings 'network.max_clients', 'network.max_companies' and 'network.max_spectators'.");
 
		return true;
 
	}
 

	
 
	IConsolePrint(CC_DEFAULT, "Invite code:                {}", _network_server_invite_code);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum clients:    {:3d}/{:3d}", _network_game_info.clients_on, _settings_client.network.max_clients);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum companies:  {:3d}/{:3d}", Company::GetNumItems(), _settings_client.network.max_companies);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum spectators: {:3d}/{:3d}", NetworkSpectatorCount(), _settings_client.network.max_spectators);
 

	
 
	return true;
 
}
src/lang/english.txt
Show inline comments
 
@@ -2042,18 +2042,18 @@ STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP 
 

	
 
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET                  :{BLACK}Search internet
 
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP          :{BLACK}Search internet for public servers
 
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN                       :{BLACK}Search LAN
 
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP               :{BLACK}Search local area network for servers
 
STR_NETWORK_SERVER_LIST_ADD_SERVER                              :{BLACK}Add server
 
STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP                      :{BLACK}Adds a server to the list which will always be checked for running games
 
STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP                      :{BLACK}Adds a server to the list. This can either be a server address or an invite code
 
STR_NETWORK_SERVER_LIST_START_SERVER                            :{BLACK}Start server
 
STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP                    :{BLACK}Start your own server
 

	
 
STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE                    :{BLACK}Enter your name
 
STR_NETWORK_SERVER_LIST_ENTER_IP                                :{BLACK}Enter the address of the host
 
STR_NETWORK_SERVER_LIST_ENTER_SERVER_ADDRESS                    :{BLACK}Enter server address or invite code
 

	
 
# Start new multiplayer server
 
STR_NETWORK_START_SERVER_CAPTION                                :{WHITE}Start new multiplayer game
 

	
 
STR_NETWORK_START_SERVER_NEW_GAME_NAME                          :{BLACK}Game name:
 
STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP                  :{BLACK}The game name will be displayed to other players in the multiplayer game selection menu
 
@@ -2133,12 +2133,14 @@ STR_NETWORK_CLIENT_LIST_SERVER          
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME                             :{BLACK}Name
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP                     :{BLACK}Name of the server you are playing on
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP                :{BLACK}Edit the name of your server
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION               :Name of the server
 
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY                       :{BLACK}Visibility
 
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP               :{BLACK}Whether other people can see your server in the public listing
 
STR_NETWORK_CLIENT_LIST_SERVER_INVITE_CODE                      :{BLACK}Invite code
 
STR_NETWORK_CLIENT_LIST_SERVER_INVITE_CODE_TOOLTIP              :{BLACK}Invite code other players can use to join this server
 
STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE                  :{BLACK}Connection type
 
STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE_TOOLTIP          :{BLACK}Whether and how your server can be reached by others
 
STR_NETWORK_CLIENT_LIST_PLAYER                                  :{BLACK}Player
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME                             :{BLACK}Name
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP                     :{BLACK}Your player name
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP                :{BLACK}Edit your player name
src/network/core/config.h
Show inline comments
 
@@ -44,13 +44,13 @@ static const uint16 UDP_MTU             
 
static const uint16 TCP_MTU                         = 32767;          ///< Number of bytes we can pack in a single TCP packet
 
static const uint16 COMPAT_MTU                      = 1460;           ///< Number of bytes we can pack in a single packet for backward compatibility
 

	
 
static const byte NETWORK_GAME_ADMIN_VERSION        =    1;           ///< What version of the admin network do we use?
 
static const byte NETWORK_GAME_INFO_VERSION         =    4;           ///< What version of game-info do we use?
 
static const byte NETWORK_COMPANY_INFO_VERSION      =    6;           ///< What version of company info is this?
 
static const byte NETWORK_COORDINATOR_VERSION       =    1;           ///< What version of game-coordinator-protocol do we use?
 
static const byte NETWORK_COORDINATOR_VERSION       =    2;           ///< What version of game-coordinator-protocol do we use?
 

	
 
static const uint NETWORK_NAME_LENGTH               =   80;           ///< The maximum length of the server name and map name, in bytes including '\0'
 
static const uint NETWORK_COMPANY_NAME_LENGTH       =  128;           ///< The maximum length of the company name, in bytes including '\0'
 
static const uint NETWORK_HOSTNAME_LENGTH           =   80;           ///< The maximum length of the host name, in bytes including '\0'
 
static const uint NETWORK_HOSTNAME_PORT_LENGTH      =   80 + 6;       ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536)
 
static const uint NETWORK_SERVER_ID_LENGTH          =   33;           ///< The maximum length of the network id of the servers, in bytes including '\0'
 
@@ -64,13 +64,16 @@ static const uint NETWORK_CHAT_LENGTH   
 
static const uint NETWORK_CONTENT_FILENAME_LENGTH   =   48;           ///< The maximum length of a content's filename, in bytes including '\0'.
 
static const uint NETWORK_CONTENT_NAME_LENGTH       =   32;           ///< The maximum length of a content's name, in bytes including '\0'.
 
static const uint NETWORK_CONTENT_VERSION_LENGTH    =   16;           ///< The maximum length of a content's version, in bytes including '\0'.
 
static const uint NETWORK_CONTENT_URL_LENGTH        =   96;           ///< The maximum length of a content's url, in bytes including '\0'.
 
static const uint NETWORK_CONTENT_DESC_LENGTH       =  512;           ///< The maximum length of a content's description, in bytes including '\0'.
 
static const uint NETWORK_CONTENT_TAG_LENGTH        =   32;           ///< The maximum length of a content's tag, in bytes including '\0'.
 
static const uint NETWORK_ERROR_DETAIL_LENGTH        = 100;           ///< The maximum length of the error detail, in bytes including '\0'
 
static const uint NETWORK_ERROR_DETAIL_LENGTH       =  100;           ///< The maximum length of the error detail, in bytes including '\0'.
 
static const uint NETWORK_INVITE_CODE_LENGTH        =   64;           ///< The maximum length of the invite code, in bytes including '\0'.
 
static const uint NETWORK_INVITE_CODE_SECRET_LENGTH =   80;           ///< The maximum length of the invite code secret, in bytes including '\0'.
 
static const uint NETWORK_TOKEN_LENGTH              =   64;           ///< The maximum length of a token, in bytes including '\0'.
 

	
 
static const uint NETWORK_GRF_NAME_LENGTH           =   80;           ///< Maximum length of the name of a GRF
 

	
 
/**
 
 * Maximum number of GRFs that can be sent.
 
 *
src/network/core/game_info.cpp
Show inline comments
 
@@ -138,13 +138,17 @@ void FillStaticNetworkServerGameInfo()
 
/**
 
 * Get the NetworkServerGameInfo structure with the latest information of the server.
 
 * @return The current NetworkServerGameInfo.
 
 */
 
const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo()
 
{
 
	/* Client_on is used as global variable to keep track on the number of clients. */
 
	/* These variables are updated inside _network_game_info as if they are global variables:
 
	 *  - clients_on
 
	 *  - invite_code
 
	 * These don't need to be updated manually here.
 
	 */
 
	_network_game_info.companies_on  = (byte)Company::GetNumItems();
 
	_network_game_info.spectators_on = NetworkSpectatorCount();
 
	_network_game_info.game_date     = _date;
 
	return &_network_game_info;
 
}
 

	
src/network/core/tcp_connect.cpp
Show inline comments
 
@@ -10,12 +10,13 @@
 
 */
 

	
 
#include "../../stdafx.h"
 
#include "../../thread.h"
 

	
 
#include "tcp.h"
 
#include "../network_coordinator.h"
 
#include "../network_internal.h"
 

	
 
#include <deque>
 

	
 
#include "../../safeguards.h"
 

	
 
@@ -45,14 +46,13 @@ TCPServerConnecter::TCPServerConnecter(c
 
		case SERVER_ADDRESS_DIRECT:
 
			this->connection_string = this->server_address.connection_string;
 
			break;
 

	
 
		case SERVER_ADDRESS_INVITE_CODE:
 
			this->status = Status::CONNECTING;
 

	
 
			// TODO -- The next commit will add this functionality.
 
			_network_coordinator_client.ConnectToServer(this->server_address.connection_string, this);
 
			break;
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 

	
src/network/core/tcp_coordinator.cpp
Show inline comments
 
@@ -24,18 +24,24 @@
 
 */
 
bool NetworkCoordinatorSocketHandler::HandlePacket(Packet *p)
 
{
 
	PacketCoordinatorType type = (PacketCoordinatorType)p->Recv_uint8();
 

	
 
	switch (type) {
 
		case PACKET_COORDINATOR_GC_ERROR:        return this->Receive_GC_ERROR(p);
 
		case PACKET_COORDINATOR_SERVER_REGISTER: return this->Receive_SERVER_REGISTER(p);
 
		case PACKET_COORDINATOR_GC_REGISTER_ACK: return this->Receive_GC_REGISTER_ACK(p);
 
		case PACKET_COORDINATOR_SERVER_UPDATE:   return this->Receive_SERVER_UPDATE(p);
 
		case PACKET_COORDINATOR_CLIENT_LISTING:  return this->Receive_CLIENT_LISTING(p);
 
		case PACKET_COORDINATOR_GC_LISTING:      return this->Receive_GC_LISTING(p);
 
		case PACKET_COORDINATOR_GC_ERROR:              return this->Receive_GC_ERROR(p);
 
		case PACKET_COORDINATOR_SERVER_REGISTER:       return this->Receive_SERVER_REGISTER(p);
 
		case PACKET_COORDINATOR_GC_REGISTER_ACK:       return this->Receive_GC_REGISTER_ACK(p);
 
		case PACKET_COORDINATOR_SERVER_UPDATE:         return this->Receive_SERVER_UPDATE(p);
 
		case PACKET_COORDINATOR_CLIENT_LISTING:        return this->Receive_CLIENT_LISTING(p);
 
		case PACKET_COORDINATOR_GC_LISTING:            return this->Receive_GC_LISTING(p);
 
		case PACKET_COORDINATOR_CLIENT_CONNECT:        return this->Receive_CLIENT_CONNECT(p);
 
		case PACKET_COORDINATOR_GC_CONNECTING:         return this->Receive_GC_CONNECTING(p);
 
		case PACKET_COORDINATOR_SERCLI_CONNECT_FAILED: return this->Receive_SERCLI_CONNECT_FAILED(p);
 
		case PACKET_COORDINATOR_GC_CONNECT_FAILED:     return this->Receive_GC_CONNECT_FAILED(p);
 
		case PACKET_COORDINATOR_CLIENT_CONNECTED:      return this->Receive_CLIENT_CONNECTED(p);
 
		case PACKET_COORDINATOR_GC_DIRECT_CONNECT:     return this->Receive_GC_DIRECT_CONNECT(p);
 

	
 
		default:
 
			Debug(net, 0, "[tcp/coordinator] Received invalid packet type {}", type);
 
			return false;
 
	}
 
}
 
@@ -79,6 +85,12 @@ bool NetworkCoordinatorSocketHandler::Re
 
bool NetworkCoordinatorSocketHandler::Receive_GC_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_ERROR); }
 
bool NetworkCoordinatorSocketHandler::Receive_SERVER_REGISTER(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERVER_REGISTER); }
 
bool NetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_REGISTER_ACK); }
 
bool NetworkCoordinatorSocketHandler::Receive_SERVER_UPDATE(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERVER_UPDATE); }
 
bool NetworkCoordinatorSocketHandler::Receive_CLIENT_LISTING(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_CLIENT_LISTING); }
 
bool NetworkCoordinatorSocketHandler::Receive_GC_LISTING(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_LISTING); }
 
bool NetworkCoordinatorSocketHandler::Receive_CLIENT_CONNECT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_CLIENT_CONNECT); }
 
bool NetworkCoordinatorSocketHandler::Receive_GC_CONNECTING(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_CONNECTING); }
 
bool NetworkCoordinatorSocketHandler::Receive_SERCLI_CONNECT_FAILED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERCLI_CONNECT_FAILED); }
 
bool NetworkCoordinatorSocketHandler::Receive_GC_CONNECT_FAILED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_CONNECT_FAILED); }
 
bool NetworkCoordinatorSocketHandler::Receive_CLIENT_CONNECTED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_CLIENT_CONNECTED); }
 
bool NetworkCoordinatorSocketHandler::Receive_GC_DIRECT_CONNECT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_DIRECT_CONNECT); }
src/network/core/tcp_coordinator.h
Show inline comments
 
@@ -20,21 +20,28 @@
 
/**
 
 * Enum with all types of TCP Game Coordinator packets. The order MUST not be changed.
 
 *
 
 * GC     -> packets from Game Coordinator to either Client or Server.
 
 * SERVER -> packets from Server to Game Coordinator.
 
 * CLIENT -> packets from Client to Game Coordinator.
 
 * SERCLI -> packets from either the Server or Client to Game Coordinator.
 
 **/
 
enum PacketCoordinatorType {
 
	PACKET_COORDINATOR_GC_ERROR,        ///< Game Coordinator indicates there was an error.
 
	PACKET_COORDINATOR_SERVER_REGISTER, ///< Server registration.
 
	PACKET_COORDINATOR_GC_REGISTER_ACK, ///< Game Coordinator accepts the registration.
 
	PACKET_COORDINATOR_SERVER_UPDATE,   ///< Server sends an set intervals an update of the server.
 
	PACKET_COORDINATOR_CLIENT_LISTING,  ///< Client is requesting a listing of all public servers.
 
	PACKET_COORDINATOR_GC_LISTING,      ///< Game Coordinator returns a listing of all public servers.
 
	PACKET_COORDINATOR_END,             ///< Must ALWAYS be on the end of this list!! (period).
 
	PACKET_COORDINATOR_GC_ERROR,              ///< Game Coordinator indicates there was an error.
 
	PACKET_COORDINATOR_SERVER_REGISTER,       ///< Server registration.
 
	PACKET_COORDINATOR_GC_REGISTER_ACK,       ///< Game Coordinator accepts the registration.
 
	PACKET_COORDINATOR_SERVER_UPDATE,         ///< Server sends an set intervals an update of the server.
 
	PACKET_COORDINATOR_CLIENT_LISTING,        ///< Client is requesting a listing of all public servers.
 
	PACKET_COORDINATOR_GC_LISTING,            ///< Game Coordinator returns a listing of all public servers.
 
	PACKET_COORDINATOR_CLIENT_CONNECT,        ///< Client wants to connect to a server based on an invite code.
 
	PACKET_COORDINATOR_GC_CONNECTING,         ///< Game Coordinator informs the client of the token assigned to the connection attempt.
 
	PACKET_COORDINATOR_SERCLI_CONNECT_FAILED, ///< Client/server tells the Game Coordinator the current connection attempt failed.
 
	PACKET_COORDINATOR_GC_CONNECT_FAILED,     ///< Game Coordinator informs client/server it has given up on the connection attempt.
 
	PACKET_COORDINATOR_CLIENT_CONNECTED,      ///< Client informs the Game Coordinator the connection with the server is established.
 
	PACKET_COORDINATOR_GC_DIRECT_CONNECT,     ///< Game Coordinator tells client to directly connect to the hostname:port of the server.
 
	PACKET_COORDINATOR_END,                   ///< Must ALWAYS be on the end of this list!! (period)
 
};
 

	
 
/**
 
 * The type of connection the Game Coordinator can detect we have.
 
 */
 
enum ConnectionType {
 
@@ -46,12 +53,13 @@ enum ConnectionType {
 
/**
 
 * The type of error from the Game Coordinator.
 
 */
 
enum NetworkCoordinatorErrorType {
 
	NETWORK_COORDINATOR_ERROR_UNKNOWN,             ///< There was an unknown error.
 
	NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED, ///< Your request for registration failed.
 
	NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE, ///< The invite code given is invalid.
 
};
 

	
 
/** Base socket handler for all Game Coordinator TCP sockets. */
 
class NetworkCoordinatorSocketHandler : public NetworkTCPSocketHandler {
 
protected:
 
	bool ReceiveInvalidPacket(PacketCoordinatorType type);
 
@@ -73,21 +81,25 @@ protected:
 
	 * Server is starting a multiplayer game and wants to let the
 
	 * Game Coordinator know.
 
	 *
 
	 *  uint8   Game Coordinator protocol version.
 
	 *  uint8   Type of game (see ServerGameType).
 
	 *  uint16  Local port of the server.
 
	 *  string  Invite code the server wants to use (can be empty; coordinator will assign a new invite code).
 
	 *  string  Secret that belongs to the invite code (empty if invite code is empty).
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_SERVER_REGISTER(Packet *p);
 

	
 
	/**
 
	 * Game Coordinator acknowledges the registration.
 
	 *
 
	 *  string  Invite code that can be used to join this server.
 
	 *  string  Secret that belongs to the invite code (only needed if reusing the invite code on next SERVER_REGISTER).
 
	 *  uint8   Type of connection was detected (see ConnectionType).
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_GC_REGISTER_ACK(Packet *p);
 
@@ -127,12 +139,85 @@ protected:
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_GC_LISTING(Packet *p);
 

	
 
	/**
 
	 * Client wants to connect to a Server.
 
	 *
 
	 *  uint8   Game Coordinator protocol version.
 
	 *  string  Invite code of the Server to join.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_CLIENT_CONNECT(Packet *p);
 

	
 
	/**
 
	 * Game Coordinator informs the Client under what token it will start the
 
	 * attempt to connect the Server and Client together.
 
	 *
 
	 *  string  Token to track the current connect request.
 
	 *  string  Invite code of the Server to join.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_GC_CONNECTING(Packet *p);
 

	
 
	/**
 
	 * Client or Server failed to connect to the remote side.
 
	 *
 
	 *  uint8   Game Coordinator protocol version.
 
	 *  string  Token to track the current connect request.
 
	 *  uint8   Tracking number to track current connect request.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_SERCLI_CONNECT_FAILED(Packet *p);
 

	
 
	/**
 
	 * Game Coordinator informs the Client that it failed to find a way to
 
	 * connect the Client to the Server. Any open connections for this token
 
	 * should be closed now.
 
	 *
 
	 *  string  Token to track the current connect request.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_GC_CONNECT_FAILED(Packet *p);
 

	
 
	/**
 
	 * Client informs the Game Coordinator the connection with the Server is
 
	 * established. The Client will disconnect from the Game Coordinator next.
 
	 *
 
	 *  uint8   Game Coordinator protocol version.
 
	 *  string  Token to track the current connect request.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_CLIENT_CONNECTED(Packet *p);
 

	
 
	/**
 
	 * Game Coordinator requests that the Client makes a direct connection to
 
	 * the indicated peer, which is a Server.
 
	 *
 
	 *  string  Token to track the current connect request.
 
	 *  uint8   Tracking number to track current connect request.
 
	 *  string  Hostname of the peer.
 
	 *  uint16  Port of the peer.
 
	 *
 
	 * @param p The packet that was just received.
 
	 * @return True upon success, otherwise false.
 
	 */
 
	virtual bool Receive_GC_DIRECT_CONNECT(Packet *p);
 

	
 
	bool HandlePacket(Packet *p);
 
public:
 
	/**
 
	 * Create a new cs socket handler for a given cs.
 
	 * @param s The socket we are connected with.
 
	 */
src/network/network.cpp
Show inline comments
 
@@ -586,15 +586,19 @@ void NetworkClose(bool close_admins)
 
			cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
		}
 
		ServerNetworkGameSocketHandler::CloseListeners();
 
		ServerNetworkAdminSocketHandler::CloseListeners();
 

	
 
		_network_coordinator_client.CloseConnection();
 
	} else if (MyClient::my_client != nullptr) {
 
		MyClient::SendQuit();
 
		MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
	} else {
 
		if (MyClient::my_client != nullptr) {
 
			MyClient::SendQuit();
 
			MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
		}
 

	
 
		_network_coordinator_client.CloseAllTokens();
 
	}
 

	
 
	TCPConnecter::KillAll();
 

	
 
	_networking = false;
 
	_network_server = false;
src/network/network_coordinator.cpp
Show inline comments
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 
@@ -24,19 +23,47 @@
 

	
 
#include "../safeguards.h"
 

	
 
static const auto NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES = std::chrono::seconds(30); ///< How many time between updates the server sends to the Game Coordinator.
 
ClientNetworkCoordinatorSocketHandler _network_coordinator_client; ///< The connection to the Game Coordinator.
 
ConnectionType _network_server_connection_type = CONNECTION_TYPE_UNKNOWN; ///< What type of connection the Game Coordinator detected we are on.
 
std::string _network_server_invite_code = ""; ///< Our invite code as indicated by the Game Coordinator.
 

	
 
/** Connect to a game server by IP:port. */
 
class NetworkDirectConnecter : public TCPConnecter {
 
private:
 
	std::string token;     ///< Token of this connection.
 
	uint8 tracking_number; ///< Tracking number of this connection.
 

	
 
public:
 
	/**
 
	 * Try to establish a direct (hostname:port based) connection.
 
	 * @param hostname The hostname of the server.
 
	 * @param port The port of the server.
 
	 * @param token The token as given by the Game Coordinator to track this connection attempt.
 
	 * @param tracking_number The tracking number as given by the Game Coordinator to track this connection attempt.
 
	 */
 
	NetworkDirectConnecter(const std::string &hostname, uint16 port, const std::string &token, uint8 tracking_number) : TCPConnecter(hostname, port), token(token), tracking_number(tracking_number) {}
 

	
 
	void OnFailure() override
 
	{
 
		_network_coordinator_client.ConnectFailure(this->token, this->tracking_number);
 
	}
 

	
 
	void OnConnect(SOCKET s) override
 
	{
 
		_network_coordinator_client.ConnectSuccess(this->token, s);
 
	}
 
};
 

	
 
/** Connect to the Game Coordinator server. */
 
class NetworkCoordinatorConnecter : TCPConnecter {
 
public:
 
	/**
 
	 * Initiate the connecting.
 
	 * @param address The address of the Game Coordinator server.
 
	 * @param connection_string The address of the Game Coordinator server.
 
	 */
 
	NetworkCoordinatorConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_COORDINATOR_SERVER_PORT) {}
 

	
 
	void OnFailure() override
 
	{
 
		_network_coordinator_client.connecting = false;
 
@@ -70,30 +97,53 @@ bool ClientNetworkCoordinatorSocketHandl
 
			/* To prevent that we constantly try to reconnect, switch to private game. */
 
			_settings_client.network.server_advertise = false;
 

	
 
			this->CloseConnection();
 
			return false;
 

	
 
		case NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE: {
 
			/* Find the connecter based on the invite code. */
 
			auto connecter_it = this->connecter_pre.find(detail);
 
			if (connecter_it == this->connecter_pre.end()) return true;
 
			this->connecter_pre.erase(connecter_it);
 

	
 
			/* Mark the server as offline. */
 
			NetworkGameList *item = NetworkGameListAddItem(detail);
 
			item->online = false;
 

	
 
			UpdateNetworkGameWindow();
 
			return true;
 
		}
 

	
 
		default:
 
			Debug(net, 0, "Invalid error type {} received from Game Coordinator", error);
 
			this->CloseConnection();
 
			return false;
 
	}
 
}
 

	
 
bool ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p)
 
{
 
	/* Schedule sending an update. */
 
	this->next_update = std::chrono::steady_clock::now();
 

	
 
	_settings_client.network.server_invite_code = p->Recv_string(NETWORK_INVITE_CODE_LENGTH);
 
	_settings_client.network.server_invite_code_secret = p->Recv_string(NETWORK_INVITE_CODE_SECRET_LENGTH);
 
	_network_server_connection_type = (ConnectionType)p->Recv_uint8();
 

	
 
	if (_network_server_connection_type == CONNECTION_TYPE_ISOLATED) {
 
		ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_ISOLATED, STR_NETWORK_ERROR_COORDINATOR_ISOLATED_DETAIL, WL_ERROR);
 
	}
 

	
 
	/* Users can change the invite code in the settings, but this has no effect
 
	 * on the invite code as assigned by the server. So
 
	 * _network_server_invite_code contains the current invite code,
 
	 * and _settings_client.network.server_invite_code contains the one we will
 
	 * attempt to re-use when registering again. */
 
	_network_server_invite_code = _settings_client.network.server_invite_code;
 

	
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	if (_network_dedicated) {
 
		std::string connection_type;
 
		switch (_network_server_connection_type) {
 
			case CONNECTION_TYPE_ISOLATED: connection_type = "Remote players can't connect"; break;
 
@@ -104,13 +154,16 @@ bool ClientNetworkCoordinatorSocketHandl
 
		}
 

	
 
		Debug(net, 3, "----------------------------------------");
 
		Debug(net, 3, "Your server is now registered with the Game Coordinator:");
 
		Debug(net, 3, "  Game type:       Public");
 
		Debug(net, 3, "  Connection type: {}", connection_type);
 
		Debug(net, 3, "  Invite code:     {}", _network_server_invite_code);
 
		Debug(net, 3, "----------------------------------------");
 
	} else {
 
		Debug(net, 3, "Game Coordinator registered our server with invite code '{}'", _network_server_invite_code);
 
	}
 

	
 
	return true;
 
}
 

	
 
bool ClientNetworkCoordinatorSocketHandler::Receive_GC_LISTING(Packet *p)
 
@@ -127,13 +180,13 @@ bool ClientNetworkCoordinatorSocketHandl
 
		std::string connection_string = p->Recv_string(NETWORK_HOSTNAME_PORT_LENGTH);
 

	
 
		/* Read the NetworkGameInfo from the packet. */
 
		NetworkGameInfo ngi = {};
 
		DeserializeNetworkGameInfo(p, &ngi);
 

	
 
		/* Now we know the join-key, we can add it to our list. */
 
		/* Now we know the connection string, we can add it to our list. */
 
		NetworkGameList *item = NetworkGameListAddItem(connection_string);
 

	
 
		/* Clear any existing GRFConfig chain. */
 
		ClearGRFConfigList(&item->info.grfconfig);
 
		/* Copy the new NetworkGameInfo info. */
 
		item->info = ngi;
 
@@ -146,12 +199,64 @@ bool ClientNetworkCoordinatorSocketHandl
 
	}
 

	
 
	UpdateNetworkGameWindow();
 
	return true;
 
}
 

	
 
bool ClientNetworkCoordinatorSocketHandler::Receive_GC_CONNECTING(Packet *p)
 
{
 
	std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
 
	std::string invite_code = p->Recv_string(NETWORK_INVITE_CODE_LENGTH);
 

	
 
	/* Find the connecter based on the invite code. */
 
	auto connecter_it = this->connecter_pre.find(invite_code);
 
	if (connecter_it == this->connecter_pre.end()) {
 
		this->CloseConnection();
 
		return false;
 
	}
 

	
 
	/* Now store it based on the token. */
 
	this->connecter[token] = connecter_it->second;
 
	this->connecter_pre.erase(connecter_it);
 

	
 
	return true;
 
}
 

	
 
bool ClientNetworkCoordinatorSocketHandler::Receive_GC_CONNECT_FAILED(Packet *p)
 
{
 
	std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
 

	
 
	auto connecter_it = this->connecter.find(token);
 
	if (connecter_it != this->connecter.end()) {
 
		connecter_it->second->SetFailure();
 
		this->connecter.erase(connecter_it);
 
	}
 

	
 
	/* Close all remaining connections. */
 
	this->CloseToken(token);
 

	
 
	return true;
 
}
 

	
 
bool ClientNetworkCoordinatorSocketHandler::Receive_GC_DIRECT_CONNECT(Packet *p)
 
{
 
	std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
 
	uint8 tracking_number = p->Recv_uint8();
 
	std::string hostname = p->Recv_string(NETWORK_HOSTNAME_LENGTH);
 
	uint16 port = p->Recv_uint16();
 

	
 
	/* Ensure all other pending connection attempts are killed. */
 
	if (this->game_connecter != nullptr) {
 
		this->game_connecter->Kill();
 
		this->game_connecter = nullptr;
 
	}
 

	
 
	this->game_connecter = new NetworkDirectConnecter(hostname, port, token, tracking_number);
 
	return true;
 
}
 

	
 
void ClientNetworkCoordinatorSocketHandler::Connect()
 
{
 
	/* We are either already connected or are trying to connect. */
 
	if (this->sock != INVALID_SOCKET || this->connecting) return;
 

	
 
	this->Reopen();
 
@@ -169,19 +274,21 @@ NetworkRecvStatus ClientNetworkCoordinat
 
	this->CloseSocket();
 
	this->connecting = false;
 

	
 
	_network_server_connection_type = CONNECTION_TYPE_UNKNOWN;
 
	this->next_update = {};
 

	
 
	this->CloseAllTokens();
 

	
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
/**
 
 * Register our server to receive our join-key.
 
 * Register our server to receive our invite code.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::Register()
 
{
 
	_network_server_connection_type = CONNECTION_TYPE_UNKNOWN;
 
	this->next_update = {};
 

	
 
@@ -190,12 +297,19 @@ void ClientNetworkCoordinatorSocketHandl
 
	this->Connect();
 

	
 
	Packet *p = new Packet(PACKET_COORDINATOR_SERVER_REGISTER);
 
	p->Send_uint8(NETWORK_COORDINATOR_VERSION);
 
	p->Send_uint8(SERVER_GAME_TYPE_PUBLIC);
 
	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("");
 
		p->Send_string("");
 
	} else {
 
		p->Send_string(_settings_client.network.server_invite_code);
 
		p->Send_string(_settings_client.network.server_invite_code_secret);
 
	}
 

	
 
	this->SendPacket(p);
 
}
 

	
 
/**
 
 * Send an update of our server status to the Game Coordinator.
 
@@ -227,12 +341,129 @@ void ClientNetworkCoordinatorSocketHandl
 
	p->Send_string(_openttd_revision);
 

	
 
	this->SendPacket(p);
 
}
 

	
 
/**
 
 * Join a server based on an invite code.
 
 * @param invite_code The invite code of the server to connect to.
 
 * @param connecter The connecter of the request.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter)
 
{
 
	assert(StrStartsWith(invite_code, "+"));
 

	
 
	if (this->connecter_pre.find(invite_code) != this->connecter_pre.end()) {
 
		/* If someone is hammering the refresh key, one can sent out two
 
		 * requests for the same invite code. There isn't really a great way
 
		 * of handling this, so just ignore this request. */
 
		connecter->SetFailure();
 
		return;
 
	}
 

	
 
	/* Initially we store based on invite code; on first reply we know the
 
	 * token, and will start using that key instead. */
 
	this->connecter_pre[invite_code] = connecter;
 

	
 
	this->Connect();
 

	
 
	Packet *p = new Packet(PACKET_COORDINATOR_CLIENT_CONNECT);
 
	p->Send_uint8(NETWORK_COORDINATOR_VERSION);
 
	p->Send_string(invite_code);
 

	
 
	this->SendPacket(p);
 
}
 

	
 
/**
 
 * Callback from a Connecter to let the Game Coordinator know the connection failed.
 
 * @param token Token of the connecter that failed.
 
 * @param tracking_number Tracking number of the connecter that failed.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::ConnectFailure(const std::string &token, uint8 tracking_number)
 
{
 
	/* Connecter will destroy itself. */
 
	this->game_connecter = nullptr;
 

	
 
	Packet *p = new Packet(PACKET_COORDINATOR_SERCLI_CONNECT_FAILED);
 
	p->Send_uint8(NETWORK_COORDINATOR_VERSION);
 
	p->Send_string(token);
 
	p->Send_uint8(tracking_number);
 

	
 
	this->SendPacket(p);
 

	
 
	auto connecter_it = this->connecter.find(token);
 
	assert(connecter_it != this->connecter.end());
 

	
 
	connecter_it->second->SetFailure();
 
	this->connecter.erase(connecter_it);
 
}
 

	
 
/**
 
 * Callback from a Connecter to let the Game Coordinator know the connection
 
 * to the game server is established.
 
 * @param token Token of the connecter that succeeded.
 
 * @param sock The socket that the connecter can now use.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::ConnectSuccess(const std::string &token, SOCKET sock)
 
{
 
	/* Connecter will destroy itself. */
 
	this->game_connecter = nullptr;
 

	
 
	assert(!_network_server);
 

	
 
	Packet *p = new Packet(PACKET_COORDINATOR_CLIENT_CONNECTED);
 
	p->Send_uint8(NETWORK_COORDINATOR_VERSION);
 
	p->Send_string(token);
 
	this->SendPacket(p);
 

	
 
	auto connecter_it = this->connecter.find(token);
 
	assert(connecter_it != this->connecter.end());
 

	
 
	connecter_it->second->SetConnected(sock);
 
	this->connecter.erase(connecter_it);
 

	
 
	/* Close all remaining connections. */
 
	this->CloseToken(token);
 
}
 

	
 
/**
 
 * Close everything related to this connection token.
 
 * @param token The connection token to close.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::CloseToken(const std::string &token)
 
{
 
	/* Ensure all other pending connection attempts are also killed. */
 
	if (this->game_connecter != nullptr) {
 
		this->game_connecter->Kill();
 
		this->game_connecter = nullptr;
 
	}
 
}
 

	
 
/**
 
 * Close all pending connection tokens.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::CloseAllTokens()
 
{
 
	/* Ensure all other pending connection attempts are also killed. */
 
	if (this->game_connecter != nullptr) {
 
		this->game_connecter->Kill();
 
		this->game_connecter = nullptr;
 
	}
 

	
 
	/* Mark any pending connecters as failed. */
 
	for (auto &[token, it] : this->connecter) {
 
		it->SetFailure();
 
	}
 
	for (auto &[invite_code, it] : this->connecter_pre) {
 
		it->SetFailure();
 
	}
 
	this->connecter.clear();
 
	this->connecter_pre.clear();
 
}
 

	
 
/**
 
 * Check whether we received/can send some data from/to the Game Coordinator server and
 
 * when that's the case handle it appropriately.
 
 */
 
void ClientNetworkCoordinatorSocketHandler::SendReceive()
 
{
 
	/* Private games are not listed via the Game Coordinator. */
src/network/network_coordinator.h
Show inline comments
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 
@@ -9,12 +8,13 @@
 
/** @file network_coordinator.h Part of the network protocol handling Game Coordinator requests. */
 

	
 
#ifndef NETWORK_COORDINATOR_H
 
#define NETWORK_COORDINATOR_H
 

	
 
#include "core/tcp_coordinator.h"
 
#include <map>
 

	
 
/**
 
 * Game Coordinator communication.
 
 *
 
 * For servers:
 
 *  - Server sends SERVER_REGISTER.
 
@@ -22,23 +22,38 @@
 
 *  - Game Coordinator sends GC_REGISTER_ACK with type of connection.
 
 *  - Server sends every 30 seconds SERVER_UPDATE.
 
 *
 
 * For clients (listing):
 
 *  - Client sends CLIENT_LISTING.
 
 *  - Game Coordinator returns the full list of public servers via GC_LISTING (multiple packets).
 
 *
 
 * For clients (connecting):
 
 *  - Client sends CLIENT_CONNECT.
 
 *  - Game Coordinator checks what type of connections the servers supports:
 
 *    1) Direct connect?
 
 *        - Send the client a GC_CONNECT with the peer address.
 
 *        - a) Client connects, client sends CLIENT_CONNECTED to Game Coordinator.
 
 *        - b) Client connect fails, client sends CLIENT_CONNECT_FAILED to Game Coordinator.
 
 *  - If all fails, Game Coordinator sends GC_CONNECT_FAILED to indicate no connection is possible.
 
 */
 

	
 
/** Class for handling the client side of the Game Coordinator connection. */
 
class ClientNetworkCoordinatorSocketHandler : public NetworkCoordinatorSocketHandler {
 
private:
 
	std::chrono::steady_clock::time_point next_update; ///< When to send the next update (if server and public).
 
	std::map<std::string, TCPServerConnecter *> connecter; ///< Based on tokens, the current connecters that are pending.
 
	std::map<std::string, TCPServerConnecter *> connecter_pre; ///< Based on invite codes, the current connecters that are pending.
 
	TCPConnecter *game_connecter = nullptr; ///< Pending connecter to the game server.
 

	
 
protected:
 
	bool Receive_GC_ERROR(Packet *p) override;
 
	bool Receive_GC_REGISTER_ACK(Packet *p) override;
 
	bool Receive_GC_LISTING(Packet *p) override;
 
	bool Receive_GC_CONNECTING(Packet *p) override;
 
	bool Receive_GC_CONNECT_FAILED(Packet *p) override;
 
	bool Receive_GC_DIRECT_CONNECT(Packet *p) override;
 

	
 
public:
 
	/** The idle timeout; when to close the connection because it's idle. */
 
	static constexpr std::chrono::seconds IDLE_TIMEOUT = std::chrono::seconds(60);
 

	
 
	std::chrono::steady_clock::time_point last_activity;  ///< The last time there was network activity.
 
@@ -46,16 +61,23 @@ public:
 

	
 
	ClientNetworkCoordinatorSocketHandler() : connecting(false) {}
 

	
 
	NetworkRecvStatus CloseConnection(bool error = true) override;
 
	void SendReceive();
 

	
 
	void ConnectFailure(const std::string &token, uint8 tracking_number);
 
	void ConnectSuccess(const std::string &token, SOCKET sock);
 

	
 
	void Connect();
 
	void CloseToken(const std::string &token);
 
	void CloseAllTokens();
 

	
 
	void Register();
 
	void SendServerUpdate();
 
	void GetListing();
 

	
 
	void ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter);
 
};
 

	
 
extern ClientNetworkCoordinatorSocketHandler _network_coordinator_client;
 

	
 
#endif /* NETWORK_COORDINATOR_H */
src/network/network_gui.cpp
Show inline comments
 
@@ -748,13 +748,13 @@ public:
 
				break;
 

	
 
			case WID_NG_ADD: // Add a server
 
				SetDParamStr(0, _settings_client.network.connect_to_ip);
 
				ShowQueryString(
 
					STR_JUST_RAW_STRING,
 
					STR_NETWORK_SERVER_LIST_ENTER_IP,
 
					STR_NETWORK_SERVER_LIST_ENTER_SERVER_ADDRESS,
 
					NETWORK_HOSTNAME_PORT_LENGTH,  // maximum number of characters including '\0'
 
					this, CS_ALPHANUMERAL, QSF_ACCEPT_UNCHANGED);
 
				break;
 

	
 
			case WID_NG_START: // Start server
 
				ShowNetworkStartServerWindow();
 
@@ -1630,12 +1630,17 @@ static const NWidgetPart _nested_client_
 
				NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY, STR_NULL),
 
					NWidget(NWID_SPACER), SetMinimalSize(10, 0), SetFill(1, 0), SetResize(1, 0),
 
					NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_CL_SERVER_VISIBILITY), SetDataTip(STR_BLACK_STRING, STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP),
 
				EndContainer(),
 
				NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER_INVITE_CODE, STR_NULL),
 
					NWidget(NWID_SPACER), SetMinimalSize(10, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_SERVER_INVITE_CODE), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetDataTip(STR_BLACK_RAW_STRING, STR_NETWORK_CLIENT_LIST_SERVER_INVITE_CODE_TOOLTIP), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
 
				EndContainer(),
 
				NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE, STR_NULL),
 
					NWidget(NWID_SPACER), SetMinimalSize(10, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_SERVER_CONNECTION_TYPE), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE_TOOLTIP), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
 
				EndContainer(),
 
			EndContainer(),
 
		EndContainer(),
 
@@ -2068,12 +2073,18 @@ public:
 
				break;
 

	
 
			case WID_CL_SERVER_VISIBILITY:
 
				SetDParam(0, _server_visibility_dropdown[_settings_client.network.server_advertise]);
 
				break;
 

	
 
			case WID_CL_SERVER_INVITE_CODE: {
 
				static std::string empty = {};
 
				SetDParamStr(0, _network_server_connection_type == CONNECTION_TYPE_UNKNOWN ? empty : _network_server_invite_code);
 
				break;
 
			}
 

	
 
			case WID_CL_SERVER_CONNECTION_TYPE:
 
				SetDParam(0, STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE_UNKNOWN + _network_server_connection_type);
 
				break;
 

	
 
			case WID_CL_CLIENT_NAME:
 
				SetDParamStr(0, _settings_client.network.client_name);
src/network/network_internal.h
Show inline comments
 
@@ -81,12 +81,13 @@ extern bool _network_first_time;
 
/* Vars needed for the join-GUI */
 
extern NetworkJoinStatus _network_join_status;
 
extern uint8 _network_join_waiting;
 
extern uint32 _network_join_bytes;
 
extern uint32 _network_join_bytes_total;
 
extern ConnectionType _network_server_connection_type;
 
extern std::string _network_server_invite_code;
 

	
 
extern uint8 _network_reconnect;
 

	
 
extern CompanyMask _network_company_passworded;
 

	
 
void NetworkQueryServer(const std::string &connection_string);
src/settings_type.h
Show inline comments
 
@@ -263,12 +263,14 @@ struct NetworkSettings {
 
	uint16      max_password_time;                        ///< maximum amount of time, in game ticks, a client may take to enter the password
 
	uint16      max_lag_time;                             ///< maximum amount of time, in game ticks, a client may be lagging behind the server
 
	bool        pause_on_join;                            ///< pause the game when people join
 
	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
 
	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
 
	std::string server_password;                          ///< password for joining this server
 
	std::string rcon_password;                            ///< password for rconsole (server side)
 
	std::string admin_password;                           ///< password for the admin network
 
	bool        server_advertise;                         ///< Advertise the server to the game coordinator.
 
	std::string client_name;                              ///< name of the player (as client)
src/table/settings/network_secrets_settings.ini
Show inline comments
 
@@ -71,6 +71,20 @@ def      = nullptr
 
[SDTC_SSTR]
 
var      = network.network_id
 
type     = SLE_STR
 
length   = NETWORK_SERVER_ID_LENGTH
 
flags    = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
 
def      = nullptr
 

	
 
[SDTC_SSTR]
 
var      = network.server_invite_code
 
type     = SLE_STR
 
length   = NETWORK_INVITE_CODE_LENGTH
 
flags    = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
 
def      = nullptr
 

	
 
[SDTC_SSTR]
 
var      = network.server_invite_code_secret
 
type     = SLE_STR
 
length   = NETWORK_INVITE_CODE_SECRET_LENGTH
 
flags    = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
 
def      = nullptr
src/widgets/network_widget.h
Show inline comments
 
@@ -98,12 +98,13 @@ enum NetworkLobbyWidgets {
 
enum ClientListWidgets {
 
	WID_CL_PANEL,                      ///< Panel of the window.
 
	WID_CL_SERVER_SELECTOR,            ///< Selector to hide the server frame.
 
	WID_CL_SERVER_NAME,                ///< Server name.
 
	WID_CL_SERVER_NAME_EDIT,           ///< Edit button for server name.
 
	WID_CL_SERVER_VISIBILITY,          ///< Server visibility.
 
	WID_CL_SERVER_INVITE_CODE,         ///< Invite code for this server.
 
	WID_CL_SERVER_CONNECTION_TYPE,     ///< The type of connection the Game Coordinator detected for this server.
 
	WID_CL_CLIENT_NAME,                ///< Client name.
 
	WID_CL_CLIENT_NAME_EDIT,           ///< Edit button for client name.
 
	WID_CL_MATRIX,                     ///< Company/client list.
 
	WID_CL_SCROLLBAR,                  ///< Scrollbar for company/client list.
 
	WID_CL_COMPANY_JOIN,               ///< Used for QueryWindow when a company has a password.
0 comments (0 inline, 0 general)