@@ -879,60 +879,66 @@ CommandCost CmdCompanyCtrl(DoCommandFlag
/* A new company could not be created, revert to being a spectator */
if (c == nullptr) {
/* We check for "ci != nullptr" as a client could have left by
* the time we execute this command. */
if (_network_server && ci != nullptr) {
ci->client_playas = COMPANY_SPECTATOR;
NetworkUpdateClientInfo(ci->client_id);
}
break;
/* Send new companies, before potentially setting the password. Otherwise,
* the password update could be sent when the company is not yet known. */
NetworkAdminCompanyNew(c);
NetworkServerNewCompany(c, ci);
/* This is the client (or non-dedicated server) who wants a new company */
if (client_id == _network_own_client_id) {
assert(_local_company == COMPANY_SPECTATOR);
SetLocalCompany(c->index);
if (!_settings_client.network.default_company_pass.empty()) {
NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass);
/* In network games, we need to try setting the company manager face here to sync it to all clients.
* If a favorite company manager face is selected, choose it. Otherwise, use a random face. */
if (_company_manager_face != 0) Command<CMD_SET_COMPANY_MANAGER_FACE>::SendNet(STR_NULL, c->index, _company_manager_face);
/* Now that we have a new company, broadcast our company settings to
* all clients so everything is in sync */
SyncCompanySettings();
MarkWholeScreenDirty();
case CCA_NEW_AI: { // Make a new AI company
if (company_id != INVALID_COMPANY && company_id >= MAX_COMPANIES) return CMD_ERROR;
/* For network games, company deletion is delayed. */
if (!_networking && company_id != INVALID_COMPANY && Company::IsValidID(company_id)) return CMD_ERROR;
if (!(flags & DC_EXEC)) return CommandCost();
/* For network game, just assume deletion happened. */
assert(company_id == INVALID_COMPANY || !Company::IsValidID(company_id));
Company *c = DoStartupNewCompany(true, company_id);
if (c != nullptr) NetworkServerNewCompany(c, nullptr);
if (c != nullptr) {
NetworkServerNewCompany(c, nullptr);
case CCA_DELETE: { // Delete a company
if (reason >= CRR_END) return CMD_ERROR;
/* We can't delete the last existing company in singleplayer mode. */
if (!_networking && Company::GetNumItems() == 1) return CMD_ERROR;
Company *c = Company::GetIfValid(company_id);
if (c == nullptr) return CMD_ERROR;
@@ -844,42 +844,39 @@ void NetworkAdminClientQuit(ClientID cli
* @param error_code the error that was caused.
*/
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
{
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
as->SendClientError(client_id, error_code);
/**
* Notify the admin network of company details.
* Notify the admin network of a new company.
* @param company the company of which details will be sent into the admin network.
* @param new_company whether this is a new company or not.
void NetworkAdminCompanyInfo(const Company *company, bool new_company)
void NetworkAdminCompanyNew(const Company *company)
if (company == nullptr) {
Debug(net, 1, "[admin] Empty company given for update");
return;
if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
as->SendCompanyNew(company->index);
as->SendCompanyInfo(company);
if (new_company) {
* Notify the admin network of company updates.
* @param company company of which updates are going to be sent into the admin network.
void NetworkAdminCompanyUpdate(const Company *company)
if (company == nullptr) return;
@@ -94,24 +94,24 @@ public:
* @return an iterable ensemble of all active admin sockets
static Pool::IterateWrapperFiltered<ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter> IterateActive(size_t from = 0)
return Pool::IterateWrapperFiltered<ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter>(from, ServerNetworkAdminSocketHandlerFilter{});
};
void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client = false);
void NetworkAdminClientUpdate(const NetworkClientInfo *ci);
void NetworkAdminClientQuit(ClientID client_id);
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code);
void NetworkAdminCompanyInfo(const Company *company, bool new_company);
void NetworkAdminCompanyNew(const Company *company);
void NetworkAdminCompanyUpdate(const Company *company);
void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr);
void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64_t data = 0, bool from_admin = false);
void NetworkAdminUpdate(AdminUpdateFrequency freq);
void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const std::string_view string);
void NetworkAdminConsole(const std::string_view origin, const std::string_view string);
void NetworkAdminGameScript(const std::string_view json);
void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket &cp);
#endif /* NETWORK_ADMIN_H */
@@ -2189,22 +2189,19 @@ void NetworkServerNewCompany(const Compa
_network_company_states[c->index].months_empty = 0;
_network_company_states[c->index].password.clear();
NetworkServerUpdateCompanyPassworded(c->index, false);
if (ci != nullptr) {
/* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
ci->client_playas = c->index;
Command<CMD_RENAME_PRESIDENT>::SendNet(STR_NULL, c->index, ci->client_name);
/* Announce new company on network. */
NetworkAdminCompanyInfo(c, true);
/* ci is nullptr when replaying, or for AIs. In neither case there is a client.
We need to send Admin port update here so that they first know about the new company
and then learn about a possibly joining client (see FS#6025) */
NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
Status change: