1
0
Fork 0

Codechange: Use EnumBitSet for AdminUpdateFrequency. (#13819)

pull/13831/head
Peter Nelson 2025-03-15 21:18:20 +00:00 committed by GitHub
parent 8d4639e525
commit 3b004c57bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 46 additions and 46 deletions

View File

@ -223,7 +223,7 @@ Last updated: 2024-03-26
## 5.1) Receiving chat ## 5.1) Receiving chat
Register `ADMIN_UPDATE_CHAT` at `ADMIN_FREQUENCY_AUTOMATIC` to receive chat. Register `ADMIN_UPDATE_CHAT` at `AdminUpdateFrequency::Automatic` to receive chat.
The application will be able to receive all chat the server can see. The application will be able to receive all chat the server can see.
The configuration option `network.server_admin_chat` specifies whether The configuration option `network.server_admin_chat` specifies whether

View File

@ -266,7 +266,7 @@ void DebugReconsiderSendRemoteMessages()
bool enable = _settings_client.gui.developer >= 2; bool enable = _settings_client.gui.developer >= 2;
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CONSOLE].Test(AdminUpdateFrequency::Automatic)) {
enable = true; enable = true;
break; break;
} }

View File

@ -93,16 +93,16 @@ enum AdminUpdateType : uint8_t {
}; };
/** Update frequencies an admin can register. */ /** Update frequencies an admin can register. */
enum AdminUpdateFrequency : uint8_t { enum class AdminUpdateFrequency : uint8_t {
ADMIN_FREQUENCY_POLL = 0x01, ///< The admin can poll this. Poll, ///< The admin can poll this.
ADMIN_FREQUENCY_DAILY = 0x02, ///< The admin gets information about this on a daily basis. Daily, ///< The admin gets information about this on a daily basis.
ADMIN_FREQUENCY_WEEKLY = 0x04, ///< The admin gets information about this on a weekly basis. Weekly, ///< The admin gets information about this on a weekly basis.
ADMIN_FREQUENCY_MONTHLY = 0x08, ///< The admin gets information about this on a monthly basis. Monthly, ///< The admin gets information about this on a monthly basis.
ADMIN_FREQUENCY_QUARTERLY = 0x10, ///< The admin gets information about this on a quarterly basis. Quarterly, ///< The admin gets information about this on a quarterly basis.
ADMIN_FREQUENCY_ANUALLY = 0x20, ///< The admin gets information about this on a yearly basis. Annually, ///< The admin gets information about this on a yearly basis.
ADMIN_FREQUENCY_AUTOMATIC = 0x40, ///< The admin gets information about this when it changes. Automatic, ///< The admin gets information about this when it changes.
}; };
DECLARE_ENUM_AS_BIT_SET(AdminUpdateFrequency) using AdminUpdateFrequencies = EnumBitSet<AdminUpdateFrequency, uint8_t>;
/** Reasons for removing a company - communicated to admins. */ /** Reasons for removing a company - communicated to admins. */
enum AdminCompanyRemoveReason : uint8_t { enum AdminCompanyRemoveReason : uint8_t {
@ -142,7 +142,7 @@ protected:
/** /**
* Register updates to be sent at certain frequencies (as announced in the PROTOCOL packet): * Register updates to be sent at certain frequencies (as announced in the PROTOCOL packet):
* uint16_t Update type (see #AdminUpdateType). Note integer type - see "Certain Packet Information" in docs/admin_network.md. * uint16_t Update type (see #AdminUpdateType). Note integer type - see "Certain Packet Information" in docs/admin_network.md.
* uint16_t Update frequency (see #AdminUpdateFrequency), setting #ADMIN_FREQUENCY_POLL is always ignored. * uint16_t Update frequency (see #AdminUpdateFrequency), setting #AdminUpdateFrequency::Poll is always ignored.
* @param p The packet that was just received. * @param p The packet that was just received.
* @return The state the network should have. * @return The state the network should have.
*/ */
@ -150,7 +150,7 @@ protected:
/** /**
* Poll the server for certain updates, an invalid poll (e.g. not existent id) gets silently dropped: * Poll the server for certain updates, an invalid poll (e.g. not existent id) gets silently dropped:
* uint8_t #AdminUpdateType the server should answer for, only if #AdminUpdateFrequency #ADMIN_FREQUENCY_POLL is advertised in the PROTOCOL packet. Note integer type - see "Certain Packet Information" in docs/admin_network.md. * uint8_t #AdminUpdateType the server should answer for, only if #AdminUpdateFrequency::Poll is advertised in the PROTOCOL packet. Note integer type - see "Certain Packet Information" in docs/admin_network.md.
* uint32_t ID relevant to the packet type, e.g. * uint32_t ID relevant to the packet type, e.g.
* - the client ID for #ADMIN_UPDATE_CLIENT_INFO. Use UINT32_MAX to show all clients. * - the client ID for #ADMIN_UPDATE_CLIENT_INFO. Use UINT32_MAX to show all clients.
* - the company ID for #ADMIN_UPDATE_COMPANY_INFO. Use UINT32_MAX to show all companies. * - the company ID for #ADMIN_UPDATE_COMPANY_INFO. Use UINT32_MAX to show all companies.

View File

@ -43,17 +43,17 @@ static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
/** Frequencies, which may be registered for a certain update type. */ /** Frequencies, which may be registered for a certain update type. */
static const AdminUpdateFrequency _admin_update_type_frequencies[] = { static const AdminUpdateFrequencies _admin_update_type_frequencies[] = {
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_DATE {AdminUpdateFrequency::Poll, AdminUpdateFrequency::Daily, AdminUpdateFrequency::Weekly, AdminUpdateFrequency::Monthly, AdminUpdateFrequency::Quarterly, AdminUpdateFrequency::Annually}, // ADMIN_UPDATE_DATE
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CLIENT_INFO {AdminUpdateFrequency::Poll, AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_CLIENT_INFO
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_COMPANY_INFO {AdminUpdateFrequency::Poll, AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_COMPANY_INFO
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_ECONOMY {AdminUpdateFrequency::Poll, AdminUpdateFrequency::Weekly, AdminUpdateFrequency::Monthly, AdminUpdateFrequency::Quarterly, AdminUpdateFrequency::Annually}, // ADMIN_UPDATE_COMPANY_ECONOMY
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_STATS {AdminUpdateFrequency::Poll, AdminUpdateFrequency::Weekly, AdminUpdateFrequency::Monthly, AdminUpdateFrequency::Quarterly, AdminUpdateFrequency::Annually}, // ADMIN_UPDATE_COMPANY_STATS
ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CHAT { AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_CHAT
ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CONSOLE { AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_CONSOLE
ADMIN_FREQUENCY_POLL, ///< ADMIN_UPDATE_CMD_NAMES {AdminUpdateFrequency::Poll, }, // ADMIN_UPDATE_CMD_NAMES
ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CMD_LOGGING { AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_CMD_LOGGING
ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_GAMESCRIPT { AdminUpdateFrequency::Automatic, }, // ADMIN_UPDATE_GAMESCRIPT
}; };
/** Sanity check. */ /** Sanity check. */
static_assert(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END); static_assert(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
@ -76,8 +76,8 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
Debug(net, 3, "[admin] '{}' ({}) has disconnected", this->admin_name, this->admin_version); Debug(net, 3, "[admin] '{}' ({}) has disconnected", this->admin_name, this->admin_version);
if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = AdminID::Invalid(); if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = AdminID::Invalid();
if (this->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) { if (this->update_frequency[ADMIN_UPDATE_CONSOLE].Test(AdminUpdateFrequency::Automatic)) {
this->update_frequency[ADMIN_UPDATE_CONSOLE] = (AdminUpdateFrequency)0; this->update_frequency[ADMIN_UPDATE_CONSOLE] = {};
DebugReconsiderSendRemoteMessages(); DebugReconsiderSendRemoteMessages();
} }
} }
@ -155,7 +155,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
for (int i = 0; i < ADMIN_UPDATE_END; i++) { for (int i = 0; i < ADMIN_UPDATE_END; i++) {
p->Send_bool (true); p->Send_bool (true);
p->Send_uint16(i); p->Send_uint16(i);
p->Send_uint16(_admin_update_type_frequencies[i]); p->Send_uint16(_admin_update_type_frequencies[i].base());
} }
p->Send_bool(false); p->Send_bool(false);
@ -661,9 +661,9 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENC
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
AdminUpdateType type = (AdminUpdateType)p.Recv_uint16(); AdminUpdateType type = (AdminUpdateType)p.Recv_uint16();
AdminUpdateFrequency freq = (AdminUpdateFrequency)p.Recv_uint16(); AdminUpdateFrequencies freq = static_cast<AdminUpdateFrequencies>(p.Recv_uint16());
if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) { if (type >= ADMIN_UPDATE_END || !_admin_update_type_frequencies[type].All(freq)) {
/* The server does not know of this UpdateType. */ /* The server does not know of this UpdateType. */
Debug(net, 1, "[admin] Not supported update frequency {} ({}) from '{}' ({})", type, freq, this->admin_name, this->admin_version); Debug(net, 1, "[admin] Not supported update frequency {} ({}) from '{}' ({})", type, freq, this->admin_name, this->admin_version);
return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
@ -879,7 +879,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(P
void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client) void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO].Test(AdminUpdateFrequency::Automatic)) {
as->SendClientInfo(cs, cs->GetInfo()); as->SendClientInfo(cs, cs->GetInfo());
if (new_client) { if (new_client) {
as->SendClientJoin(cs->client_id); as->SendClientJoin(cs->client_id);
@ -895,7 +895,7 @@ void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
void NetworkAdminClientUpdate(const NetworkClientInfo *ci) void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO].Test(AdminUpdateFrequency::Automatic)) {
as->SendClientUpdate(ci); as->SendClientUpdate(ci);
} }
} }
@ -908,7 +908,7 @@ void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
void NetworkAdminClientQuit(ClientID client_id) void NetworkAdminClientQuit(ClientID client_id)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO].Test(AdminUpdateFrequency::Automatic)) {
as->SendClientQuit(client_id); as->SendClientQuit(client_id);
} }
} }
@ -922,7 +922,7 @@ void NetworkAdminClientQuit(ClientID client_id)
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code) void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO].Test(AdminUpdateFrequency::Automatic)) {
as->SendClientError(client_id, error_code); as->SendClientError(client_id, error_code);
} }
} }
@ -940,7 +940,7 @@ void NetworkAdminCompanyNew(const Company *company)
} }
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue; if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != AdminUpdateFrequency::Automatic) continue;
as->SendCompanyNew(company->index); as->SendCompanyNew(company->index);
as->SendCompanyInfo(company); as->SendCompanyInfo(company);
@ -956,7 +956,7 @@ void NetworkAdminCompanyUpdate(const Company *company)
if (company == nullptr) return; if (company == nullptr) return;
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue; if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != AdminUpdateFrequency::Automatic) continue;
as->SendCompanyUpdate(company); as->SendCompanyUpdate(company);
} }
@ -983,7 +983,7 @@ void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_i
if (from_admin) return; if (from_admin) return;
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CHAT].Test(AdminUpdateFrequency::Automatic)) {
as->SendChat(action, desttype, client_id, msg, data); as->SendChat(action, desttype, client_id, msg, data);
} }
} }
@ -1008,7 +1008,7 @@ void NetworkServerSendAdminRcon(AdminID admin_index, TextColour colour_code, con
void NetworkAdminConsole(const std::string_view origin, const std::string_view string) void NetworkAdminConsole(const std::string_view origin, const std::string_view string)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CONSOLE].Test(AdminUpdateFrequency::Automatic)) {
as->SendConsole(origin, string); as->SendConsole(origin, string);
} }
} }
@ -1021,7 +1021,7 @@ void NetworkAdminConsole(const std::string_view origin, const std::string_view s
void NetworkAdminGameScript(const std::string_view json) void NetworkAdminGameScript(const std::string_view json)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT].Test(AdminUpdateFrequency::Automatic)) {
as->SendGameScript(json); as->SendGameScript(json);
} }
} }
@ -1037,7 +1037,7 @@ void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacke
ClientID client_id = owner == nullptr ? _network_own_client_id : owner->client_id; ClientID client_id = owner == nullptr ? _network_own_client_id : owner->client_id;
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING].Test(AdminUpdateFrequency::Automatic)) {
as->SendCmdLogging(client_id, cp); as->SendCmdLogging(client_id, cp);
} }
} }
@ -1061,7 +1061,7 @@ void NetworkAdminUpdate(AdminUpdateFrequency freq)
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
for (int i = 0; i < ADMIN_UPDATE_END; i++) { for (int i = 0; i < ADMIN_UPDATE_END; i++) {
if (as->update_frequency[i] & freq) { if (as->update_frequency[i].Test(freq)) {
/* Update the admin for the required details */ /* Update the admin for the required details */
switch (i) { switch (i) {
case ADMIN_UPDATE_DATE: case ADMIN_UPDATE_DATE:

View File

@ -43,7 +43,7 @@ protected:
NetworkRecvStatus SendAuthRequest(); NetworkRecvStatus SendAuthRequest();
NetworkRecvStatus SendEnableEncryption(); NetworkRecvStatus SendEnableEncryption();
public: public:
std::array<AdminUpdateFrequency, ADMIN_UPDATE_END> update_frequency{}; ///< Admin requested update intervals. std::array<AdminUpdateFrequencies, ADMIN_UPDATE_END> update_frequency{}; ///< Admin requested update intervals.
std::chrono::steady_clock::time_point connect_time{}; ///< Time of connection. std::chrono::steady_clock::time_point connect_time{}; ///< Time of connection.
NetworkAddress address{}; ///< Address of the admin. NetworkAddress address{}; ///< Address of the admin.

View File

@ -1874,7 +1874,7 @@ static IntervalTimer<TimerGameEconomy> _economy_network_yearly({TimerGameEconomy
{ {
if (!_network_server) return; if (!_network_server) return;
NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY); NetworkAdminUpdate(AdminUpdateFrequency::Annually);
}); });
/** Quarterly "callback". Called whenever the economy quarter changes. */ /** Quarterly "callback". Called whenever the economy quarter changes. */
@ -1883,7 +1883,7 @@ static IntervalTimer<TimerGameEconomy> _network_quarterly({TimerGameEconomy::QUA
if (!_network_server) return; if (!_network_server) return;
NetworkAutoCleanCompanies(); NetworkAutoCleanCompanies();
NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY); NetworkAdminUpdate(AdminUpdateFrequency::Quarterly);
}); });
/** Economy monthly "callback". Called whenever the economy month changes. */ /** Economy monthly "callback". Called whenever the economy month changes. */
@ -1892,7 +1892,7 @@ static IntervalTimer<TimerGameEconomy> _network_monthly({TimerGameEconomy::MONTH
if (!_network_server) return; if (!_network_server) return;
NetworkAutoCleanCompanies(); NetworkAutoCleanCompanies();
NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY); NetworkAdminUpdate(AdminUpdateFrequency::Monthly);
}); });
/** Economy weekly "callback". Called whenever the economy week changes. */ /** Economy weekly "callback". Called whenever the economy week changes. */
@ -1900,7 +1900,7 @@ static IntervalTimer<TimerGameEconomy> _network_weekly({TimerGameEconomy::WEEK,
{ {
if (!_network_server) return; if (!_network_server) return;
NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY); NetworkAdminUpdate(AdminUpdateFrequency::Weekly);
}); });
/** Daily "callback". Called whenever the economy date changes. */ /** Daily "callback". Called whenever the economy date changes. */
@ -1908,7 +1908,7 @@ static IntervalTimer<TimerGameEconomy> _economy_network_daily({TimerGameEconomy:
{ {
if (!_network_server) return; if (!_network_server) return;
NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY); NetworkAdminUpdate(AdminUpdateFrequency::Daily);
}); });
/** /**