Changeset - r25386:b146841c350c
[Not reviewed]
master
0 8 0
rubidium42 - 3 years ago 2021-05-05 17:21:12
rubidium@openttd.org
Change: [Network] Update server's NetworkServerGameInfo only when needed

Split the updating in a "static" version that only needs to be called when a new map is loaded or some settings are changed, and a "dynamic" version that updates everything that changes regularly such as the current game date or the number of spectators.
8 files changed with 42 insertions and 13 deletions:
0 comments (0 inline, 0 general)
src/network/core/game_info.cpp
Show inline comments
 
@@ -113,43 +113,50 @@ void CheckGameCompatibility(NetworkGameI
 
{
 
	/* Check if we are allowed on this server based on the revision-check. */
 
	ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision);
 
	ngi.compatible = ngi.version_compatible;
 

	
 
	/* Check if we have all the GRFs on the client-system too. */
 
	for (const GRFConfig *c = ngi.grfconfig; c != nullptr; c = c->next) {
 
		if (c->status == GCS_NOT_FOUND) ngi.compatible = false;
 
	}
 
}
 

	
 
/**
 
 * Get the NetworkServerGameInfo structure with the latest information of the server.
 
 * @return The current NetworkServerGameInfo.
 
 * Fill a NetworkServerGameInfo structure with the static content, or things
 
 * that are so static they can be updated on request from a settings change.
 
 */
 
const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo()
 
void FillStaticNetworkServerGameInfo()
 
{
 
	_network_game_info.use_password   = !StrEmpty(_settings_client.network.server_password);
 
	_network_game_info.start_date     = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
 
	_network_game_info.clients_max    = _settings_client.network.max_clients;
 
	_network_game_info.companies_max  = _settings_client.network.max_companies;
 
	_network_game_info.spectators_max = _settings_client.network.max_spectators;
 
	_network_game_info.map_width      = MapSizeX();
 
	_network_game_info.map_height     = MapSizeY();
 
	_network_game_info.landscape      = _settings_game.game_creation.landscape;
 
	_network_game_info.dedicated      = _network_dedicated;
 
	_network_game_info.grfconfig      = _grfconfig;
 

	
 
	strecpy(_network_game_info.server_name, _settings_client.network.server_name, lastof(_network_game_info.server_name));
 
	strecpy(_network_game_info.server_revision, GetNetworkRevisionString(), lastof(_network_game_info.server_revision));
 
}
 

	
 
/**
 
 * 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. */
 
	_network_game_info.companies_on  = (byte)Company::GetNumItems();
 
	_network_game_info.spectators_on = NetworkSpectatorCount();
 
	_network_game_info.game_date     = _date;
 
	return &_network_game_info;
 
}
 

	
 
/**
 
 * Function that is called for every GRFConfig that is read when receiving
 
 * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
 
 * function must set all appropriate fields. This GRF is later appended to
 
 * the grfconfig list of the NetworkGameInfo.
src/network/core/game_info.h
Show inline comments
 
@@ -85,21 +85,22 @@ struct NetworkServerGameInfo {
 
struct NetworkGameInfo : NetworkServerGameInfo {
 
	bool version_compatible;                        ///< Can we connect to this server or not? (based on server_revision)
 
	bool compatible;                                ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
 
	byte game_info_version;                         ///< Version of the game info
 
};
 

	
 
extern NetworkServerGameInfo _network_game_info;
 

	
 
const char *GetNetworkRevisionString();
 
bool IsNetworkCompatibleVersion(const char *other);
 
void CheckGameCompatibility(NetworkGameInfo &ngi);
 

	
 
void FillStaticNetworkServerGameInfo();
 
const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo();
 

	
 
void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf);
 
void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf);
 

	
 
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info);
 
void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info);
 

	
 
#endif /* NETWORK_CORE_GAME_INFO_H */
src/network/network.cpp
Show inline comments
 
@@ -796,24 +796,25 @@ void NetworkClientJoinGame()
 
	_network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
 
	ShowJoinStatusWindow();
 

	
 
	new TCPClientConnecter(_network_join.address);
 
}
 

	
 
static void NetworkInitGameInfo()
 
{
 
	if (StrEmpty(_settings_client.network.server_name)) {
 
		strecpy(_settings_client.network.server_name, "Unnamed Server", lastof(_settings_client.network.server_name));
 
	}
 

	
 
	FillStaticNetworkServerGameInfo();
 
	/* The server is a client too */
 
	_network_game_info.clients_on = _network_dedicated ? 0 : 1;
 

	
 
	/* There should be always space for the server. */
 
	assert(NetworkClientInfo::CanAllocateItem());
 
	NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER);
 
	ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST;
 

	
 
	strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
 
}
 

	
 
bool NetworkServerStart()
src/network/network_func.h
Show inline comments
 
@@ -59,24 +59,25 @@ void NetworkClientSendChat(NetworkAction
 
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio);
 
bool NetworkCompanyIsPassworded(CompanyID company_id);
 
bool NetworkMaxCompaniesReached();
 
bool NetworkMaxSpectatorsReached();
 
void NetworkPrintClients();
 
void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode);
 

	
 
/*** Commands ran by the server ***/
 
void NetworkServerDailyLoop();
 
void NetworkServerMonthlyLoop();
 
void NetworkServerYearlyLoop();
 
void NetworkServerSendConfigUpdate();
 
void NetworkServerUpdateGameInfo();
 
void NetworkServerShowStatusToConsole();
 
bool NetworkServerStart();
 
void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci);
 
bool NetworkServerChangeClientName(ClientID client_id, const char *new_name);
 

	
 

	
 
void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
 
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string);
 
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data = 0, bool from_admin = false);
 

	
 
void NetworkServerKickClient(ClientID client_id, const char *reason);
 
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason);
src/network/network_server.cpp
Show inline comments
 
@@ -1983,24 +1983,30 @@ void NetworkServerShowStatusToConsole()
 
}
 

	
 
/**
 
 * Send Config Update
 
 */
 
void NetworkServerSendConfigUpdate()
 
{
 
	for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 
		if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
 
	}
 
}
 

	
 
/** Update the server's NetworkServerGameInfo due to changes in settings. */
 
void NetworkServerUpdateGameInfo()
 
{
 
	if (_network_server) FillStaticNetworkServerGameInfo();
 
}
 

	
 
/**
 
 * Tell that a particular company is (not) passworded.
 
 * @param company_id The company that got/removed the password.
 
 * @param passworded Whether the password was received or removed.
 
 */
 
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
 
{
 
	if (NetworkCompanyIsPassworded(company_id) == passworded) return;
 

	
 
	SB(_network_company_passworded, company_id, 1, !!passworded);
 
	SetWindowClassesDirty(WC_COMPANY);
 

	
src/openttd.cpp
Show inline comments
 
@@ -823,53 +823,66 @@ int openttd_main(int argc, char *argv[])
 
void HandleExitGameRequest()
 
{
 
	if (_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) { // do not ask to quit on the main screen
 
		_exit_game = true;
 
	} else if (_settings_client.gui.autosave_on_exit) {
 
		DoExitSave();
 
		_exit_game = true;
 
	} else {
 
		AskExitGame();
 
	}
 
}
 

	
 
/**
 
 * Triggers everything that should be triggered when starting a game.
 
 * @param dedicated_server Whether this is a dedicated server or not.
 
 */
 
static void OnStartGame(bool dedicated_server)
 
{
 
	/* Update the local company for a loaded game. It is either always
 
	 * company #1 (eg 0) or in the case of a dedicated server a spectator */
 
	SetLocalCompany(dedicated_server ? COMPANY_SPECTATOR : COMPANY_FIRST);
 

	
 
	/* Update the static game info to set the values from the new game. */
 
	NetworkServerUpdateGameInfo();
 
	/* Execute the game-start script */
 
	IConsoleCmdExec("exec scripts/game_start.scr 0");
 
}
 

	
 
static void MakeNewGameDone()
 
{
 
	SettingsDisableElrail(_settings_game.vehicle.disable_elrails);
 

	
 
	/* In a dedicated server, the server does not play */
 
	if (!VideoDriver::GetInstance()->HasGUI()) {
 
		SetLocalCompany(COMPANY_SPECTATOR);
 
		OnStartGame(true);
 
		if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
 
		IConsoleCmdExec("exec scripts/game_start.scr 0");
 
		return;
 
	}
 

	
 
	/* Create a single company */
 
	DoStartupNewCompany(false);
 

	
 
	Company *c = Company::Get(COMPANY_FIRST);
 
	c->settings = _settings_client.company;
 

	
 
	/* Overwrite color from settings if needed
 
	 * COLOUR_END corresponds to Random colour */
 
	if (_settings_client.gui.starting_colour != COLOUR_END) {
 
		c->colour = _settings_client.gui.starting_colour;
 
		ResetCompanyLivery(c);
 
		_company_colours[c->index] = (Colours)c->colour;
 
	}
 

	
 
	IConsoleCmdExec("exec scripts/game_start.scr 0");
 

	
 
	SetLocalCompany(COMPANY_FIRST);
 
	OnStartGame(false);
 

	
 
	InitializeRailGUI();
 
	InitializeRoadGUI();
 

	
 
	/* We are the server, we start a new company (not dedicated),
 
	 * so set the default password *if* needed. */
 
	if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
 
		NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass);
 
	}
 

	
 
	if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
 

	
 
@@ -1023,29 +1036,25 @@ void SwitchToMode(SwitchMode new_mode)
 
		case SM_LOAD_GAME: { // Load game, Play Scenario
 
			ResetGRFConfig(true);
 
			ResetWindowSystem();
 

	
 
			if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, NO_DIRECTORY)) {
 
				SetDParamStr(0, GetSaveLoadErrorString());
 
				ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
 
			} else {
 
				if (_file_to_saveload.abstract_ftype == FT_SCENARIO) {
 
					/* Reset engine pool to simplify changing engine NewGRFs in scenario editor. */
 
					EngineOverrideManager::ResetToCurrentNewGRFConfig();
 
				}
 
				/* Update the local company for a loaded game. It is either always
 
				 * company #1 (eg 0) or in the case of a dedicated server a spectator */
 
				SetLocalCompany(_network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST);
 
				/* Execute the game-start script */
 
				IConsoleCmdExec("exec scripts/game_start.scr 0");
 
				OnStartGame(_network_dedicated);
 
				/* Decrease pause counter (was increased from opening load dialog) */
 
				DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
 
			}
 
			break;
 
		}
 

	
 
		case SM_RESTART_HEIGHTMAP: // Load a heightmap and start a new game from it with current settings
 
		case SM_START_HEIGHTMAP: // Load a heightmap and start a new game from it
 
			MakeNewGame(true, new_mode == SM_START_HEIGHTMAP);
 
			break;
 

	
 
		case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor
src/settings.cpp
Show inline comments
 
@@ -1407,38 +1407,40 @@ static bool InvalidateShipPathCache(int3
 
static bool UpdateClientName(int32 p1)
 
{
 
	NetworkUpdateClientName();
 
	return true;
 
}
 

	
 
static bool UpdateServerPassword(int32 p1)
 
{
 
	if (strcmp(_settings_client.network.server_password, "*") == 0) {
 
		_settings_client.network.server_password[0] = '\0';
 
	}
 

	
 
	NetworkServerUpdateGameInfo();
 
	return true;
 
}
 

	
 
static bool UpdateRconPassword(int32 p1)
 
{
 
	if (strcmp(_settings_client.network.rcon_password, "*") == 0) {
 
		_settings_client.network.rcon_password[0] = '\0';
 
	}
 

	
 
	return true;
 
}
 

	
 
static bool UpdateClientConfigValues(int32 p1)
 
{
 
	NetworkServerUpdateGameInfo();
 
	if (_network_server) NetworkServerSendConfigUpdate();
 

	
 
	return true;
 
}
 

	
 
/* End - Callback Functions */
 

	
 
/**
 
 * Prepare for reading and old diff_custom by zero-ing the memory.
 
 */
 
static void PrepareOldDiffCustom()
 
{
src/table/settings.ini
Show inline comments
 
@@ -3953,24 +3953,25 @@ cat      = SC_BASIC
 
[SDTC_STR]
 
var      = network.default_company_pass
 
type     = SLE_STRB
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
def      = nullptr
 

	
 
[SDTC_STR]
 
var      = network.server_name
 
type     = SLE_STRB
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
guiflags = SGF_NETWORK_ONLY
 
def      = nullptr
 
proc     = UpdateClientConfigValues
 
cat      = SC_BASIC
 

	
 
[SDTC_STR]
 
var      = network.connect_to_ip
 
type     = SLE_STRB
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
def      = nullptr
 

	
 
[SDTC_STR]
 
var      = network.network_id
 
type     = SLE_STRB
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
@@ -4020,24 +4021,25 @@ min      = 1
 
max      = MAX_COMPANIES
 
proc     = UpdateClientConfigValues
 
cat      = SC_BASIC
 

	
 
[SDTC_VAR]
 
var      = network.max_clients
 
type     = SLE_UINT8
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
guiflags = SGF_NETWORK_ONLY
 
def      = 25
 
min      = 2
 
max      = MAX_CLIENTS
 
proc     = UpdateClientConfigValues
 
cat      = SC_BASIC
 

	
 
[SDTC_VAR]
 
var      = network.max_spectators
 
type     = SLE_UINT8
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
guiflags = SGF_NETWORK_ONLY
 
def      = 15
 
min      = 0
 
max      = MAX_CLIENTS
 
proc     = UpdateClientConfigValues
 
cat      = SC_BASIC
0 comments (0 inline, 0 general)