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

Feature: servers can now set a Message Of The Day #9469

Closed
wants to merge 5 commits into from
Closed
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
35 changes: 9 additions & 26 deletions src/lang/english.txt
Expand Up @@ -2068,6 +2068,8 @@ STR_NETWORK_START_SERVER_CAPTION :{WHITE}Start ne

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
STR_NETWORK_START_SERVER_MOTD :{BLACK}Message Of The Day:
STR_NETWORK_START_SERVER_MOTD_TOOLTIP :{BLACK}When clients join they are shown this Message Of The Day
STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Set password
STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protect your game with a password if you don't want it to be publicly accessible

Expand All @@ -2084,31 +2086,6 @@ STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Other pl

STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE :{BLACK}Enter a name for the network game

# Network game lobby
STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Multiplayer game lobby

STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Preparing to join: {ORANGE}{RAW_STRING}
STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}A list of all companies currently in this game. You can either join one or start a new one if there is a free company slot

STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}COMPANY INFO
STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Company name: {WHITE}{RAW_STRING}
STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}Inauguration: {WHITE}{NUM}
STR_NETWORK_GAME_LOBBY_VALUE :{SILVER}Company value: {WHITE}{CURRENCY_LONG}
STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE :{SILVER}Current balance: {WHITE}{CURRENCY_LONG}
STR_NETWORK_GAME_LOBBY_LAST_YEARS_INCOME :{SILVER}Last year's income: {WHITE}{CURRENCY_LONG}
STR_NETWORK_GAME_LOBBY_PERFORMANCE :{SILVER}Performance: {WHITE}{NUM}

STR_NETWORK_GAME_LOBBY_VEHICLES :{SILVER}Vehicles: {WHITE}{NUM} {TRAIN}, {NUM} {LORRY}, {NUM} {BUS}, {NUM} {SHIP}, {NUM} {PLANE}
STR_NETWORK_GAME_LOBBY_STATIONS :{SILVER}Stations: {WHITE}{NUM} {TRAIN}, {NUM} {LORRY}, {NUM} {BUS}, {NUM} {SHIP}, {NUM} {PLANE}
STR_NETWORK_GAME_LOBBY_PLAYERS :{SILVER}Players: {WHITE}{RAW_STRING}

STR_NETWORK_GAME_LOBBY_NEW_COMPANY :{BLACK}New company
STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company
STR_NETWORK_GAME_LOBBY_SPECTATE_GAME :{BLACK}Spectate game
STR_NETWORK_GAME_LOBBY_SPECTATE_GAME_TOOLTIP :{BLACK}Watch the game as a spectator
STR_NETWORK_GAME_LOBBY_JOIN_COMPANY :{BLACK}Join company
STR_NETWORK_GAME_LOBBY_JOIN_COMPANY_TOOLTIP :{BLACK}Help manage this company

# Network connecting window
STR_NETWORK_CONNECTING_CAPTION :{WHITE}Connecting...

Expand All @@ -2132,11 +2109,16 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disconne
STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server is protected. Enter password
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company is protected. Enter password

STR_NETWORK_MOTD_CAPTION :{WHITE}Welcome to {RAW_STRING}!
STR_NETWORK_MOTD_TEXT :{BLACK}{RAW_STRING}
STR_NETWORK_MOTD_IF_SPECTATOR :{BLACK}To start playing, join a (new) company via the "Online Players" window.
STR_NETWORK_MOTD_CLOSE :{BLACK}Close

# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online players

# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multiplayer
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Online Players
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}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
Expand Down Expand Up @@ -2236,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT :{WHITE}Connecti
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}A protocol error was detected and the connection was closed
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Your player name has not been set. The name can be set at the top of the Multiplayer window
STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Your server name has not been set. The name can be set at the top of the Multiplayer window
STR_NETWORK_ERROR_BAD_SERVER_MOTD :{WHITE}The Message Of The Day has not been set. The message can be set in the Start Server window
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}The revision of this client does not match the server's revision
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong password
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full
Expand Down
1 change: 1 addition & 0 deletions src/network/core/config.h
Expand Up @@ -53,6 +53,7 @@ static const byte NETWORK_COMPANY_INFO_VERSION = 6; ///< What
static const byte NETWORK_COORDINATOR_VERSION = 5; ///< 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_MOTD_LENGTH = 1000; ///< The maximum length of the server Message Of The Day, 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)
Expand Down
2 changes: 1 addition & 1 deletion src/network/core/tcp_game.h
Expand Up @@ -38,7 +38,7 @@ enum PacketGameType {
PACKET_CLIENT_JOIN, ///< The client telling the server it wants to join.
PACKET_SERVER_ERROR, ///< Server sending an error message to the client.

/* Packets used for the pre-game lobby. */
/* Packets used for the pre-game lobby (unused, but remain for backward/forward compatibility). */
PACKET_CLIENT_COMPANY_INFO, ///< Request information about all companies.
PACKET_SERVER_COMPANY_INFO, ///< Information about a single company.

Expand Down
57 changes: 20 additions & 37 deletions src/network/network.cpp
Expand Up @@ -657,42 +657,6 @@ void NetworkQueryServer(const std::string &connection_string)
new TCPQueryConnecter(connection_string);
}

/** Non blocking connection to query servers for their game and company info. */
class TCPLobbyQueryConnecter : TCPServerConnecter {
private:
std::string connection_string;

public:
TCPLobbyQueryConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}

void OnFailure() override
{
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);

ShowErrorMessage(STR_NETWORK_ERROR_NOCONNECTION, INVALID_STRING_ID, WL_ERROR);
}

void OnConnect(SOCKET s) override
{
_networking = true;
new ClientNetworkGameSocketHandler(s, this->connection_string);
MyClient::SendInformationQuery(true);
}
};

/**
* Query a server to fetch the game-info for the lobby.
* @param connection_string the address to query.
*/
void NetworkQueryLobbyServer(const std::string &connection_string)
{
if (!_network_available) return;

NetworkInitialize();

new TCPLobbyQueryConnecter(connection_string);
}

/**
* Validates an address entered as a string and adds the server to
* the list. If you use this function, the games will be marked
Expand Down Expand Up @@ -853,7 +817,7 @@ static void NetworkInitGameInfo()
* Trim the given server name in place, i.e. remove leading and trailing spaces.
* After the trim check whether the server name is not empty.
* When the server name is empty a GUI error message is shown telling the
* user to set the servername and this function returns false.
* user to set the server name and this function returns false.
*
* @param server_name The server name to validate. It will be trimmed of leading
* and trailing spaces.
Expand All @@ -868,6 +832,25 @@ bool NetworkValidateServerName(std::string &server_name)
return false;
}

/**
* Trim the given server MOTD in place, i.e. remove leading and trailing spaces.
* After the trim check whether the server MOTD is not empty.
* When the server MOTD is empty a GUI error message is shown telling the
* user to set the server MOTD and this function returns false.
*
* @param server_name The server MOTD to validate. It will be trimmed of leading
* and trailing spaces.
* @return True iff the server MOTD is valid.
*/
bool NetworkValidateServerMessageOfTheDay(std::string &server_motd)
{
StrTrimInPlace(server_motd);
if (!server_motd.empty()) return true;

ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_MOTD, INVALID_STRING_ID, WL_ERROR);
return false;
}

/**
* Check whether the client and server name are set, for a dedicated server and if not set them to some default
* value and tell the user to change this as soon as possible.
Expand Down
59 changes: 19 additions & 40 deletions src/network/network_client.cpp
Expand Up @@ -28,6 +28,7 @@
#include "network_base.h"
#include "network_client.h"
#include "network_gamelist.h"
#include "network_gui.h"
#include "../core/backup_type.hpp"
#include "../thread.h"

Expand Down Expand Up @@ -174,6 +175,9 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvSta
CSleep(3 * MILLISECONDS_PER_TICK);
}

/* Reset MOTD so we show it next time we join the server. */
_network_server_motd = "";

delete this;

return status;
Expand Down Expand Up @@ -314,6 +318,10 @@ static std::string _password_server_id;

/** Maximum number of companies of the currently joined server. */
static uint8 _network_server_max_companies;
/** The current name of the server you are on. */
std::string _network_server_name;
/** The current Message Of The Day of the server you are on. */
std::string _network_server_motd;

/** Information about the game to join to. */
NetworkJoinInfo _network_join;
Expand Down Expand Up @@ -567,11 +575,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe
{
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_GAME_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;

NetworkGameList *item = GetLobbyGameInfo();
if (item == nullptr) {
/* This is not the lobby, so add it to the game list. */
item = NetworkGameListAddItem(this->connection_string);
}
NetworkGameList *item = NetworkGameListAddItem(this->connection_string);

/* Clear any existing GRFConfig chain. */
ClearGRFConfigList(&item->info.grfconfig);
Expand All @@ -582,9 +586,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe
/* Ensure we consider the server online. */
item->online = true;

/* It could be either window, but only one is open, so redraw both. */
UpdateNetworkGameWindow();
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);

/* We will receive company info next, so keep connection open. */
if (this->status == STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_OKAY;
Expand All @@ -595,39 +597,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Pa
{
if (this->status != STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;

byte company_info_version = p->Recv_uint8();

if (!this->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
/* We have received all data... (there are no more packets coming) */
if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY;

CompanyID current = (Owner)p->Recv_uint8();
if (current >= MAX_COMPANIES) return NETWORK_RECV_STATUS_CLOSE_QUERY;

NetworkCompanyInfo *company_info = GetLobbyCompanyInfo(current);
if (company_info == nullptr) return NETWORK_RECV_STATUS_CLOSE_QUERY;

company_info->company_name = p->Recv_string(NETWORK_COMPANY_NAME_LENGTH);
company_info->inaugurated_year = p->Recv_uint32();
company_info->company_value = p->Recv_uint64();
company_info->money = p->Recv_uint64();
company_info->income = p->Recv_uint64();
company_info->performance = p->Recv_uint16();
company_info->use_password = p->Recv_bool();
for (uint i = 0; i < NETWORK_VEH_END; i++) {
company_info->num_vehicle[i] = p->Recv_uint16();
}
for (uint i = 0; i < NETWORK_VEH_END; i++) {
company_info->num_station[i] = p->Recv_uint16();
}
company_info->ai = p->Recv_bool();

company_info->clients = p->Recv_string(NETWORK_CLIENTS_LENGTH);

SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);

return NETWORK_RECV_STATUS_OKAY;
}
/* Unused, but this packet is part of the "this will never change" packet group. */

return NETWORK_RECV_STATUS_CLOSE_QUERY;
}
Expand Down Expand Up @@ -940,6 +910,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
SetLocalCompany(_network_join.company);
}

ShowClientList();

return NETWORK_RECV_STATUS_OKAY;
}

Expand Down Expand Up @@ -1187,6 +1159,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(P
if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;

_network_server_max_companies = p->Recv_uint8();
_network_server_name = p->Recv_string(NETWORK_NAME_LENGTH);
std::string new_motd = p->Recv_string(NETWORK_MOTD_LENGTH);

if (new_motd != _network_server_motd) {
_network_server_motd = new_motd;
ShowNetworkMessageOfTheDay();
}

return NETWORK_RECV_STATUS_OKAY;
}
Expand Down
1 change: 1 addition & 0 deletions src/network/network_func.h
Expand Up @@ -38,6 +38,7 @@ bool NetworkIsValidClientName(const std::string_view client_name);
bool NetworkValidateOurClientName();
bool NetworkValidateClientName(std::string &client_name);
bool NetworkValidateServerName(std::string &server_name);
bool NetworkValidateServerMessageOfTheDay(std::string &server_motd);
void NetworkUpdateClientName(const std::string &client_name);
void NetworkUpdateServerGameType();
bool NetworkCompanyHasClients(CompanyID company);
Expand Down