diff --git a/console_cmds.c b/console_cmds.c --- a/console_cmds.c +++ b/console_cmds.c @@ -790,6 +790,57 @@ DEF_CONSOLE_CMD(ConSet) { return NULL; } + // setting the server autoclean on/off + if (strcmp(argv[1],"autoclean_companies") == 0) { + if (!_network_server) { + IConsolePrintF(_iconsole_color_error, "You are not the server"); + return NULL; + } + if (argc == 3) { + if (strcmp(argv[2], "on") == 0 || atoi(argv[2]) == 1) + _network_autoclean_companies = true; + else + _network_autoclean_companies = false; + IConsolePrintF(_iconsole_color_warning, "Autoclean-companies changed to '%s'", (_network_autoclean_companies)?"on":"off"); + } else { + IConsolePrintF(_iconsole_color_default, "Current autoclean-companies is '%s'", (_network_autoclean_companies)?"on":"off"); + IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_companies on/off."); + } + return NULL; + } + + // setting the server autoclean protected + if (strcmp(argv[1],"autoclean_protected") == 0) { + if (!_network_server) { + IConsolePrintF(_iconsole_color_error, "You are not the server"); + return NULL; + } + if (argc == 3) { + _network_autoclean_protected = atoi(argv[2]); + IConsolePrintF(_iconsole_color_warning, "Autoclean-protected changed to '%d'", _network_autoclean_protected); + } else { + IConsolePrintF(_iconsole_color_default, "Current autoclean-protected is '%d'", _network_autoclean_protected); + IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_protected ."); + } + return NULL; + } + + // setting the server autoclean protected + if (strcmp(argv[1],"autoclean_unprotected") == 0) { + if (!_network_server) { + IConsolePrintF(_iconsole_color_error, "You are not the server"); + return NULL; + } + if (argc == 3) { + _network_autoclean_unprotected = atoi(argv[2]); + IConsolePrintF(_iconsole_color_warning, "Autoclean-unprotected changed to '%d'", _network_autoclean_unprotected); + } else { + IConsolePrintF(_iconsole_color_default, "Current autoclean-unprotected is '%d'", _network_autoclean_unprotected); + IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_unprotected ."); + } + return NULL; + } + #endif /* ENABLE_NETWORK */ // Patch-options @@ -811,13 +862,16 @@ DEF_CONSOLE_CMD(ConSet) { IConsolePrint(_iconsole_color_error, "Unknown setting"); IConsolePrint(_iconsole_color_error, "Known settings are:"); #ifdef ENABLE_NETWORK - IConsolePrint(_iconsole_color_error, " - server_pw \"\""); + IConsolePrint(_iconsole_color_error, " - autoclean_companies on/off"); + IConsolePrint(_iconsole_color_error, " - autoclean_protected "); + IConsolePrint(_iconsole_color_error, " - autoclean_unprotected "); IConsolePrint(_iconsole_color_error, " - company_pw \"\""); IConsolePrint(_iconsole_color_error, " - name \"\""); - IConsolePrint(_iconsole_color_error, " - servername \"\""); + IConsolePrint(_iconsole_color_error, " - server_name \"\""); + IConsolePrint(_iconsole_color_error, " - server_advertise on/off"); + IConsolePrint(_iconsole_color_error, " - server_bind_ip "); IConsolePrint(_iconsole_color_error, " - server_port "); - IConsolePrint(_iconsole_color_error, " - server_bind_ip "); - IConsolePrint(_iconsole_color_error, " - server_advertise on/off"); + IConsolePrint(_iconsole_color_error, " - server_pw \"\""); #endif /* ENABLE_NETWORK */ IConsolePrint(_iconsole_color_error, " - patch []"); diff --git a/misc.c b/misc.c --- a/misc.c +++ b/misc.c @@ -7,6 +7,8 @@ #include "assert.h" #include "saveload.h" #include "network.h" +#include "network_data.h" +#include "network_server.h" extern void StartupEconomy(); extern void InitNewsItemStructs(); @@ -667,6 +669,10 @@ void IncreaseDate() TownsMonthlyLoop(); IndustryMonthlyLoop(); StationMonthlyLoop(); +#ifdef ENABLE_NETWORK + if (_network_server) + NetworkServerMonthlyLoop(); +#endif /* ENABLE_NETWORK */ } /* check if we entered a new year? */ diff --git a/network.h b/network.h --- a/network.h +++ b/network.h @@ -83,6 +83,7 @@ typedef struct NetworkPlayerInfo { uint16 num_vehicle[NETWORK_VEHICLE_TYPES]; // How many vehicles are there of this type? uint16 num_station[NETWORK_STATION_TYPES]; // How many stations are there of this type? char players[NETWORK_PLAYERS_LENGTH]; // The players that control this company (Name1, name2, ..) + uint16 months_empty; // How many months the company is empty } NetworkPlayerInfo; typedef struct NetworkClientInfo { @@ -175,6 +176,10 @@ VARDEF uint16 _network_udp_broadcast; VARDEF bool _network_advertise; VARDEF uint16 _network_last_advertise_date; +VARDEF bool _network_autoclean_companies; +VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months +VARDEF uint8 _network_autoclean_protected; // Unprotect a company after X months + #endif /* ENABLE_NETWORK */ // Those variables must always be registered! diff --git a/network_server.c b/network_server.c --- a/network_server.c +++ b/network_server.c @@ -629,6 +629,10 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); } } + + /* Make sure companies to who people try to join are not autocleaned */ + if (playas >= 1 && playas <= MAX_PLAYERS) + _network_player_info[playas-1].months_empty = 0; } DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD) @@ -1121,6 +1125,7 @@ void NetworkPopulateCompanyInfo(void) ClientState *cs; NetworkClientInfo *ci; int i; + uint16 months_empty; FOR_ALL_PLAYERS(p) { if (!p->is_active) { @@ -1130,7 +1135,9 @@ void NetworkPopulateCompanyInfo(void) // Clean the info but not the password ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password)); + months_empty = _network_player_info[p->index].months_empty; memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo)); + _network_player_info[p->index].months_empty = months_empty; ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password)); // Grap the company name @@ -1228,6 +1235,67 @@ void NetworkUpdateClientInfo(uint16 clie } } +/* Check if the server has autoclean_companies activated + Two things happen: + 1) If a company is not protected, it is closed after 1 year (for example) + 2) If a company is protected, protection is disabled after 3 years (for example) + (and item 1. happens a year later) */ +static void NetworkAutoCleanCompanies() +{ + ClientState *cs; + NetworkClientInfo *ci; + Player *p; + bool clients_in_company[MAX_PLAYERS]; + + if (!_network_autoclean_companies) + return; + + memset(clients_in_company, 0, sizeof(clients_in_company)); + + /* Detect the active companies */ + FOR_ALL_CLIENTS(cs) { + ci = DEREF_CLIENT_INFO(cs); + if (ci->client_playas >= 1 && ci->client_playas <= MAX_PLAYERS) { + clients_in_company[ci->client_playas-1] = true; + } + } + if (!_network_dedicated) { + ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); + if (ci->client_playas >= 1 && ci->client_playas <= MAX_PLAYERS) { + clients_in_company[ci->client_playas-1] = true; + } + } + + /* Go through all the comapnies */ + FOR_ALL_PLAYERS(p) { + /* Skip the non-active once */ + if (!p->is_active || p->is_ai) + continue; + + if (!clients_in_company[p->index]) { + /* The company is empty for one month more */ + _network_player_info[p->index].months_empty++; + + /* Is the company empty for autoclean_unprotected-months, and is there no protection? */ + if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') { + /* Shut the company down */ + DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL); + IConsolePrintF(_iconsole_color_default, "Auto-cleaned company #%d", p->index+1); + } + /* Is the compnay empty for autoclean_protected-months, and there is a protection? */ + if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') { + /* Unprotect the company */ + _network_player_info[p->index].password[0] = '\0'; + IConsolePrintF(_iconsole_color_default, "Auto-removed protection from company #%d", p->index+1); + _network_player_info[p->index].months_empty = 0; + } + } else { + /* It is not empty, reset the date */ + _network_player_info[p->index].months_empty = 0; + } + } +} + // This function changes new_name to a name that is unique (by adding #1 ...) // and it returns true if that succeeded. bool NetworkFindName(char new_name[NETWORK_NAME_LENGTH]) @@ -1385,4 +1453,9 @@ void NetworkServer_Tick(void) NetworkUDPAdvertise(); } +void NetworkServerMonthlyLoop() +{ + NetworkAutoCleanCompanies(); +} + #endif /* ENABLE_NETWORK */ diff --git a/network_server.h b/network_server.h --- a/network_server.h +++ b/network_server.h @@ -14,6 +14,7 @@ void NetworkServer_HandleChat(NetworkAct bool NetworkServer_ReadPackets(ClientState *cs); void NetworkServer_Tick(); +void NetworkServerMonthlyLoop(); #endif /* ENABLE_NETWORK */ diff --git a/players.c b/players.c --- a/players.c +++ b/players.c @@ -665,6 +665,8 @@ int32 CmdPlayerCtrl(int x, int y, uint32 NetworkUpdateClientInfo(ci->client_index); if (ci->client_playas != 0 && ci->client_playas <= MAX_PLAYERS) { + _network_player_info[p->index].months_empty = 0; + memcpy(_decode_parameters, ci->client_name, 32); /* XXX - What are the consequents of this? It is needed, but is it bad? */ _docommand_recursive = 0; diff --git a/settings.c b/settings.c --- a/settings.c +++ b/settings.c @@ -733,6 +733,9 @@ static const SettingDesc network_setting {"server_name", SDT_STRINGBUF | (lengthof(_network_server_name) << 16), NULL, &_network_server_name, NULL}, {"connect_to_ip", SDT_STRINGBUF | (lengthof(_network_default_ip) << 16), NULL, &_network_default_ip, NULL}, {"network_id", SDT_STRINGBUF | (lengthof(_network_unique_id) << 16), NULL, &_network_unique_id, NULL}, + {"autoclean_companies", SDT_BOOL, (void*)false, &_network_autoclean_companies, NULL}, + {"autoclean_unprotected", SDT_UINT8, (void*)12, &_network_autoclean_unprotected, NULL}, + {"autoclean_protected", SDT_UINT8, (void*)36, &_network_autoclean_protected, NULL}, {NULL, 0, NULL, NULL, NULL} }; #endif /* ENABLE_NETWORK */