From cb2ef1ea4b74c3d73ba86d978c001784d398bf27 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 26 Apr 2021 15:18:10 +0200 Subject: [PATCH 001/800] Codechange: move all NetworkGameInfo related functions to a single file It currently was a bit scattered over the place. Part of NetworkGameInfo is also the GRF Identifiers that goes with it. --- src/console_cmds.cpp | 1 + src/network/core/CMakeLists.txt | 3 +- src/network/core/core.cpp | 28 -- src/network/core/core.h | 2 - src/network/core/game_info.cpp | 323 +++++++++++++++++++++++ src/network/core/{game.h => game_info.h} | 62 ++++- src/network/core/tcp_http.cpp | 1 + src/network/core/udp.cpp | 137 +--------- src/network/core/udp.h | 48 +--- src/network/network.cpp | 81 +----- src/network/network_admin.cpp | 1 + src/network/network_base.h | 1 + src/network/network_client.cpp | 3 +- src/network/network_func.h | 2 +- src/network/network_gamelist.h | 1 + src/network/network_gui.h | 1 + src/network/network_internal.h | 2 - src/network/network_server.cpp | 3 +- src/network/network_type.h | 2 +- src/network/network_udp.cpp | 54 +--- 20 files changed, 407 insertions(+), 349 deletions(-) create mode 100644 src/network/core/game_info.cpp rename src/network/core/{game.h => game_info.h} (51%) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 048b8b3e93..8cdf9c664e 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -13,6 +13,7 @@ #include "engine_func.h" #include "landscape.h" #include "saveload/saveload.h" +#include "network/core/game_info.h" #include "network/network.h" #include "network/network_func.h" #include "network/network_base.h" diff --git a/src/network/core/CMakeLists.txt b/src/network/core/CMakeLists.txt index c9368a5b46..37cc3e1954 100644 --- a/src/network/core/CMakeLists.txt +++ b/src/network/core/CMakeLists.txt @@ -4,7 +4,8 @@ add_files( config.h core.cpp core.h - game.h + game_info.cpp + game_info.h host.cpp host.h os_abstraction.h diff --git a/src/network/core/core.cpp b/src/network/core/core.cpp index 8c5c5c2292..5c12cb2242 100644 --- a/src/network/core/core.cpp +++ b/src/network/core/core.cpp @@ -65,31 +65,3 @@ const char *NetworkGetErrorString(int error) return buffer; } #endif /* defined(_WIN32) */ - -/** - * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet - * @param p the packet to write the data to - * @param grf the GRFIdentifier to serialize - */ -void NetworkSocketHandler::SendGRFIdentifier(Packet *p, const GRFIdentifier *grf) -{ - uint j; - p->Send_uint32(grf->grfid); - for (j = 0; j < sizeof(grf->md5sum); j++) { - p->Send_uint8 (grf->md5sum[j]); - } -} - -/** - * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet - * @param p the packet to read the data from - * @param grf the GRFIdentifier to deserialize - */ -void NetworkSocketHandler::ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf) -{ - uint j; - grf->grfid = p->Recv_uint32(); - for (j = 0; j < sizeof(grf->md5sum); j++) { - grf->md5sum[j] = p->Recv_uint8(); - } -} diff --git a/src/network/core/core.h b/src/network/core/core.h index bf83adc72c..aac36080ff 100644 --- a/src/network/core/core.h +++ b/src/network/core/core.h @@ -71,8 +71,6 @@ public: */ void Reopen() { this->has_quit = false; } - void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf); - void ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf); void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len = NETWORK_COMPANY_NAME_LENGTH); }; diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp new file mode 100644 index 0000000000..bea687af80 --- /dev/null +++ b/src/network/core/game_info.cpp @@ -0,0 +1,323 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** + * @file game_info.cpp Functions to convert NetworkGameInfo to Packet and back. + */ + +#include "../../stdafx.h" +#include "game_info.h" +#include "../../core/bitmath_func.hpp" +#include "../../company_base.h" +#include "../../date_func.h" +#include "../../debug.h" +#include "../../map_func.h" +#include "../../settings_type.h" +#include "../../string_func.h" +#include "../../rev.h" +#include "../network_func.h" +#include "../network.h" +#include "packet.h" + +#include "../../safeguards.h" + + +/** + * How many hex digits of the git hash to include in network revision string. + * Determined as 10 hex digits + 2 characters for -g/-u/-m prefix. + */ +static const uint GITHASH_SUFFIX_LEN = 12; + +NetworkServerGameInfo _network_game_info; ///< Information about our game. + +/** + * Get the network version string used by this build. + * The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes. + */ +const char *GetNetworkRevisionString() +{ + /* This will be allocated on heap and never free'd, but only once so not a "real" leak. */ + static char *network_revision = nullptr; + + if (!network_revision) { + /* Start by taking a chance on the full revision string. */ + network_revision = stredup(_openttd_revision); + /* Ensure it's not longer than the packet buffer length. */ + if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0'; + + /* Tag names are not mangled further. */ + if (_openttd_revision_tagged) { + DEBUG(net, 1, "Network revision name is '%s'", network_revision); + return network_revision; + } + + /* Prepare a prefix of the git hash. + * Size is length + 1 for terminator, +2 for -g prefix. */ + assert(_openttd_revision_modified < 3); + char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-"; + githash_suffix[1] = "gum"[_openttd_revision_modified]; + for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) { + githash_suffix[i] = _openttd_revision_hash[i-2]; + } + + /* Where did the hash start in the original string? + * Overwrite from that position, unless that would go past end of packet buffer length. */ + ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision; + if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix); + /* Replace the git hash in revision string. */ + strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH); + assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than + DEBUG(net, 1, "Network revision name is '%s'", network_revision); + } + + return network_revision; +} + +/** + * Extract the git hash from the revision string. + * @param revstr The revision string (formatted as DATE-BRANCH-GITHASH). + * @return The git has part of the revision. + */ +static const char *ExtractNetworkRevisionHash(const char *revstr) +{ + return strrchr(revstr, '-'); +} + +/** + * Checks whether the given version string is compatible with our version. + * First tries to match the full string, if that fails, attempts to compare just git hashes. + * @param other the version string to compare to + */ +bool IsNetworkCompatibleVersion(const char *other) +{ + if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true; + + /* If this version is tagged, then the revision string must be a complete match, + * since there is no git hash suffix in it. + * This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */ + if (_openttd_revision_tagged) return false; + + const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString()); + const char *hash2 = ExtractNetworkRevisionHash(other); + return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0); +} + +/** + * Fill a NetworkGameInfo structure with the latest information of the server. + * @param ngi the NetworkGameInfo struct to fill with data. + */ +void FillNetworkGameInfo(NetworkGameInfo &ngi) +{ + /* Update some game_info */ + ngi.clients_on = _network_game_info.clients_on; + ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); + + ngi.use_password = !StrEmpty(_settings_client.network.server_password); + ngi.clients_max = _settings_client.network.max_clients; + ngi.companies_on = (byte)Company::GetNumItems(); + ngi.companies_max = _settings_client.network.max_companies; + ngi.spectators_on = NetworkSpectatorCount(); + ngi.spectators_max = _settings_client.network.max_spectators; + ngi.game_date = _date; + ngi.map_width = MapSizeX(); + ngi.map_height = MapSizeY(); + ngi.map_set = _settings_game.game_creation.landscape; + ngi.dedicated = _network_dedicated; + ngi.grfconfig = _grfconfig; + + strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name)); + strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision)); +} + +/** + * 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. + * @param config the GRF to handle. + */ +static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) +{ + /* Find the matching GRF file */ + const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum); + if (f == nullptr) { + /* Don't know the GRF, so mark game incompatible and the (possibly) + * already resolved name for this GRF (another server has sent the + * name of the GRF already */ + config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true); + config->status = GCS_NOT_FOUND; + } else { + config->filename = f->filename; + config->name = f->name; + config->info = f->info; + config->url = f->url; + } + SetBit(config->flags, GCF_COPY); +} + +/** + * Serializes the NetworkGameInfo struct to the packet. + * @param p the packet to write the data to. + * @param info the NetworkGameInfo struct to serialize from. + */ +void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info) +{ + p->Send_uint8 (NETWORK_GAME_INFO_VERSION); + + /* + * Please observe the order. + * The parts must be read in the same order as they are sent! + */ + + /* Update the documentation in game_info.h on changes + * to the NetworkGameInfo wire-protocol! */ + + /* NETWORK_GAME_INFO_VERSION = 4 */ + { + /* Only send the GRF Identification (GRF_ID and MD5 checksum) of + * the GRFs that are needed, i.e. the ones that the server has + * selected in the NewGRF GUI and not the ones that are used due + * to the fact that they are in [newgrf-static] in openttd.cfg */ + const GRFConfig *c; + uint count = 0; + + /* Count number of GRFs to send information about */ + for (c = info->grfconfig; c != nullptr; c = c->next) { + if (!HasBit(c->flags, GCF_STATIC)) count++; + } + p->Send_uint8 (count); // Send number of GRFs + + /* Send actual GRF Identifications */ + for (c = info->grfconfig; c != nullptr; c = c->next) { + if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident); + } + } + + /* NETWORK_GAME_INFO_VERSION = 3 */ + p->Send_uint32(info->game_date); + p->Send_uint32(info->start_date); + + /* NETWORK_GAME_INFO_VERSION = 2 */ + p->Send_uint8 (info->companies_max); + p->Send_uint8 (info->companies_on); + p->Send_uint8 (info->spectators_max); + + /* NETWORK_GAME_INFO_VERSION = 1 */ + p->Send_string(info->server_name); + p->Send_string(info->server_revision); + p->Send_uint8 (0); // Used to be server-lang. + p->Send_bool (info->use_password); + p->Send_uint8 (info->clients_max); + p->Send_uint8 (info->clients_on); + p->Send_uint8 (info->spectators_on); + p->Send_string(""); // Used to be map-name. + p->Send_uint16(info->map_width); + p->Send_uint16(info->map_height); + p->Send_uint8 (info->map_set); + p->Send_bool (info->dedicated); +} + +/** + * Deserializes the NetworkGameInfo struct from the packet. + * @param p the packet to read the data from. + * @param info the NetworkGameInfo to deserialize into. + */ +void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) +{ + static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11 + + info->game_info_version = p->Recv_uint8(); + + /* + * Please observe the order. + * The parts must be read in the same order as they are sent! + */ + + /* Update the documentation in game_info.h on changes + * to the NetworkGameInfo wire-protocol! */ + + switch (info->game_info_version) { + case 4: { + GRFConfig **dst = &info->grfconfig; + uint i; + uint num_grfs = p->Recv_uint8(); + + /* Broken/bad data. It cannot have that many NewGRFs. */ + if (num_grfs > NETWORK_MAX_GRF_COUNT) return; + + for (i = 0; i < num_grfs; i++) { + GRFConfig *c = new GRFConfig(); + DeserializeGRFIdentifier(p, &c->ident); + HandleIncomingNetworkGameInfoGRFConfig(c); + + /* Append GRFConfig to the list */ + *dst = c; + dst = &c->next; + } + FALLTHROUGH; + } + + case 3: + info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); + info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); + FALLTHROUGH; + + case 2: + info->companies_max = p->Recv_uint8 (); + info->companies_on = p->Recv_uint8 (); + info->spectators_max = p->Recv_uint8 (); + FALLTHROUGH; + + case 1: + p->Recv_string(info->server_name, sizeof(info->server_name)); + p->Recv_string(info->server_revision, sizeof(info->server_revision)); + p->Recv_uint8 (); // Used to contain server-lang. + info->use_password = p->Recv_bool (); + info->clients_max = p->Recv_uint8 (); + info->clients_on = p->Recv_uint8 (); + info->spectators_on = p->Recv_uint8 (); + if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier + info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; + info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; + } + while (p->Recv_uint8() != 0) {} // Used to contain the map-name. + info->map_width = p->Recv_uint16(); + info->map_height = p->Recv_uint16(); + info->map_set = p->Recv_uint8 (); + info->dedicated = p->Recv_bool (); + + if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0; + } +} + +/** + * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet + * @param p the packet to write the data to. + * @param grf the GRFIdentifier to serialize. + */ +void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf) +{ + uint j; + p->Send_uint32(grf->grfid); + for (j = 0; j < sizeof(grf->md5sum); j++) { + p->Send_uint8(grf->md5sum[j]); + } +} + +/** + * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet + * @param p the packet to read the data from. + * @param grf the GRFIdentifier to deserialize. + */ +void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf) +{ + uint j; + grf->grfid = p->Recv_uint32(); + for (j = 0; j < sizeof(grf->md5sum); j++) { + grf->md5sum[j] = p->Recv_uint8(); + } +} diff --git a/src/network/core/game.h b/src/network/core/game_info.h similarity index 51% rename from src/network/core/game.h rename to src/network/core/game_info.h index 29eca418f0..7767005117 100644 --- a/src/network/core/game.h +++ b/src/network/core/game_info.h @@ -6,17 +6,56 @@ */ /** - * @file game.h Information about a game that is sent between a - * game server, game client and masterserver. + * @file game_info.h Convert NetworkGameInfo to Packet and back. */ -#ifndef NETWORK_CORE_GAME_H -#define NETWORK_CORE_GAME_H +#ifndef NETWORK_CORE_GAME_INFO_H +#define NETWORK_CORE_GAME_INFO_H #include "config.h" +#include "core.h" #include "../../newgrf_config.h" #include "../../date_type.h" +/* + * NetworkGameInfo has several revisions which we still need to support on the + * wire. The table below shows the version and size for each field of the + * serialized NetworkGameInfo. + * + * Version: Bytes: Description: + * all 1 the version of this packet's structure + * + * 4+ 1 number of GRFs attached (n) + * 4+ n * 20 unique identifier for GRF files. Consists of: + * - one 4 byte variable with the GRF ID + * - 16 bytes (sent sequentially) for the MD5 checksum + * of the GRF + * + * 3+ 4 current game date in days since 1-1-0 (DMY) + * 3+ 4 game introduction date in days since 1-1-0 (DMY) + * + * 2+ 1 maximum number of companies allowed on the server + * 2+ 1 number of companies on the server + * 2+ 1 maximum number of spectators allowed on the server + * + * 1+ var string with the name of the server + * 1+ var string with the revision of the server + * 1+ 1 the language run on the server + * (0 = any, 1 = English, 2 = German, 3 = French) + * 1+ 1 whether the server uses a password (0 = no, 1 = yes) + * 1+ 1 maximum number of clients allowed on the server + * 1+ 1 number of clients on the server + * 1+ 1 number of spectators on the server + * 1 & 2 2 current game date in days since 1-1-1920 (DMY) + * 1 & 2 2 game introduction date in days since 1-1-1920 (DMY) + * 1+ var string with the name of the map + * 1+ 2 width of the map in tiles + * 1+ 2 height of the map in tiles + * 1+ 1 type of map: + * (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland) + * 1+ 1 whether the server is dedicated (0 = no, 1 = yes) + */ + /** * The game information that is not generated on-the-fly and has to * be sent to the clients. @@ -50,6 +89,17 @@ struct NetworkGameInfo : NetworkServerGameInfo { byte map_set; ///< Graphical set }; -const char * GetNetworkRevisionString(); +extern NetworkServerGameInfo _network_game_info; -#endif /* NETWORK_CORE_GAME_H */ +const char *GetNetworkRevisionString(); +bool IsNetworkCompatibleVersion(const char *other); + +void FillNetworkGameInfo(NetworkGameInfo &ngi); + +void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf); +void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf); + +void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info); +void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info); + +#endif /* NETWORK_CORE_GAME_INFO_H */ diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index d57f4eceb7..ee74c45070 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -13,6 +13,7 @@ #include "../../debug.h" #include "../../rev.h" #include "../network_func.h" +#include "game_info.h" #include "tcp_http.h" diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index df5140e2b5..ffc86d825f 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -12,6 +12,7 @@ #include "../../stdafx.h" #include "../../date_func.h" #include "../../debug.h" +#include "game_info.h" #include "udp.h" #include "../../safeguards.h" @@ -150,142 +151,6 @@ void NetworkUDPSocketHandler::ReceivePackets() } } - -/** - * Serializes the NetworkGameInfo struct to the packet - * @param p the packet to write the data to - * @param info the NetworkGameInfo struct to serialize - */ -void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info) -{ - p->Send_uint8 (NETWORK_GAME_INFO_VERSION); - - /* - * Please observe the order. - * The parts must be read in the same order as they are sent! - */ - - /* Update the documentation in udp.h on changes - * to the NetworkGameInfo wire-protocol! */ - - /* NETWORK_GAME_INFO_VERSION = 4 */ - { - /* Only send the GRF Identification (GRF_ID and MD5 checksum) of - * the GRFs that are needed, i.e. the ones that the server has - * selected in the NewGRF GUI and not the ones that are used due - * to the fact that they are in [newgrf-static] in openttd.cfg */ - const GRFConfig *c; - uint count = 0; - - /* Count number of GRFs to send information about */ - for (c = info->grfconfig; c != nullptr; c = c->next) { - if (!HasBit(c->flags, GCF_STATIC)) count++; - } - p->Send_uint8 (count); // Send number of GRFs - - /* Send actual GRF Identifications */ - for (c = info->grfconfig; c != nullptr; c = c->next) { - if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident); - } - } - - /* NETWORK_GAME_INFO_VERSION = 3 */ - p->Send_uint32(info->game_date); - p->Send_uint32(info->start_date); - - /* NETWORK_GAME_INFO_VERSION = 2 */ - p->Send_uint8 (info->companies_max); - p->Send_uint8 (info->companies_on); - p->Send_uint8 (info->spectators_max); - - /* NETWORK_GAME_INFO_VERSION = 1 */ - p->Send_string(info->server_name); - p->Send_string(info->server_revision); - p->Send_uint8 (0); // Used to be server-lang. - p->Send_bool (info->use_password); - p->Send_uint8 (info->clients_max); - p->Send_uint8 (info->clients_on); - p->Send_uint8 (info->spectators_on); - p->Send_string(""); // Used to be map-name. - p->Send_uint16(info->map_width); - p->Send_uint16(info->map_height); - p->Send_uint8 (info->map_set); - p->Send_bool (info->dedicated); -} - -/** - * Deserializes the NetworkGameInfo struct from the packet - * @param p the packet to read the data from - * @param info the NetworkGameInfo to deserialize into - */ -void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info) -{ - static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11 - - info->game_info_version = p->Recv_uint8(); - - /* - * Please observe the order. - * The parts must be read in the same order as they are sent! - */ - - /* Update the documentation in udp.h on changes - * to the NetworkGameInfo wire-protocol! */ - - switch (info->game_info_version) { - case 4: { - GRFConfig **dst = &info->grfconfig; - uint i; - uint num_grfs = p->Recv_uint8(); - - /* Broken/bad data. It cannot have that many NewGRFs. */ - if (num_grfs > NETWORK_MAX_GRF_COUNT) return; - - for (i = 0; i < num_grfs; i++) { - GRFConfig *c = new GRFConfig(); - this->ReceiveGRFIdentifier(p, &c->ident); - this->HandleIncomingNetworkGameInfoGRFConfig(c); - - /* Append GRFConfig to the list */ - *dst = c; - dst = &c->next; - } - FALLTHROUGH; - } - - case 3: - info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); - info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); - FALLTHROUGH; - - case 2: - info->companies_max = p->Recv_uint8 (); - info->companies_on = p->Recv_uint8 (); - info->spectators_max = p->Recv_uint8 (); - FALLTHROUGH; - - case 1: - p->Recv_string(info->server_name, sizeof(info->server_name)); - p->Recv_string(info->server_revision, sizeof(info->server_revision)); - p->Recv_uint8 (); // Used to contain server-lang. - info->use_password = p->Recv_bool (); - info->clients_max = p->Recv_uint8 (); - info->clients_on = p->Recv_uint8 (); - info->spectators_on = p->Recv_uint8 (); - if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier - info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; - info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; - } - while (p->Recv_uint8() != 0) {} // Used to contain the map-name. - info->map_width = p->Recv_uint16(); - info->map_height = p->Recv_uint16(); - info->map_set = p->Recv_uint8 (); - info->dedicated = p->Recv_bool (); - - if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0; - } -} - /** * Handle an incoming packets by sending it to the correct function. * @param p the received packet diff --git a/src/network/core/udp.h b/src/network/core/udp.h index ddbbd4515f..881fb0a612 100644 --- a/src/network/core/udp.h +++ b/src/network/core/udp.h @@ -13,7 +13,6 @@ #define NETWORK_CORE_UDP_H #include "address.h" -#include "game.h" #include "packet.h" /** Enum with all types of UDP packets. The order MUST not be changed **/ @@ -63,40 +62,7 @@ protected: /** * Return of server information to the client. - * This packet has several legacy versions, so we list the version and size of each "field": - * - * Version: Bytes: Description: - * all 1 the version of this packet's structure - * - * 4+ 1 number of GRFs attached (n) - * 4+ n * 20 unique identifier for GRF files. Consists of: - * - one 4 byte variable with the GRF ID - * - 16 bytes (sent sequentially) for the MD5 checksum - * of the GRF - * - * 3+ 4 current game date in days since 1-1-0 (DMY) - * 3+ 4 game introduction date in days since 1-1-0 (DMY) - * - * 2+ 1 maximum number of companies allowed on the server - * 2+ 1 number of companies on the server - * 2+ 1 maximum number of spectators allowed on the server - * - * 1+ var string with the name of the server - * 1+ var string with the revision of the server - * 1+ 1 the language run on the server - * (0 = any, 1 = English, 2 = German, 3 = French) - * 1+ 1 whether the server uses a password (0 = no, 1 = yes) - * 1+ 1 maximum number of clients allowed on the server - * 1+ 1 number of clients on the server - * 1+ 1 number of spectators on the server - * 1 & 2 2 current game date in days since 1-1-1920 (DMY) - * 1 & 2 2 game introduction date in days since 1-1-1920 (DMY) - * 1+ var string with the name of the map - * 1+ 2 width of the map in tiles - * 1+ 2 height of the map in tiles - * 1+ 1 type of map: - * (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland) - * 1+ 1 whether the server is dedicated (0 = no, 1 = yes) + * Serialized NetworkGameInfo. See game_info.h for details. * @param p The received packet. * @param client_addr The origin of the packet. */ @@ -217,15 +183,6 @@ protected: virtual void Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr); void HandleUDPPacket(Packet *p, NetworkAddress *client_addr); - - /** - * 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. - * @param config the GRF to handle - */ - virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); } public: NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr); @@ -237,9 +194,6 @@ public: void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false); void ReceivePackets(); - - void SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info); - void ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info); }; #endif /* NETWORK_CORE_UDP_H */ diff --git a/src/network/network.cpp b/src/network/network.cpp index 812456b4e2..9a45ce06e1 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -54,7 +54,6 @@ bool _network_server; ///< network-server is active bool _network_available; ///< is network mode available? bool _network_dedicated; ///< are we a dedicated server? bool _is_network_server; ///< Does this client wants to be a network-server? -NetworkServerGameInfo _network_game_info; ///< Information about our game. NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies. ClientID _network_own_client_id; ///< Our client identifier. ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client. @@ -603,9 +602,10 @@ public: } }; -/* Query a server to fetch his game-info - * If game_info is true, only the gameinfo is fetched, - * else only the client_info is fetched */ +/** + * Query a server to fetch his game-info. + * @param address the address to query. + */ void NetworkTCPQueryServer(NetworkAddress address) { if (!_network_available) return; @@ -1110,79 +1110,6 @@ void NetworkShutDown() NetworkCoreShutdown(); } -/** - * How many hex digits of the git hash to include in network revision string. - * Determined as 10 hex digits + 2 characters for -g/-u/-m prefix. - */ -static const uint GITHASH_SUFFIX_LEN = 12; - -/** - * Get the network version string used by this build. - * The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes. - */ -const char * GetNetworkRevisionString() -{ - /* This will be allocated on heap and never free'd, but only once so not a "real" leak. */ - static char *network_revision = nullptr; - - if (!network_revision) { - /* Start by taking a chance on the full revision string. */ - network_revision = stredup(_openttd_revision); - /* Ensure it's not longer than the packet buffer length. */ - if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0'; - - /* Tag names are not mangled further. */ - if (_openttd_revision_tagged) { - DEBUG(net, 1, "Network revision name is '%s'", network_revision); - return network_revision; - } - - /* Prepare a prefix of the git hash. - * Size is length + 1 for terminator, +2 for -g prefix. */ - assert(_openttd_revision_modified < 3); - char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-"; - githash_suffix[1] = "gum"[_openttd_revision_modified]; - for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) { - githash_suffix[i] = _openttd_revision_hash[i-2]; - } - - /* Where did the hash start in the original string? - * Overwrite from that position, unless that would go past end of packet buffer length. */ - ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision; - if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix); - /* Replace the git hash in revision string. */ - strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH); - assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than - DEBUG(net, 1, "Network revision name is '%s'", network_revision); - } - - return network_revision; -} - -static const char *ExtractNetworkRevisionHash(const char *revstr) -{ - return strrchr(revstr, '-'); -} - -/** - * Checks whether the given version string is compatible with our version. - * First tries to match the full string, if that fails, attempts to compare just git hashes. - * @param other the version string to compare to - */ -bool IsNetworkCompatibleVersion(const char *other) -{ - if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true; - - /* If this version is tagged, then the revision string must be a complete match, - * since there is no git hash suffix in it. - * This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */ - if (_openttd_revision_tagged) return false; - - const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString()); - const char *hash2 = ExtractNetworkRevisionHash(other); - return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0); -} - #ifdef __EMSCRIPTEN__ extern "C" { diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 1b86c3e561..7b49754515 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../strings_func.h" #include "../date_func.h" +#include "core/game_info.h" #include "network_admin.h" #include "network_base.h" #include "network_server.h" diff --git a/src/network/network_base.h b/src/network/network_base.h index 15f410dbc4..9ad0300629 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -14,6 +14,7 @@ #include "core/address.h" #include "../core/pool_type.hpp" #include "../company_type.h" +#include "../date_type.h" /** Type for the pool with client information. */ typedef Pool NetworkClientInfoPool; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index d5fe64b11d..f496923076 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -23,6 +23,7 @@ #include "../gfx_func.h" #include "../error.h" #include "../rev.h" +#include "core/game_info.h" #include "network.h" #include "network_base.h" #include "network_client.h" @@ -730,7 +731,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P /* Check all GRFs */ for (; grf_count > 0; grf_count--) { GRFIdentifier c; - this->ReceiveGRFIdentifier(p, &c); + DeserializeGRFIdentifier(p, &c); /* Check whether we know this GRF */ const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); diff --git a/src/network/network_func.h b/src/network/network_func.h index 66719b2166..a0f163345e 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -22,8 +22,8 @@ #include "../gfx_type.h" #include "../openttd.h" #include "../company_type.h" +#include "../string_type.h" -extern NetworkServerGameInfo _network_game_info; extern NetworkCompanyState *_network_company_states; extern ClientID _network_own_client_id; diff --git a/src/network/network_gamelist.h b/src/network/network_gamelist.h index 8e61f3a93b..ce35c01d8b 100644 --- a/src/network/network_gamelist.h +++ b/src/network/network_gamelist.h @@ -11,6 +11,7 @@ #define NETWORK_GAMELIST_H #include "core/address.h" +#include "core/game_info.h" #include "network_type.h" /** Structure with information shown in the game list (GUI) */ diff --git a/src/network/network_gui.h b/src/network/network_gui.h index 5124955626..b8ed68225b 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -11,6 +11,7 @@ #define NETWORK_GUI_H #include "../company_type.h" +#include "../date_type.h" #include "../economy_type.h" #include "../window_type.h" #include "network_type.h" diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 352416320d..c64eac7954 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -94,8 +94,6 @@ void NetworkAddServer(const char *b); void NetworkRebuildHostList(); void UpdateNetworkGameWindow(); -bool IsNetworkCompatibleVersion(const char *version); - /* From network_command.cpp */ /** * Everything we need to know about a command to be able to execute it. diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 67952bca69..6bc6f82916 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../strings_func.h" #include "../date_func.h" +#include "core/game_info.h" #include "network_admin.h" #include "network_server.h" #include "network_udp.h" @@ -477,7 +478,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck() p->Send_uint8 (grf_count); for (c = _grfconfig; c != nullptr; c = c->next) { - if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident); + if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident); } this->SendPacket(p); diff --git a/src/network/network_type.h b/src/network/network_type.h index 4c75346da6..4dcdd8c03d 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -10,7 +10,7 @@ #ifndef NETWORK_TYPE_H #define NETWORK_TYPE_H -#include "core/game.h" +#include "core/config.h" /** How many clients can we have */ static const uint MAX_CLIENTS = 255; diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index f7db689d4b..8e661e9393 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -16,6 +16,7 @@ #include "../date_func.h" #include "../map_func.h" #include "../debug.h" +#include "core/game_info.h" #include "network_gamelist.h" #include "network_internal.h" #include "network_udp.h" @@ -171,29 +172,10 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ } NetworkGameInfo ngi; - - /* Update some game_info */ - ngi.clients_on = _network_game_info.clients_on; - ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); - - ngi.use_password = !StrEmpty(_settings_client.network.server_password); - ngi.clients_max = _settings_client.network.max_clients; - ngi.companies_on = (byte)Company::GetNumItems(); - ngi.companies_max = _settings_client.network.max_companies; - ngi.spectators_on = NetworkSpectatorCount(); - ngi.spectators_max = _settings_client.network.max_spectators; - ngi.game_date = _date; - ngi.map_width = MapSizeX(); - ngi.map_height = MapSizeY(); - ngi.map_set = _settings_game.game_creation.landscape; - ngi.dedicated = _network_dedicated; - ngi.grfconfig = _grfconfig; - - strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name)); - strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision)); + FillNetworkGameInfo(ngi); Packet packet(PACKET_UDP_SERVER_RESPONSE); - this->SendNetworkGameInfo(&packet, &ngi); + SerializeNetworkGameInfo(&packet, &ngi); /* Let the client know that we are here */ this->SendPacket(&packet, client_addr); @@ -284,7 +266,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ GRFIdentifier c; const GRFConfig *f; - this->ReceiveGRFIdentifier(p, &c); + DeserializeGRFIdentifier(p, &c); /* Find the matching GRF file */ f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); @@ -311,7 +293,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ /* The name could be an empty string, if so take the filename */ strecpy(name, in_reply[i]->GetName(), lastof(name)); - this->SendGRFIdentifier(&packet, &in_reply[i]->ident); + SerializeGRFIdentifier(&packet, &in_reply[i]->ident); packet.Send_string(name); } @@ -326,7 +308,6 @@ protected: void Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) override; void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) override; void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) override; - void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) override; public: virtual ~ClientNetworkUDPSocketHandler() {} }; @@ -344,7 +325,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd item = NetworkGameListAddItem(*client_addr); ClearGRFConfigList(&item->info.grfconfig); - this->ReceiveNetworkGameInfo(p, &item->info); + DeserializeNetworkGameInfo(p, &item->info); item->info.compatible = true; { @@ -373,7 +354,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd packet.Send_uint8(in_request_count); for (i = 0; i < in_request_count; i++) { - this->SendGRFIdentifier(&packet, &in_request[i]->ident); + SerializeGRFIdentifier(&packet, &in_request[i]->ident); } this->SendPacket(&packet, &item->address); @@ -447,7 +428,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd char name[NETWORK_GRF_NAME_LENGTH]; GRFIdentifier c; - this->ReceiveGRFIdentifier(p, &c); + DeserializeGRFIdentifier(p, &c); p->Recv_string(name, sizeof(name)); /* An empty name is not possible under normal circumstances @@ -464,25 +445,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd } } -void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) -{ - /* Find the matching GRF file */ - const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum); - if (f == nullptr) { - /* Don't know the GRF, so mark game incompatible and the (possibly) - * already resolved name for this GRF (another server has sent the - * name of the GRF already */ - config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true); - config->status = GCS_NOT_FOUND; - } else { - config->filename = f->filename; - config->name = f->name; - config->info = f->info; - config->url = f->url; - } - SetBit(config->flags, GCF_COPY); -} - /** Broadcast to all ips */ static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) { From 84c75a7b9a8aeb60506454260f9c98454ffb8ab5 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 27 Apr 2021 19:58:32 +0200 Subject: [PATCH 002/800] Codechange: be explicit in pointer comparisons --- src/network/core/game_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index bea687af80..b664bb580a 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -103,7 +103,7 @@ bool IsNetworkCompatibleVersion(const char *other) const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString()); const char *hash2 = ExtractNetworkRevisionHash(other); - return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0); + return hash1 != nullptr && hash2 != nullptr && strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0; } /** From b3003dd163ab6b7902da33fa6cfaa29e45556db1 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 26 Apr 2021 20:02:27 +0200 Subject: [PATCH 003/800] Add: ability to retrieve game info from server over TCP --- src/network/core/tcp_game.cpp | 4 ++++ src/network/core/tcp_game.h | 19 ++++++++++++++++++- src/network/network_server.cpp | 19 +++++++++++++++++++ src/network/network_server.h | 2 ++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 06e56e2291..eb53db5acd 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -71,6 +71,8 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p) case PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p); case PACKET_CLIENT_JOIN: return this->Receive_CLIENT_JOIN(p); case PACKET_SERVER_ERROR: return this->Receive_SERVER_ERROR(p); + case PACKET_CLIENT_GAME_INFO: return this->Receive_CLIENT_GAME_INFO(p); + case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p); case PACKET_CLIENT_COMPANY_INFO: return this->Receive_CLIENT_COMPANY_INFO(p); case PACKET_SERVER_COMPANY_INFO: return this->Receive_SERVER_COMPANY_INFO(p); case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p); @@ -157,6 +159,8 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) { ret NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_BANNED); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_JOIN); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR); } +NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_INFO); } +NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); } diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index 95b5f8c6c7..6dcc0bd01f 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -24,7 +24,7 @@ */ enum PacketGameType { /* - * These first three pair of packets (thus six in + * These first four pair of packets (thus eight in * total) must remain in this order for backward * and forward compatibility between clients that * are trying to join directly. @@ -42,6 +42,10 @@ enum PacketGameType { PACKET_CLIENT_COMPANY_INFO, ///< Request information about all companies. PACKET_SERVER_COMPANY_INFO, ///< Information about a single company. + /* Packets used to get the game info. */ + PACKET_CLIENT_GAME_INFO, ///< Request information about the server. + PACKET_SERVER_GAME_INFO, ///< Information about the server. + /* * Packets after here assume that the client * and server are running the same version. As @@ -183,6 +187,19 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_ERROR(Packet *p); + /** + * Request game information. + * @param p The packet that was just received. + */ + virtual NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p); + + /** + * Sends information about the game. + * Serialized NetworkGameInfo. See game_info.h for details. + * @param p The packet that was just received. + */ + virtual NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p); + /** * Request company information (in detail). * @param p The packet that was just received. diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 6bc6f82916..fd69a8d37a 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -353,6 +353,20 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientIn return NETWORK_RECV_STATUS_OKAY; } +/** Send the client information about the server. */ +NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfo() +{ + NetworkGameInfo ngi; + FillNetworkGameInfo(ngi); + + Packet *p = new Packet(PACKET_SERVER_GAME_INFO); + SerializeNetworkGameInfo(p, &ngi); + + this->SendPacket(p); + + return NETWORK_RECV_STATUS_OKAY; +} + /** Send the client information about the companies. */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() { @@ -828,6 +842,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate() * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p ************/ +NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) +{ + return this->SendGameInfo(); +} + NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->SendCompanyInfo(); diff --git a/src/network/network_server.h b/src/network/network_server.h index 4f6033fab1..e72377e824 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -24,6 +24,7 @@ extern NetworkClientSocketPool _networkclientsocket_pool; class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler { protected: NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p) override; + NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p) override; NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p) override; NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p) override; NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p) override; @@ -40,6 +41,7 @@ protected: NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p) override; NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override; + NetworkRecvStatus SendGameInfo(); NetworkRecvStatus SendCompanyInfo(); NetworkRecvStatus SendNewGRFCheck(); NetworkRecvStatus SendWelcome(); From b57d845e55f733514d235e24f64b09a8744f3abc Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 26 Apr 2021 20:02:58 +0200 Subject: [PATCH 004/800] Codechange: refactor CheckGameCompatibility() from existing function Later commits use this function in other places too. --- src/network/core/game_info.cpp | 15 +++++++++++++++ src/network/core/game_info.h | 1 + src/network/network_udp.cpp | 14 ++++++-------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index b664bb580a..55b5d1749a 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -106,6 +106,21 @@ bool IsNetworkCompatibleVersion(const char *other) return hash1 != nullptr && hash2 != nullptr && strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0; } +/** + * Check if an game entry is compatible with our client. + */ +void CheckGameCompatibility(NetworkGameInfo &ngi) +{ + /* 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; + } +} + /** * Fill a NetworkGameInfo structure with the latest information of the server. * @param ngi the NetworkGameInfo struct to fill with data. diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index 7767005117..28aea75073 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -93,6 +93,7 @@ extern NetworkServerGameInfo _network_game_info; const char *GetNetworkRevisionString(); bool IsNetworkCompatibleVersion(const char *other); +void CheckGameCompatibility(NetworkGameInfo &ngi); void FillNetworkGameInfo(NetworkGameInfo &ngi); diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 8e661e9393..d62998794e 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -324,10 +324,15 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd /* Find next item */ item = NetworkGameListAddItem(*client_addr); + /* Clear any existing GRFConfig chain. */ ClearGRFConfigList(&item->info.grfconfig); + /* Retrieve the NetworkGameInfo from the packet. */ DeserializeNetworkGameInfo(p, &item->info); + /* Check for compatability with the client. */ + CheckGameCompatibility(item->info); + /* Ensure we consider the server online. */ + item->online = true; - item->info.compatible = true; { /* Checks whether there needs to be a request for names of GRFs and makes * the request if necessary. GRFs that need to be requested are the GRFs @@ -341,7 +346,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd uint in_request_count = 0; for (c = item->info.grfconfig; c != nullptr; c = c->next) { - if (c->status == GCS_NOT_FOUND) item->info.compatible = false; if (c->status != GCS_NOT_FOUND || strcmp(c->GetName(), UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue; in_request[in_request_count] = c; in_request_count++; @@ -369,12 +373,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name)); } - /* Check if we are allowed on this server based on the revision-match */ - item->info.version_compatible = IsNetworkCompatibleVersion(item->info.server_revision); - item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs - - item->online = true; - UpdateNetworkGameWindow(); } From 31f1db2d3ab1614f00a08a7f44b518a04aeadd3e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 26 Apr 2021 20:04:02 +0200 Subject: [PATCH 005/800] Change: no longer use UDP when entering the lobby of a server The lobby of a server requested some parts via UDP and some via TCP. This is strictly seen fine, but for future extensions it is a lot easier if just one protocol is used. --- src/network/network.cpp | 2 +- src/network/network_client.cpp | 34 ++++++++++++++++++++++++++++++---- src/network/network_client.h | 3 ++- src/network/network_gui.cpp | 17 +++++++++++++---- src/network/network_gui.h | 2 ++ 5 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 9a45ce06e1..c0b2e06fd4 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -598,7 +598,7 @@ public: { _networking = true; new ClientNetworkGameSocketHandler(s); - MyClient::SendCompanyInformationQuery(); + MyClient::SendInformationQuery(); } }; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index f496923076..af7073e558 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -27,6 +27,7 @@ #include "network.h" #include "network_base.h" #include "network_client.h" +#include "network_gamelist.h" #include "../core/backup_type.hpp" #include "../thread.h" @@ -341,15 +342,18 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1); * DEF_CLIENT_SEND_COMMAND has no parameters ************/ -/** Query the server for company information. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyInformationQuery() +/** + * Query the server for server information. + */ +NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery() { my_client->status = STATUS_COMPANY_INFO; _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO; SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); - Packet *p = new Packet(PACKET_CLIENT_COMPANY_INFO); - my_client->SendPacket(p); + my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO)); + my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO)); + return NETWORK_RECV_STATUS_OKAY; } @@ -571,6 +575,28 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet * return NETWORK_RECV_STATUS_SERVER_BANNED; } +NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) +{ + if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + + NetworkGameList *item = GetLobbyGameInfo(); + + /* Clear any existing GRFConfig chain. */ + ClearGRFConfigList(&item->info.grfconfig); + /* Retrieve the NetworkGameInfo from the packet. */ + DeserializeNetworkGameInfo(p, &item->info); + /* Check for compatability with the client. */ + CheckGameCompatibility(item->info); + /* Ensure we consider the server online. */ + item->online = true; + + 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; + return NETWORK_RECV_STATUS_CLOSE_QUERY; +} + NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { if (this->status != STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET; diff --git a/src/network/network_client.h b/src/network/network_client.h index d1ffe1c1d1..66cdb8ba57 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -43,6 +43,7 @@ protected: NetworkRecvStatus Receive_SERVER_FULL(Packet *p) override; NetworkRecvStatus Receive_SERVER_BANNED(Packet *p) override; NetworkRecvStatus Receive_SERVER_ERROR(Packet *p) override; + NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p) override; NetworkRecvStatus Receive_SERVER_COMPANY_INFO(Packet *p) override; NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet *p) override; NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet *p) override; @@ -79,7 +80,7 @@ public: NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override; void ClientError(NetworkRecvStatus res); - static NetworkRecvStatus SendCompanyInformationQuery(); + static NetworkRecvStatus SendInformationQuery(); static NetworkRecvStatus SendJoin(); static NetworkRecvStatus SendCommand(const CommandPacket *cp); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index ebba47d851..57127aee81 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1482,10 +1482,10 @@ struct NetworkLobbyWindow : public Window { break; case WID_NL_REFRESH: // Refresh - NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info - NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data /* Clear the information so removed companies don't remain */ for (auto &company : this->company_info) company = {}; + + NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); break; } } @@ -1553,8 +1553,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); - NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info - NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data + NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); } @@ -1570,6 +1569,16 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company) return (lobby != nullptr && company < MAX_COMPANIES) ? &lobby->company_info[company] : nullptr; } +/** + * Get the game information for the lobby. + * @return the game info struct to write the (downloaded) data to. + */ +NetworkGameList *GetLobbyGameInfo() +{ + NetworkLobbyWindow *lobby = dynamic_cast(FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY)); + return lobby != nullptr ? lobby->server : nullptr; +} + /* The window below gives information about the connected clients * and also makes able to kick them (if server) and stuff like that. */ diff --git a/src/network/network_gui.h b/src/network/network_gui.h index b8ed68225b..e4ccf4e783 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -15,6 +15,7 @@ #include "../economy_type.h" #include "../window_type.h" #include "network_type.h" +#include "network_gamelist.h" void ShowNetworkNeedPassword(NetworkPasswordType npt); void ShowNetworkChatQueryWindow(DestType type, int dest); @@ -37,5 +38,6 @@ struct NetworkCompanyInfo : NetworkCompanyStats { }; NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company); +NetworkGameList *GetLobbyGameInfo(); #endif /* NETWORK_GUI_H */ From a341852cd56d6a3f83dfdb293426b1c38786da0b Mon Sep 17 00:00:00 2001 From: Milek7 Date: Wed, 28 Apr 2021 00:22:03 +0200 Subject: [PATCH 006/800] Fix: missing include in network/core/packet.h (#9123) --- src/network/core/packet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/core/packet.h b/src/network/core/packet.h index d55dad316a..bc7bab6c4f 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -17,6 +17,7 @@ #include "core.h" #include "../../string_type.h" #include +#include typedef uint16 PacketSize; ///< Size of the whole packet. typedef uint8 PacketType; ///< Identifier for the packet From 267703c14be579b168125e2b3fbab2e407638ced Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 28 Apr 2021 17:53:26 +0000 Subject: [PATCH 007/800] Update: Translations from eints spanish (mexican): 40 changes by absay english (us): 1 change by 2TallTyler korean: 3 changes by telk5093 german: 1 change by danidoedel finnish: 1 change by hpiirai catalan: 1 change by J0anJosep portuguese: 45 changes by azulcosta portuguese (brazilian): 44 changes by Vimerum --- src/lang/brazilian_portuguese.txt | 46 +++++++++++++++++++++++++++-- src/lang/catalan.txt | 1 + src/lang/english_US.txt | 1 + src/lang/finnish.txt | 1 + src/lang/german.txt | 1 + src/lang/korean.txt | 5 ++-- src/lang/portuguese.txt | 48 +++++++++++++++++++++++++++++-- src/lang/spanish_MX.txt | 42 +++++++++++++++++++++++++-- 8 files changed, 136 insertions(+), 9 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 92c6929b82..96e9fbbd1c 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaio STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Dirigem na esquerda STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Dirigem na direita -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das cidades +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nome das cidades: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Selecionar o estilo dos nomes das cidades ############ start of townname region @@ -994,6 +994,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :A cada 12 meses STR_GAME_OPTIONS_LANGUAGE :{BLACK}Idioma STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Selecionar o idioma da interface do jogo +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% concluído) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Tela cheia STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Marcar esta caixa para jogar OpenTTD modo de tela cheia @@ -1991,6 +1992,8 @@ STR_FACE_TIE :Gravata: STR_FACE_EARRING :Brinco: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Alterar gravata ou brinco +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador @@ -2054,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}O nome d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Definir senha STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteja o jogo com uma senha se não desejar que seja publicamente acessível +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilidade +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se outras pessoas podem ver seu servidor na lista pública STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Num máx de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Escolha o número máximo de clientes. Não é necessário estarem todos preenchidos @@ -2117,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa está protegida. Digite a senha # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jogadores online # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijogador +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nome +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nome do servidor que você está jogando +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Edita o nome do seu servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nome do servidor +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidade +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se outras pessoas podem ver seu servidor na lista pública +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nome +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Seu nome de jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Edita seu nome de jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Seu nome de jogador +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Ações administrativas a serem executadas para esse cliente +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Ações administrativas a serem executadas para essa empresa +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Junta-se a essa empresa +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Envia uma mensagem a esse jogador +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Envia uma mensagem a todos os jogadores dessa empresa +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Envia uma mensagem a todos os espectadores +STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Cria uma nova empresa e se une a ela +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Esse é você +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Esse é o hospedeiro do jogo +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Banir +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Excluir +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Desbloqueio com senha +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Ação de administrador +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Você tem certeza que quer expulsar o jogador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Você tem certeza que quer banir o jogador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Você tem certeza que quer excluir a empresa '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Você tem certeza que quer restaurar a senha da empresa '{COMPANY}'? STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente @@ -2166,6 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Não foi STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi possível estabelecer conexão STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a conexão foi encerrada +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multijogador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A versão deste cliente não condiz com a versão do servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Senha incorreta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}O servidor está cheio @@ -2178,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Você de STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Seu computador é lento demais para acompanhar o servidor STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Seu computador demorou demais para baixar o mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Seu computador demorou demais para entrar no servidor +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Seu nome de jogador não é válido ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral @@ -2200,6 +2240,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :não recebeu se STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :tempo esgotado STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :a baixa do mapa demorou demais STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :o processamento do mapa demorou demais +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nome de cliente inválido ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possível perda de conexão @@ -3039,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atenção: STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erro: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Erro Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Um erro de NewGRF fatal ocorreu:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Um erro NewGRF ocorreu:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} não irá funcionar com a versão do TTDPatch encontrada pelo OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} funciona na versão {STRING} de TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} é projetado para ser usado com {STRING} diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 6dd49f586b..34b6cfb0b4 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -3080,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Alerta: {S STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}S'ha produït un error fatal de NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}S'ha produït un error relacionat amb els NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionarà amb la versió TTDPatch informada per l'OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} és per la versió {STRING} de TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} està dissenyat per ser utilitzat amb {STRING} diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 444e46462f..dd81df78e3 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -3079,6 +3079,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warning: { STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}A fatal NewGRF error has occurred:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}A NewGRF error has occurred:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} will not work with the TTDPatch version reported by OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} is for the {STRING} version of TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} is designed to be used with {STRING} diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 4e795f5949..4b5765492b 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -3079,6 +3079,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Varoitus: STR_NEWGRF_ERROR_MSG_ERROR :{RED}Virhe: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Virhe: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Vakava NewGRF-virhe on tapahtunut:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF-virhe on tapahtunut:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} ei toimi OpenTTD:n ilmoittaman TTDPatch-version kanssa STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} on TTD:n {STRING}-versiota varten STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} ja {STRING} on suunniteltu toimimaan yhdessä diff --git a/src/lang/german.txt b/src/lang/german.txt index 2c30fea557..79df8af49c 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -3080,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warnung: { STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fehler: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Schwerer Fehler: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ein schwerer NewGRF-Fehler ist aufgetreten:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ein NewGRF-Fehler ist aufgetreten:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} funktioniert nicht im Zusammenhang mit der von OpenTTD ermittelten TTDPatch-Version STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} ist für die {STRING}-Version von TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} ist für die Nutzung mit {STRING} vorgesehen diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 95efeeead7..2a51f3dfcc 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -1808,8 +1808,8 @@ STR_CONFIG_ERROR :{WHITE}설정 STR_CONFIG_ERROR_ARRAY :{WHITE}... 배열 '{STRING}'에서 오류 발생 STR_CONFIG_ERROR_INVALID_VALUE :{WHITE}... '{1:STRING}'에 잘못된 값('{0:STRING}')이 지정되었습니다. STR_CONFIG_ERROR_TRAILING_CHARACTERS :{WHITE}... '{STRING}' 설정의 끝에 후행 문자가 있습니다. -STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... NewGRF '{STRING}' 무시중: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침 -STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 NewGRF '{STRING}' 무시중: {STRING} +STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... '{STRING}' NewGRF를 무시합니다: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침 +STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 '{STRING}' NewGRF를 무시합니다: {STRING} STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :찾을 수 없음 STR_CONFIG_ERROR_INVALID_GRF_UNSAFE :사용하기에 불안함 STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :NewGRF 시스템 @@ -3080,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}경고: {S STR_NEWGRF_ERROR_MSG_ERROR :{RED}오류: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}치명적 오류: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}치명적인 NewGRF 오류가 발생했습니다:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF 관련 오류가 발생했습니다:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING}{G 1 "은" "는"} OpenTTD에서 보고된 TTDPatch 버전에서 작동하지 않을 것입니다 STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING}{G 1 "은" "는"} {STRING} 버전의 TTD를 위한 것입니다 STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING}{G 1 "은" "는"} {STRING}{G 1 "와" "과"} 같이 사용해야 합니다 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index fadf6b9f90..d97e52569a 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit da Mal STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Circular pela esquerda STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Circular pela direita -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das localidades +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das localidades: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Seleccionar o estilo dos nomes das localidades ############ start of townname region @@ -994,6 +994,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Cada 12 meses STR_GAME_OPTIONS_LANGUAGE :{BLACK}Idioma STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Seleccionar o idioma da interface do jogo +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% completado) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Ecrã Inteiro STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Seleccione esta opção para jogar o OpenTTD em modo de ecrã inteiro @@ -1991,6 +1992,8 @@ STR_FACE_TIE :Gravata: STR_FACE_EARRING :Brinco: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Mudar gravata ou brinco +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador @@ -2043,7 +2046,7 @@ STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adiciona STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP :{BLACK}Iniciar um servidor próprio -STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Digite teu nome +STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Introduza o seu nome STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Introduza o endereço IP do servidor # Start new multiplayer server @@ -2054,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}O nome d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Definir palavra-chave STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteja o jogo com uma senha se não desejar que pessoas indesejadas se juntem +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilidade +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se as outras pessoas podem ver o seu servidor na lista pública STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Escolha o número máximo de clientes. Não necessitam estar todos presentes. @@ -2117,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduza palavra-chave # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jogadores "online" # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multi-jogador +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nome +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nome do servidor onde está a jogar +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Editar o nome do seu servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nome do servidor +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidade +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se as outras pessoas podem ver o seu servidor na lista pública +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nome +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}O seu nome de jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Editar o seu nome de jogador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :O seu nome de jogador +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Ações administrativas para executar a este cliente +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Ações administrativas para executar a esta empresa +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Juntar-se a esta empresa +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Enviar uma mensagem a este jogador +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Enviar uma mensagem a todos os jogadores desta empresa +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Enviar uma mensagem a todos os espectadores +STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Criar uma nova empresa e juntar-se a ela +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este é você +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este é o anfitrião do jogo +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Banir +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Apagar +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :desbloquear com palavra-passe +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Ação administrativa +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Tem a certeza que quer expulsar o jogador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Tem a certeza que quer banir o jogador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Tem a certeza que quer apagar a empresa '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Tem a certeza que quer restabelecer a palavra-chave da empresa '{COMPANY}'? STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente @@ -2166,6 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Não foi STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi possível estabelecer ligação STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM}. STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a ligação foi encerrada +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}O seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multi-jogador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A revisão deste cliente não condiz com a revisão do servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Palavra-chave incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Servidor cheio @@ -2178,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Demorou STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}O seu computador é demasiado lento para acompanhar com o servidor STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}O seu computador demorou demasiado a transferir o mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}O seu computador demorou demasiado a ligar ao servidor +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}O seu nome de jogador não é válido ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral @@ -2200,6 +2240,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :não foi recebi STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :demasiado tempo (geral) STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :demorou demasiado a transferir o mapa STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :demorou demasiado a processar o mapa +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nome de cliente inválido ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possível perda de conexão @@ -3039,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Aviso: {SI STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erro: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ocorreu um erro fatal num NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ocorreu um erro de NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} não funciona com a versão do TTDPatch reportada por OpenTTD. STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} é para a versão {STRING} do TTD. STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} foi concebido para ser usado com {STRING} diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 74b8b10cff..08d5bdea6b 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit malasio STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Manejar por la izquierda STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Manejar por la derecha -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de pueblos +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de pueblos: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Elegir el estilo de nombres para pueblos ############ start of townname region @@ -1992,6 +1992,8 @@ STR_FACE_TIE :Corbata: STR_FACE_EARRING :Aretes: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o aretes +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador @@ -2055,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}La parti STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Establecer contraseña STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteger la partida con una contraseña para prevenir el acceso a otras personas +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilidad +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Quién puede ver tu servidor en la lista pública STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Número máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Elegir el número máximo de clientes. No es necesario que se conecten todos @@ -2118,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introducir contraseña # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jugadores conectados # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijugador +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nombre +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nombre del servidor en el que estás jugando +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Modificar nombre del servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nombre del servidor +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidad +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Quién puede ver tu servidor en la lista pública +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nombre +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Tu nombre de jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Modificar nombre de jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Tu nombre de jugador +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Acciones administrativas para este cliente +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Acciones administrativas para esta empresa +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Unirse a esta empresa +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Enviar mensaje a este jugador +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Enviar mensaje a todos los jugadores de la empresa +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Enviar mensaje a los espectadores +STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva empresa) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crear nueva empresa y unirse a ella +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este eres tú +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este es el host del juego +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bloquear acceso +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Eliminar +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Restablecer contraseña +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Acción de aministrador +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}¿Sacar al jugador "{STRING}"? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}¿Bloquear acceso al jugador "{STRING}"? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}¿Eliminar la empresa "{COMPANY}"? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}¿Restablecer contraseña de la empresa "{COMPANY}"? STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente @@ -3043,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atención: STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Error fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ocurrió un error fatal de NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ocurrió un error de NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionará con la con la versión de TTDPatch reportada por OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} es la para la versión {STRING} de TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} está diseñado para usarse con {STRING} From 8e9eca6dddf238c77f01d93afcefcca262447e98 Mon Sep 17 00:00:00 2001 From: Milek7 Date: Wed, 28 Apr 2021 23:06:47 +0200 Subject: [PATCH 008/800] Codechange: Use __attribute__ access none to silence GCC 11 -Wmaybe-uninitialized warnings (#9124) --- src/stdafx.h | 6 ++++++ src/string_func.h | 16 ++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/stdafx.h b/src/stdafx.h index 6a33223455..19009f5ff5 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -138,6 +138,12 @@ # endif #endif /* __GNUC__ || __clang__ */ +#if __GNUC__ > 11 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1) +# define NOACCESS(args) __attribute__ ((access (none, args))) +#else +# define NOACCESS(args) +#endif + #if defined(__WATCOMC__) # define NORETURN # define CDECL diff --git a/src/string_func.h b/src/string_func.h index 6c894b3cba..4fe9d7b825 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -30,25 +30,25 @@ #include "core/bitmath_func.hpp" #include "string_type.h" -char *strecat(char *dst, const char *src, const char *last); -char *strecpy(char *dst, const char *src, const char *last); -char *stredup(const char *src, const char *last = nullptr); +char *strecat(char *dst, const char *src, const char *last) NOACCESS(3); +char *strecpy(char *dst, const char *src, const char *last) NOACCESS(3); +char *stredup(const char *src, const char *last = nullptr) NOACCESS(2); -int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4); -int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0); +int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4) NOACCESS(2); +int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0) NOACCESS(2); char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); -void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2); std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void ValidateString(const char *str); -void str_fix_scc_encoded(char *str, const char *last); +void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2); void str_strip_colours(char *str); bool strtolower(char *str); bool strtolower(std::string &str, std::string::size_type offs = 0); -bool StrValid(const char *str, const char *last); +bool StrValid(const char *str, const char *last) NOACCESS(2); void StrTrimInPlace(char *str); /** From 96dc0d04ecb12ee83909782b9a2c39f336de7d9a Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 28 Apr 2021 23:09:03 +0200 Subject: [PATCH 009/800] Fix b3003dd1: swap SERVER_GAME_INFO with CLIENT_GAME_INFO (#9129) The idea is that if you query an older server that does not support this packet yet, the client receives an error. The assumption was that on every "illegal packet" the connection would be closed. This turns out to be false. Now CLIENT_GAME_INFO aligns with the old PACKET_CLIENT_NEWGRFS_CHECKED, which does a pre-check (which fails), and an error is sent back and the connection is closed. This is not a nice solution, but it is the best we got. --- src/network/core/tcp_game.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index 6dcc0bd01f..5fe9cd465d 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -43,8 +43,8 @@ enum PacketGameType { PACKET_SERVER_COMPANY_INFO, ///< Information about a single company. /* Packets used to get the game info. */ - PACKET_CLIENT_GAME_INFO, ///< Request information about the server. PACKET_SERVER_GAME_INFO, ///< Information about the server. + PACKET_CLIENT_GAME_INFO, ///< Request information about the server. /* * Packets after here assume that the client From ae7f07de74a8d242dce8a67eaece26be9d06f064 Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 28 Apr 2021 22:32:43 +0100 Subject: [PATCH 010/800] Fix: Incorrect vertical alignment of icon and text in DropDownListIconItem. (#9133) This happens if the bounding dimensions are changed so that each item is the same size, as happens on the railtype/roadtype dropdown lists, as the vertical offset was calculated before this dimension is changed. --- src/widgets/dropdown.cpp | 12 +++--------- src/widgets/dropdown_type.h | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 97c755e4bc..6b1debb9db 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -72,13 +72,7 @@ StringID DropDownListCharStringItem::String() const DropDownListIconItem::DropDownListIconItem(SpriteID sprite, PaletteID pal, StringID string, int result, bool masked) : DropDownListParamStringItem(string, result, masked), sprite(sprite), pal(pal) { this->dim = GetSpriteSize(sprite); - if (this->dim.height < (uint)FONT_HEIGHT_NORMAL) { - this->sprite_y = (FONT_HEIGHT_NORMAL - dim.height) / 2; - this->text_y = 0; - } else { - this->sprite_y = 0; - this->text_y = (dim.height - FONT_HEIGHT_NORMAL) / 2; - } + this->sprite_y = dim.height; } uint DropDownListIconItem::Height(uint width) const @@ -94,8 +88,8 @@ uint DropDownListIconItem::Width() const void DropDownListIconItem::Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const { bool rtl = _current_text_dir == TD_RTL; - DrawSprite(this->sprite, this->pal, rtl ? right - this->dim.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + this->sprite_y); - DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : (this->dim.width + WD_FRAMERECT_LEFT)), right - WD_FRAMERECT_RIGHT - (rtl ? (this->dim.width + WD_FRAMERECT_RIGHT) : 0), top + this->text_y, this->String(), sel ? TC_WHITE : TC_BLACK); + DrawSprite(this->sprite, this->pal, rtl ? right - this->dim.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, CenterBounds(top, bottom, this->sprite_y)); + DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : (this->dim.width + WD_FRAMERECT_LEFT)), right - WD_FRAMERECT_RIGHT - (rtl ? (this->dim.width + WD_FRAMERECT_RIGHT) : 0), CenterBounds(top, bottom, FONT_HEIGHT_NORMAL), this->String(), sel ? TC_WHITE : TC_BLACK); } void DropDownListIconItem::SetDimension(Dimension d) diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index a1f240e96d..5dfa9ed58b 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -84,7 +84,6 @@ class DropDownListIconItem : public DropDownListParamStringItem { PaletteID pal; Dimension dim; uint sprite_y; - uint text_y; public: DropDownListIconItem(SpriteID sprite, PaletteID pal, StringID string, int result, bool masked); From 3b3d80c8efbf3310a80e0540b4436a7ded147378 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 28 Apr 2021 21:49:58 +0100 Subject: [PATCH 011/800] Cleanup: Replace FOR_ALL_SORTED_RAILTYPES macro with range iterator. --- src/company_gui.cpp | 9 +++------ src/rail.h | 6 ------ src/rail_gui.cpp | 5 ++--- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index c9e3eaf861..3706db2f5e 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1840,8 +1840,7 @@ struct CompanyInfrastructureWindow : Window size->width = std::max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width); - RailType rt; - FOR_ALL_SORTED_RAILTYPES(rt) { + for (const auto &rt : _sorted_railtypes) { if (HasBit(this->railtypes, rt)) { lines++; SetDParam(0, GetRailTypeInfo(rt)->strings.name); @@ -1973,8 +1972,7 @@ struct CompanyInfrastructureWindow : Window if (this->railtypes != RAILTYPES_NONE) { /* Draw name of each valid railtype. */ - RailType rt; - FOR_ALL_SORTED_RAILTYPES(rt) { + for (const auto &rt : _sorted_railtypes) { if (HasBit(this->railtypes, rt)) { SetDParam(0, GetRailTypeInfo(rt)->strings.name); DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING); @@ -1991,8 +1989,7 @@ struct CompanyInfrastructureWindow : Window case WID_CI_RAIL_COUNT: { /* Draw infrastructure count for each valid railtype. */ uint32 rail_total = c->infrastructure.GetRailTotal(); - RailType rt; - FOR_ALL_SORTED_RAILTYPES(rt) { + for (const auto &rt : _sorted_railtypes) { if (HasBit(this->railtypes, rt)) { this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total)); } diff --git a/src/rail.h b/src/rail.h index c5775b9467..a0bbb0109b 100644 --- a/src/rail.h +++ b/src/rail.h @@ -464,10 +464,4 @@ RailType AllocateRailType(RailTypeLabel label); extern std::vector _sorted_railtypes; extern RailTypes _railtypes_hidden_mask; -/** - * Loop header for iterating over railtypes, sorted by sortorder. - * @param var Railtype. - */ -#define FOR_ALL_SORTED_RAILTYPES(var) for (uint8 index = 0; index < _sorted_railtypes.size() && (var = _sorted_railtypes[index], true) ; index++) - #endif /* RAIL_H */ diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index f0f5beccac..49c7d736af 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -2191,17 +2191,16 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option) } Dimension d = { 0, 0 }; - RailType rt; /* Get largest icon size, to ensure text is aligned on each menu item. */ if (!for_replacement) { - FOR_ALL_SORTED_RAILTYPES(rt) { + for (const auto &rt : _sorted_railtypes) { if (!HasBit(used_railtypes, rt)) continue; const RailtypeInfo *rti = GetRailTypeInfo(rt); d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_rail)); } } - FOR_ALL_SORTED_RAILTYPES(rt) { + for (const auto &rt : _sorted_railtypes) { /* If it's not used ever, don't show it to the user. */ if (!HasBit(used_railtypes, rt)) continue; From de81afdf4bfb97a48533489101e3aa0e5eb2cb4f Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 28 Apr 2021 21:50:23 +0100 Subject: [PATCH 012/800] Cleanup: Replace FOR_ALL_SORTED_ROADTYPES macro with range iterator. --- src/company_gui.cpp | 9 +++------ src/road.h | 6 ------ src/road_gui.cpp | 10 ++++------ 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 3706db2f5e..f9eceba177 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1862,8 +1862,7 @@ struct CompanyInfrastructureWindow : Window size->width = std::max(size->width, GetStringBoundingBox(widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT).width); - RoadType rt; - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) { lines++; SetDParam(0, GetRoadTypeInfo(rt)->strings.name); @@ -2005,8 +2004,7 @@ struct CompanyInfrastructureWindow : Window DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT); /* Draw name of each valid roadtype. */ - RoadType rt; - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) { SetDParam(0, GetRoadTypeInfo(rt)->strings.name); DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING); @@ -2019,8 +2017,7 @@ struct CompanyInfrastructureWindow : Window case WID_CI_ROAD_COUNT: case WID_CI_TRAM_COUNT: { uint32 road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal(); - RoadType rt; - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) { this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total)); } diff --git a/src/road.h b/src/road.h index 1082ab2729..becbf40512 100644 --- a/src/road.h +++ b/src/road.h @@ -305,10 +305,4 @@ bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt); extern std::vector _sorted_roadtypes; extern RoadTypes _roadtypes_hidden_mask; -/** - * Loop header for iterating over roadtypes, sorted by sortorder. - * @param var Roadtype. - */ -#define FOR_ALL_SORTED_ROADTYPES(var) for (uint8 index = 0; index < _sorted_roadtypes.size() && (var = _sorted_roadtypes[index], true) ; index++) - #endif /* ROAD_H */ diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 9aa1952477..9cc68028d5 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -1313,17 +1313,16 @@ DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, b } Dimension d = { 0, 0 }; - RoadType rt; /* Get largest icon size, to ensure text is aligned on each menu item. */ if (!for_replacement) { - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (!HasBit(used_roadtypes, rt)) continue; const RoadTypeInfo *rti = GetRoadTypeInfo(rt); d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_road)); } } - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { /* If it's not used ever, don't show it to the user. */ if (!HasBit(used_roadtypes, rt)) continue; @@ -1365,13 +1364,12 @@ DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts) /* If it's not used ever, don't show it to the user. */ Dimension d = { 0, 0 }; - RoadType rt; - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (!HasBit(used_roadtypes, rt)) continue; const RoadTypeInfo *rti = GetRoadTypeInfo(rt); d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_road)); } - FOR_ALL_SORTED_ROADTYPES(rt) { + for (const auto &rt : _sorted_roadtypes) { if (!HasBit(used_roadtypes, rt)) continue; const RoadTypeInfo *rti = GetRoadTypeInfo(rt); From 20ac0b41484ebcaef3f8bdc9d4410903fd499386 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 28 Apr 2021 21:50:46 +0100 Subject: [PATCH 013/800] Cleanup: Replace FOR_ALL_SORTED_CARGOSPECS macro with range iterator. --- src/cargotype.cpp | 2 +- src/cargotype.h | 7 ------- src/strings.cpp | 3 +-- src/vehicle_gui.cpp | 3 +-- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/cargotype.cpp b/src/cargotype.cpp index e30b9899f1..81818d5f9d 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -181,7 +181,7 @@ void InitializeSortedCargoSpecs() _standard_cargo_mask = 0; _sorted_standard_cargo_specs_size = 0; - FOR_ALL_SORTED_CARGOSPECS(cargo) { + for (const auto &cargo : _sorted_cargo_specs) { if (cargo->classes & CC_SPECIAL) break; _sorted_standard_cargo_specs_size++; SetBit(_standard_cargo_mask, cargo->Index()); diff --git a/src/cargotype.h b/src/cargotype.h index f6b3eaead5..afc501a2f2 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -156,13 +156,6 @@ static inline bool IsCargoInClass(CargoID c, CargoClass cc) #define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, CargoTypes, cargo_bits) -/** - * Loop header for iterating over cargoes, sorted by name. This includes phony cargoes like regearing cargoes. - * @param var Reference getting the cargospec. - * @see CargoSpec - */ -#define FOR_ALL_SORTED_CARGOSPECS(var) for (uint8 index = 0; index < _sorted_cargo_specs.size() && (var = _sorted_cargo_specs[index], true) ; index++) - /** * Loop header for iterating over 'real' cargoes, sorted by name. Phony cargoes like regearing cargoes are skipped. * @param var Reference getting the cargospec. diff --git a/src/strings.cpp b/src/strings.cpp index d533db1fce..e340a2b1c4 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1171,8 +1171,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg CargoTypes cmask = args->GetInt64(SCC_CARGO_LIST); bool first = true; - const CargoSpec *cs; - FOR_ALL_SORTED_CARGOSPECS(cs) { + for (const auto &cs : _sorted_cargo_specs) { if (!HasBit(cmask, cs->Index())) continue; if (buff >= last - 2) break; // ',' and ' ' diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index f4b5185865..c6f2ee52a7 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -513,8 +513,7 @@ struct RefitWindow : public Window { /* Loop through all cargoes in the refit mask */ int current_index = 0; - const CargoSpec *cs; - FOR_ALL_SORTED_CARGOSPECS(cs) { + for (const auto &cs : _sorted_cargo_specs) { CargoID cid = cs->Index(); /* Skip cargo type if it's not listed */ if (!HasBit(cmask, cid)) { From 356bbbb90aaa3ac981b69693ce40d3afdaa6ea33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Thu, 29 Apr 2021 14:26:08 +0200 Subject: [PATCH 014/800] Fix: [MinGW] Set minimum OS version to Windows XP (#9135) --- src/network/network_chat_gui.cpp | 6 +++--- src/saveload/saveload.cpp | 2 +- src/script/api/script_date.cpp | 3 ++- src/script/squirrel.cpp | 5 +++-- src/stdafx.h | 15 +++++++++------ 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 862a0a4cbf..14edc15032 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -7,9 +7,6 @@ /** @file network_chat_gui.cpp GUI for handling chat messages. */ -#include /* va_list */ -#include - #include "../stdafx.h" #include "../strings_func.h" #include "../blitter/factory.hpp" @@ -28,6 +25,9 @@ #include "table/strings.h" +#include /* va_list */ +#include + #include "../safeguards.h" /** The draw buffer must be able to contain the chat message, client name and the "[All]" message, diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index dcfcc9f431..f5e823a0df 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -19,7 +19,6 @@ *
  • repeat this until everything is done, and flush any remaining output to file * */ -#include #include "../stdafx.h" #include "../debug.h" @@ -44,6 +43,7 @@ #include "../fios.h" #include "../error.h" #include +#include #include #ifdef __EMSCRIPTEN__ # include diff --git a/src/script/api/script_date.cpp b/src/script/api/script_date.cpp index 9946a26ec6..ae3dff78c6 100644 --- a/src/script/api/script_date.cpp +++ b/src/script/api/script_date.cpp @@ -7,11 +7,12 @@ /** @file script_date.cpp Implementation of ScriptDate. */ -#include #include "../../stdafx.h" #include "script_date.hpp" #include "../../date_func.h" +#include + #include "../../safeguards.h" /* static */ bool ScriptDate::IsValidDate(Date date) diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index b9d614e8d0..77f84a6416 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -7,8 +7,6 @@ /** @file squirrel.cpp the implementation of the Squirrel class. It handles all Squirrel-stuff and gives a nice API back to work with. */ -#include -#include #include "../stdafx.h" #include "../debug.h" #include "squirrel_std.hpp" @@ -21,6 +19,9 @@ #include <../squirrel/sqvm.h> #include "../core/alloc_func.hpp" +#include +#include + /** * In the memory allocator for Squirrel we want to directly use malloc/realloc, so when the OS * does not have enough memory the game does not go into unrecoverable error mode and kill the diff --git a/src/stdafx.h b/src/stdafx.h index 19009f5ff5..819eb0e614 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -10,6 +10,15 @@ #ifndef STDAFX_H #define STDAFX_H +#if defined(_WIN32) + /* MinGW defaults to Windows 7 if none of these are set, and they must be set before any MinGW header is included */ +# define NTDDI_VERSION NTDDI_WINXP // Windows XP +# define _WIN32_WINNT 0x501 // Windows XP +# define _WIN32_WINDOWS 0x501 // Windows XP +# define WINVER 0x0501 // Windows XP +# define _WIN32_IE_ 0x0600 // 6.0 (XP+) +#endif + #ifdef _MSC_VER /* Stop Microsoft (and clang-cl) compilers from complaining about potentially-unsafe/potentially-non-standard functions */ # define _CRT_SECURE_NO_DEPRECATE @@ -164,12 +173,6 @@ /* Stuff for MSVC */ #if defined(_MSC_VER) # pragma once -# define NTDDI_VERSION NTDDI_WINXP // Windows XP -# define _WIN32_WINNT 0x501 // Windows XP -# define _WIN32_WINDOWS 0x501 // Windows XP -# define WINVER 0x0501 // Windows XP -# define _WIN32_IE_ 0x0600 // 6.0 (XP+) - # define NOMINMAX // Disable min/max macros in windows.h. # pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data From 72a05921b06b02b04af6e86d981f55de4960ca61 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 29 Apr 2021 17:52:22 +0000 Subject: [PATCH 015/800] Update: Translations from eints norwegian (bokmal): 16 changes by Anolitt finnish: 2 changes by hpiirai --- src/lang/finnish.txt | 4 ++-- src/lang/norwegian_bokmal.txt | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 4b5765492b..4435cca260 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -4463,7 +4463,7 @@ STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Ei voi r STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Satamaa ei voi rakentaa tähän... STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Lentokenttää ei voi rakentaa... -STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liitä yhteen useampi asema/lastausalue. +STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva asema tai kuormausalue. STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... asema liian levittäytynyt STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Liian monta asemaa ja lastausaluetta. STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Rautatieasema on jakautunut liian moneen osaan @@ -4496,7 +4496,7 @@ STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Satama p STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Lentokenttä pitää tuhota ensin. # Waypoint related errors -STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liittää useamman kuin yhden reittipisteen +STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva reittipiste. STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Liian lähellä toista reittipistettä STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Junien reittipistettä ei voi rakentaa tähän... diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 623c346ac1..b79089f237 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -1994,6 +1994,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Ørering: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Endre slips eller ørering +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Offentlig # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Flerspiller @@ -2057,6 +2058,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Spillnav STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Sett passord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskytt ditt spill med et passord hvis du ikke vil at hvem som helst skal bli med på det +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Synlighet STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maks antall klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS.small :dra og slipp @@ -2124,8 +2126,21 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firmaet STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste over klienter # Network client list +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Navn +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Om andre mennesker kan se serveren din i den offentlige oppføringen +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Spiller +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Navn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Rediger ditt spillernavn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ditt spillernavn +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrative handlinger å utføre for denne klienten +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Bli med i dette firmaet +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send en melding til alle spillerne i dette firmaet +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send en melding til alle tilskuerne +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Opprett et nytt firma og bli med i det +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Spark +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Er du sikker på at du vil utestenge spiller '{STRING}'? STR_NETWORK_SERVER :Tjener STR_NETWORK_CLIENT :Klient @@ -3046,6 +3061,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Advarsel: STR_NEWGRF_ERROR_MSG_ERROR :{RED}Feil: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}En fatal NewGRF-feil har oppstått:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}En NewGRF feil har oppstått:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} virker ikke med TTDPatch-versjonen som er rapportert av OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} er for versjon {STRING} av TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} er laget for bruk med {STRING} From 0b460bf4a17e12ba479e0822b8f9b7de29ac5816 Mon Sep 17 00:00:00 2001 From: PeterN Date: Thu, 29 Apr 2021 18:58:26 +0100 Subject: [PATCH 016/800] Fix: 'Cache' top and bottom lines of textfile viewer to avoid overdraw. (#9131) * Fix: 'Cache' top and bottom lines of textfile viewer to avoid overdraw. The text file viewer calculated the number of lines required to set the scrollbar, but did not retain this information, so this was recalculated on every draw operation. This includes overdrawing text outside the bounds of the current scroll position. With this change the top and bottom lines for each line of text are remembered, and reflowing is avoided where possible. Text outside the current scroll bounds is not drawn. Additionally the scroll interval is now based on text lines instead of pixel lines, which increases the text capacity depending on the font size. * Fix: Limit text viewer to showing 64k lines. Text files with more than 64k wrapped lines would exceed the scrollbar capacity and cause an assert. This is harder to reach now that the scrollbar counts lines instead of pixels. --- src/textfile_gui.cpp | 81 ++++++++++++++++++++++++++++++-------------- src/textfile_gui.h | 16 +++++++-- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index 075898fd71..ac8da5c2e9 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -67,7 +67,6 @@ TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc) this->GetWidget(WID_TF_CAPTION)->SetDataTip(STR_TEXTFILE_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar - this->vscroll->SetStepSize(FONT_HEIGHT_MONO); } /* virtual */ TextfileWindow::~TextfileWindow() @@ -79,23 +78,38 @@ TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc) * Get the total height of the content displayed in this window, if wrapping is disabled. * @return the height in pixels */ -uint TextfileWindow::GetContentHeight() +uint TextfileWindow::ReflowContent() { - int max_width = this->GetWidget(WID_TF_BACKGROUND)->current_x - WD_FRAMETEXT_LEFT - WD_FRAMERECT_RIGHT; - uint height = 0; - for (uint i = 0; i < this->lines.size(); i++) { - height += GetStringHeight(this->lines[i], max_width, FS_MONO); + if (!IsWidgetLowered(WID_TF_WRAPTEXT)) { + for (auto &line : this->lines) { + line.top = height; + height++; + line.bottom = height; + } + } else { + int max_width = this->GetWidget(WID_TF_BACKGROUND)->current_x - WD_FRAMETEXT_LEFT - WD_FRAMERECT_RIGHT; + for (auto &line : this->lines) { + line.top = height; + height += GetStringHeight(line.text, max_width, FS_MONO) / FONT_HEIGHT_MONO; + line.bottom = height; + } } return height; } +uint TextfileWindow::GetContentHeight() +{ + if (this->lines.size() == 0) return 0; + return this->lines.back().bottom; +} + /* virtual */ void TextfileWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { switch (widget) { case WID_TF_BACKGROUND: - resize->height = 1; + resize->height = FONT_HEIGHT_MONO; size->height = 4 * resize->height + TOP_SPACING + BOTTOM_SPACING; // At least 4 lines are visible. size->width = std::max(200u, size->width); // At least 200 pixels wide. @@ -104,18 +118,17 @@ uint TextfileWindow::GetContentHeight() } /** Set scrollbars to the right lengths. */ -void TextfileWindow::SetupScrollbars() +void TextfileWindow::SetupScrollbars(bool force_reflow) { if (IsWidgetLowered(WID_TF_WRAPTEXT)) { - this->vscroll->SetCount(this->GetContentHeight()); + /* Reflow is mandatory if text wrapping is on */ + uint height = this->ReflowContent(); + this->vscroll->SetCount(std::min(UINT16_MAX, height)); this->hscroll->SetCount(0); } else { - uint max_length = 0; - for (uint i = 0; i < this->lines.size(); i++) { - max_length = std::max(max_length, GetStringBoundingBox(this->lines[i], FS_MONO).width); - } - this->vscroll->SetCount((uint)this->lines.size() * FONT_HEIGHT_MONO); - this->hscroll->SetCount(max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); + uint height = force_reflow ? this->ReflowContent() : this->GetContentHeight(); + this->vscroll->SetCount(std::min(UINT16_MAX, height)); + this->hscroll->SetCount(this->max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); } this->SetWidgetDisabledState(WID_TF_HSCROLLBAR, IsWidgetLowered(WID_TF_WRAPTEXT)); @@ -126,7 +139,6 @@ void TextfileWindow::SetupScrollbars() switch (widget) { case WID_TF_WRAPTEXT: this->ToggleWidgetLoweredState(WID_TF_WRAPTEXT); - this->SetupScrollbars(); this->InvalidateData(); break; } @@ -148,14 +160,18 @@ void TextfileWindow::SetupScrollbars() /* Draw content (now coordinates given to DrawString* are local to the new clipping region). */ int line_height = FONT_HEIGHT_MONO; - int y_offset = -this->vscroll->GetPosition(); + int pos = this->vscroll->GetPosition(); + int cap = this->vscroll->GetCapacity(); - for (uint i = 0; i < this->lines.size(); i++) { + for (auto &line : this->lines) { + if (line.bottom < pos) continue; + if (line.top > pos + cap) break; + + int y_offset = (line.top - pos) * line_height; if (IsWidgetLowered(WID_TF_WRAPTEXT)) { - y_offset = DrawStringMultiLine(0, right - x, y_offset, bottom - y, this->lines[i], TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); + DrawStringMultiLine(0, right - x, y_offset, bottom - y, line.text, TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); } else { - DrawString(-this->hscroll->GetPosition(), right - x, y_offset, this->lines[i], TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); - y_offset += line_height; // margin to previous element + DrawString(-this->hscroll->GetPosition(), right - x, y_offset, line.text, TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); } } @@ -167,7 +183,14 @@ void TextfileWindow::SetupScrollbars() this->vscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND, TOP_SPACING + BOTTOM_SPACING); this->hscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND); - this->SetupScrollbars(); + this->SetupScrollbars(false); +} + +/* virtual */ void TextfileWindow::OnInvalidateData(int data, bool gui_scope) +{ + if (!gui_scope) return; + + this->SetupScrollbars(true); } /* virtual */ void TextfileWindow::Reset() @@ -184,7 +207,7 @@ void TextfileWindow::SetupScrollbars() { if (this->search_iterator >= this->lines.size()) return nullptr; - return this->lines[this->search_iterator++]; + return this->lines[this->search_iterator++].text; } /* virtual */ bool TextfileWindow::Monospace() @@ -364,14 +387,22 @@ static void Xunzip(byte **bufp, size_t *sizep) str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); /* Split the string on newlines. */ - this->lines.push_back(p); + int row = 0; + this->lines.emplace_back(row, p); for (; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; - this->lines.push_back(p + 1); + this->lines.emplace_back(++row, p + 1); } } + /* Calculate maximum text line length. */ + uint max_length = 0; + for (auto &line : this->lines) { + max_length = std::max(max_length, GetStringBoundingBox(line.text, FS_MONO).width); + } + this->max_length = max_length; + CheckForMissingGlyphs(true, this); } diff --git a/src/textfile_gui.h b/src/textfile_gui.h index d67435c015..5f1db14ca9 100644 --- a/src/textfile_gui.h +++ b/src/textfile_gui.h @@ -19,13 +19,23 @@ const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filenam /** Window for displaying a textfile */ struct TextfileWindow : public Window, MissingGlyphSearcher { + struct Line { + int top; ///< Top scroll position. + int bottom; ///< Bottom scroll position. + const char *text; ///< Pointer to text buffer. + + Line(int top, const char *text) : top(top), bottom(top + 1), text(text) {} + }; + TextfileType file_type; ///< Type of textfile to view. Scrollbar *vscroll; ///< Vertical scrollbar. Scrollbar *hscroll; ///< Horizontal scrollbar. char *text; ///< Lines of text from the NewGRF's textfile. - std::vector lines; ///< #text, split into lines in a table with lines. + std::vector lines; ///< #text, split into lines in a table with lines. uint search_iterator; ///< Iterator for the font check search. + uint max_length; ///< Maximum length of unwrapped text line. + static const int TOP_SPACING = WD_FRAMETEXT_TOP; ///< Additional spacing at the top of the #WID_TF_BACKGROUND widget. static const int BOTTOM_SPACING = WD_FRAMETEXT_BOTTOM; ///< Additional spacing at the bottom of the #WID_TF_BACKGROUND widget. @@ -36,6 +46,7 @@ struct TextfileWindow : public Window, MissingGlyphSearcher { void OnClick(Point pt, int widget, int click_count) override; void DrawWidget(const Rect &r, int widget) const override; void OnResize() override; + void OnInvalidateData(int data = 0, bool gui_scope = true) override; void Reset() override; FontSize DefaultSize() override; @@ -46,8 +57,9 @@ struct TextfileWindow : public Window, MissingGlyphSearcher { virtual void LoadTextfile(const char *textfile, Subdirectory dir); private: + uint ReflowContent(); uint GetContentHeight(); - void SetupScrollbars(); + void SetupScrollbars(bool force_reflow); }; #endif /* TEXTFILE_GUI_H */ From a8afbe74bfdbe6aa9ceb88c8e70c63bfe37aeda0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 29 Apr 2021 12:01:54 +0200 Subject: [PATCH 017/800] Cleanup: remove write-only variable "hostname" in NetworkGameList --- src/network/core/game_info.h | 1 - src/network/network_gamelist.cpp | 1 - src/network/network_udp.cpp | 5 ----- 3 files changed, 7 deletions(-) diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index 28aea75073..324c6ea4aa 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -74,7 +74,6 @@ struct NetworkGameInfo : NetworkServerGameInfo { uint16 map_width; ///< Map width uint16 map_height; ///< Map height char server_name[NETWORK_NAME_LENGTH]; ///< Server name - char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any) char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) bool dedicated; ///< Is this a dedicated server? bool version_compatible; ///< Can we connect to this server or not? (based on server_revision) diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index dfe07bdbbb..3ee5099b73 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -51,7 +51,6 @@ static void NetworkGameListHandleDelayedInsert() ClearGRFConfigList(&item->info.grfconfig); memset(&item->info, 0, sizeof(item->info)); strecpy(item->info.server_name, ins_item->info.server_name, lastof(item->info.server_name)); - strecpy(item->info.hostname, ins_item->info.hostname, lastof(item->info.hostname)); item->online = false; } item->manually |= ins_item->manually; diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index d62998794e..bb71e5ceaa 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -92,7 +92,6 @@ static void DoNetworkUDPQueryServer(NetworkAddress &address, bool needs_mutex, b /* Clear item in gamelist */ NetworkGameList *item = CallocT(1); address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name)); - strecpy(item->info.hostname, address.GetHostname(), lastof(item->info.hostname)); item->address = address; item->manually = manually; NetworkGameListAddItemDelayed(item); @@ -365,10 +364,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd } } - if (item->info.hostname[0] == '\0') { - seprintf(item->info.hostname, lastof(item->info.hostname), "%s", client_addr->GetHostname()); - } - if (client_addr->GetAddress()->ss_family == AF_INET6) { strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name)); } From 99f998805ba835f48a8061762fa19761760c7451 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 29 Apr 2021 12:05:43 +0200 Subject: [PATCH 018/800] Codechange: use std::string over stack-based strings if possible --- src/network/core/address.cpp | 32 +++++++++++++++----------------- src/network/network_gui.cpp | 5 ++--- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index e53566c0bb..8b51e2c082 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -313,8 +313,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp) { const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype); const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family); - char address[NETWORK_HOSTNAME_LENGTH + 6 + 7]; - NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(address, lastof(address)); + std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(); SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (sock == INVALID_SOCKET) { @@ -328,7 +327,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp) int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen); if (err != 0 && NetworkGetLastError() != EINPROGRESS) { - DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address, family, NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address.c_str(), family, NetworkGetLastErrorString()); closesocket(sock); return INVALID_SOCKET; } @@ -344,14 +343,14 @@ static SOCKET ConnectLoopProc(addrinfo *runp) tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS; int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv); if (n < 0) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkGetLastErrorString()); closesocket(sock); return INVALID_SOCKET; } /* If no fd is selected, the timeout has been reached. */ if (n == 0) { - DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address); + DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address.c_str()); closesocket(sock); return INVALID_SOCKET; } @@ -359,13 +358,13 @@ static SOCKET ConnectLoopProc(addrinfo *runp) /* Retrieve last error, if any, on the socket. */ err = GetSocketError(sock); if (err != 0) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetErrorString(err)); + DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkGetErrorString(err)); closesocket(sock); return INVALID_SOCKET; } /* Connection succeeded. */ - DEBUG(net, 1, "[%s] connected to %s", type, address); + DEBUG(net, 1, "[%s] connected to %s", type, address.c_str()); return sock; } @@ -390,48 +389,47 @@ static SOCKET ListenLoopProc(addrinfo *runp) { const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype); const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family); - char address[NETWORK_HOSTNAME_LENGTH + 6 + 7]; - NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(address, lastof(address)); + std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(); SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (sock == INVALID_SOCKET) { - DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, NetworkGetLastErrorString()); + DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); return INVALID_SOCKET; } if (runp->ai_socktype == SOCK_STREAM && !SetNoDelay(sock)) { - DEBUG(net, 3, "[%s] setting TCP_NODELAY failed for port %s", type, address); + DEBUG(net, 3, "[%s] setting TCP_NODELAY failed for port %s", type, address.c_str()); } int on = 1; /* The (const char*) cast is needed for windows!! */ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, NetworkGetLastErrorString()); + DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); } #ifndef __OS2__ if (runp->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, NetworkGetLastErrorString()); + DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address.c_str(), NetworkGetLastErrorString()); } #endif if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) { - DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); closesocket(sock); return INVALID_SOCKET; } if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) { - DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); closesocket(sock); return INVALID_SOCKET; } /* Connection succeeded */ - if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed for %s port %s", type, family, address); + if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed for %s port %s", type, family, address.c_str()); - DEBUG(net, 1, "[%s] listening on %s port %s", type, family, address); + DEBUG(net, 1, "[%s] listening on %s port %s", type, family, address.c_str()); return sock; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 57127aee81..e1f9a791ba 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -645,9 +645,8 @@ public: DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version y += FONT_HEIGHT_NORMAL; - char network_addr_buffer[NETWORK_HOSTNAME_LENGTH + 6 + 7]; - sel->address.GetAddressAsString(network_addr_buffer, lastof(network_addr_buffer)); - SetDParamStr(0, network_addr_buffer); + std::string address = sel->address.GetAddressAsString(); + SetDParamStr(0, address.c_str()); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address y += FONT_HEIGHT_NORMAL; From be37a2cab831cb645ef0f51dbcc944bd750f6926 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 29 Apr 2021 12:09:03 +0200 Subject: [PATCH 019/800] Codechange: use NetworkAddress instead of two host/port variables where possible This also means we no longer need last_host/last_port, but can just use a single last_joined setting. --- src/console_cmds.cpp | 26 ++----- src/network/core/address.cpp | 4 +- src/network/core/config.h | 1 + src/network/core/tcp_http.cpp | 6 +- src/network/network.cpp | 125 ++++++++++++++++--------------- src/network/network_func.h | 10 ++- src/network/network_gamelist.cpp | 2 +- src/network/network_gui.cpp | 23 +++--- src/openttd.cpp | 40 ++++------ src/settings_type.h | 5 +- src/table/settings.ini | 11 +-- 11 files changed, 112 insertions(+), 141 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 8cdf9c664e..7ab6d3179e 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -893,15 +893,16 @@ DEF_CONSOLE_CMD(ConNetworkReconnect) break; } - if (StrEmpty(_settings_client.network.last_host)) { + if (StrEmpty(_settings_client.network.last_joined)) { IConsolePrint(CC_DEFAULT, "No server for reconnecting."); return true; } /* Don't resolve the address first, just print it directly as it comes from the config file. */ - IConsolePrintF(CC_DEFAULT, "Reconnecting to %s:%d...", _settings_client.network.last_host, _settings_client.network.last_port); + IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined); - NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, playas); + NetworkAddress address = ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT); + NetworkClientConnectGame(address, playas); return true; } @@ -917,18 +918,11 @@ DEF_CONSOLE_CMD(ConNetworkConnect) if (argc < 2) return false; if (_networking) NetworkDisconnect(); // we are in network-mode, first close it! - const char *port = nullptr; - const char *company = nullptr; - char *ip = argv[1]; - /* Default settings: default port and new company */ - uint16 rport = NETWORK_DEFAULT_PORT; CompanyID join_as = COMPANY_NEW_COMPANY; + NetworkAddress address = ParseGameConnectionString(&join_as, argv[1], NETWORK_DEFAULT_PORT); - ParseGameConnectionString(&company, &port, ip); - - IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip); - if (company != nullptr) { - join_as = (CompanyID)atoi(company); + IConsolePrintF(CC_DEFAULT, "Connecting to %s...", address.GetAddressAsString().c_str()); + if (join_as != COMPANY_NEW_COMPANY) { IConsolePrintF(CC_DEFAULT, " company-no: %d", join_as); /* From a user pov 0 is a new company, internally it's different and all @@ -938,12 +932,8 @@ DEF_CONSOLE_CMD(ConNetworkConnect) join_as--; } } - if (port != nullptr) { - rport = atoi(port); - IConsolePrintF(CC_DEFAULT, " port: %s", port); - } - NetworkClientConnectGame(ip, rport, join_as); + NetworkClientConnectGame(address, join_as); return true; } diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 8b51e2c082..e91751c33f 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -101,8 +101,8 @@ void NetworkAddress::GetAddressAsString(char *buffer, const char *last, bool wit */ std::string NetworkAddress::GetAddressAsString(bool with_family) { - /* 6 = for the : and 5 for the decimal port number */ - char buf[NETWORK_HOSTNAME_LENGTH + 6 + 7]; + /* 7 extra are for with_family, which adds " (IPvX)". */ + char buf[NETWORK_HOSTNAME_PORT_LENGTH + 7]; this->GetAddressAsString(buf, lastof(buf), with_family); return buf; } diff --git a/src/network/core/config.h b/src/network/core/config.h index 866d1791d4..cacc907faf 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -56,6 +56,7 @@ static const byte NETWORK_MASTER_SERVER_VERSION = 2; ///< What vers 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_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) static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0' static const uint NETWORK_REVISION_LENGTH = 33; ///< The maximum length of the revision, in bytes including '\0' static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH) diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index ee74c45070..99eca1cb74 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -203,11 +203,7 @@ int NetworkHTTPSocketHandler::HandleHeader() *url = '\0'; - /* Fetch the hostname, and possible port number. */ - const char *port = nullptr; - ParseConnectionString(&port, hname); - - NetworkAddress address(hname, port == nullptr ? 80 : atoi(port)); + NetworkAddress address = ParseConnectionString(hname, 80); /* Restore the URL. */ *url = '/'; diff --git a/src/network/network.cpp b/src/network/network.cpp index c0b2e06fd4..0be46bbf35 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -446,45 +446,15 @@ static void CheckPauseOnJoin() CheckPauseHelper(NetworkHasJoiningClient(), PM_PAUSED_JOIN); } -/** - * Converts a string to ip/port - * Format: IP:port - * - * connection_string will be re-terminated to separate out the hostname, port will - * be set to the port strings given by the user, inside the memory area originally - * occupied by connection_string. - */ -void ParseConnectionString(const char **port, char *connection_string) -{ - bool ipv6 = (strchr(connection_string, ':') != strrchr(connection_string, ':')); - for (char *p = connection_string; *p != '\0'; p++) { - switch (*p) { - case '[': - ipv6 = true; - break; - - case ']': - ipv6 = false; - break; - - case ':': - if (ipv6) break; - *port = p + 1; - *p = '\0'; - break; - } - } -} - /** * Converts a string to ip/port/company * Format: IP:port#company * - * connection_string will be re-terminated to separate out the hostname, and company and port will - * be set to the company and port strings given by the user, inside the memory area originally - * occupied by connection_string. + * connection_string will be re-terminated to separate out the hostname, port will + * be set to the port strings given by the user, inside the memory area originally + * occupied by connection_string. Similar for company, if set. */ -void ParseGameConnectionString(const char **company, const char **port, char *connection_string) +void ParseFullConnectionString(const char **company, const char **port, char *connection_string) { bool ipv6 = (strchr(connection_string, ':') != strrchr(connection_string, ':')); for (char *p = connection_string; *p != '\0'; p++) { @@ -498,6 +468,7 @@ void ParseGameConnectionString(const char **company, const char **port, char *co break; case '#': + if (company == nullptr) continue; *company = p + 1; *p = '\0'; break; @@ -511,6 +482,51 @@ void ParseGameConnectionString(const char **company, const char **port, char *co } } +/** + * Convert a string containing either "hostname" or "hostname:ip" to a + * NetworkAddress. + * + * @param connection_string The string to parse. + * @param default_port The default port to set port to if not in connection_string. + * @return A valid NetworkAddress of the parsed information. + */ +NetworkAddress ParseConnectionString(const char *connection_string, int default_port) +{ + char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH]; + strecpy(internal_connection_string, connection_string, lastof(internal_connection_string)); + + const char *port = nullptr; + ParseFullConnectionString(nullptr, &port, internal_connection_string); + + int rport = port != nullptr ? atoi(port) : default_port; + return NetworkAddress(internal_connection_string, rport); +} + +/** + * Convert a string containing either "hostname" or "hostname:ip" to a + * NetworkAddress, where the string can be postfixed with "#company" to + * indicate the requested company. + * + * @param company Pointer to the company variable to set iff indicted. + * @param connection_string The string to parse. + * @param default_port The default port to set port to if not in connection_string. + * @return A valid NetworkAddress of the parsed information. + */ +NetworkAddress ParseGameConnectionString(CompanyID *company, const char *connection_string, int default_port) +{ + char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company + strecpy(internal_connection_string, connection_string, lastof(internal_connection_string)); + + const char *port_s = nullptr; + const char *company_s = nullptr; + ParseFullConnectionString(&company_s, &port_s, internal_connection_string); + + if (company_s != nullptr) *company = (CompanyID)atoi(company_s); + + int port = port_s != nullptr ? atoi(port_s) : default_port; + return NetworkAddress(internal_connection_string, port); +} + /** * Handle the accepting of a connection to the server. * @param s The socket of the new connection. @@ -616,26 +632,17 @@ void NetworkTCPQueryServer(NetworkAddress address) new TCPQueryConnecter(address); } -/* Validates an address entered as a string and adds the server to +/** + * Validates an address entered as a string and adds the server to * the list. If you use this function, the games will be marked - * as manually added. */ -void NetworkAddServer(const char *b) + * as manually added. + * @param connection_string The IP:port to add to the list. + */ +void NetworkAddServer(const char *connection_string) { - if (*b != '\0') { - const char *port = nullptr; - char host[NETWORK_HOSTNAME_LENGTH]; - uint16 rport; + if (StrEmpty(connection_string)) return; - strecpy(host, b, lastof(host)); - - strecpy(_settings_client.network.connect_to_ip, b, lastof(_settings_client.network.connect_to_ip)); - rport = NETWORK_DEFAULT_PORT; - - ParseConnectionString(&port, host); - if (port != nullptr) rport = atoi(port); - - NetworkUDPQueryServer(NetworkAddress(host, rport), true); - } + NetworkUDPQueryServer(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT), true); } /** @@ -688,16 +695,13 @@ public: /* Used by clients, to connect to a server */ -void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password, const char *join_company_password) +void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password) { if (!_network_available) return; - - if (port == 0) return; - if (!NetworkValidateClientName()) return; - strecpy(_settings_client.network.last_host, hostname, lastof(_settings_client.network.last_host)); - _settings_client.network.last_port = port; + strecpy(_settings_client.network.last_joined, address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); + _network_join_as = join_as; _network_join_server_password = join_server_password; _network_join_company_password = join_company_password; @@ -708,7 +712,7 @@ void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_ _network_join_status = NETWORK_JOIN_STATUS_CONNECTING; ShowJoinStatusWindow(); - new TCPClientConnecter(NetworkAddress(hostname, port)); + new TCPClientConnecter(address); } static void NetworkInitGameInfo() @@ -1059,13 +1063,12 @@ static void NetworkGenerateServerId() seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output); } -void NetworkStartDebugLog(const char *hostname, uint16 port) +void NetworkStartDebugLog(NetworkAddress &address) { extern SOCKET _debug_socket; // Comes from debug.c - DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", hostname, port); + DEBUG(net, 0, "Redirecting DEBUG() to %s", address.GetAddressAsString().c_str()); - NetworkAddress address(hostname, port); SOCKET s = address.Connect(); if (s == INVALID_SOCKET) { DEBUG(net, 0, "Failed to open socket for redirection DEBUG()"); diff --git a/src/network/network_func.h b/src/network/network_func.h index a0f163345e..967bb62603 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -18,6 +18,7 @@ // #define DEBUG_FAILED_DUMP_COMMANDS #include "network_type.h" +#include "core/address.h" #include "../console_type.h" #include "../gfx_type.h" #include "../openttd.h" @@ -45,14 +46,15 @@ void NetworkReboot(); void NetworkDisconnect(bool blocking = false, bool close_admins = true); void NetworkGameLoop(); void NetworkBackgroundLoop(); -void ParseConnectionString(const char **port, char *connection_string); -void ParseGameConnectionString(const char **company, const char **port, char *connection_string); -void NetworkStartDebugLog(const char *hostname, uint16 port); +void ParseFullConnectionString(const char **company, const char **port, char *connection_string); +NetworkAddress ParseConnectionString(const char *connection_string, int default_port); +NetworkAddress ParseGameConnectionString(CompanyID *company, const char *connection_string, int default_port); +void NetworkStartDebugLog(NetworkAddress &address); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); -void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); void NetworkClientRequestMove(CompanyID company, const char *pass = ""); void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index 3ee5099b73..6d4285c854 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -151,7 +151,7 @@ void NetworkGameListRequery() /* item gets mostly zeroed by NetworkUDPQueryServer */ uint8 retries = item->retries; - NetworkUDPQueryServer(NetworkAddress(item->address)); + NetworkUDPQueryServer(item->address); item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries; } } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index e1f9a791ba..3204b2b962 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -472,7 +472,7 @@ public: EM_ASM(if (window["openttd_server_list"]) openttd_server_list()); #endif - this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); + this->last_joined = NetworkGameListAddItem(ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT)); this->server = this->last_joined; if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address); @@ -735,7 +735,7 @@ public: ShowQueryString( STR_JUST_RAW_STRING, STR_NETWORK_SERVER_LIST_ENTER_IP, - NETWORK_HOSTNAME_LENGTH, // maximum number of characters including '\0' + NETWORK_HOSTNAME_PORT_LENGTH, // maximum number of characters including '\0' this, CS_ALPHANUMERAL, QSF_ACCEPT_UNCHANGED); break; @@ -745,8 +745,6 @@ public: case WID_NG_JOIN: // Join Game if (this->server != nullptr) { - seprintf(_settings_client.network.last_host, lastof(_settings_client.network.last_host), "%s", this->server->address.GetHostname()); - _settings_client.network.last_port = this->server->address.GetPort(); ShowNetworkLobbyWindow(this->server); } break; @@ -827,7 +825,10 @@ public: void OnQueryTextFinished(char *str) override { - if (!StrEmpty(str)) NetworkAddServer(str); + if (!StrEmpty(str)) { + strecpy(_settings_client.network.connect_to_ip, str, lastof(_settings_client.network.connect_to_ip)); + NetworkAddServer(str); + } } void OnResize() override @@ -1469,22 +1470,22 @@ struct NetworkLobbyWindow : public Window { case WID_NL_JOIN: // Join company /* Button can be clicked only when it is enabled. */ - NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, this->company); + NetworkClientConnectGame(this->server->address, this->company); break; case WID_NL_NEW: // New company - NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_NEW_COMPANY); + NetworkClientConnectGame(this->server->address, COMPANY_NEW_COMPANY); break; case WID_NL_SPECTATE: // Spectate game - NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR); + NetworkClientConnectGame(this->server->address, COMPANY_SPECTATOR); break; case WID_NL_REFRESH: // Refresh /* Clear the information so removed companies don't remain */ for (auto &company : this->company_info) company = {}; - NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); + NetworkTCPQueryServer(this->server->address); break; } } @@ -1552,7 +1553,9 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); - NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); + strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); + + NetworkTCPQueryServer(ngl->address); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); } diff --git a/src/openttd.cpp b/src/openttd.cpp index 016d482873..b128243854 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -473,29 +473,21 @@ struct AfterNewGRFScan : NewGRFScanCallback { if (_switch_mode != SM_NONE) MakeNewgameSettingsLive(); if (_network_available && network_conn != nullptr) { - const char *port = nullptr; - const char *company = nullptr; - uint16 rport = NETWORK_DEFAULT_PORT; CompanyID join_as = COMPANY_NEW_COMPANY; + NetworkAddress address = ParseGameConnectionString(&join_as, network_conn, NETWORK_DEFAULT_PORT); - ParseGameConnectionString(&company, &port, network_conn); - - if (company != nullptr) { - join_as = (CompanyID)atoi(company); - - if (join_as != COMPANY_SPECTATOR) { - join_as--; - if (join_as >= MAX_COMPANIES) { - delete this; - return; - } + if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) { + join_as--; + if (join_as >= MAX_COMPANIES) { + delete this; + return; } } - if (port != nullptr) rport = atoi(port); LoadIntroGame(); _switch_mode = SM_NONE; - NetworkClientConnectGame(network_conn, rport, join_as, join_server_password, join_company_password); + + NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); } /* After the scan we're not used anymore. */ @@ -585,7 +577,7 @@ int openttd_main(int argc, char *argv[]) SetDebugString("net=6"); if (mgo.opt != nullptr) { const char *port = nullptr; - ParseConnectionString(&port, mgo.opt); + ParseFullConnectionString(nullptr, &port, mgo.opt); if (!StrEmpty(mgo.opt)) scanner->dedicated_host = mgo.opt; if (port != nullptr) scanner->dedicated_port = atoi(port); } @@ -771,15 +763,8 @@ int openttd_main(int argc, char *argv[]) NetworkStartUp(); // initialize network-core if (debuglog_conn != nullptr && _network_available) { - const char *port = nullptr; - uint16 rport; - - rport = NETWORK_DEFAULT_DEBUGLOG_PORT; - - ParseConnectionString(&port, debuglog_conn); - if (port != nullptr) rport = atoi(port); - - NetworkStartDebugLog(debuglog_conn, rport); + NetworkAddress address = ParseConnectionString(debuglog_conn, NETWORK_DEFAULT_DEBUGLOG_PORT); + NetworkStartDebugLog(address); } if (!HandleBootstrap()) { @@ -1491,7 +1476,8 @@ void GameLoop() if (_network_reconnect > 0 && --_network_reconnect == 0) { /* This means that we want to reconnect to the last host * We do this here, because it means that the network is really closed */ - NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR); + NetworkAddress address = ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT); + NetworkClientConnectGame(address, COMPANY_SPECTATOR); } /* Singleplayer */ StateGameLoop(); diff --git a/src/settings_type.h b/src/settings_type.h index bb078205b8..5361fc3f1f 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -269,7 +269,7 @@ struct NetworkSettings { bool server_advertise; ///< advertise the server to the masterserver char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) char default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form - char connect_to_ip[NETWORK_HOSTNAME_LENGTH]; ///< default for the "Add server" query + char connect_to_ip[NETWORK_HOSTNAME_PORT_LENGTH]; ///< default for the "Add server" query char network_id[NETWORK_SERVER_ID_LENGTH]; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use uint8 autoclean_unprotected; ///< remove passwordless companies after this many months @@ -281,8 +281,7 @@ struct NetworkSettings { Year restart_game_year; ///< year the server restarts uint8 min_active_clients; ///< minimum amount of active clients to unpause the game bool reload_cfg; ///< reload the config file before restarting - char last_host[NETWORK_HOSTNAME_LENGTH]; ///< IP address of the last joined server - uint16 last_port; ///< port of the last joined server + char last_joined[NETWORK_HOSTNAME_PORT_LENGTH]; ///< Last joined server bool no_http_content_downloads; ///< do not do content downloads over HTTP }; diff --git a/src/table/settings.ini b/src/table/settings.ini index 391a5b427f..4e64bd0326 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -4069,21 +4069,12 @@ def = false cat = SC_EXPERT [SDTC_STR] -var = network.last_host +var = network.last_joined type = SLE_STRB flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = """" cat = SC_EXPERT -[SDTC_VAR] -var = network.last_port -type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -def = 0 -min = 0 -max = UINT16_MAX -cat = SC_EXPERT - [SDTC_BOOL] var = network.no_http_content_downloads flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC From a61696d6c565ff92c6604b12eefe36198d094056 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Thu, 29 Apr 2021 16:43:13 +0200 Subject: [PATCH 020/800] Change: [Network] Encapsulate logic about the connection string to the network code (#23) --- src/console_cmds.cpp | 21 ++------------------- src/network/core/tcp_http.cpp | 2 +- src/network/network.cpp | 26 +++++++++++++++++++++----- src/network/network_func.h | 7 ++----- src/network/network_internal.h | 4 ++++ src/openttd.cpp | 19 +++---------------- 6 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 7ab6d3179e..9dce399096 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -901,8 +901,7 @@ DEF_CONSOLE_CMD(ConNetworkReconnect) /* Don't resolve the address first, just print it directly as it comes from the config file. */ IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined); - NetworkAddress address = ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT); - NetworkClientConnectGame(address, playas); + NetworkClientConnectGame(_settings_client.network.last_joined, playas); return true; } @@ -918,23 +917,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect) if (argc < 2) return false; if (_networking) NetworkDisconnect(); // we are in network-mode, first close it! - CompanyID join_as = COMPANY_NEW_COMPANY; - NetworkAddress address = ParseGameConnectionString(&join_as, argv[1], NETWORK_DEFAULT_PORT); - - IConsolePrintF(CC_DEFAULT, "Connecting to %s...", address.GetAddressAsString().c_str()); - if (join_as != COMPANY_NEW_COMPANY) { - IConsolePrintF(CC_DEFAULT, " company-no: %d", join_as); - - /* From a user pov 0 is a new company, internally it's different and all - * companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */ - if (join_as != COMPANY_SPECTATOR) { - if (join_as > MAX_COMPANIES) return false; - join_as--; - } - } - - NetworkClientConnectGame(address, join_as); - + NetworkClientConnectGame(argv[1], COMPANY_NEW_COMPANY); return true; } diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index 99eca1cb74..e0c269fafb 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -12,7 +12,7 @@ #include "../../stdafx.h" #include "../../debug.h" #include "../../rev.h" -#include "../network_func.h" +#include "../network_internal.h" #include "game_info.h" #include "tcp_http.h" diff --git a/src/network/network.cpp b/src/network/network.cpp index 0be46bbf35..d7cf9367a1 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -490,10 +490,10 @@ void ParseFullConnectionString(const char **company, const char **port, char *co * @param default_port The default port to set port to if not in connection_string. * @return A valid NetworkAddress of the parsed information. */ -NetworkAddress ParseConnectionString(const char *connection_string, int default_port) +NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port) { char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH]; - strecpy(internal_connection_string, connection_string, lastof(internal_connection_string)); + strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string)); const char *port = nullptr; ParseFullConnectionString(nullptr, &port, internal_connection_string); @@ -512,10 +512,10 @@ NetworkAddress ParseConnectionString(const char *connection_string, int default_ * @param default_port The default port to set port to if not in connection_string. * @return A valid NetworkAddress of the parsed information. */ -NetworkAddress ParseGameConnectionString(CompanyID *company, const char *connection_string, int default_port) +NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port) { char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company - strecpy(internal_connection_string, connection_string, lastof(internal_connection_string)); + strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string)); const char *port_s = nullptr; const char *company_s = nullptr; @@ -693,6 +693,20 @@ public: } }; +void NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) +{ + CompanyID join_as = default_company; + NetworkAddress address = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT); + + if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) { + join_as--; + if (join_as >= MAX_COMPANIES) { + return; + } + } + + NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); +} /* Used by clients, to connect to a server */ void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password) @@ -1063,10 +1077,12 @@ static void NetworkGenerateServerId() seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output); } -void NetworkStartDebugLog(NetworkAddress &address) +void NetworkStartDebugLog(const std::string &connection_string) { extern SOCKET _debug_socket; // Comes from debug.c + NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT); + DEBUG(net, 0, "Redirecting DEBUG() to %s", address.GetAddressAsString().c_str()); SOCKET s = address.Connect(); diff --git a/src/network/network_func.h b/src/network/network_func.h index 967bb62603..cd2b291bc7 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -18,7 +18,6 @@ // #define DEBUG_FAILED_DUMP_COMMANDS #include "network_type.h" -#include "core/address.h" #include "../console_type.h" #include "../gfx_type.h" #include "../openttd.h" @@ -47,14 +46,12 @@ void NetworkDisconnect(bool blocking = false, bool close_admins = true); void NetworkGameLoop(); void NetworkBackgroundLoop(); void ParseFullConnectionString(const char **company, const char **port, char *connection_string); -NetworkAddress ParseConnectionString(const char *connection_string, int default_port); -NetworkAddress ParseGameConnectionString(CompanyID *company, const char *connection_string, int default_port); -void NetworkStartDebugLog(NetworkAddress &address); +void NetworkStartDebugLog(const std::string &connection_string); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); -void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +void NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); void NetworkClientRequestMove(CompanyID company, const char *pass = ""); void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index c64eac7954..ff3c8c22d2 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -119,4 +119,8 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); +void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port); +NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port); + #endif /* NETWORK_INTERNAL_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index b128243854..fbeeba793e 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -473,21 +473,10 @@ struct AfterNewGRFScan : NewGRFScanCallback { if (_switch_mode != SM_NONE) MakeNewgameSettingsLive(); if (_network_available && network_conn != nullptr) { - CompanyID join_as = COMPANY_NEW_COMPANY; - NetworkAddress address = ParseGameConnectionString(&join_as, network_conn, NETWORK_DEFAULT_PORT); - - if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) { - join_as--; - if (join_as >= MAX_COMPANIES) { - delete this; - return; - } - } - LoadIntroGame(); _switch_mode = SM_NONE; - NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); + NetworkClientConnectGame(network_conn, COMPANY_NEW_COMPANY, join_server_password, join_company_password); } /* After the scan we're not used anymore. */ @@ -763,8 +752,7 @@ int openttd_main(int argc, char *argv[]) NetworkStartUp(); // initialize network-core if (debuglog_conn != nullptr && _network_available) { - NetworkAddress address = ParseConnectionString(debuglog_conn, NETWORK_DEFAULT_DEBUGLOG_PORT); - NetworkStartDebugLog(address); + NetworkStartDebugLog(debuglog_conn); } if (!HandleBootstrap()) { @@ -1476,8 +1464,7 @@ void GameLoop() if (_network_reconnect > 0 && --_network_reconnect == 0) { /* This means that we want to reconnect to the last host * We do this here, because it means that the network is really closed */ - NetworkAddress address = ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT); - NetworkClientConnectGame(address, COMPANY_SPECTATOR); + NetworkClientConnectGame(_settings_client.network.last_joined, COMPANY_SPECTATOR); } /* Singleplayer */ StateGameLoop(); From 14e92bd8e241998ced263ee542965a71bbdd77a5 Mon Sep 17 00:00:00 2001 From: glx22 Date: Wed, 28 Apr 2021 21:24:24 +0200 Subject: [PATCH 021/800] Codechange: Replace window related FOR_ALL with range-based for loops --- src/misc_gui.cpp | 3 +- src/sound.cpp | 3 +- src/viewport.cpp | 11 ++-- src/widgets/dropdown.cpp | 3 +- src/window.cpp | 131 +++++++++++++-------------------------- src/window_gui.h | 68 ++++++++++++++++++-- 6 files changed, 113 insertions(+), 106 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 9be207ac60..b2de451404 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -1284,8 +1284,7 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback { if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0); - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue; const QueryWindow *qw = (const QueryWindow *)w; diff --git a/src/sound.cpp b/src/sound.cpp index 7d70fa760d..d91476729b 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -238,8 +238,7 @@ static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, in { if (_settings_client.music.effect_vol == 0) return; - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { const Viewport *vp = w->viewport; if (vp != nullptr && diff --git a/src/viewport.cpp b/src/viewport.cpp index aae659d53d..303e027600 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -268,7 +268,7 @@ static Point _vp_move_offs; static void DoSetViewportPosition(const Window *w, int left, int top, int width, int height) { - FOR_ALL_WINDOWS_FROM_BACK_FROM(w, w) { + for (const Window *w : Window::IterateFromBack(w)) { if (left + width > w->left && w->left + w->width > left && top + height > w->top && @@ -1475,8 +1475,7 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const zoomlevels[zoom].bottom = this->top + ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM + 1, zoom); } - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { Viewport *vp = w->viewport; if (vp != nullptr && vp->zoom <= maxzoom) { assert(vp->width != 0); @@ -1949,8 +1948,7 @@ bool MarkAllViewportsDirty(int left, int top, int right, int bottom) { bool dirty = false; - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { Viewport *vp = w->viewport; if (vp != nullptr) { assert(vp->width != 0); @@ -1963,8 +1961,7 @@ bool MarkAllViewportsDirty(int left, int top, int right, int bottom) void ConstrainAllViewportsZoom() { - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if (w->viewport == nullptr) continue; ZoomLevel zoom = static_cast(Clamp(w->viewport->zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max)); diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 6b1debb9db..f5536f52f4 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -505,8 +505,7 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt */ int HideDropDownMenu(Window *pw) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class != WC_DROPDOWN_MENU) continue; DropdownWindow *dw = dynamic_cast(w); diff --git a/src/window.cpp b/src/window.cpp index 2216fb2418..a82afc7cda 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -898,8 +898,7 @@ static bool MayBeShown(const Window *w) */ static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom) { - const Window *v; - FOR_ALL_WINDOWS_FROM_BACK_FROM(v, w->z_front) { + for (const Window *v : Window::IterateFromBack(w->z_front)) { if (MayBeShown(v) && right > v->left && bottom > v->top && @@ -958,13 +957,11 @@ static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bo */ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) { - Window *w; - DrawPixelInfo *old_dpi = _cur_dpi; DrawPixelInfo bk; _cur_dpi = &bk; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (MayBeShown(w) && right > w->left && bottom > w->top && @@ -1057,8 +1054,7 @@ void Window::SetShaded(bool make_shaded) */ static Window *FindChildWindow(const Window *w, WindowClass wc) { - Window *v; - FOR_ALL_WINDOWS_FROM_BACK(v) { + for (Window *v : Window::IterateFromBack()) { if ((wc == WC_INVALID || wc == v->window_class) && v->parent == w) return v; } @@ -1132,8 +1128,7 @@ Window::~Window() */ Window *FindWindowById(WindowClass cls, WindowNumber number) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls && w->window_number == number) return w; } @@ -1148,8 +1143,7 @@ Window *FindWindowById(WindowClass cls, WindowNumber number) */ Window *FindWindowByClass(WindowClass cls) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls) return w; } @@ -1176,13 +1170,11 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) */ void DeleteWindowByClass(WindowClass cls) { - Window *w; - restart_search: /* When we find the window to delete, we need to restart the search * as deleting this window could cascade in deleting (many) others * anywhere in the z-array */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls) { delete w; goto restart_search; @@ -1198,13 +1190,11 @@ restart_search: */ void DeleteCompanyWindows(CompanyID id) { - Window *w; - restart_search: /* When we find the window to delete, we need to restart the search * as deleting this window could cascade in deleting (many) others * anywhere in the z-array */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->owner == id) { delete w; goto restart_search; @@ -1224,8 +1214,7 @@ restart_search: */ void ChangeWindowOwner(Owner old_owner, Owner new_owner) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->owner != old_owner) continue; switch (w->window_class) { @@ -1594,8 +1583,7 @@ static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolb if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false; /* Make sure it is not obscured by any window. */ - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (right > w->left && @@ -1640,8 +1628,7 @@ static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolb if (top < toolbar_y || top > _screen.height - (height >> 2)) return false; /* Make sure it is not obscured by any window. */ - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (left + width > w->left && @@ -1678,8 +1665,7 @@ static Point GetAutoPlacePosition(int width, int height) * The new window must be entirely on-screen, and not overlap with an existing window. * Eight starting points are tried, two at each corner. */ - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (IsGoodAutoPlace1(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; @@ -1696,7 +1682,7 @@ static Point GetAutoPlacePosition(int width, int height) * The new window may be partly off-screen, and must not overlap with an existing window. * Only four starting points are tried. */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (IsGoodAutoPlace2(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; @@ -1713,7 +1699,7 @@ static Point GetAutoPlacePosition(int width, int height) int offset_y = std::max(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM); restart: - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->left == left && w->top == top) { left += offset_x; top += offset_y; @@ -1880,8 +1866,7 @@ Window::Window(WindowDesc *desc) : window_desc(desc), mouse_capture_widget(-1) */ Window *FindWindowFromPt(int x, int y) { - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if (MayBeShown(w) && IsInsideBS(x, w->left, w->width) && IsInsideBS(y, w->top, w->height)) { return w; } @@ -1918,10 +1903,9 @@ void UnInitWindowSystem() { UnshowCriticalError(); - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) delete w; + for (Window *w : Window::IterateFromFront()) delete w; - for (w = _z_front_window; w != nullptr; /* nothing */) { + for (Window *w = _z_front_window; w != nullptr; /* nothing */) { Window *to_del = w; w = w->z_back; free(to_del); @@ -1948,8 +1932,7 @@ static void DecreaseWindowCounters() if (_scroller_click_timeout != 0) _scroller_click_timeout--; if (hundredth_tick_timeout != 0) hundredth_tick_timeout--; - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if (!_network_dedicated && hundredth_tick_timeout == 0) w->OnHundredthTick(); if (_scroller_click_timeout == 0) { @@ -1975,7 +1958,7 @@ static void DecreaseWindowCounters() w->OnMouseLoop(); } - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if ((w->flags & WF_TIMEOUT) && --w->timeout_timer == 0) { CLRBITS(w->flags, WF_TIMEOUT); @@ -2217,8 +2200,7 @@ static EventState HandleWindowDragging() if (_left_button_down && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; /* Otherwise find the window... */ - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->flags & WF_DRAGGING) { /* Stop the dragging if the left mouse button was released */ if (!_left_button_down) { @@ -2234,13 +2216,11 @@ static EventState HandleWindowDragging() int ny = y; if (_settings_client.gui.window_snap_radius != 0) { - const Window *v; - int hsnap = _settings_client.gui.window_snap_radius; int vsnap = _settings_client.gui.window_snap_radius; int delta; - FOR_ALL_WINDOWS_FROM_BACK(v) { + for (const Window *v : Window::IterateFromBack()) { if (v == w) continue; // Don't snap at yourself if (y + w->height > v->top && y < v->top + v->height) { @@ -2454,8 +2434,7 @@ static void HandleScrollbarScrolling(Window *w) */ static EventState HandleActiveWidget() { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->mouse_capture_widget >= 0) { /* Abort if no button is clicked any more. */ if (!_left_button_down) { @@ -2565,8 +2544,7 @@ static bool MaybeBringWindowToFront(Window *w) w_height = w->unshaded_size.height; } - Window *u; - FOR_ALL_WINDOWS_FROM_BACK_FROM(u, w->z_front) { + for (Window *u : Window::IterateFromBack(w->z_front)) { /* A modal child will prevent the activation of the parent window */ if (u->parent == w && (u->window_desc->flags & WDF_MODAL)) { u->SetWhiteBorder(); @@ -2708,8 +2686,7 @@ void HandleKeypress(uint keycode, WChar key) } /* Call the event, start with the uppermost window, but ignore the toolbar. */ - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if (w->window_class == WC_MAIN_TOOLBAR) continue; if (w->window_desc->hotkeys != nullptr) { int hotkey = w->window_desc->hotkeys->CheckMatch(keycode); @@ -2718,7 +2695,7 @@ void HandleKeypress(uint keycode, WChar key) if (w->OnKeyPress(key, keycode) == ES_HANDLED) return; } - w = FindWindowById(WC_MAIN_TOOLBAR, 0); + Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); /* When there is no toolbar w is null, check for that */ if (w != nullptr) { if (w->window_desc->hotkeys != nullptr) { @@ -2737,8 +2714,7 @@ void HandleKeypress(uint keycode, WChar key) void HandleCtrlChanged() { /* Call the event, start with the uppermost window. */ - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if (w->OnCTRLStateChange() == ES_HANDLED) return; } } @@ -3073,8 +3049,8 @@ static void CheckSoftLimit() for (;;) { uint deletable_count = 0; - Window *w, *last_deletable = nullptr; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + Window *last_deletable = nullptr; + for (Window *w : Window::IterateFromFront()) { if (w->window_class == WC_MAIN_WINDOW || IsVitalWindow(w) || (w->flags & WF_STICKY)) continue; last_deletable = w; @@ -3127,8 +3103,7 @@ void InputLoop() */ void CallWindowRealtimeTickEvent(uint delta_ms) { - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { w->OnRealtimeTick(delta_ms); } } @@ -3156,10 +3131,8 @@ void UpdateWindows() NetworkChatMessageLoop(); } - Window *w; - /* Process invalidations before anything else. */ - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { w->ProcessScheduledInvalidations(); w->ProcessHighlightedInvalidations(); } @@ -3192,7 +3165,7 @@ void UpdateWindows() if (window_timer.HasElapsed()) { window_timer.SetInterval(MILLISECONDS_PER_TICK); - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { if ((w->flags & WF_WHITE_BORDER) && --w->white_border_timer == 0) { CLRBITS(w->flags, WF_WHITE_BORDER); w->SetDirty(); @@ -3202,7 +3175,7 @@ void UpdateWindows() DrawDirtyBlocks(); - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { /* Update viewport only if window is not shaded. */ if (w->viewport != nullptr && !w->IsShaded()) UpdateViewportPosition(w); } @@ -3218,8 +3191,7 @@ void UpdateWindows() */ void SetWindowDirty(WindowClass cls, WindowNumber number) { - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == cls && w->window_number == number) w->SetDirty(); } } @@ -3232,8 +3204,7 @@ void SetWindowDirty(WindowClass cls, WindowNumber number) */ void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index) { - const Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == cls && w->window_number == number) { w->SetWidgetDirty(widget_index); } @@ -3246,8 +3217,7 @@ void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_inde */ void SetWindowClassesDirty(WindowClass cls) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class == cls) w->SetDirty(); } } @@ -3319,8 +3289,7 @@ void Window::ProcessHighlightedInvalidations() */ void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls && w->window_number == number) { w->InvalidateData(data, gui_scope); } @@ -3337,9 +3306,7 @@ void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool g */ void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope) { - Window *w; - - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls) { w->InvalidateData(data, gui_scope); } @@ -3351,8 +3318,7 @@ void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope) */ void CallWindowGameTickEvent() { - Window *w; - FOR_ALL_WINDOWS_FROM_FRONT(w) { + for (Window *w : Window::IterateFromFront()) { w->OnGameTick(); } } @@ -3365,13 +3331,11 @@ void CallWindowGameTickEvent() */ void DeleteNonVitalWindows() { - Window *w; - restart_search: /* When we find the window to delete, we need to restart the search * as deleting this window could cascade in deleting (many) others * anywhere in the z-array */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_SELECT_GAME && w->window_class != WC_MAIN_TOOLBAR && @@ -3394,8 +3358,6 @@ restart_search: */ void DeleteAllNonVitalWindows() { - Window *w; - /* Delete every window except for stickied ones, then sticky ones as well */ DeleteNonVitalWindows(); @@ -3403,7 +3365,7 @@ restart_search: /* When we find the window to delete, we need to restart the search * as deleting this window could cascade in deleting (many) others * anywhere in the z-array */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->flags & WF_STICKY) { delete w; goto restart_search; @@ -3428,20 +3390,18 @@ void DeleteAllMessages() */ void DeleteConstructionWindows() { - Window *w; - restart_search: /* When we find the window to delete, we need to restart the search * as deleting this window could cascade in deleting (many) others * anywhere in the z-array */ - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->window_desc->flags & WDF_CONSTRUCTION) { delete w; goto restart_search; } } - FOR_ALL_WINDOWS_FROM_BACK(w) w->SetDirty(); + for (const Window *w : Window::IterateFromBack()) w->SetDirty(); } /** Delete all always on-top windows to get an empty screen */ @@ -3460,8 +3420,7 @@ void ReInitAllWindows() extern void InitDepotWindowBlockSizes(); InitDepotWindowBlockSizes(); - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { w->ReInit(); } @@ -3550,8 +3509,7 @@ int PositionNetworkChatWindow(Window *w) */ void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (const Window *w : Window::IterateFromBack()) { if (w->viewport != nullptr && w->viewport->follow_vehicle == from_index) { w->viewport->follow_vehicle = to_index; w->SetDirty(); @@ -3569,8 +3527,7 @@ void RelocateAllWindows(int neww, int newh) { DeleteWindowById(WC_DROPDOWN_MENU, 0); - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { + for (Window *w : Window::IterateFromBack()) { int left, top; /* XXX - this probably needs something more sane. For example specifying * in a 'backup'-desc that the window should always be centered. */ diff --git a/src/window_gui.h b/src/window_gui.h index 67a799c3d3..66c867a547 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -810,6 +810,68 @@ public: * @pre this->IsNewGRFInspectable() */ virtual void ShowNewGRFInspectWindow() const { NOT_REACHED(); } + + /** + * Iterator to iterate all valid Windows + * @tparam T Type of the class/struct that is going to be iterated + * @tparam Tfront Wether we iterate from front + */ + template + struct WindowIterator { + typedef T value_type; + typedef T *pointer; + typedef T &reference; + typedef size_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit WindowIterator(T *start) : w(start) + { + this->Validate(); + } + + bool operator==(const WindowIterator &other) const { return this->w == other.w; } + bool operator!=(const WindowIterator &other) const { return !(*this == other); } + T * operator*() const { return this->w; } + WindowIterator & operator++() { this->Next(); this->Validate(); return *this; } + + private: + T *w; + void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); } + void Next() { if (this->w != nullptr) this->w = Tfront ? this->w->z_back : this->w->z_front; } + }; + + /** + * Iterable ensemble of all valid Windows + * @tparam T Type of the class/struct that is going to be iterated + * @tparam Tfront Wether we iterate from front + */ + template + struct Iterate { + Iterate(T *from) : from(from) {} + WindowIterator begin() { return WindowIterator(this->from); } + WindowIterator end() { return WindowIterator(nullptr); } + bool empty() { return this->begin() == this->end(); } + private: + T *from; + }; + + /** + * Returns an iterable ensemble of all valid Window from back to front + * @tparam T Type of the class/struct that is going to be iterated + * @param from index of the first Window to consider + * @return an iterable ensemble of all valid Window + */ + template + static Iterate IterateFromBack(T *from = _z_back_window) { return Iterate(from); } + + /** + * Returns an iterable ensemble of all valid Window from front to back + * @tparam T Type of the class/struct that is going to be iterated + * @param from index of the first Window to consider + * @return an iterable ensemble of all valid Window + */ + template + static Iterate IterateFromFront(T *from = _z_front_window) { return Iterate(from); } }; /** @@ -888,12 +950,6 @@ void GuiShowTooltips(Window *parent, StringID str, uint paramcount = 0, const ui /* widget.cpp */ int GetWidgetFromPos(const Window *w, int x, int y); -/** Iterate over all windows */ -#define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start) for (w = start; w != nullptr; w = w->z_front) if (w->window_class != WC_INVALID) -#define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = start; w != nullptr; w = w->z_back) if (w->window_class != WC_INVALID) -#define FOR_ALL_WINDOWS_FROM_BACK(w) FOR_ALL_WINDOWS_FROM_BACK_FROM(w, _z_back_window) -#define FOR_ALL_WINDOWS_FROM_FRONT(w) FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, _z_front_window) - extern Point _cursorpos_drag_start; extern int _scrollbar_start_pos; From 9a8756d7ed6fdde20bad9be8c8b8bc8fda0170f9 Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 29 Apr 2021 17:51:05 +0200 Subject: [PATCH 022/800] Codechange: Replace FOR_ALL_CARGOSPECS with range-based for loops --- src/cargotype.cpp | 10 ++---- src/cargotype.h | 47 ++++++++++++++++++++++++++--- src/economy.cpp | 3 +- src/newgrf.cpp | 6 ++-- src/newgrf_station.cpp | 3 +- src/script/api/script_cargolist.cpp | 3 +- src/station_cmd.cpp | 3 +- src/town_cmd.cpp | 3 +- 8 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/cargotype.cpp b/src/cargotype.cpp index 81818d5f9d..bf9561dda8 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -84,8 +84,7 @@ void SetupCargoForClimate(LandscapeID l) */ CargoID GetCargoIDByLabel(CargoLabel cl) { - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (cs->label == cl) return cs->Index(); } @@ -103,8 +102,7 @@ CargoID GetCargoIDByBitnum(uint8 bitnum) { if (bitnum == INVALID_CARGO) return CT_INVALID; - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (cs->bitnum == bitnum) return cs->Index(); } @@ -132,7 +130,6 @@ SpriteID CargoSpec::GetCargoIcon() const std::vector _sorted_cargo_specs; ///< Cargo specifications sorted alphabetically by name. uint8 _sorted_standard_cargo_specs_size; ///< Number of standard cargo specifications stored in the _sorted_cargo_specs array. - /** Sort cargo specifications by their name. */ static bool CargoSpecNameSorter(const CargoSpec * const &a, const CargoSpec * const &b) { @@ -169,9 +166,8 @@ static bool CargoSpecClassSorter(const CargoSpec * const &a, const CargoSpec * c void InitializeSortedCargoSpecs() { _sorted_cargo_specs.clear(); - const CargoSpec *cargo; /* Add each cargo spec to the list. */ - FOR_ALL_CARGOSPECS(cargo) { + for (const CargoSpec *cargo : CargoSpec::Iterate()) { _sorted_cargo_specs.push_back(cargo); } diff --git a/src/cargotype.h b/src/cargotype.h index afc501a2f2..4a295f1ae5 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -122,6 +122,49 @@ struct CargoSpec { SpriteID GetCargoIcon() const; + /** + * Iterator to iterate all valid CargoSpec + */ + struct Iterator { + typedef CargoSpec value_type; + typedef CargoSpec *pointer; + typedef CargoSpec &reference; + typedef size_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit Iterator(size_t index) : index(index) + { + this->ValidateIndex(); + }; + + bool operator==(const Iterator &other) const { return this->index == other.index; } + bool operator!=(const Iterator &other) const { return !(*this == other); } + CargoSpec * operator*() const { return CargoSpec::Get(this->index); } + Iterator & operator++() { this->index++; this->ValidateIndex(); return *this; } + + private: + size_t index; + void ValidateIndex() { while (this->index < CargoSpec::GetArraySize() && !(CargoSpec::Get(this->index)->IsValid())) this->index++; } + }; + + /* + * Iterable ensemble of all valid CargoSpec + */ + struct IterateWrapper { + size_t from; + IterateWrapper(size_t from = 0) : from(from) {} + Iterator begin() { return Iterator(this->from); } + Iterator end() { return Iterator(CargoSpec::GetArraySize()); } + bool empty() { return this->begin() == this->end(); } + }; + + /** + * Returns an iterable ensemble of all valid CargoSpec + * @param from index of the first CargoSpec to consider + * @return an iterable ensemble of all valid CargoSpec + */ + static IterateWrapper Iterate(size_t from = 0) { return IterateWrapper(from); } + private: static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs @@ -150,10 +193,6 @@ static inline bool IsCargoInClass(CargoID c, CargoClass cc) return (CargoSpec::Get(c)->classes & cc) != 0; } -#define FOR_ALL_CARGOSPECS_FROM(var, start) for (size_t cargospec_index = start; var = nullptr, cargospec_index < CargoSpec::GetArraySize(); cargospec_index++) \ - if ((var = CargoSpec::Get(cargospec_index))->IsValid()) -#define FOR_ALL_CARGOSPECS(var) FOR_ALL_CARGOSPECS_FROM(var, 0) - #define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, CargoTypes, cargo_bits) /** diff --git a/src/economy.cpp b/src/economy.cpp index 716446ba9e..9982e79e02 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -798,8 +798,7 @@ void RecomputePrices() } /* Setup cargo payment */ - CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (CargoSpec *cs : CargoSpec::Iterate()) { cs->current_payment = ((int64)cs->initial_payment * _economy.inflation_payment) >> 16; } diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 46bd5a6558..19cc436dd7 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5332,8 +5332,7 @@ static CargoID TranslateCargo(uint8 feature, uint8 ctype) return CT_INVALID; } - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (cs->bitnum == ctype) { grfmsg(6, "TranslateCargo: Cargo bitnum %d mapped to cargo type %d.", ctype, cs->Index()); return cs->Index(); @@ -8811,8 +8810,7 @@ static void CalculateRefitMasks() if (_gted[engine].cargo_allowed != 0) { /* Build up the list of cargo types from the set cargo classes. */ - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (_gted[engine].cargo_allowed & cs->classes) SetBit(mask, cs->Index()); if (_gted[engine].cargo_disallowed & cs->classes) SetBit(not_mask, cs->Index()); } diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index a127d54c9b..fa3f831aa5 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -572,8 +572,7 @@ StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseSt } else if (Station::IsExpected(this->station_scope.st)) { const Station *st = Station::From(this->station_scope.st); /* Pick the first cargo that we have waiting */ - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (this->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != nullptr && st->goods[cs->Index()].cargo.TotalCount() > 0) { ctype = cs->Index(); diff --git a/src/script/api/script_cargolist.cpp b/src/script/api/script_cargolist.cpp index fbd150c6cf..0019dc5e91 100644 --- a/src/script/api/script_cargolist.cpp +++ b/src/script/api/script_cargolist.cpp @@ -19,8 +19,7 @@ ScriptCargoList::ScriptCargoList() { - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { this->AddItem(cs->Index()); } } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 7266ad6187..482b954625 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3467,8 +3467,7 @@ static void UpdateStationRating(Station *st) byte_inc_sat(&st->time_since_load); byte_inc_sat(&st->time_since_unload); - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { GoodsEntry *ge = &st->goods[cs->Index()]; /* Slowly increase the rating back to his original level in the case we * didn't deliver cargo yet to this station. This happens when a bribe diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 43f3523f8e..a0f5df23ed 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2779,8 +2779,7 @@ CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 */ const CargoSpec *FindFirstCargoWithTownEffect(TownEffect effect) { - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (cs->town_effect == effect) return cs; } return nullptr; From f018471b36fe1ffaedf98430b4156ad369e26c66 Mon Sep 17 00:00:00 2001 From: PeterN Date: Thu, 29 Apr 2021 22:46:42 +0100 Subject: [PATCH 023/800] Cleanup: Remove old FiosList helper methods. (#9139) --- src/console_cmds.cpp | 4 +- src/fios.cpp | 35 ++++++++-------- src/fios.h | 86 +--------------------------------------- src/fios_gui.cpp | 20 +++++----- src/os/windows/win32.cpp | 2 +- 5 files changed, 30 insertions(+), 117 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 9dce399096..401a52b1f9 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -59,7 +59,7 @@ public: /** Declare the file storage cache as being invalid, also clears all stored files. */ void InvalidateFileList() { - this->Clear(); + this->clear(); this->file_list_valid = false; } @@ -403,7 +403,7 @@ DEF_CONSOLE_CMD(ConListFiles) } _console_file_list.ValidateFileList(true); - for (uint i = 0; i < _console_file_list.Length(); i++) { + for (uint i = 0; i < _console_file_list.size(); i++) { IConsolePrintF(CC_DEFAULT, "%d) %s", i, _console_file_list[i].title); } diff --git a/src/fios.cpp b/src/fios.cpp index b68da08f80..8528e8c622 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -63,11 +63,6 @@ bool FiosItem::operator< (const FiosItem &other) const return (_savegame_sort_order & SORT_DESCENDING) ? r > 0 : r < 0; } -FileList::~FileList() -{ - this->Clear(); -} - /** * Construct a file list with the given kind of files, for the stated purpose. * @param abstract_filetype Kind of files to collect. @@ -75,7 +70,7 @@ FileList::~FileList() */ void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop) { - this->Clear(); + this->clear(); assert(fop == SLO_LOAD || fop == SLO_SAVE); switch (abstract_filetype) { @@ -107,7 +102,8 @@ void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperati */ const FiosItem *FileList::FindItem(const char *file) { - for (const FiosItem *item = this->Begin(); item != this->End(); item++) { + for (const auto &it : *this) { + const FiosItem *item = ⁢ if (strcmp(file, item->name) == 0) return item; if (strcmp(file, item->title) == 0) return item; } @@ -117,13 +113,14 @@ const FiosItem *FileList::FindItem(const char *file) int i = strtol(file, &endptr, 10); if (file == endptr || *endptr != '\0') i = -1; - if (IsInsideMM(i, 0, this->Length())) return this->Get(i); + if (IsInsideMM(i, 0, this->size())) return &this->at(i); /* As a last effort assume it is an OpenTTD savegame and * that the ".sav" part was not given. */ char long_file[MAX_PATH]; seprintf(long_file, lastof(long_file), "%s.sav", file); - for (const FiosItem *item = this->Begin(); item != this->End(); item++) { + for (const auto &it : *this) { + const FiosItem *item = ⁢ if (strcmp(long_file, item->name) == 0) return item; if (strcmp(long_file, item->title) == 0) return item; } @@ -302,11 +299,11 @@ bool FiosFileScanner::AddFile(const std::string &filename, size_t basepath_lengt FiosType type = this->callback_proc(this->fop, filename, ext.c_str(), fios_title, lastof(fios_title)); if (type == FIOS_TYPE_INVALID) return false; - for (const FiosItem *fios = file_list.Begin(); fios != file_list.End(); fios++) { - if (filename == fios->name) return false; + for (const auto &fios : file_list) { + if (filename == fios.name) return false; } - FiosItem *fios = file_list.Append(); + FiosItem *fios = &file_list.emplace_back(); #ifdef _WIN32 // Retrieve the file modified date using GetFileTime rather than stat to work around an obscure MSVC bug that affects Windows XP HANDLE fh = CreateFile(OTTD2FS(filename).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); @@ -367,13 +364,13 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c size_t sort_start; char d_name[sizeof(fios->name)]; - file_list.Clear(); + file_list.clear(); assert(_fios_path != nullptr); /* A parent directory link exists if we are not in the root directory */ if (!FiosIsRoot(_fios_path->c_str())) { - fios = file_list.Append(); + fios = &file_list.emplace_back(); fios->type = FIOS_TYPE_PARENT; fios->mtime = 0; strecpy(fios->name, "..", lastof(fios->name)); @@ -390,7 +387,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) && (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) && strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) { - fios = file_list.Append(); + fios = &file_list.emplace_back(); fios->type = FIOS_TYPE_DIR; fios->mtime = 0; strecpy(fios->name, d_name, lastof(fios->name)); @@ -407,12 +404,12 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c { SortingBits order = _savegame_sort_order; _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; - std::sort(file_list.files.begin(), file_list.files.end()); + std::sort(file_list.begin(), file_list.end()); _savegame_sort_order = order; } /* This is where to start sorting for the filenames */ - sort_start = file_list.Length(); + sort_start = file_list.size(); /* Show files */ FiosFileScanner scanner(fop, callback_proc, file_list); @@ -422,12 +419,12 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c scanner.Scan(nullptr, subdir, true, true); } - std::sort(file_list.files.begin() + sort_start, file_list.files.end()); + std::sort(file_list.begin() + sort_start, file_list.end()); /* Show drives */ FiosGetDrives(file_list); - file_list.Compact(); + file_list.shrink_to_fit(); } /** diff --git a/src/fios.h b/src/fios.h index 3a16b6426a..28a1cc6aa5 100644 --- a/src/fios.h +++ b/src/fios.h @@ -109,94 +109,10 @@ struct FiosItem { }; /** List of file information. */ -class FileList { +class FileList : public std::vector { public: - ~FileList(); - - /** - * Construct a new entry in the file list. - * @return Pointer to the new items to be initialized. - */ - inline FiosItem *Append() - { - return &this->files.emplace_back(); - } - - /** - * Get the number of files in the list. - * @return The number of files stored in the list. - */ - inline size_t Length() const - { - return this->files.size(); - } - - /** - * Get a pointer to the first file information. - * @return Address of the first file information. - */ - inline const FiosItem *Begin() const - { - return this->files.data(); - } - - /** - * Get a pointer behind the last file information. - * @return Address behind the last file information. - */ - inline const FiosItem *End() const - { - return this->Begin() + this->Length(); - } - - /** - * Get a pointer to the indicated file information. File information must exist. - * @return Address of the indicated existing file information. - */ - inline const FiosItem *Get(size_t index) const - { - return this->files.data() + index; - } - - /** - * Get a pointer to the indicated file information. File information must exist. - * @return Address of the indicated existing file information. - */ - inline FiosItem *Get(size_t index) - { - return this->files.data() + index; - } - - inline const FiosItem &operator[](size_t index) const - { - return this->files[index]; - } - - /** - * Get a reference to the indicated file information. File information must exist. - * @return The requested file information. - */ - inline FiosItem &operator[](size_t index) - { - return this->files[index]; - } - - /** Remove all items from the list. */ - inline void Clear() - { - this->files.clear(); - } - - /** Compact the list down to the smallest block size boundary. */ - inline void Compact() - { - this->files.shrink_to_fit(); - } - void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop); const FiosItem *FindItem(const char *file); - - std::vector files; ///< The list of files. }; enum SortingBits { diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index e1133dd3cc..8de6235d62 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -249,8 +249,8 @@ static void SortSaveGameList(FileList &file_list) * Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE) * Only sort savegames/scenarios, not directories */ - for (const FiosItem *item = file_list.Begin(); item != file_list.End(); item++) { - switch (item->type) { + for (const auto &item : file_list) { + switch (item.type) { case FIOS_TYPE_DIR: sort_start++; break; case FIOS_TYPE_PARENT: sort_start++; break; case FIOS_TYPE_DRIVE: sort_end++; break; @@ -258,7 +258,7 @@ static void SortSaveGameList(FileList &file_list) } } - std::sort(file_list.files.begin() + sort_start, file_list.files.end() - sort_end); + std::sort(file_list.begin() + sort_start, file_list.end() - sort_end); } struct SaveLoadWindow : public Window { @@ -437,14 +437,14 @@ public: uint y = r.top + WD_FRAMERECT_TOP; uint scroll_pos = this->vscroll->GetPosition(); - for (uint row = 0; row < this->fios_items.Length(); row++) { + for (uint row = 0; row < this->fios_items.size(); row++) { if (!this->fios_items_shown[row]) { /* The current item is filtered out : we do not show it */ scroll_pos++; continue; } if (row < scroll_pos) continue; - const FiosItem *item = this->fios_items.Get(row); + const FiosItem *item = &this->fios_items[row]; if (item == this->selected) { GfxFillRect(r.left + 1, y, r.right, y + this->resize.step_height, PC_DARK_BLUE); @@ -651,7 +651,7 @@ public: if (!this->fios_items_shown[i]) y++; i++; } - const FiosItem *file = this->fios_items.Get(y); + const FiosItem *file = &this->fios_items[y]; const char *name = FiosBrowseTo(file); if (name == nullptr) { @@ -734,7 +734,7 @@ public: if (!this->fios_items_shown[i]) y++; i++; } - const FiosItem *file = this->fios_items.Get(y); + const FiosItem *file = &this->fios_items[y]; if (file != this->highlighted) { this->highlighted = file; @@ -812,7 +812,7 @@ public: _fios_path_changed = true; this->fios_items.BuildFileList(this->abstract_filetype, this->fop); - this->vscroll->SetCount((uint)this->fios_items.Length()); + this->vscroll->SetCount((uint)this->fios_items.size()); this->selected = nullptr; _load_check_data.Clear(); @@ -852,10 +852,10 @@ public: case SLIWD_FILTER_CHANGES: /* Filter changes */ - this->fios_items_shown.resize(this->fios_items.Length()); + this->fios_items_shown.resize(this->fios_items.size()); uint items_shown_count = 0; ///< The number of items shown in the list /* We pass through every fios item */ - for (uint i = 0; i < this->fios_items.Length(); i++) { + for (uint i = 0; i < this->fios_items.size(); i++) { if (this->string_filter.IsEmpty()) { /* We don't filter anything out if the filter editbox is empty */ this->fios_items_shown[i] = true; diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index ddcfd4866c..eee81be402 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -209,7 +209,7 @@ void FiosGetDrives(FileList &file_list) GetLogicalDriveStrings(lengthof(drives), drives); for (s = drives; *s != '\0';) { - FiosItem *fios = file_list.Append(); + FiosItem *fios = &file_list.emplace_back(); fios->type = FIOS_TYPE_DRIVE; fios->mtime = 0; seprintf(fios->name, lastof(fios->name), "%c:", s[0] & 0xFF); From f00564eeb20a09647f6f52b4ca5b39cb1e6a59aa Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 30 Apr 2021 00:16:41 +0200 Subject: [PATCH 024/800] Fix: String validation could leave invalid Utf8 encoded strings (#9096) In case a character was encoded in multiple bytes, but required fewer bytes to be encoded, the first byte would be copied to the output leaving an invalid Utf8 encoded string. Later uses of the validated string would use the same decode logic, which would yield a question mark and just read a single byte, so nothing dangerous happened. Furthermore, because the next byte would not be a first byte of an encoded Utf8 character, the last few valid characters could be removed by the validation as well. --- src/string.cpp | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/string.cpp b/src/string.cpp index dfd01450e0..38f7d1bd10 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -192,19 +192,35 @@ static void str_validate(T &dst, const char *str, const char *last, StringValida while (str <= last && *str != '\0') { size_t len = Utf8EncodedCharLen(*str); - /* If the character is unknown, i.e. encoded length is 0 - * we assume worst case for the length check. - * The length check is needed to prevent Utf8Decode to read - * over the terminating '\0' if that happens to be placed - * within the encoding of an UTF8 character. */ - if ((len == 0 && str + 4 > last) || str + len > last) break; - WChar c; - len = Utf8Decode(&c, str); - /* It's possible to encode the string termination character - * into a multiple bytes. This prevents those termination - * characters to be skipped */ - if (c == '\0') break; + /* If the first byte does not look like the first byte of an encoded + * character, i.e. encoded length is 0, then this byte is definitely bad + * and it should be skipped. + * When the first byte looks like the first byte of an encoded character, + * then the remaining bytes in the string are checked whether the whole + * encoded character can be there. If that is not the case, this byte is + * skipped. + * Finally we attempt to decode the encoded character, which does certain + * extra validations to see whether the correct number of bytes were used + * to encode the character. If that is not the case, the byte is probably + * invalid and it is skipped. We could emit a question mark, but then the + * logic below cannot just copy bytes, it would need to re-encode the + * decoded characters as the length in bytes may have changed. + * + * The goals here is to get as much valid Utf8 encoded characters from the + * source string to the destination string. + * + * Note: a multi-byte encoded termination ('\0') will trigger the encoded + * char length and the decoded length to differ, so it will be ignored as + * invalid character data. If it were to reach the termination, then we + * would also reach the "last" byte of the string and a normal '\0' + * termination will be placed after it. + */ + if (len == 0 || str + len > last || len != Utf8Decode(&c, str)) { + /* Maybe the next byte is still a valid character? */ + str++; + continue; + } if ((IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) || ((settings & SVS_ALLOW_CONTROL_CODE) != 0 && c == SCC_ENCODED)) { /* Copy the character back. Even if dst is current the same as str @@ -225,6 +241,8 @@ static void str_validate(T &dst, const char *str, const char *last, StringValida if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) *dst++ = '?'; } } + + /* String termination, if needed, is left to the caller of this function. */ } /** From 69118d063f9316e10128580f790175cd2779abdc Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 30 Apr 2021 11:34:47 +0200 Subject: [PATCH 025/800] Change: use TCP for everything except for master-server and initial server scan (#9130) This means that pressing Refresh button and adding servers manually now uses TCP. The master-server and initial scan are still UDP as they will be replaced by Game Coordinator; no need to change this now. If we query a server that is too old, show a proper warning to the user informing him the server is too old. --- os/emscripten/pre.js | 10 +++++--- src/lang/english.txt | 1 + src/network/network.cpp | 44 +++++++++++++++++++++++--------- src/network/network_client.cpp | 35 +++++++++++++++++++------ src/network/network_client.h | 6 +++-- src/network/network_gamelist.cpp | 10 -------- src/network/network_gui.cpp | 11 ++++---- src/network/network_internal.h | 4 +-- 8 files changed, 78 insertions(+), 43 deletions(-) diff --git a/os/emscripten/pre.js b/os/emscripten/pre.js index 1563e4f95b..82664004ea 100644 --- a/os/emscripten/pre.js +++ b/os/emscripten/pre.js @@ -65,10 +65,14 @@ Module.preRun.push(function() { } window.openttd_server_list = function() { - add_server = Module.cwrap("em_openttd_add_server", null, ["string", "number"]); + add_server = Module.cwrap("em_openttd_add_server", null, ["string"]); - /* Add servers that support WebSocket here. Example: - * add_server("localhost", 3979); */ + /* Add servers that support WebSocket here. Examples: + * add_server("localhost"); + * add_server("localhost:3979"); + * add_server("127.0.0.1:3979"); + * add_server("[::1]:3979"); + */ } var leftButtonDown = false; diff --git a/src/lang/english.txt b/src/lang/english.txt index 3037bf90fe..f8e3618e51 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2217,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your com STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Your computer took too long to download the map STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Your computer took too long to join the server STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your player name is not valid +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}The queried server is too old for this client ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :general error diff --git a/src/network/network.cpp b/src/network/network.cpp index d7cf9367a1..c31a67487d 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -602,8 +602,11 @@ static void NetworkInitialize(bool close_admins = true) /** Non blocking connection create to query servers */ class TCPQueryConnecter : TCPConnecter { +private: + bool request_company_info; + public: - TCPQueryConnecter(const NetworkAddress &address) : TCPConnecter(address) {} + TCPQueryConnecter(const NetworkAddress &address, bool request_company_info) : TCPConnecter(address), request_company_info(request_company_info) {} void OnFailure() override { @@ -613,36 +616,53 @@ public: void OnConnect(SOCKET s) override { _networking = true; - new ClientNetworkGameSocketHandler(s); - MyClient::SendInformationQuery(); + new ClientNetworkGameSocketHandler(s, address); + MyClient::SendInformationQuery(request_company_info); } }; /** * Query a server to fetch his game-info. * @param address the address to query. + * @param request_company_info Whether to request company info too. */ -void NetworkTCPQueryServer(NetworkAddress address) +void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info) { if (!_network_available) return; NetworkDisconnect(); NetworkInitialize(); - new TCPQueryConnecter(address); + new TCPQueryConnecter(address, request_company_info); } /** * Validates an address entered as a string and adds the server to * the list. If you use this function, the games will be marked * as manually added. - * @param connection_string The IP:port to add to the list. + * @param connection_string The IP:port of the server to add. + * @return The entry on the game list. */ -void NetworkAddServer(const char *connection_string) +NetworkGameList *NetworkAddServer(const std::string &connection_string) { - if (StrEmpty(connection_string)) return; + if (connection_string.empty()) return nullptr; - NetworkUDPQueryServer(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT), true); + NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT); + + /* Ensure the item already exists in the list */ + NetworkGameList *item = NetworkGameListAddItem(address); + if (StrEmpty(item->info.server_name)) { + ClearGRFConfigList(&item->info.grfconfig); + address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name)); + item->manually = true; + + NetworkRebuildHostList(); + UpdateNetworkGameWindow(); + } + + NetworkTCPQueryServer(address); + + return item; } /** @@ -687,7 +707,7 @@ public: void OnConnect(SOCKET s) override { _networking = true; - new ClientNetworkGameSocketHandler(s); + new ClientNetworkGameSocketHandler(s, this->address); IConsoleCmdExec("exec scripts/on_client.scr 0"); NetworkClient_Connected(); } @@ -1132,9 +1152,9 @@ void NetworkShutDown() #ifdef __EMSCRIPTEN__ extern "C" { -void CDECL em_openttd_add_server(const char *host, int port) +void CDECL em_openttd_add_server(const char *connection_string) { - NetworkUDPQueryServer(NetworkAddress(host, port), true); + NetworkAddServer(connection_string); } } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index af7073e558..f73c8be528 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -145,7 +145,7 @@ void ClientNetworkEmergencySave() * Create a new socket for the client side of the game connection. * @param s The socket to connect with. */ -ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s), savegame(nullptr), status(STATUS_INACTIVE) +ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address) : NetworkGameSocketHandler(s), address(address), savegame(nullptr), status(STATUS_INACTIVE) { assert(ClientNetworkGameSocketHandler::my_client == nullptr); ClientNetworkGameSocketHandler::my_client = this; @@ -345,14 +345,18 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1); /** * Query the server for server information. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery() +NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery(bool request_company_info) { - my_client->status = STATUS_COMPANY_INFO; - _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO; - SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); - + my_client->status = STATUS_GAME_INFO; my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO)); - my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO)); + + if (request_company_info) { + my_client->status = STATUS_COMPANY_INFO; + _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO; + SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + + my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO)); + } return NETWORK_RECV_STATUS_OKAY; } @@ -577,9 +581,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet * NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) { - if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + 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->address); + } /* Clear any existing GRFConfig chain. */ ClearGRFConfigList(&item->info.grfconfig); @@ -590,6 +598,8 @@ 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. */ + SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); /* We will receive company info next, so keep connection open. */ @@ -727,6 +737,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8(); + /* If we query a server that is 1.11.1 or older, we get an + * NETWORK_ERROR_NOT_EXPECTED on requesting the game info. Show a special + * error popup in that case. + */ + if (error == NETWORK_ERROR_NOT_EXPECTED && (this->status == STATUS_GAME_INFO || this->status == STATUS_COMPANY_INFO)) { + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_TOO_OLD, INVALID_STRING_ID, WL_CRITICAL); + return NETWORK_RECV_STATUS_CLOSE_QUERY; + } + StringID err = STR_NETWORK_ERROR_LOSTCONNECTION; if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error]; /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */ diff --git a/src/network/network_client.h b/src/network/network_client.h index 66cdb8ba57..40b8eedf92 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -15,12 +15,14 @@ /** Class for handling the client side of the game connection. */ class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler { private: + NetworkAddress address; ///< Address we are connected to. struct PacketReader *savegame; ///< Packet reader for reading the savegame. byte token; ///< The token we need to send back to the server to prove we're the right client. /** Status of the connection with the server. */ enum ServerStatus { STATUS_INACTIVE, ///< The client is not connected nor active. + STATUS_GAME_INFO, ///< We are trying to get the game information. STATUS_COMPANY_INFO, ///< We are trying to get company information. STATUS_JOIN, ///< We are trying to join a server. STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs. @@ -74,13 +76,13 @@ protected: static NetworkRecvStatus SendMapOk(); void CheckConnection(); public: - ClientNetworkGameSocketHandler(SOCKET s); + ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address); ~ClientNetworkGameSocketHandler(); NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override; void ClientError(NetworkRecvStatus res); - static NetworkRecvStatus SendInformationQuery(); + static NetworkRecvStatus SendInformationQuery(bool request_company_info); static NetworkRecvStatus SendJoin(); static NetworkRecvStatus SendCommand(const CommandPacket *cp); diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index 6d4285c854..12dbbce615 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -69,15 +69,6 @@ static void NetworkGameListHandleDelayedInsert() */ NetworkGameList *NetworkGameListAddItem(NetworkAddress address) { - const char *hostname = address.GetHostname(); - - /* Do not query the 'any' address. */ - if (StrEmpty(hostname) || - strcmp(hostname, "0.0.0.0") == 0 || - strcmp(hostname, "::") == 0) { - return nullptr; - } - NetworkGameList *item, *prev_item; prev_item = nullptr; @@ -95,7 +86,6 @@ NetworkGameList *NetworkGameListAddItem(NetworkAddress address) } else { prev_item->next = item; } - DEBUG(net, 4, "[gamelist] added server to list"); UpdateNetworkGameWindow(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 3204b2b962..590f2f5e09 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -472,9 +472,8 @@ public: EM_ASM(if (window["openttd_server_list"]) openttd_server_list()); #endif - this->last_joined = NetworkGameListAddItem(ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT)); + this->last_joined = NetworkAddServer(_settings_client.network.last_joined); this->server = this->last_joined; - if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address); this->requery_timer.SetInterval(MILLISECONDS_PER_TICK); @@ -750,7 +749,7 @@ public: break; case WID_NG_REFRESH: // Refresh - if (this->server != nullptr) NetworkUDPQueryServer(this->server->address); + if (this->server != nullptr) NetworkTCPQueryServer(this->server->address); break; case WID_NG_NEWGRF: // NewGRF Settings @@ -971,7 +970,7 @@ void ShowNetworkGameWindow() first = false; /* Add all servers from the config file to our list. */ for (const auto &iter : _network_host_list) { - NetworkAddServer(iter.c_str()); + NetworkAddServer(iter); } } @@ -1485,7 +1484,7 @@ struct NetworkLobbyWindow : public Window { /* Clear the information so removed companies don't remain */ for (auto &company : this->company_info) company = {}; - NetworkTCPQueryServer(this->server->address); + NetworkTCPQueryServer(this->server->address, true); break; } } @@ -1555,7 +1554,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); - NetworkTCPQueryServer(ngl->address); + NetworkTCPQueryServer(ngl->address, true); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index ff3c8c22d2..683c954e82 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -87,10 +87,10 @@ extern uint8 _network_reconnect; extern CompanyMask _network_company_passworded; -void NetworkTCPQueryServer(NetworkAddress address); +void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info = false); void GetBindAddresses(NetworkAddressList *addresses, uint16 port); -void NetworkAddServer(const char *b); +struct NetworkGameList *NetworkAddServer(const std::string &connection_string); void NetworkRebuildHostList(); void UpdateNetworkGameWindow(); From e162aff7a3d1dfcde1a9d02780235c617b6d4983 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 30 Apr 2021 12:05:54 +0200 Subject: [PATCH 026/800] Cleanup: remove weird left-over comment in yapf.hpp --- src/pathfinder/yapf/yapf.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pathfinder/yapf/yapf.hpp b/src/pathfinder/yapf/yapf.hpp index 134c0dcf98..097aaf0f3a 100644 --- a/src/pathfinder/yapf/yapf.hpp +++ b/src/pathfinder/yapf/yapf.hpp @@ -15,9 +15,6 @@ #include "../pf_performance_timer.hpp" #include "yapf.h" -//#undef FORCEINLINE -//#define inline inline - #include "../../misc/fixedsizearray.hpp" #include "../../misc/array.hpp" #include "../../misc/hashtable.hpp" From 665a3928e2f07e6ee1faed1c8b08fe3a68fbc37a Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 30 Apr 2021 11:57:37 +0200 Subject: [PATCH 027/800] Remove: performance measurements in YAPF YAPF was constantly measuring its performance, but only at certain debug-levels this information was shown. Now after years, I sincerely wonder if anyone still knows about this feature and who still use it. Especially with the new framerate window, this detailed performance is not as meaningful anymore as it once was. --- src/pathfinder/CMakeLists.txt | 1 - src/pathfinder/follow_track.hpp | 18 +++--- src/pathfinder/npf/npf.cpp | 1 + src/pathfinder/pf_performance_timer.hpp | 80 ------------------------- src/pathfinder/yapf/yapf.hpp | 1 - src/pathfinder/yapf/yapf_base.hpp | 38 ++++-------- src/pathfinder/yapf/yapf_costcache.hpp | 8 --- src/pathfinder/yapf/yapf_costrail.hpp | 8 +-- src/pathfinder/yapf/yapf_rail.cpp | 2 - 9 files changed, 20 insertions(+), 137 deletions(-) delete mode 100644 src/pathfinder/pf_performance_timer.hpp diff --git a/src/pathfinder/CMakeLists.txt b/src/pathfinder/CMakeLists.txt index 2e275706f2..0616371622 100644 --- a/src/pathfinder/CMakeLists.txt +++ b/src/pathfinder/CMakeLists.txt @@ -5,5 +5,4 @@ add_files( follow_track.hpp pathfinder_func.h pathfinder_type.h - pf_performance_timer.hpp ) diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 9b95578fd5..7e5e0e39b7 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -18,7 +18,6 @@ #include "../tunnelbridge_map.h" #include "../depot_map.h" #include "pathfinder_func.h" -#include "pf_performance_timer.hpp" /** * Track follower helper template class (can serve pathfinders and vehicle @@ -49,34 +48,32 @@ struct CFollowTrackT bool m_is_station; ///< last turn passed station int m_tiles_skipped; ///< number of skipped tunnel or station tiles ErrorCode m_err; - CPerformanceTimer *m_pPerf; RailTypes m_railtypes; - inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr) + inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES) { - Init(v, railtype_override, pPerf); + Init(v, railtype_override); } - inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr) + inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES) { assert(IsRailTT()); m_veh = nullptr; - Init(o, railtype_override, pPerf); + Init(o, railtype_override); } - inline void Init(const VehicleType *v, RailTypes railtype_override, CPerformanceTimer *pPerf) + inline void Init(const VehicleType *v, RailTypes railtype_override) { assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN)); m_veh = v; - Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override, pPerf); + Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override); } - inline void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf) + inline void Init(Owner o, RailTypes railtype_override) { assert(!IsRoadTT() || m_veh != nullptr); assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES); m_veh_owner = o; - m_pPerf = pPerf; /* don't worry, all is inlined so compiler should remove unnecessary initializations */ m_old_tile = INVALID_TILE; m_old_td = INVALID_TRACKDIR; @@ -237,7 +234,6 @@ protected: /** stores track status (available trackdirs) for the new tile into m_new_td_bits */ inline bool QueryNewTileTrackStatus() { - CPerfStart perf(*m_pPerf); if (IsRailTT() && IsPlainRailTile(m_new_tile)) { m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101); } else if (IsRoadTT()) { diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index 315b43b0e7..0094521615 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -8,6 +8,7 @@ /** @file npf.cpp Implementation of the NPF pathfinder. */ #include "../../stdafx.h" +#include "../../debug.h" #include "../../network/network.h" #include "../../viewport_func.h" #include "../../ship.h" diff --git a/src/pathfinder/pf_performance_timer.hpp b/src/pathfinder/pf_performance_timer.hpp deleted file mode 100644 index 66ec9695f8..0000000000 --- a/src/pathfinder/pf_performance_timer.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file pf_performance_timer.hpp Performance timer for pathfinders. */ - -#ifndef PF_PERFORMANCE_TIMER_HPP -#define PF_PERFORMANCE_TIMER_HPP - -#include "../debug.h" - -struct CPerformanceTimer -{ - int64 m_start; - int64 m_acc; - - CPerformanceTimer() : m_start(0), m_acc(0) {} - - inline void Start() - { - m_start = QueryTime(); - } - - inline void Stop() - { - m_acc += QueryTime() - m_start; - } - - inline int Get(int64 coef) - { - return (int)(m_acc * coef / QueryFrequency()); - } - - inline int64 QueryTime() - { - return ottd_rdtsc(); - } - - inline int64 QueryFrequency() - { - return ((int64)2200 * 1000000); - } -}; - -struct CPerfStartReal -{ - CPerformanceTimer *m_pperf; - - inline CPerfStartReal(CPerformanceTimer& perf) : m_pperf(&perf) - { - if (m_pperf != nullptr) m_pperf->Start(); - } - - inline ~CPerfStartReal() - { - Stop(); - } - - inline void Stop() - { - if (m_pperf != nullptr) { - m_pperf->Stop(); - m_pperf = nullptr; - } - } -}; - -struct CPerfStartFake -{ - inline CPerfStartFake(CPerformanceTimer& perf) {} - inline ~CPerfStartFake() {} - inline void Stop() {} -}; - -typedef CPerfStartFake CPerfStart; - -#endif /* PF_PERFORMANCE_TIMER_HPP */ diff --git a/src/pathfinder/yapf/yapf.hpp b/src/pathfinder/yapf/yapf.hpp index 097aaf0f3a..36df4db951 100644 --- a/src/pathfinder/yapf/yapf.hpp +++ b/src/pathfinder/yapf/yapf.hpp @@ -12,7 +12,6 @@ #include "../../landscape.h" #include "../pathfinder_func.h" -#include "../pf_performance_timer.hpp" #include "yapf.h" #include "../../misc/fixedsizearray.hpp" diff --git a/src/pathfinder/yapf/yapf_base.hpp b/src/pathfinder/yapf/yapf_base.hpp index c04fa2af92..b34e40a673 100644 --- a/src/pathfinder/yapf/yapf_base.hpp +++ b/src/pathfinder/yapf/yapf_base.hpp @@ -13,8 +13,6 @@ #include "../../debug.h" #include "../../settings_type.h" -extern int _total_pf_time_us; - /** * CYapfBaseT - A-star type path finder base class. * Derive your own pathfinder from it. You must provide the following template argument: @@ -67,12 +65,6 @@ protected: int m_stats_cost_calcs; ///< stats - how many node's costs were calculated int m_stats_cache_hits; ///< stats - how many node's costs were reused from cache -public: - CPerformanceTimer m_perf_cost; ///< stats - total CPU time of this run - CPerformanceTimer m_perf_slope_cost; ///< stats - slope calculation CPU time - CPerformanceTimer m_perf_ts_cost; ///< stats - GetTrackStatus() CPU time - CPerformanceTimer m_perf_other_cost; ///< stats - other CPU time - public: int m_num_steps; ///< this is there for debugging purposes (hope it doesn't hurt) @@ -120,9 +112,6 @@ public: { m_veh = v; - CPerformanceTimer perf; - perf.Start(); - Yapf().PfSetStartupNodes(); bool bDestFound = true; @@ -150,25 +139,18 @@ public: bDestFound &= (m_pBestDestNode != nullptr); - perf.Stop(); - if (_debug_yapf_level >= 2) { - int t = perf.Get(1000000); - _total_pf_time_us += t; + if (_debug_yapf_level >= 3) { + UnitID veh_idx = (m_veh != nullptr) ? m_veh->unitnumber : 0; + char ttc = Yapf().TransportTypeChar(); + float cache_hit_ratio = (m_stats_cache_hits == 0) ? 0.0f : ((float)m_stats_cache_hits / (float)(m_stats_cache_hits + m_stats_cost_calcs) * 100.0f); + int cost = bDestFound ? m_pBestDestNode->m_cost : -1; + int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1; - if (_debug_yapf_level >= 3) { - UnitID veh_idx = (m_veh != nullptr) ? m_veh->unitnumber : 0; - char ttc = Yapf().TransportTypeChar(); - float cache_hit_ratio = (m_stats_cache_hits == 0) ? 0.0f : ((float)m_stats_cache_hits / (float)(m_stats_cache_hits + m_stats_cost_calcs) * 100.0f); - int cost = bDestFound ? m_pBestDestNode->m_cost : -1; - int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1; - - DEBUG(yapf, 3, "[YAPF%c]%c%4d- %d us - %d rounds - %d open - %d closed - CHR %4.1f%% - C %d D %d - c%d(sc%d, ts%d, o%d) -- ", - ttc, bDestFound ? '-' : '!', veh_idx, t, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(), - cache_hit_ratio, cost, dist, m_perf_cost.Get(1000000), m_perf_slope_cost.Get(1000000), - m_perf_ts_cost.Get(1000000), m_perf_other_cost.Get(1000000) - ); - } + DEBUG(yapf, 3, "[YAPF%c]%c%4d- %d rounds - %d open - %d closed - CHR %4.1f%% - C %d D %d", + ttc, bDestFound ? '-' : '!', veh_idx, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(), cache_hit_ratio, cost, dist + ); } + return bDestFound; } diff --git a/src/pathfinder/yapf/yapf_costcache.hpp b/src/pathfinder/yapf/yapf_costcache.hpp index c56c47b5f2..1b4d52cff2 100644 --- a/src/pathfinder/yapf/yapf_costcache.hpp +++ b/src/pathfinder/yapf/yapf_costcache.hpp @@ -182,16 +182,8 @@ protected: inline static Cache& stGetGlobalCache() { static int last_rail_change_counter = 0; - static Date last_date = 0; static Cache C; - /* some statistics */ - if (last_date != _date) { - last_date = _date; - DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000); - _total_pf_time_us = 0; - } - /* delete the cache sometimes... */ if (last_rail_change_counter != Cache::s_rail_change_counter) { last_rail_change_counter = Cache::s_rail_change_counter; diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 6bed27cba6..b50300b618 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -86,7 +86,6 @@ protected: public: inline int SlopeCost(TileIndex tile, Trackdir td) { - CPerfStart perf_cost(Yapf().m_perf_slope_cost); if (!stSlopeCost(tile, td)) return 0; return Yapf().PfGetSettings().rail_slope_penalty; } @@ -172,7 +171,6 @@ public: { int cost = 0; /* if there is one-way signal in the opposite direction, then it is not our way */ - CPerfStart perf_cost(Yapf().m_perf_other_cost); if (IsTileType(tile, MP_RAILWAY)) { bool has_signal_against = HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir)); bool has_signal_along = HasSignalOnTrackdir(tile, trackdir); @@ -275,8 +273,6 @@ public: assert(tf->m_new_tile == n.m_key.m_tile); assert((HasTrackdir(tf->m_new_td_bits, n.m_key.m_td))); - CPerfStart perf_cost(Yapf().m_perf_cost); - /* Does the node have some parent node? */ bool has_parent = (n.m_parent != nullptr); @@ -326,7 +322,7 @@ public: EndSegmentReasonBits end_segment_reason = ESRB_NONE; - TrackFollower tf_local(v, Yapf().GetCompatibleRailTypes(), &Yapf().m_perf_ts_cost); + TrackFollower tf_local(v, Yapf().GetCompatibleRailTypes()); if (!has_parent) { /* We will jump to the middle of the cost calculator assuming that segment cache is not used. */ @@ -484,7 +480,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th /* Move to the next tile/trackdir. */ tf = &tf_local; - tf_local.Init(v, Yapf().GetCompatibleRailTypes(), &Yapf().m_perf_ts_cost); + tf_local.Init(v, Yapf().GetCompatibleRailTypes()); if (!tf_local.Follow(cur.tile, cur.td)) { assert(tf_local.m_err != TrackFollower::EC_NONE); diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index 3b6686f20d..41aa5fdbd8 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -34,8 +34,6 @@ template void DumpState(Tpf &pf1, Tpf &pf2) fclose(f2); } -int _total_pf_time_us = 0; - template class CYapfReserveTrack { From 3dbd6475fec5ebd63b18004bb94048460c4fb4a3 Mon Sep 17 00:00:00 2001 From: PeterN Date: Fri, 30 Apr 2021 12:03:07 +0100 Subject: [PATCH 028/800] Codechange: Use C++ features for train wagon overrides. (#9141) This removes the need for C-style array management and allows use of iterators to perform wagon override lookups. --- src/engine.cpp | 11 ----------- src/engine_base.h | 12 ++++++++---- src/newgrf_engine.cpp | 43 +++++-------------------------------------- src/newgrf_engine.h | 2 -- 4 files changed, 13 insertions(+), 55 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 60b0d42224..41cd9dba80 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -66,12 +66,6 @@ static_assert(lengthof(_orig_rail_vehicle_info) + lengthof(_orig_road_vehicle_in const uint EngineOverrideManager::NUM_DEFAULT_ENGINES = _engine_counts[VEH_TRAIN] + _engine_counts[VEH_ROAD] + _engine_counts[VEH_SHIP] + _engine_counts[VEH_AIRCRAFT]; -Engine::Engine() : - overrides_count(0), - overrides(nullptr) -{ -} - Engine::Engine(VehicleType type, EngineID base) { this->type = type; @@ -136,11 +130,6 @@ Engine::Engine(VehicleType type, EngineID base) } } -Engine::~Engine() -{ - UnloadWagonOverrides(this); -} - /** * Checks whether the engine is a valid (non-articulated part of an) engine. * @return true if enabled diff --git a/src/engine_base.h b/src/engine_base.h index 2e434b589e..7822111e77 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -15,6 +15,12 @@ #include "core/pool_type.hpp" #include "newgrf_commons.h" +struct WagonOverride { + std::vector engines; + CargoID cargo; + const SpriteGroup *group; +}; + typedef Pool EnginePool; extern EnginePool _engine_pool; @@ -56,13 +62,11 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { * evaluating callbacks. */ GRFFilePropsBase grf_prop; - uint16 overrides_count; - struct WagonOverride *overrides; + std::vector overrides; uint16 list_position; - Engine(); + Engine() {} Engine(VehicleType type, EngineID base); - ~Engine(); bool IsEnabled() const; /** diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index ee14098c28..cd12148558 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -26,62 +26,29 @@ #include "safeguards.h" -struct WagonOverride { - EngineID *train_id; - uint trains; - CargoID cargo; - const SpriteGroup *group; -}; - void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains) { Engine *e = Engine::Get(engine); - WagonOverride *wo; assert(cargo < NUM_CARGO + 2); // Include CT_DEFAULT and CT_PURCHASE pseudo cargoes. - e->overrides_count++; - e->overrides = ReallocT(e->overrides, e->overrides_count); - - wo = &e->overrides[e->overrides_count - 1]; + WagonOverride *wo = &e->overrides.emplace_back(); wo->group = group; wo->cargo = cargo; - wo->trains = trains; - wo->train_id = MallocT(trains); - memcpy(wo->train_id, train_id, trains * sizeof *train_id); + wo->engines.assign(train_id, train_id + trains); } const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine) { const Engine *e = Engine::Get(engine); - for (uint i = 0; i < e->overrides_count; i++) { - const WagonOverride *wo = &e->overrides[i]; - - if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue; - - for (uint j = 0; j < wo->trains; j++) { - if (wo->train_id[j] == overriding_engine) return wo->group; - } + for (const WagonOverride &wo : e->overrides) { + if (wo.cargo != cargo && wo.cargo != CT_DEFAULT) continue; + if (std::find(wo.engines.begin(), wo.engines.end(), overriding_engine) != wo.engines.end()) return wo.group; } return nullptr; } -/** - * Unload all wagon override sprite groups. - */ -void UnloadWagonOverrides(Engine *e) -{ - for (uint i = 0; i < e->overrides_count; i++) { - WagonOverride *wo = &e->overrides[i]; - free(wo->train_id); - } - free(e->overrides); - e->overrides_count = 0; - e->overrides = nullptr; -} - - void SetCustomEngineSprites(EngineID engine, byte cargo, const SpriteGroup *group) { Engine *e = Engine::Get(engine); diff --git a/src/newgrf_engine.h b/src/newgrf_engine.h index f830ff499d..90d755d3c4 100644 --- a/src/newgrf_engine.h +++ b/src/newgrf_engine.h @@ -116,8 +116,6 @@ enum VehicleTrigger { }; void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger); -void UnloadWagonOverrides(Engine *e); - void AlterVehicleListOrder(EngineID engine, uint target); void CommitVehicleListOrderChanges(); From 5153e1b6e38a75ef6eeb71760941018139feedea Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 01:18:22 +0100 Subject: [PATCH 029/800] Cleanup: Horizontal widget size is commonly width rather than length. --- src/widget.cpp | 6 +++--- src/widget_type.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 1e3afb1557..74a89eaeaf 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1503,12 +1503,12 @@ void NWidgetVertical::AssignSizePosition(SizingType sizing, uint x, uint y, uint /** * Generic spacer widget. - * @param length Horizontal size of the spacer widget. + * @param width Horizontal size of the spacer widget. * @param height Vertical size of the spacer widget. */ -NWidgetSpacer::NWidgetSpacer(int length, int height) : NWidgetResizeBase(NWID_SPACER, 0, 0) +NWidgetSpacer::NWidgetSpacer(int width, int height) : NWidgetResizeBase(NWID_SPACER, 0, 0) { - this->SetMinimalSize(length, height); + this->SetMinimalSize(width, height); this->SetResize(0, 0); } diff --git a/src/widget_type.h b/src/widget_type.h index e1fd92f638..c4c46ce66c 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -543,7 +543,7 @@ private: */ class NWidgetSpacer : public NWidgetResizeBase { public: - NWidgetSpacer(int length, int height); + NWidgetSpacer(int width, int height); void SetupSmallestSize(Window *w, bool init_array) override; void FillNestedArray(NWidgetBase **array, uint length) override; From 4c6cca459a678a5f1970b3ee5f23141d7ed89528 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 01:35:51 +0100 Subject: [PATCH 030/800] Cleanup: Remove fairly redundant DrawDropdown() function. --- src/widget.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 74a89eaeaf..78da9457cc 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -623,19 +623,6 @@ static inline void DrawButtonDropdown(const Rect &r, Colours colour, bool clicke } } -/** - * Draw a dropdown #WWT_DROPDOWN widget. - * @param r Rectangle containing the widget. - * @param colour Background colour of the widget. - * @param clicked The widget is lowered. - * @param str Text of the button. - * @param align Alignment of the text. - */ -static inline void DrawDropdown(const Rect &r, Colours colour, bool clicked, StringID str, StringAlignment align) -{ - DrawButtonDropdown(r, colour, false, clicked, str, align); -} - /** * Paint all widgets of a window. */ @@ -2639,7 +2626,7 @@ void NWidgetLeaf::Draw(const Window *w) case WWT_DROPDOWN: if (this->index >= 0) w->SetStringParameters(this->index); - DrawDropdown(r, this->colour, clicked, this->widget_data, this->align); + DrawButtonDropdown(r, this->colour, false, clicked, this->widget_data, this->align); break; case NWID_BUTTON_DROPDOWN: From 4f93dd95e4251e3227a55ee125838cefce173ef3 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 21 Apr 2021 23:55:16 +0100 Subject: [PATCH 031/800] Cleanup: Tidy up resize, fill and minimal size on widgets in town list window. --- src/town_gui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 1a7085c964..0629490393 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -647,12 +647,12 @@ static const NWidgetPart _nested_town_directory_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TD_SORT_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), - NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(35, 12), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), + NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(1, 0), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN, WID_TD_LIST), SetMinimalSize(196, 0), SetDataTip(0x0, STR_TOWN_DIRECTORY_LIST_TOOLTIP), - SetFill(1, 0), SetResize(0, 10), SetScrollbar(WID_TD_SCROLLBAR), EndContainer(), + SetFill(1, 0), SetResize(0, 1), SetScrollbar(WID_TD_SCROLLBAR), EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN), - NWidget(WWT_TEXT, COLOUR_BROWN, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 0, 2), SetMinimalSize(196, 12), SetFill(1, 0), SetDataTip(STR_TOWN_POPULATION, STR_NULL), + NWidget(WWT_TEXT, COLOUR_BROWN, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 2, 2), SetMinimalSize(196, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetDataTip(STR_TOWN_POPULATION, STR_NULL), EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), From 2efa390a7d2091b2c2cef4aa7f986fdcb24eac2a Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 01:17:30 +0100 Subject: [PATCH 032/800] Codechange: Simplify calling of DrawCharCentered() --- src/gfx.cpp | 10 ++++++---- src/gfx_func.h | 2 +- src/osk_gui.cpp | 5 +---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index d540f4dfe0..d3c730be12 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -891,15 +891,17 @@ const char *GetCharAtPosition(const char *str, int x, FontSize start_fontsize) /** * Draw single character horizontally centered around (x,y) * @param c Character (glyph) to draw - * @param x X position to draw character - * @param y Y position to draw character + * @param r Rectangle to draw character within * @param colour Colour to use, for details see _string_colourmap in * table/palettes.h or docs/ottd-colourtext-palette.png or the enum TextColour in gfx_type.h */ -void DrawCharCentered(WChar c, int x, int y, TextColour colour) +void DrawCharCentered(WChar c, const Rect &r, TextColour colour) { SetColourRemap(colour); - GfxMainBlitter(GetGlyph(FS_NORMAL, c), x - GetCharacterWidth(FS_NORMAL, c) / 2, y, BM_COLOUR_REMAP); + GfxMainBlitter(GetGlyph(FS_NORMAL, c), + CenterBounds(r.left, r.right, GetCharacterWidth(FS_NORMAL, c)), + CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL), + BM_COLOUR_REMAP); } /** diff --git a/src/gfx_func.h b/src/gfx_func.h index a4db8a045a..18b1966f9b 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -96,7 +96,7 @@ int DrawString(int left, int right, int top, StringID str, TextColour colour = T int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL); int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL); -void DrawCharCentered(WChar c, int x, int y, TextColour colour); +void DrawCharCentered(WChar c, const Rect &r, TextColour colour); void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE); void GfxFillPolygon(const std::vector &shape, int colour, FillRectMode mode = FILLRECT_OPAQUE); diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 60c9023b82..233bb1c7aa 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -103,10 +103,7 @@ struct OskWindow : public Window { if (widget < WID_OSK_LETTERS) return; widget -= WID_OSK_LETTERS; - DrawCharCentered(_keyboard[this->shift][widget], - r.left + (r.right - r.left) / 2, - r.top + (r.bottom - r.top - FONT_HEIGHT_NORMAL) / 2, - TC_BLACK); + DrawCharCentered(_keyboard[this->shift][widget], r, TC_BLACK); } void OnClick(Point pt, int widget, int click_count) override From f5569763c9f34a32f59257f61f9797d54ace7b21 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 5 Apr 2021 20:28:00 +0100 Subject: [PATCH 033/800] Fix: Specify width when width is required instead of top. --- src/widget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 78da9457cc..705b93a946 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -2280,19 +2280,19 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, case WWT_SHADEBOX: this->SetFill(0, 0); - this->SetMinimalSize(WD_SHADEBOX_TOP, WD_CAPTION_HEIGHT); + this->SetMinimalSize(WD_SHADEBOX_WIDTH, WD_CAPTION_HEIGHT); this->SetDataTip(STR_NULL, STR_TOOLTIP_SHADE); break; case WWT_DEBUGBOX: this->SetFill(0, 0); - this->SetMinimalSize(WD_DEBUGBOX_TOP, WD_CAPTION_HEIGHT); + this->SetMinimalSize(WD_DEBUGBOX_WIDTH, WD_CAPTION_HEIGHT); this->SetDataTip(STR_NULL, STR_TOOLTIP_DEBUG); break; case WWT_DEFSIZEBOX: this->SetFill(0, 0); - this->SetMinimalSize(WD_DEFSIZEBOX_TOP, WD_CAPTION_HEIGHT); + this->SetMinimalSize(WD_DEFSIZEBOX_WIDTH, WD_CAPTION_HEIGHT); this->SetDataTip(STR_NULL, STR_TOOLTIP_DEFSIZE); break; From 03a43b824711898fe2c9f401a48fe2420d0abc28 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 8 Apr 2021 09:02:38 +0100 Subject: [PATCH 034/800] Cleanup: Call SetMinimalSize instead of setting min_y directly. --- src/widget.cpp | 5 +++-- src/widget_type.h | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 705b93a946..931b525d47 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -2268,7 +2268,8 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, case WWT_CAPTION: this->SetFill(1, 0); this->SetResize(1, 0); - this->min_y = WD_CAPTION_HEIGHT; + this->SetMinimalSize(0, WD_CAPTION_HEIGHT); + this->SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM, FS_NORMAL); this->SetDataTip(data, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); break; @@ -2310,7 +2311,7 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, case WWT_DROPDOWN: this->SetFill(0, 0); - this->min_y = WD_DROPDOWN_HEIGHT; + this->SetMinimalSize(0, WD_DROPDOWN_HEIGHT); this->SetAlignment(SA_TOP | SA_LEFT); break; diff --git a/src/widget_type.h b/src/widget_type.h index c4c46ce66c..077261ff26 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -251,7 +251,7 @@ public: void SetFill(uint fill_x, uint fill_y); void SetResize(uint resize_x, uint resize_y); - void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl); + void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; uint min_x; ///< Minimal horizontal size of only this widget. uint min_y; ///< Minimal vertical size of only this widget. @@ -470,8 +470,8 @@ class NWidgetHorizontal : public NWidgetPIPContainer { public: NWidgetHorizontal(NWidContainerFlags flags = NC_NONE); - void SetupSmallestSize(Window *w, bool init_array); - void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl); + void SetupSmallestSize(Window *w, bool init_array) override; + void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; }; /** @@ -482,7 +482,7 @@ class NWidgetHorizontalLTR : public NWidgetHorizontal { public: NWidgetHorizontalLTR(NWidContainerFlags flags = NC_NONE); - void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl); + void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; }; /** @@ -493,8 +493,8 @@ class NWidgetVertical : public NWidgetPIPContainer { public: NWidgetVertical(NWidContainerFlags flags = NC_NONE); - void SetupSmallestSize(Window *w, bool init_array); - void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl); + void SetupSmallestSize(Window *w, bool init_array) override; + void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; }; /** From 6fe5353da2a0d3d60f8375b28536213e67cd869c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 02:13:55 +0100 Subject: [PATCH 035/800] Cleanup: Set unchanging scrollbar properties in constructor. --- src/widget.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 931b525d47..aae1a51651 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -2108,6 +2108,22 @@ NWidgetScrollbar::NWidgetScrollbar(WidgetType tp, Colours colour, int index) : N { assert(tp == NWID_HSCROLLBAR || tp == NWID_VSCROLLBAR); this->SetIndex(index); + + switch (this->type) { + case NWID_HSCROLLBAR: + this->SetResize(1, 0); + this->SetFill(1, 0); + this->SetDataTip(0x0, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST); + break; + + case NWID_VSCROLLBAR: + this->SetResize(0, 1); + this->SetFill(0, 1); + this->SetDataTip(0x0, STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST); + break; + + default: NOT_REACHED(); + } } void NWidgetScrollbar::SetupSmallestSize(Window *w, bool init_array) @@ -2122,16 +2138,10 @@ void NWidgetScrollbar::SetupSmallestSize(Window *w, bool init_array) switch (this->type) { case NWID_HSCROLLBAR: this->SetMinimalSize(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height); - this->SetResize(1, 0); - this->SetFill(1, 0); - this->SetDataTip(0x0, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST); break; case NWID_VSCROLLBAR: this->SetMinimalSize(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3); - this->SetResize(0, 1); - this->SetFill(0, 1); - this->SetDataTip(0x0, STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST); break; default: NOT_REACHED(); From 4791ff28627eabe6322352428dc1b42344f545b9 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 5 Apr 2021 18:43:12 +0100 Subject: [PATCH 036/800] Fix: Recalculate padding and minimum sizes when GUI or Font zoom is changed. --- src/gfx.cpp | 2 +- src/gfxinit.cpp | 2 +- src/network/network_gui.cpp | 4 +- src/newgrf_gui.cpp | 2 +- src/osk_gui.cpp | 2 +- src/settings.cpp | 2 +- src/settings_gui.cpp | 7 +-- src/video/video_driver.cpp | 2 +- src/widget.cpp | 90 ++++++++++++++++++++++++++++++++----- src/widget_type.h | 33 ++++++++++++-- src/widgets/dropdown.cpp | 2 +- src/window.cpp | 3 +- src/window_func.h | 6 ++- 13 files changed, 129 insertions(+), 28 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index d3c730be12..1f4b40a54c 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1285,7 +1285,7 @@ void LoadStringWidthTable(bool monospace) } } - ReInitAllWindows(); + ReInitAllWindows(false); } /** diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 7e2c2cc625..b744eaa5ef 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -323,7 +323,7 @@ void CheckBlitter() ClearFontCache(); GfxClearSpriteCache(); - ReInitAllWindows(); + ReInitAllWindows(false); } /** Initialise and load all the sprites. */ diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 590f2f5e09..b2feacc955 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -98,7 +98,9 @@ public: this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP)); leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP); - leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK).width + GetSpriteSize(SPR_BLOT).width + GetSpriteSize(SPR_FLAGS_BASE).width, 12); + leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK, nullptr, ZOOM_LVL_OUT_4X).width + + GetSpriteSize(SPR_BLOT, nullptr, ZOOM_LVL_OUT_4X).width + + GetSpriteSize(SPR_FLAGS_BASE, nullptr, ZOOM_LVL_OUT_4X).width, 12); leaf->SetFill(0, 1); this->Add(leaf); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 3465a94379..6316a7c4bf 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1972,7 +1972,7 @@ static void NewGRFConfirmationCallback(Window *w, bool confirmed) w->InvalidateData(); - ReInitAllWindows(); + ReInitAllWindows(false); DeleteWindowByClass(WC_BUILD_OBJECT); } } diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 233bb1c7aa..119f26eae9 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -237,7 +237,7 @@ static void AddKey(NWidgetHorizontal *hor, int height, int num_half, WidgetType hor->Add(spc); } NWidgetLeaf *leaf = new NWidgetLeaf(widtype, COLOUR_GREY, widnum, widdata, STR_NULL); - leaf->SetMinimalSize(ScaleGUITrad(key_width), height); + leaf->SetMinimalSizeAbsolute(ScaleGUITrad(key_width), height); hor->Add(leaf); } diff --git a/src/settings.cpp b/src/settings.cpp index 9b97107a34..c5819297fc 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1172,7 +1172,7 @@ static bool InvalidateNewGRFChangeWindows(int32 p1) { InvalidateWindowClassesData(WC_SAVELOAD); DeleteWindowByClass(WC_GAME_OPTIONS); - ReInitAllWindows(); + ReInitAllWindows(_gui_zoom_cfg); return true; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 52d900e6e8..47524bcfba 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -530,7 +530,7 @@ struct GameOptionsWindow : Window { case WID_GO_CURRENCY_DROPDOWN: // Currency if (index == CURRENCY_CUSTOM) ShowCustCurrency(); this->opt->locale.currency = index; - ReInitAllWindows(); + ReInitAllWindows(false); break; case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options @@ -545,7 +545,7 @@ struct GameOptionsWindow : Window { ClearAllCachedNames(); UpdateAllVirtCoords(); CheckBlitter(); - ReInitAllWindows(); + ReInitAllWindows(false); break; case WID_GO_RESOLUTION_DROPDOWN: // Change resolution @@ -573,7 +573,7 @@ struct GameOptionsWindow : Window { UpdateCursorSize(); UpdateAllVirtCoords(); FixTitleGameZoom(); - ReInitAllWindows(); + ReInitAllWindows(true); } break; } @@ -587,6 +587,7 @@ struct GameOptionsWindow : Window { ClearFontCache(); LoadStringWidthTable(); UpdateAllVirtCoords(); + ReInitAllWindows(true); } break; } diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index eaff0b7414..d8fbe0400a 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -115,7 +115,7 @@ void VideoDriver::RealChangeBlitter(const char *repl_blitter) this->ClearSystemSprites(); ClearFontCache(); GfxClearSpriteCache(); - ReInitAllWindows(); + ReInitAllWindows(false); } void VideoDriver::Tick() diff --git a/src/widget.cpp b/src/widget.cpp index aae1a51651..68bc43d78f 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -822,6 +822,14 @@ NWidgetBase *NWidgetBase::GetWidgetOfType(WidgetType tp) return (this->type == tp) ? this : nullptr; } +void NWidgetBase::AdjustPaddingForZoom() +{ + this->padding_top = ScaleGUITrad(this->uz_padding_top); + this->padding_right = ScaleGUITrad(this->uz_padding_right); + this->padding_bottom = ScaleGUITrad(this->uz_padding_bottom); + this->padding_left = ScaleGUITrad(this->uz_padding_left); +} + /** * Constructor for resizable nested widgets. * @param tp Nested widget type. @@ -834,6 +842,15 @@ NWidgetResizeBase::NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y) : this->fill_y = fill_y; } +void NWidgetResizeBase::AdjustPaddingForZoom() +{ + if (!this->absolute) { + this->min_x = ScaleGUITrad(this->uz_min_x); + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); + } + NWidgetBase::AdjustPaddingForZoom(); +} + /** * Set minimal size of the widget. * @param min_x Horizontal minimal size of the widget. @@ -841,6 +858,20 @@ NWidgetResizeBase::NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y) : */ void NWidgetResizeBase::SetMinimalSize(uint min_x, uint min_y) { + this->uz_min_x = std::max(this->uz_min_x, min_x); + this->uz_min_y = std::max(this->uz_min_y, min_y); + this->min_x = ScaleGUITrad(this->uz_min_x); + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); +} + +/** + * Set absolute (post-scaling) minimal size of the widget. + * @param min_x Horizontal minimal size of the widget. + * @param min_y Vertical minimal size of the widget. + */ +void NWidgetResizeBase::SetMinimalSizeAbsolute(uint min_x, uint min_y) +{ + this->absolute = true; this->min_x = std::max(this->min_x, min_x); this->min_y = std::max(this->min_y, min_y); } @@ -853,7 +884,10 @@ void NWidgetResizeBase::SetMinimalSize(uint min_x, uint min_y) */ void NWidgetResizeBase::SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size) { - this->min_y = min_lines * GetCharacterHeight(size) + spacing; + this->uz_text_lines = min_lines; + this->uz_text_spacing = spacing; + this->uz_text_size = size; + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); } /** @@ -991,6 +1025,14 @@ NWidgetBase *NWidgetContainer::GetWidgetOfType(WidgetType tp) return nullptr; } +void NWidgetContainer::AdjustPaddingForZoom() +{ + for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { + child_wid->AdjustPaddingForZoom(); + } + NWidgetBase::AdjustPaddingForZoom(); +} + /** * Append widget \a wid to container. * @param wid Widget to append. @@ -1032,6 +1074,14 @@ void NWidgetStacked::SetIndex(int index) this->index = index; } +void NWidgetStacked::AdjustPaddingForZoom() +{ + for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { + child_wid->AdjustPaddingForZoom(); + } + NWidgetContainer::AdjustPaddingForZoom(); +} + void NWidgetStacked::SetupSmallestSize(Window *w, bool init_array) { if (this->index >= 0 && init_array) { // Fill w->nested_array[] @@ -1145,6 +1195,14 @@ NWidgetPIPContainer::NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags this->flags = flags; } +void NWidgetPIPContainer::AdjustPaddingForZoom() +{ + this->pip_pre = ScaleGUITrad(this->uz_pip_pre); + this->pip_inter = ScaleGUITrad(this->uz_pip_inter); + this->pip_post = ScaleGUITrad(this->uz_pip_post); + NWidgetContainer::AdjustPaddingForZoom(); +} + /** * Set additional pre/inter/post space for the container. * @@ -1156,9 +1214,13 @@ NWidgetPIPContainer::NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags */ void NWidgetPIPContainer::SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post) { - this->pip_pre = pip_pre; - this->pip_inter = pip_inter; - this->pip_post = pip_post; + this->uz_pip_pre = pip_pre; + this->uz_pip_inter = pip_inter; + this->uz_pip_post = pip_post; + + this->pip_pre = ScaleGUITrad(this->uz_pip_pre); + this->pip_inter = ScaleGUITrad(this->uz_pip_inter); + this->pip_post = ScaleGUITrad(this->uz_pip_post); } void NWidgetPIPContainer::Draw(const Window *w) @@ -1813,6 +1875,12 @@ void NWidgetBackground::SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post) this->child->SetPIP(pip_pre, pip_inter, pip_post); } +void NWidgetBackground::AdjustPaddingForZoom() +{ + if (child != nullptr) child->AdjustPaddingForZoom(); + NWidgetCore::AdjustPaddingForZoom(); +} + void NWidgetBackground::SetupSmallestSize(Window *w, bool init_array) { if (init_array && this->index >= 0) { @@ -2137,11 +2205,11 @@ void NWidgetScrollbar::SetupSmallestSize(Window *w, bool init_array) switch (this->type) { case NWID_HSCROLLBAR: - this->SetMinimalSize(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height); + this->SetMinimalSizeAbsolute(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height); break; case NWID_VSCROLLBAR: - this->SetMinimalSize(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3); + this->SetMinimalSizeAbsolute(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3); break; default: NOT_REACHED(); @@ -2768,7 +2836,7 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest, NWidgetResizeBase *nwrb = dynamic_cast(*dest); if (nwrb != nullptr) { assert(parts->u.xy.x >= 0 && parts->u.xy.y >= 0); - nwrb->SetMinimalSize(ScaleGUITrad(parts->u.xy.x), ScaleGUITrad(parts->u.xy.y)); + nwrb->SetMinimalSize(parts->u.xy.x, parts->u.xy.y); } break; } @@ -2814,15 +2882,15 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest, } case WPT_PADDING: - if (*dest != nullptr) (*dest)->SetPadding(ScaleGUITrad(parts->u.padding.top), ScaleGUITrad(parts->u.padding.right), ScaleGUITrad(parts->u.padding.bottom), ScaleGUITrad(parts->u.padding.left)); + if (*dest != nullptr) (*dest)->SetPadding(parts->u.padding.top, parts->u.padding.right, parts->u.padding.bottom, parts->u.padding.left); break; case WPT_PIPSPACE: { NWidgetPIPContainer *nwc = dynamic_cast(*dest); - if (nwc != nullptr) nwc->SetPIP(ScaleGUITrad(parts->u.pip.pre), ScaleGUITrad(parts->u.pip.inter), ScaleGUITrad(parts->u.pip.post)); + if (nwc != nullptr) nwc->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post); NWidgetBackground *nwb = dynamic_cast(*dest); - if (nwb != nullptr) nwb->SetPIP(ScaleGUITrad(parts->u.pip.pre), ScaleGUITrad(parts->u.pip.inter), ScaleGUITrad(parts->u.pip.post)); + if (nwb != nullptr) nwb->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post); break; } @@ -3019,7 +3087,7 @@ NWidgetBase *MakeCompanyButtonRows(int *biggest_index, int widget_first, int wid NWidgetHorizontal *hor = nullptr; // Storage for buttons in one row. int hor_length = 0; - Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON); + Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_OUT_4X); sprite_size.width += WD_MATRIX_LEFT + WD_MATRIX_RIGHT; sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed diff --git a/src/widget_type.h b/src/widget_type.h index 077261ff26..2007113565 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -127,6 +127,7 @@ class NWidgetBase : public ZeroedMemoryAllocator { public: NWidgetBase(WidgetType tp); + virtual void AdjustPaddingForZoom(); virtual void SetupSmallestSize(Window *w, bool init_array) = 0; virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) = 0; @@ -148,10 +149,11 @@ public: */ inline void SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left) { - this->padding_top = top; - this->padding_right = right; - this->padding_bottom = bottom; - this->padding_left = left; + this->uz_padding_top = top; + this->uz_padding_right = right; + this->uz_padding_bottom = bottom; + this->uz_padding_left = left; + this->AdjustPaddingForZoom(); } inline uint GetHorizontalStepSize(SizingType sizing) const; @@ -195,6 +197,11 @@ public: uint8 padding_bottom; ///< Paddings added to the bottom of the widget. Managed by parent container widget. uint8 padding_left; ///< Paddings added to the left of the widget. Managed by parent container widget. (parent container may swap this with padding_right for RTL) + uint8 uz_padding_top; ///< Unscaled top padding, for resize calculation. + uint8 uz_padding_right; ///< Unscaled right padding, for resize calculation. + uint8 uz_padding_bottom; ///< Unscaled bottom padding, for resize calculation. + uint8 uz_padding_left; ///< Unscaled left padding, for resize calculation. + protected: inline void StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height); }; @@ -246,7 +253,9 @@ class NWidgetResizeBase : public NWidgetBase { public: NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y); + void AdjustPaddingForZoom() override; void SetMinimalSize(uint min_x, uint min_y); + void SetMinimalSizeAbsolute(uint min_x, uint min_y); void SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size); void SetFill(uint fill_x, uint fill_y); void SetResize(uint resize_x, uint resize_y); @@ -255,6 +264,14 @@ public: uint min_x; ///< Minimal horizontal size of only this widget. uint min_y; ///< Minimal vertical size of only this widget. + + bool absolute; ///< Set if minimum size is fixed and should not be resized. + uint uz_min_x; ///< Unscaled Minimal horizontal size of only this widget. + uint uz_min_y; ///< Unscaled Minimal vertical size of only this widget. + + uint8 uz_text_lines; ///< 'Unscaled' text lines, stored for resize calculation. + uint8 uz_text_spacing; ///< 'Unscaled' text padding, stored for resize calculation. + FontSize uz_text_size; ///< 'Unscaled' font size, stored for resize calculation. }; /** Nested widget flags that affect display and interaction with 'real' widgets. */ @@ -385,6 +402,7 @@ public: NWidgetContainer(WidgetType tp); ~NWidgetContainer(); + void AdjustPaddingForZoom() override; void Add(NWidgetBase *wid); void FillNestedArray(NWidgetBase **array, uint length) override; @@ -423,6 +441,7 @@ public: void SetIndex(int index); + void AdjustPaddingForZoom() override; void SetupSmallestSize(Window *w, bool init_array) override; void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; void FillNestedArray(NWidgetBase **array, uint length) override; @@ -450,6 +469,7 @@ class NWidgetPIPContainer : public NWidgetContainer { public: NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = NC_NONE); + void AdjustPaddingForZoom() override; void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post); void Draw(const Window *w) override; @@ -460,6 +480,10 @@ protected: uint8 pip_pre; ///< Amount of space before first widget. uint8 pip_inter; ///< Amount of space between widgets. uint8 pip_post; ///< Amount of space after last widget. + + uint8 uz_pip_pre; ///< Unscaled space before first widget. + uint8 uz_pip_inter; ///< Unscaled space between widgets. + uint8 uz_pip_post; ///< Unscaled space after last widget. }; /** @@ -565,6 +589,7 @@ public: void Add(NWidgetBase *nwid); void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post); + void AdjustPaddingForZoom() override; void SetupSmallestSize(Window *w, bool init_array) override; void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index f5536f52f4..8f4a8634ee 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -153,7 +153,7 @@ struct DropdownWindow : Window { uint items_width = size.width - (scroll ? NWidgetScrollbar::GetVerticalDimension().width : 0); NWidgetCore *nwi = this->GetWidget(WID_DM_ITEMS); - nwi->SetMinimalSize(items_width, size.height + 4); + nwi->SetMinimalSizeAbsolute(items_width, size.height + 4); nwi->colour = wi_colour; nwi = this->GetWidget(WID_DM_SCROLL); diff --git a/src/window.cpp b/src/window.cpp index a82afc7cda..a409726002 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -3412,7 +3412,7 @@ void HideVitalWindows() } /** Re-initialize all windows. */ -void ReInitAllWindows() +void ReInitAllWindows(bool zoom_changed) { NWidgetLeaf::InvalidateDimensionCache(); // Reset cached sizes of several widgets. NWidgetScrollbar::InvalidateDimensionCache(); @@ -3421,6 +3421,7 @@ void ReInitAllWindows() InitDepotWindowBlockSizes(); for (Window *w : Window::IterateFromBack()) { + if (zoom_changed) w->nested_root->AdjustPaddingForZoom(); w->ReInit(); } diff --git a/src/window_func.h b/src/window_func.h index 20866b34d9..fba00944a5 100644 --- a/src/window_func.h +++ b/src/window_func.h @@ -43,7 +43,11 @@ void DeleteConstructionWindows(); void HideVitalWindows(); void ShowVitalWindows(); -void ReInitAllWindows(); +/** + * Re-initialize all windows. + * @param zoom_changed Set if windows are being re-initialized due to a zoom level changed. + */ +void ReInitAllWindows(bool zoom_changed); void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index); void SetWindowDirty(WindowClass cls, WindowNumber number); From d32df00b5c1040f34a4ade8c2a6911853b3ea00a Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 18 Apr 2021 11:30:28 +0100 Subject: [PATCH 037/800] Codechange: No longer necessary to manually resize volume sliders. --- src/settings_gui.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 47524bcfba..34c073fe92 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -402,16 +402,6 @@ struct GameOptionsWindow : Window { } break; - case WID_GO_BASE_SFX_VOLUME: - case WID_GO_BASE_MUSIC_VOLUME: - size->width = ScaleGUITrad(67); - size->height = ScaleGUITrad(12); - resize->width = 0; - resize->height = 0; - fill->width = 0; - fill->height = 0; - break; - default: { int selected; DropDownList list = this->BuildDropDownList(widget, &selected); @@ -716,7 +706,7 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 7), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), NWidget(NWID_SPACER), SetMinimalSize(150, 12), SetFill(1, 0), - NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_SFX_VOLUME), SetMinimalSize(67, 12), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_SFX_VOLUME), SetMinimalSize(67, 12), SetFill(0, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), EndContainer(), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7), @@ -730,7 +720,7 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 7), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0), - NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_MUSIC_VOLUME), SetMinimalSize(67, 12), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_MUSIC_VOLUME), SetMinimalSize(67, 12), SetFill(0, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), EndContainer(), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7), From 63cc340dc189d3613a8604c8287fc8e647d5cb01 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 20 Apr 2021 11:49:34 +0100 Subject: [PATCH 038/800] Codechange: Apply minimum size to toolbar widgets --- src/toolbar_gui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index fc8b183470..4cbd13dbf7 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2234,7 +2234,9 @@ static NWidgetBase *MakeMainToolbar(int *biggest_index) hor->Add(new NWidgetSpacer(0, 0)); break; } - hor->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i)); + NWidgetLeaf *leaf = new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i); + leaf->SetMinimalSize(20, 20); + hor->Add(leaf); } *biggest_index = std::max(*biggest_index, WID_TN_SWITCH_BAR); From 56a6f66903de5b999c686008b1d3243f0c61f5f4 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 19 Apr 2021 09:29:49 +0100 Subject: [PATCH 039/800] Codechange: Use text lines instead of pixel height of font for link graph widgets. --- src/linkgraph/linkgraph_gui.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 2d715aaf58..e0986fdb59 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -383,7 +383,8 @@ NWidgetBase *MakeSaturationLegendLinkGraphGUI(int *biggest_index) NWidgetVertical *panel = new NWidgetVertical(NC_EQUALSIZE); for (uint i = 0; i < lengthof(LinkGraphOverlay::LINK_COLOURS); ++i) { NWidgetBackground * wid = new NWidgetBackground(WWT_PANEL, COLOUR_DARK_GREEN, i + WID_LGL_SATURATION_FIRST); - wid->SetMinimalSize(50, FONT_HEIGHT_SMALL); + wid->SetMinimalSize(50, 0); + wid->SetMinimalTextLines(1, 0, FS_SMALL); wid->SetFill(1, 1); wid->SetResize(0, 0); panel->Add(wid); @@ -403,14 +404,16 @@ NWidgetBase *MakeCargoesLegendLinkGraphGUI(int *biggest_index) row = new NWidgetHorizontal(NC_EQUALSIZE); } NWidgetBackground * wid = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, i + WID_LGL_CARGO_FIRST); - wid->SetMinimalSize(25, FONT_HEIGHT_SMALL); + wid->SetMinimalSize(25, 0); + wid->SetMinimalTextLines(1, 0, FS_SMALL); wid->SetFill(1, 1); wid->SetResize(0, 0); row->Add(wid); } /* Fill up last row */ for (uint i = 0; i < 4 - (NUM_CARGO - 1) % 5; ++i) { - NWidgetSpacer *spc = new NWidgetSpacer(25, FONT_HEIGHT_SMALL); + NWidgetSpacer *spc = new NWidgetSpacer(25, 0); + spc->SetMinimalTextLines(1, 0, FS_SMALL); spc->SetFill(1, 1); spc->SetResize(0, 0); row->Add(spc); From 09206be05448a7900bfa1f83c0b87212110fd96e Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 01:19:54 +0100 Subject: [PATCH 040/800] Fix: Use unscaled values for padding OSK --- src/osk_gui.cpp | 56 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 119f26eae9..155343f041 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -212,10 +212,13 @@ struct OskWindow : public Window { static const int HALF_KEY_WIDTH = 7; // Width of 1/2 key in pixels. static const int INTER_KEY_SPACE = 2; // Number of pixels between two keys. +static const int TOP_KEY_PADDING = 2; // Vertical padding for the top row of keys. +static const int KEY_PADDING = 6; // Vertical padding for remaining key rows. + /** * Add a key widget to a row of the keyboard. * @param hor Row container to add key widget to. - * @param height Height of the key (all keys in a row should have equal height). + * @param pad_y Vertical padding of the key (all keys in a row should have equal padding). * @param num_half Number of 1/2 key widths that this key has. * @param widtype Widget type of the key. Must be either \c NWID_SPACER for an invisible key, or a \c WWT_* widget. * @param widnum Widget number of the key. @@ -223,21 +226,24 @@ static const int INTER_KEY_SPACE = 2; // Number of pixels between two keys. * @param biggest_index Collected biggest widget index so far. * @note Key width is measured in 1/2 keys to allow for 1/2 key shifting between rows. */ -static void AddKey(NWidgetHorizontal *hor, int height, int num_half, WidgetType widtype, int widnum, uint16 widdata, int *biggest_index) +static void AddKey(NWidgetHorizontal *hor, int pad_y, int num_half, WidgetType widtype, int widnum, uint16 widdata, int *biggest_index) { int key_width = HALF_KEY_WIDTH + (INTER_KEY_SPACE + HALF_KEY_WIDTH) * (num_half - 1); if (widtype == NWID_SPACER) { if (!hor->IsEmpty()) key_width += INTER_KEY_SPACE; - NWidgetSpacer *spc = new NWidgetSpacer(ScaleGUITrad(key_width), height); + NWidgetSpacer *spc = new NWidgetSpacer(key_width, 0); + spc->SetMinimalTextLines(1, pad_y, FS_NORMAL); hor->Add(spc); } else { if (!hor->IsEmpty()) { - NWidgetSpacer *spc = new NWidgetSpacer(ScaleGUITrad(INTER_KEY_SPACE), height); + NWidgetSpacer *spc = new NWidgetSpacer(INTER_KEY_SPACE, 0); + spc->SetMinimalTextLines(1, pad_y, FS_NORMAL); hor->Add(spc); } NWidgetLeaf *leaf = new NWidgetLeaf(widtype, COLOUR_GREY, widnum, widdata, STR_NULL); - leaf->SetMinimalSizeAbsolute(ScaleGUITrad(key_width), height); + leaf->SetMinimalSize(key_width, 0); + leaf->SetMinimalTextLines(1, pad_y, FS_NORMAL); hor->Add(leaf); } @@ -248,11 +254,10 @@ static void AddKey(NWidgetHorizontal *hor, int height, int num_half, WidgetType static NWidgetBase *MakeTopKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontal(); - int key_height = FONT_HEIGHT_NORMAL + 2; - AddKey(hor, key_height, 6 * 2, WWT_TEXTBTN, WID_OSK_CANCEL, STR_BUTTON_CANCEL, biggest_index); - AddKey(hor, key_height, 6 * 2, WWT_TEXTBTN, WID_OSK_OK, STR_BUTTON_OK, biggest_index); - AddKey(hor, key_height, 2 * 2, WWT_PUSHIMGBTN, WID_OSK_BACKSPACE, SPR_OSK_BACKSPACE, biggest_index); + AddKey(hor, TOP_KEY_PADDING, 6 * 2, WWT_TEXTBTN, WID_OSK_CANCEL, STR_BUTTON_CANCEL, biggest_index); + AddKey(hor, TOP_KEY_PADDING, 6 * 2, WWT_TEXTBTN, WID_OSK_OK, STR_BUTTON_OK, biggest_index); + AddKey(hor, TOP_KEY_PADDING, 2 * 2, WWT_PUSHIMGBTN, WID_OSK_BACKSPACE, SPR_OSK_BACKSPACE, biggest_index); return hor; } @@ -260,10 +265,9 @@ static NWidgetBase *MakeTopKeys(int *biggest_index) static NWidgetBase *MakeNumberKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); - int key_height = FONT_HEIGHT_NORMAL + 6; for (int widnum = WID_OSK_NUMBERS_FIRST; widnum <= WID_OSK_NUMBERS_LAST; widnum++) { - AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); } return hor; } @@ -272,13 +276,12 @@ static NWidgetBase *MakeNumberKeys(int *biggest_index) static NWidgetBase *MakeQwertyKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); - int key_height = FONT_HEIGHT_NORMAL + 6; - AddKey(hor, key_height, 3, WWT_PUSHIMGBTN, WID_OSK_SPECIAL, SPR_OSK_SPECIAL, biggest_index); + AddKey(hor, KEY_PADDING, 3, WWT_PUSHIMGBTN, WID_OSK_SPECIAL, SPR_OSK_SPECIAL, biggest_index); for (int widnum = WID_OSK_QWERTY_FIRST; widnum <= WID_OSK_QWERTY_LAST; widnum++) { - AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); } - AddKey(hor, key_height, 1, NWID_SPACER, 0, 0, biggest_index); + AddKey(hor, KEY_PADDING, 1, NWID_SPACER, 0, 0, biggest_index); return hor; } @@ -286,11 +289,10 @@ static NWidgetBase *MakeQwertyKeys(int *biggest_index) static NWidgetBase *MakeAsdfgKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); - int key_height = FONT_HEIGHT_NORMAL + 6; - AddKey(hor, key_height, 4, WWT_IMGBTN, WID_OSK_CAPS, SPR_OSK_CAPS, biggest_index); + AddKey(hor, KEY_PADDING, 4, WWT_IMGBTN, WID_OSK_CAPS, SPR_OSK_CAPS, biggest_index); for (int widnum = WID_OSK_ASDFG_FIRST; widnum <= WID_OSK_ASDFG_LAST; widnum++) { - AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); } return hor; } @@ -299,13 +301,12 @@ static NWidgetBase *MakeAsdfgKeys(int *biggest_index) static NWidgetBase *MakeZxcvbKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); - int key_height = FONT_HEIGHT_NORMAL + 6; - AddKey(hor, key_height, 3, WWT_IMGBTN, WID_OSK_SHIFT, SPR_OSK_SHIFT, biggest_index); + AddKey(hor, KEY_PADDING, 3, WWT_IMGBTN, WID_OSK_SHIFT, SPR_OSK_SHIFT, biggest_index); for (int widnum = WID_OSK_ZXCVB_FIRST; widnum <= WID_OSK_ZXCVB_LAST; widnum++) { - AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index); } - AddKey(hor, key_height, 1, NWID_SPACER, 0, 0, biggest_index); + AddKey(hor, KEY_PADDING, 1, NWID_SPACER, 0, 0, biggest_index); return hor; } @@ -313,13 +314,12 @@ static NWidgetBase *MakeZxcvbKeys(int *biggest_index) static NWidgetBase *MakeSpacebarKeys(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontal(); - int key_height = FONT_HEIGHT_NORMAL + 6; - AddKey(hor, key_height, 8, NWID_SPACER, 0, 0, biggest_index); - AddKey(hor, key_height, 13, WWT_PUSHTXTBTN, WID_OSK_SPACE, STR_EMPTY, biggest_index); - AddKey(hor, key_height, 3, NWID_SPACER, 0, 0, biggest_index); - AddKey(hor, key_height, 2, WWT_PUSHIMGBTN, WID_OSK_LEFT, SPR_OSK_LEFT, biggest_index); - AddKey(hor, key_height, 2, WWT_PUSHIMGBTN, WID_OSK_RIGHT, SPR_OSK_RIGHT, biggest_index); + AddKey(hor, KEY_PADDING, 8, NWID_SPACER, 0, 0, biggest_index); + AddKey(hor, KEY_PADDING, 13, WWT_PUSHTXTBTN, WID_OSK_SPACE, STR_EMPTY, biggest_index); + AddKey(hor, KEY_PADDING, 3, NWID_SPACER, 0, 0, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHIMGBTN, WID_OSK_LEFT, SPR_OSK_LEFT, biggest_index); + AddKey(hor, KEY_PADDING, 2, WWT_PUSHIMGBTN, WID_OSK_RIGHT, SPR_OSK_RIGHT, biggest_index); return hor; } From 1df510c297636652d826c512b009015f3de3a3b8 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 18:21:14 +0100 Subject: [PATCH 041/800] Fix: Company Key window scaling. --- src/graph_gui.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 67399c327f..52b37d6779 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -21,6 +21,7 @@ #include "sortlist_type.h" #include "core/geometry_func.hpp" #include "currency.h" +#include "zoom_func.h" #include "widgets/graph_widget.h" @@ -65,11 +66,11 @@ struct GraphLegendWindow : Window { bool rtl = _current_text_dir == TD_RTL; Dimension d = GetSpriteSize(SPR_COMPANY_ICON); - DrawCompanyIcon(cid, rtl ? r.right - d.width - 2 : r.left + 2, r.top + (r.bottom - r.top - d.height) / 2); + DrawCompanyIcon(cid, rtl ? r.right - d.width - ScaleGUITrad(2) : r.left + ScaleGUITrad(2), CenterBounds(r.top, r.bottom, d.height)); SetDParam(0, cid); SetDParam(1, cid); - DrawString(r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : (d.width + 4)), r.right - (rtl ? (d.width + 4) : (uint)WD_FRAMERECT_RIGHT), r.top + (r.bottom - r.top + 1 - FONT_HEIGHT_NORMAL) / 2, STR_COMPANY_NAME_COMPANY_NUM, HasBit(_legend_excluded_companies, cid) ? TC_BLACK : TC_WHITE); + DrawString(r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : (d.width + ScaleGUITrad(4))), r.right - (rtl ? (d.width + ScaleGUITrad(4)) : (uint)WD_FRAMERECT_RIGHT), CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL), STR_COMPANY_NAME_COMPANY_NUM, HasBit(_legend_excluded_companies, cid) ? TC_BLACK : TC_WHITE); } void OnClick(Point pt, int widget, int click_count) override @@ -110,11 +111,12 @@ struct GraphLegendWindow : Window { static NWidgetBase *MakeNWidgetCompanyLines(int *biggest_index) { NWidgetVertical *vert = new NWidgetVertical(); - uint line_height = std::max(GetSpriteSize(SPR_COMPANY_ICON).height, FONT_HEIGHT_NORMAL) + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; + uint sprite_height = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_OUT_4X).height; for (int widnum = WID_GL_FIRST_COMPANY; widnum <= WID_GL_LAST_COMPANY; widnum++) { NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_BROWN, widnum); - panel->SetMinimalSize(246, line_height); + panel->SetMinimalSize(246, sprite_height); + panel->SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM, FS_NORMAL); panel->SetFill(1, 0); panel->SetDataTip(0x0, STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP); vert->Add(panel); @@ -137,6 +139,7 @@ static const NWidgetPart _nested_graph_legend_widgets[] = { NWidgetFunction(MakeNWidgetCompanyLines), NWidget(NWID_SPACER), SetMinimalSize(2, 0), EndContainer(), + NWidget(NWID_SPACER), SetMinimalSize(0, 2), EndContainer(), }; From af70195e448e1a934fe921efcb9450ead99cb49e Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 19:07:20 +0100 Subject: [PATCH 042/800] Fix: Tidy up sizing of sprite aligner window sprite list. --- src/newgrf_debug_gui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index bd78deee97..3a5e05a77b 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -863,8 +863,9 @@ struct SpriteAlignerWindow : Window { size->height = ScaleGUITrad(200); break; case WID_SA_LIST: - resize->height = std::max(11, FONT_HEIGHT_NORMAL + 1); + resize->height = FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; resize->width = 1; + fill->height = resize->height; break; default: break; From 5434d63f914b38dbffa86fe0e5c651b79816f3f2 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 22 Apr 2021 21:47:18 +0100 Subject: [PATCH 043/800] Fix: Scale smallmap legend 'blob' to fit text. --- src/smallmap_gui.cpp | 21 +++++++++++++-------- src/smallmap_gui.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 0e7d313a67..b00cf0e7a9 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -22,6 +22,7 @@ #include "window_func.h" #include "company_base.h" #include "guitimer_func.h" +#include "zoom_func.h" #include "smallmap_gui.h" @@ -1177,8 +1178,11 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() this->min_number_of_columns = std::max(this->min_number_of_columns, num_columns); } + /* Width of the legend blob. */ + this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5; + /* The width of a column is the minimum width of all texts + the size of the blob + some spacing */ - this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + this->column_width = min_width + this->legend_width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; } /* virtual */ void SmallMapWindow::OnPaint() @@ -1216,11 +1220,12 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() uint y = y_org; uint i = 0; // Row counter for industry legend. uint row_height = FONT_HEIGHT_SMALL; + int padding = ScaleFontTrad(1); - uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT; - uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0); - uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0; - uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH; + uint text_left = rtl ? 0 : this->legend_width + WD_FRAMERECT_LEFT; + uint text_right = this->column_width - padding - (rtl ? this->legend_width + WD_FRAMERECT_RIGHT : 0); + uint blob_left = rtl ? this->column_width - padding - this->legend_width : 0; + uint blob_right = rtl ? this->column_width - padding : this->legend_width; StringID string = STR_NULL; switch (this->map_type) { @@ -1272,7 +1277,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() DrawString(x + text_left, x + text_right, y, string, TC_GREY); } else { DrawString(x + text_left, x + text_right, y, string, TC_BLACK); - GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour + GfxFillRect(x + blob_left, y + padding, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour } break; } @@ -1281,11 +1286,11 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() default: if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP); /* Anything that is not an industry or a company is using normal process */ - GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); + GfxFillRect(x + blob_left, y + padding, x + blob_right, y + row_height - 1, PC_BLACK); DrawString(x + text_left, x + text_right, y, tbl->legend); break; } - GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour + GfxFillRect(x + blob_left + 1, y + padding + 1, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour y += row_height; } diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index f1b8ece731..e2fa9074d7 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -64,7 +64,6 @@ protected: static bool show_towns; ///< Display town names in the smallmap. static int map_height_limit; ///< Currently used/cached map height limit. - static const uint LEGEND_BLOB_WIDTH = 8; ///< Width of the coloured blob in front of a line text in the #WID_SM_LEGEND widget. static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2; ///< Minimal number of columns in the #WID_SM_LEGEND widget for the #SMT_INDUSTRY legend. static const uint FORCE_REFRESH_PERIOD = 930; ///< map is redrawn after that many milliseconds. static const uint BLINK_PERIOD = 450; ///< highlight blinking interval in milliseconds. @@ -72,6 +71,7 @@ protected: uint min_number_of_columns; ///< Minimal number of columns in legends. uint min_number_of_fixed_rows; ///< Minimal number of rows in the legends for the fixed layouts only (all except #SMT_INDUSTRY). uint column_width; ///< Width of a column in the #WID_SM_LEGEND widget. + uint legend_width; ///< Width of legend 'blob'. int32 scroll_x; ///< Horizontal world coordinate of the base tile left of the top-left corner of the smallmap display. int32 scroll_y; ///< Vertical world coordinate of the base tile left of the top-left corner of the smallmap display. From 617e85cc65c8dae6dbdaad99856e36e094f16a94 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 23 Apr 2021 00:49:11 +0100 Subject: [PATCH 044/800] Fix: Scale legend blobs in Fund new industry window. --- src/industry_gui.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index cce96e6d63..85e90515aa 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -38,6 +38,7 @@ #include "widgets/dropdown_type.h" #include "widgets/industry_widget.h" #include "clear_map.h" +#include "zoom_func.h" #include "table/strings.h" @@ -283,9 +284,8 @@ class BuildIndustryWindow : public Window { IndustryType index[NUM_INDUSTRYTYPES + 1]; ///< Type of industry, in the order it was loaded bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_PROBABILITY (if ever) Scrollbar *vscroll; + Dimension legend; ///< Dimension of the legend 'blob'. - /** The offset for the text in the matrix. */ - static const int MATRIX_TEXT_OFFSET = 17; /** The largest allowed minimum-width of the window, given in line heights */ static const int MAX_MINWIDTH_LINEHEIGHTS = 20; @@ -407,6 +407,10 @@ public: void OnInit() override { + /* Width of the legend blob -- slightly larger than the smallmap legend blob. */ + this->legend.height = FONT_HEIGHT_SMALL; + this->legend.width = this->legend.height * 8 / 5; + this->SetupArrays(); } @@ -419,8 +423,8 @@ public: if (this->index[i] == INVALID_INDUSTRYTYPE) continue; d = maxdim(d, GetStringBoundingBox(GetIndustrySpec(this->index[i])->name)); } - resize->height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM; - d.width += MATRIX_TEXT_OFFSET + padding.width; + resize->height = std::max(this->legend.height, FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM; + d.width += this->legend.width + ScaleFontTrad(7) + padding.width; d.height = 5 * resize->height; *size = maxdim(*size, d); break; @@ -509,30 +513,37 @@ public: uint text_left, text_right, icon_left, icon_right; if (_current_text_dir == TD_RTL) { icon_right = r.right - WD_MATRIX_RIGHT; - icon_left = icon_right - 10; - text_right = icon_right - BuildIndustryWindow::MATRIX_TEXT_OFFSET; + icon_left = icon_right - this->legend.width; + text_right = icon_left - ScaleFontTrad(7); text_left = r.left + WD_MATRIX_LEFT; } else { icon_left = r.left + WD_MATRIX_LEFT; - icon_right = icon_left + 10; - text_left = icon_left + BuildIndustryWindow::MATRIX_TEXT_OFFSET; + icon_right = icon_left + this->legend.width; + text_left = icon_right + ScaleFontTrad(7); text_right = r.right - WD_MATRIX_RIGHT; } + /* Vertical offset for legend icon. */ + int icon_top = (this->resize.step_height - this->legend.height + 1) / 2; + int icon_bottom = icon_top + this->legend.height; + + int y = r.top; for (byte i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->count; i++) { - int y = r.top + WD_MATRIX_TOP + i * this->resize.step_height; bool selected = this->selected_index == i + this->vscroll->GetPosition(); if (this->index[i + this->vscroll->GetPosition()] == INVALID_INDUSTRYTYPE) { - DrawString(text_left, text_right, y, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE); + DrawString(text_left, text_right, y + WD_MATRIX_TOP, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE); + y += this->resize.step_height; continue; } const IndustrySpec *indsp = GetIndustrySpec(this->index[i + this->vscroll->GetPosition()]); /* Draw the name of the industry in white is selected, otherwise, in orange */ - DrawString(text_left, text_right, y, indsp->name, selected ? TC_WHITE : TC_ORANGE); - GfxFillRect(icon_left, y + 1, icon_right, y + 7, selected ? PC_WHITE : PC_BLACK); - GfxFillRect(icon_left + 1, y + 2, icon_right - 1, y + 6, indsp->map_colour); + DrawString(text_left, text_right, y + WD_MATRIX_TOP, indsp->name, selected ? TC_WHITE : TC_ORANGE); + GfxFillRect(icon_left, y + icon_top, icon_right, y + icon_bottom, selected ? PC_WHITE : PC_BLACK); + GfxFillRect(icon_left + 1, y + icon_top + 1, icon_right - 1, y + icon_bottom - 1, indsp->map_colour); + + y += this->resize.step_height; } break; } From 957beaaefcaac0fa0b90a0a8354d418e65f53e19 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 23 Apr 2021 10:18:44 +0100 Subject: [PATCH 045/800] Fix: Improved scaling and spacing of sign list window. Both company icon sprite and text now centred within each row, and extra padding added to avoid the sprites running into each other. --- src/signs_gui.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index ea55488cc7..93c4dd4312 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -194,14 +194,16 @@ struct SignListWindow : Window, SignList { switch (widget) { case WID_SIL_LIST: { uint y = r.top + WD_FRAMERECT_TOP; // Offset from top of widget. + uint text_offset_y = (this->resize.step_height - FONT_HEIGHT_NORMAL + 1) / 2; /* No signs? */ if (this->vscroll->GetCount() == 0) { - DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_STATION_LIST_NONE); + DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y + text_offset_y, STR_STATION_LIST_NONE); return; } + Dimension d = GetSpriteSize(SPR_COMPANY_ICON); bool rtl = _current_text_dir == TD_RTL; - int sprite_offset_y = (FONT_HEIGHT_NORMAL - 10) / 2 + 1; + int sprite_offset_y = (this->resize.step_height - d.height + 1) / 2; uint icon_left = 4 + (rtl ? r.right - this->text_offset : r.left); uint text_left = r.left + (rtl ? WD_FRAMERECT_LEFT : this->text_offset); uint text_right = r.right - (rtl ? this->text_offset : WD_FRAMERECT_RIGHT); @@ -213,7 +215,7 @@ struct SignListWindow : Window, SignList { if (si->owner != OWNER_NONE) DrawCompanyIcon(si->owner, icon_left, y + sprite_offset_y); SetDParam(0, si->index); - DrawString(text_left, text_right, y, STR_SIGN_NAME, TC_YELLOW); + DrawString(text_left, text_right, y + text_offset_y, STR_SIGN_NAME, TC_YELLOW); y += this->resize.step_height; } break; @@ -264,7 +266,7 @@ struct SignListWindow : Window, SignList { case WID_SIL_LIST: { Dimension spr_dim = GetSpriteSize(SPR_COMPANY_ICON); this->text_offset = WD_FRAMETEXT_LEFT + spr_dim.width + 2; // 2 pixels space between icon and the sign text. - resize->height = std::max(FONT_HEIGHT_NORMAL, spr_dim.height); + resize->height = std::max(FONT_HEIGHT_NORMAL, spr_dim.height + 2); Dimension d = {(uint)(this->text_offset + WD_FRAMETEXT_RIGHT), WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM}; *size = maxdim(*size, d); break; @@ -365,8 +367,8 @@ static const NWidgetPart _nested_sign_list_widgets[] = { EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(NWID_VERTICAL), - NWidget(WWT_PANEL, COLOUR_BROWN, WID_SIL_LIST), SetMinimalSize(WD_FRAMETEXT_LEFT + 16 + 255 + WD_FRAMETEXT_RIGHT, 50), - SetResize(1, 10), SetFill(1, 0), SetScrollbar(WID_SIL_SCROLLBAR), EndContainer(), + NWidget(WWT_PANEL, COLOUR_BROWN, WID_SIL_LIST), SetMinimalSize(WD_FRAMETEXT_LEFT + 16 + 255 + WD_FRAMETEXT_RIGHT, 0), + SetResize(1, 1), SetFill(1, 0), SetScrollbar(WID_SIL_SCROLLBAR), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 1), NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_SIL_FILTER_TEXT), SetMinimalSize(80, 12), SetResize(1, 0), SetFill(1, 0), SetPadding(2, 2, 2, 2), From 254ffe9dccbba3ef3199439b6285b2cef6edc79c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 23 Apr 2021 11:07:00 +0100 Subject: [PATCH 046/800] Fix: Scale industry chain legend blob by font size. --- src/industry_gui.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 85e90515aa..2188487453 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -1856,7 +1856,9 @@ struct CargoesField { static const int CARGO_STUB_WIDTH; static const int HOR_CARGO_WIDTH, HOR_CARGO_SPACE; static const int VERT_CARGO_SPACE, VERT_CARGO_EDGE; - static const int BLOB_DISTANCE, BLOB_WIDTH, BLOB_HEIGHT; + static const int BLOB_DISTANCE; + + static Dimension legend; static const int INDUSTRY_LINE_COLOUR; static const int CARGO_LINE_COLOUR; @@ -2060,13 +2062,13 @@ struct CargoesField { int blob_left, blob_right; if (_current_text_dir == TD_RTL) { blob_right = xpos2 - BLOB_DISTANCE; - blob_left = blob_right - BLOB_WIDTH; + blob_left = blob_right - CargoesField::legend.width; } else { blob_left = xpos + BLOB_DISTANCE; - blob_right = blob_left + BLOB_WIDTH; + blob_right = blob_left + CargoesField::legend.width; } - GfxFillRect(blob_left, ypos2 - BLOB_DISTANCE - BLOB_HEIGHT, blob_right, ypos2 - BLOB_DISTANCE, PC_BLACK); // Border - GfxFillRect(blob_left + 1, ypos2 - BLOB_DISTANCE - BLOB_HEIGHT + 1, blob_right - 1, ypos2 - BLOB_DISTANCE - 1, indsp->map_colour); + GfxFillRect(blob_left, ypos2 - BLOB_DISTANCE - CargoesField::legend.height, blob_right, ypos2 - BLOB_DISTANCE, PC_BLACK); // Border + GfxFillRect(blob_left + 1, ypos2 - BLOB_DISTANCE - CargoesField::legend.height + 1, blob_right - 1, ypos2 - BLOB_DISTANCE - 1, indsp->map_colour); } else { DrawString(xpos, xpos2, ypos, STR_INDUSTRY_CARGOES_HOUSES, TC_FROMSTRING, SA_HOR_CENTER); } @@ -2268,6 +2270,8 @@ private: static_assert(MAX_CARGOES >= cpp_lengthof(IndustrySpec, produced_cargo)); static_assert(MAX_CARGOES >= cpp_lengthof(IndustrySpec, accepts_cargo)); +Dimension CargoesField::legend; ///< Dimension of the legend blob. + int CargoesField::small_height; ///< Height of the header row. int CargoesField::normal_height; ///< Height of the non-header rows. int CargoesField::industry_width; ///< Width of an industry field. @@ -2283,8 +2287,6 @@ const int CargoesField::VERT_CARGO_EDGE = 4; ///< Amount of vertical spa const int CargoesField::VERT_CARGO_SPACE = 4; ///< Amount of vertical space between two connected cargoes at an industry. const int CargoesField::BLOB_DISTANCE = 5; ///< Distance of the industry legend colour from the edge of the industry box. -const int CargoesField::BLOB_WIDTH = 12; ///< Width of the industry legend colour, including border. -const int CargoesField::BLOB_HEIGHT = 9; ///< Height of the industry legend colour, including border const int CargoesField::INDUSTRY_LINE_COLOUR = PC_YELLOW; ///< Line colour of the industry type box. const int CargoesField::CARGO_LINE_COLOUR = PC_YELLOW; ///< Line colour around the cargo. @@ -2455,6 +2457,10 @@ struct IndustryCargoesWindow : public Window { d.height += WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM; CargoesField::small_height = d.height; + /* Width of the legend blob -- slightly larger than the smallmap legend blob. */ + CargoesField::legend.height = FONT_HEIGHT_SMALL; + CargoesField::legend.width = CargoesField::legend.height * 8 / 5; + /* Decide about the size of the box holding the text of an industry type. */ this->ind_textsize.width = 0; this->ind_textsize.height = 0; From 055067c49cb916150912d59d827b7bd706bddcfa Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 23 Apr 2021 14:39:00 +0100 Subject: [PATCH 047/800] Fix: Scale cargo lines in industry chain window. Replaces constant pixel values with values scaled based on font size. This allows the industry chain to maintain a consistent look across different sizes. Previously all except cargo line height were fixed. --- src/industry_gui.cpp | 113 ++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 2188487453..aa4d86da6c 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -1852,13 +1852,13 @@ static const uint MAX_CARGOES = 16; ///< Maximum number of cargoes carried in a /** Data about a single field in the #IndustryCargoesWindow panel. */ struct CargoesField { static const int VERT_INTER_INDUSTRY_SPACE; - static const int HOR_CARGO_BORDER_SPACE; - static const int CARGO_STUB_WIDTH; - static const int HOR_CARGO_WIDTH, HOR_CARGO_SPACE; - static const int VERT_CARGO_SPACE, VERT_CARGO_EDGE; static const int BLOB_DISTANCE; static Dimension legend; + static Dimension cargo_border; + static Dimension cargo_line; + static Dimension cargo_space; + static Dimension cargo_stub; static const int INDUSTRY_LINE_COLOUR; static const int CARGO_LINE_COLOUR; @@ -2022,9 +2022,9 @@ struct CargoesField { int n = this->u.cargo.num_cargoes; if (n % 2 == 0) { - return xpos + cargo_field_width / 2 - (HOR_CARGO_WIDTH + HOR_CARGO_SPACE / 2) * (n / 2); + return xpos + cargo_field_width / 2 - (CargoesField::cargo_line.width + CargoesField::cargo_space.width / 2) * (n / 2); } else { - return xpos + cargo_field_width / 2 - HOR_CARGO_WIDTH / 2 - (HOR_CARGO_WIDTH + HOR_CARGO_SPACE) * (n / 2); + return xpos + cargo_field_width / 2 - CargoesField::cargo_line.width / 2 - (CargoesField::cargo_line.width + CargoesField::cargo_space.width) * (n / 2); } } @@ -2082,21 +2082,21 @@ struct CargoesField { other_right = this->u.industry.other_produced; other_left = this->u.industry.other_accepted; } - ypos1 += VERT_CARGO_EDGE; + ypos1 += CargoesField::cargo_border.height + (FONT_HEIGHT_NORMAL - CargoesField::cargo_line.height) / 2; for (uint i = 0; i < CargoesField::max_cargoes; i++) { if (other_right[i] != INVALID_CARGO) { const CargoSpec *csp = CargoSpec::Get(other_right[i]); - int xp = xpos + industry_width + CARGO_STUB_WIDTH; + int xp = xpos + industry_width + CargoesField::cargo_stub.width; DrawHorConnection(xpos + industry_width, xp - 1, ypos1, csp); - GfxDrawLine(xp, ypos1, xp, ypos1 + FONT_HEIGHT_NORMAL - 1, CARGO_LINE_COLOUR); + GfxDrawLine(xp, ypos1, xp, ypos1 + CargoesField::cargo_line.height - 1, CARGO_LINE_COLOUR); } if (other_left[i] != INVALID_CARGO) { const CargoSpec *csp = CargoSpec::Get(other_left[i]); - int xp = xpos - CARGO_STUB_WIDTH; + int xp = xpos - CargoesField::cargo_stub.width; DrawHorConnection(xp + 1, xpos - 1, ypos1, csp); - GfxDrawLine(xp, ypos1, xp, ypos1 + FONT_HEIGHT_NORMAL - 1, CARGO_LINE_COLOUR); + GfxDrawLine(xp, ypos1, xp, ypos1 + CargoesField::cargo_line.height - 1, CARGO_LINE_COLOUR); } - ypos1 += FONT_HEIGHT_NORMAL + VERT_CARGO_SPACE; + ypos1 += FONT_HEIGHT_NORMAL + CargoesField::cargo_space.height; } break; } @@ -2107,15 +2107,15 @@ struct CargoesField { int bot = ypos - (this->u.cargo.bottom_end ? VERT_INTER_INDUSTRY_SPACE / 2 + 1 : 0) + normal_height - 1; int colpos = cargo_base; for (int i = 0; i < this->u.cargo.num_cargoes; i++) { - if (this->u.cargo.top_end) GfxDrawLine(colpos, top - 1, colpos + HOR_CARGO_WIDTH - 1, top - 1, CARGO_LINE_COLOUR); - if (this->u.cargo.bottom_end) GfxDrawLine(colpos, bot + 1, colpos + HOR_CARGO_WIDTH - 1, bot + 1, CARGO_LINE_COLOUR); + if (this->u.cargo.top_end) GfxDrawLine(colpos, top - 1, colpos + CargoesField::cargo_line.width - 1, top - 1, CARGO_LINE_COLOUR); + if (this->u.cargo.bottom_end) GfxDrawLine(colpos, bot + 1, colpos + CargoesField::cargo_line.width - 1, bot + 1, CARGO_LINE_COLOUR); GfxDrawLine(colpos, top, colpos, bot, CARGO_LINE_COLOUR); colpos++; const CargoSpec *csp = CargoSpec::Get(this->u.cargo.vertical_cargoes[i]); - GfxFillRect(colpos, top, colpos + HOR_CARGO_WIDTH - 2, bot, csp->legend_colour, FILLRECT_OPAQUE); - colpos += HOR_CARGO_WIDTH - 2; + GfxFillRect(colpos, top, colpos + CargoesField::cargo_line.width - 2, bot, csp->legend_colour, FILLRECT_OPAQUE); + colpos += CargoesField::cargo_line.width - 2; GfxDrawLine(colpos, top, colpos, bot, CARGO_LINE_COLOUR); - colpos += 1 + HOR_CARGO_SPACE; + colpos += 1 + CargoesField::cargo_space.width; } const CargoID *hor_left, *hor_right; @@ -2126,15 +2126,15 @@ struct CargoesField { hor_left = this->u.cargo.supp_cargoes; hor_right = this->u.cargo.cust_cargoes; } - ypos += VERT_CARGO_EDGE + VERT_INTER_INDUSTRY_SPACE / 2; + ypos += CargoesField::cargo_border.height + VERT_INTER_INDUSTRY_SPACE / 2 + (FONT_HEIGHT_NORMAL - CargoesField::cargo_line.height) / 2; for (uint i = 0; i < MAX_CARGOES; i++) { if (hor_left[i] != INVALID_CARGO) { int col = hor_left[i]; int dx = 0; const CargoSpec *csp = CargoSpec::Get(this->u.cargo.vertical_cargoes[col]); for (; col > 0; col--) { - int lf = cargo_base + col * HOR_CARGO_WIDTH + (col - 1) * HOR_CARGO_SPACE; - DrawHorConnection(lf, lf + HOR_CARGO_SPACE - dx, ypos, csp); + int lf = cargo_base + col * CargoesField::cargo_line.width + (col - 1) * CargoesField::cargo_space.width; + DrawHorConnection(lf, lf + CargoesField::cargo_space.width - dx, ypos, csp); dx = 1; } DrawHorConnection(xpos, cargo_base - dx, ypos, csp); @@ -2144,26 +2144,26 @@ struct CargoesField { int dx = 0; const CargoSpec *csp = CargoSpec::Get(this->u.cargo.vertical_cargoes[col]); for (; col < this->u.cargo.num_cargoes - 1; col++) { - int lf = cargo_base + (col + 1) * HOR_CARGO_WIDTH + col * HOR_CARGO_SPACE; - DrawHorConnection(lf + dx - 1, lf + HOR_CARGO_SPACE - 1, ypos, csp); + int lf = cargo_base + (col + 1) * CargoesField::cargo_line.width + col * CargoesField::cargo_space.width; + DrawHorConnection(lf + dx - 1, lf + CargoesField::cargo_space.width - 1, ypos, csp); dx = 1; } - DrawHorConnection(cargo_base + col * HOR_CARGO_SPACE + (col + 1) * HOR_CARGO_WIDTH - 1 + dx, xpos + CargoesField::cargo_field_width - 1, ypos, csp); + DrawHorConnection(cargo_base + col * CargoesField::cargo_space.width + (col + 1) * CargoesField::cargo_line.width - 1 + dx, xpos + CargoesField::cargo_field_width - 1, ypos, csp); } - ypos += FONT_HEIGHT_NORMAL + VERT_CARGO_SPACE; + ypos += FONT_HEIGHT_NORMAL + CargoesField::cargo_space.height; } break; } case CFT_CARGO_LABEL: - ypos += VERT_CARGO_EDGE + VERT_INTER_INDUSTRY_SPACE / 2; + ypos += CargoesField::cargo_border.height + VERT_INTER_INDUSTRY_SPACE / 2; for (uint i = 0; i < MAX_CARGOES; i++) { if (this->u.cargo_label.cargoes[i] != INVALID_CARGO) { const CargoSpec *csp = CargoSpec::Get(this->u.cargo_label.cargoes[i]); DrawString(xpos + WD_FRAMERECT_LEFT, xpos + industry_width - 1 - WD_FRAMERECT_RIGHT, ypos, csp->name, TC_WHITE, (this->u.cargo_label.left_align) ? SA_LEFT : SA_RIGHT); } - ypos += FONT_HEIGHT_NORMAL + VERT_CARGO_SPACE; + ypos += FONT_HEIGHT_NORMAL + CargoesField::cargo_space.height; } break; @@ -2188,17 +2188,17 @@ struct CargoesField { uint col; for (col = 0; col < this->u.cargo.num_cargoes; col++) { if (pt.x < cpos) break; - if (pt.x < cpos + CargoesField::HOR_CARGO_WIDTH) return this->u.cargo.vertical_cargoes[col]; - cpos += CargoesField::HOR_CARGO_WIDTH + CargoesField::HOR_CARGO_SPACE; + if (pt.x < cpos + (int)CargoesField::cargo_line.width) return this->u.cargo.vertical_cargoes[col]; + cpos += CargoesField::cargo_line.width + CargoesField::cargo_space.width; } /* col = 0 -> left of first col, 1 -> left of 2nd col, ... this->u.cargo.num_cargoes right of last-col. */ - int vpos = VERT_INTER_INDUSTRY_SPACE / 2 + VERT_CARGO_EDGE; + int vpos = VERT_INTER_INDUSTRY_SPACE / 2 + CargoesField::cargo_border.width; uint row; for (row = 0; row < MAX_CARGOES; row++) { if (pt.y < vpos) return INVALID_CARGO; if (pt.y < vpos + FONT_HEIGHT_NORMAL) break; - vpos += FONT_HEIGHT_NORMAL + VERT_CARGO_SPACE; + vpos += FONT_HEIGHT_NORMAL + CargoesField::cargo_space.width; } if (row == MAX_CARGOES) return INVALID_CARGO; @@ -2240,12 +2240,12 @@ struct CargoesField { { assert(this->type == CFT_CARGO_LABEL); - int vpos = VERT_INTER_INDUSTRY_SPACE / 2 + VERT_CARGO_EDGE; + int vpos = VERT_INTER_INDUSTRY_SPACE / 2 + CargoesField::cargo_border.height; uint row; for (row = 0; row < MAX_CARGOES; row++) { if (pt.y < vpos) return INVALID_CARGO; if (pt.y < vpos + FONT_HEIGHT_NORMAL) break; - vpos += FONT_HEIGHT_NORMAL + VERT_CARGO_SPACE; + vpos += FONT_HEIGHT_NORMAL + CargoesField::cargo_space.height; } if (row == MAX_CARGOES) return INVALID_CARGO; return this->u.cargo_label.cargoes[row]; @@ -2262,15 +2262,19 @@ private: static void DrawHorConnection(int left, int right, int top, const CargoSpec *csp) { GfxDrawLine(left, top, right, top, CARGO_LINE_COLOUR); - GfxFillRect(left, top + 1, right, top + FONT_HEIGHT_NORMAL - 2, csp->legend_colour, FILLRECT_OPAQUE); - GfxDrawLine(left, top + FONT_HEIGHT_NORMAL - 1, right, top + FONT_HEIGHT_NORMAL - 1, CARGO_LINE_COLOUR); + GfxFillRect(left, top + 1, right, top + CargoesField::cargo_line.height - 2, csp->legend_colour, FILLRECT_OPAQUE); + GfxDrawLine(left, top + CargoesField::cargo_line.height - 1, right, top + CargoesField::cargo_line.height - 1, CARGO_LINE_COLOUR); } }; static_assert(MAX_CARGOES >= cpp_lengthof(IndustrySpec, produced_cargo)); static_assert(MAX_CARGOES >= cpp_lengthof(IndustrySpec, accepts_cargo)); -Dimension CargoesField::legend; ///< Dimension of the legend blob. +Dimension CargoesField::legend; ///< Dimension of the legend blob. +Dimension CargoesField::cargo_border; ///< Dimensions of border between cargo lines and industry boxes. +Dimension CargoesField::cargo_line; ///< Dimensions of cargo lines. +Dimension CargoesField::cargo_space; ///< Dimensions of space between cargo lines. +Dimension CargoesField::cargo_stub; ///< Dimensions of cargo stub (unconnected cargo line.) int CargoesField::small_height; ///< Height of the header row. int CargoesField::normal_height; ///< Height of the non-header rows. @@ -2279,13 +2283,6 @@ int CargoesField::cargo_field_width; ///< Width of a cargo field. uint CargoesField::max_cargoes; ///< Largest number of cargoes actually on any industry. const int CargoesField::VERT_INTER_INDUSTRY_SPACE = 6; ///< Amount of space between two industries in a column. -const int CargoesField::HOR_CARGO_BORDER_SPACE = 15; ///< Amount of space between the left/right edge of a #CFT_CARGO field, and the left/right most vertical cargo. -const int CargoesField::CARGO_STUB_WIDTH = 10; ///< Width of a cargo not carried in the column (should be less than #HOR_CARGO_BORDER_SPACE). -const int CargoesField::HOR_CARGO_WIDTH = 15; ///< Width of a vertical cargo column (inclusive the border line). -const int CargoesField::HOR_CARGO_SPACE = 5; ///< Amount of horizontal space between two vertical cargoes. -const int CargoesField::VERT_CARGO_EDGE = 4; ///< Amount of vertical space between top/bottom and the top/bottom connected cargo at an industry. -const int CargoesField::VERT_CARGO_SPACE = 4; ///< Amount of vertical space between two connected cargoes at an industry. - const int CargoesField::BLOB_DISTANCE = 5; ///< Distance of the industry legend colour from the edge of the industry box. const int CargoesField::INDUSTRY_LINE_COLOUR = PC_YELLOW; ///< Line colour of the industry type box. @@ -2457,10 +2454,26 @@ struct IndustryCargoesWindow : public Window { d.height += WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM; CargoesField::small_height = d.height; - /* Width of the legend blob -- slightly larger than the smallmap legend blob. */ + /* Size of the legend blob -- slightly larger than the smallmap legend blob. */ CargoesField::legend.height = FONT_HEIGHT_SMALL; CargoesField::legend.width = CargoesField::legend.height * 8 / 5; + /* Size of cargo lines. */ + CargoesField::cargo_line.width = FONT_HEIGHT_NORMAL; + CargoesField::cargo_line.height = CargoesField::cargo_line.width; + + /* Size of border between cargo lines and industry boxes. */ + CargoesField::cargo_border.width = CargoesField::cargo_line.width * 3 / 2; + CargoesField::cargo_border.height = CargoesField::cargo_line.width / 2; + + /* Size of space between cargo lines. */ + CargoesField::cargo_space.width = CargoesField::cargo_line.width / 2; + CargoesField::cargo_space.height = CargoesField::cargo_line.height / 2; + + /* Size of cargo stub (unconnected cargo line.) */ + CargoesField::cargo_stub.width = CargoesField::cargo_line.width / 2; + CargoesField::cargo_stub.height = CargoesField::cargo_line.height; /* Unused */ + /* Decide about the size of the box holding the text of an industry type. */ this->ind_textsize.width = 0; this->ind_textsize.height = 0; @@ -2489,21 +2502,23 @@ struct IndustryCargoesWindow : public Window { d.width += 2 * HOR_TEXT_PADDING; /* Ensure the height is enough for the industry type text, for the horizontal connections, and for the cargo labels. */ - uint min_ind_height = CargoesField::VERT_CARGO_EDGE * 2 + CargoesField::max_cargoes * FONT_HEIGHT_NORMAL + (CargoesField::max_cargoes - 1) * CargoesField::VERT_CARGO_SPACE; + uint min_ind_height = CargoesField::cargo_border.height * 2 + CargoesField::max_cargoes * FONT_HEIGHT_NORMAL + (CargoesField::max_cargoes - 1) * CargoesField::cargo_space.height; d.height = std::max(d.height + 2 * VERT_TEXT_PADDING, min_ind_height); CargoesField::industry_width = d.width; CargoesField::normal_height = d.height + CargoesField::VERT_INTER_INDUSTRY_SPACE; /* Width of a #CFT_CARGO field. */ - CargoesField::cargo_field_width = CargoesField::HOR_CARGO_BORDER_SPACE * 2 + CargoesField::HOR_CARGO_WIDTH * CargoesField::max_cargoes + CargoesField::HOR_CARGO_SPACE * (CargoesField::max_cargoes - 1); + CargoesField::cargo_field_width = CargoesField::cargo_border.width * 2 + CargoesField::cargo_line.width * CargoesField::max_cargoes + CargoesField::cargo_space.width * (CargoesField::max_cargoes - 1); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { switch (widget) { case WID_IC_PANEL: + resize->height = CargoesField::normal_height; size->width = WD_FRAMETEXT_LEFT + CargoesField::industry_width * 3 + CargoesField::cargo_field_width * 2 + WD_FRAMETEXT_RIGHT; + size->height = WD_FRAMETEXT_TOP + CargoesField::small_height + 2 * resize->height + WD_FRAMETEXT_BOTTOM; break; case WID_IC_IND_DROPDOWN: @@ -2756,8 +2771,7 @@ struct IndustryCargoesWindow : public Window { this->ShortenCargoColumn(1, 1, num_indrows); this->ShortenCargoColumn(3, 1, num_indrows); - const NWidgetBase *nwp = this->GetWidget(WID_IC_PANEL); - this->vscroll->SetCount(CeilDiv(WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM + CargoesField::small_height + num_indrows * CargoesField::normal_height, nwp->resize_y)); + this->vscroll->SetCount(num_indrows); this->SetDirty(); this->NotifySmallmap(); } @@ -2824,8 +2838,7 @@ struct IndustryCargoesWindow : public Window { } this->ShortenCargoColumn(1, 1, num_indrows); - const NWidgetBase *nwp = this->GetWidget(WID_IC_PANEL); - this->vscroll->SetCount(CeilDiv(WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM + CargoesField::small_height + num_indrows * CargoesField::normal_height, nwp->resize_y)); + this->vscroll->SetCount(num_indrows); this->SetDirty(); this->NotifySmallmap(); } @@ -3072,7 +3085,7 @@ struct IndustryCargoesWindow : public Window { void OnResize() override { - this->vscroll->SetCapacityFromWidget(this, WID_IC_PANEL); + this->vscroll->SetCapacityFromWidget(this, WID_IC_PANEL, WD_FRAMERECT_TOP + CargoesField::small_height); } }; From 49aa3924404615269986e7040455827fe7263001 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 25 Apr 2021 13:48:00 +0100 Subject: [PATCH 048/800] Fix: Cargo legend blob in cargo payment rate window did not rescale. --- src/graph_gui.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 52b37d6779..c50027718a 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -879,6 +879,7 @@ void ShowCompanyValueGraph() struct PaymentRatesGraphWindow : BaseGraphWindow { uint line_height; ///< Pixel height of each cargo type row. Scrollbar *vscroll; ///< Cargo list scrollbar. + uint legend_width; ///< Width of legend 'blob'. PaymentRatesGraphWindow(WindowDesc *desc, WindowNumber window_number) : BaseGraphWindow(desc, WID_CPR_GRAPH, STR_JUST_CURRENCY_SHORT) @@ -899,6 +900,12 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { this->FinishInitNested(window_number); } + void OnInit() override + { + /* Width of the legend blob. */ + this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5; + } + void UpdateExcludedData() { this->excluded_data = 0; @@ -922,7 +929,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { SetDParam(0, cs->name); Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO); - d.width += 14; // colour field + d.width += this->legend_width + 4; // colour field d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; *size = maxdim(d, *size); @@ -945,6 +952,8 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { int x = r.left + WD_FRAMERECT_LEFT; int y = r.top; + uint row_height = FONT_HEIGHT_SMALL; + int padding = ScaleFontTrad(1); int pos = this->vscroll->GetPosition(); int max = pos + this->vscroll->GetCapacity(); @@ -960,12 +969,12 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { if (lowered) DrawFrameRect(r.left, y, r.right, y + this->line_height - 1, COLOUR_BROWN, lowered ? FR_LOWERED : FR_NONE); byte clk_dif = lowered ? 1 : 0; - int rect_x = clk_dif + (rtl ? r.right - 12 : r.left + WD_FRAMERECT_LEFT); + int rect_x = clk_dif + (rtl ? r.right - this->legend_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT); - GfxFillRect(rect_x, y + clk_dif, rect_x + 8, y + 5 + clk_dif, PC_BLACK); - GfxFillRect(rect_x + 1, y + 1 + clk_dif, rect_x + 7, y + 4 + clk_dif, cs->legend_colour); + GfxFillRect(rect_x, y + padding + clk_dif, rect_x + this->legend_width, y + row_height - 1 + clk_dif, PC_BLACK); + GfxFillRect(rect_x + 1, y + padding + 1 + clk_dif, rect_x + this->legend_width - 1, y + row_height - 2 + clk_dif, cs->legend_colour); SetDParam(0, cs->name); - DrawString(rtl ? r.left : x + 14 + clk_dif, (rtl ? r.right - 14 + clk_dif : r.right), y + clk_dif, STR_GRAPH_CARGO_PAYMENT_CARGO); + DrawString(rtl ? r.left : x + this->legend_width + 4 + clk_dif, (rtl ? r.right - this->legend_width - 4 + clk_dif : r.right), y + clk_dif, STR_GRAPH_CARGO_PAYMENT_CARGO); y += this->line_height; } From ce55cd0ce703acb3a731f7d2d783fb3462fab6c8 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 1 May 2021 08:48:29 +0100 Subject: [PATCH 049/800] Cleanup: Use GetDefaultFontHeight() call instead of direct access. This makes this part of font size setup in FreeTypeFontCache consist with OSX and Windows variants. --- src/fontcache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index d450deaca6..1290777c0f 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -428,14 +428,14 @@ void FreeTypeFontCache::SetFontSize(FontSize fs, FT_Face face, int pixels) { if (pixels == 0) { /* Try to determine a good height based on the minimal height recommended by the font. */ - int scaled_height = ScaleFontTrad(_default_font_height[this->fs]); + int scaled_height = ScaleFontTrad(this->GetDefaultFontHeight(this->fs)); pixels = scaled_height; TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head); if (head != nullptr) { /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ - int diff = scaled_height - ScaleFontTrad(_default_font_height[FS_SMALL]); + int diff = scaled_height - ScaleFontTrad(this->GetDefaultFontHeight(FS_SMALL)); pixels = Clamp(std::min(head->Lowest_Rec_PPEM, MAX_FONT_MIN_REC_SIZE) + diff, scaled_height, MAX_FONT_SIZE); } } else { From 9c6c0a0966f79996dfb7b5c7097c7d6c04a8d35c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 1 May 2021 08:54:05 +0100 Subject: [PATCH 050/800] Codechange: Scale sprite font height once on init instead of every call to GetHeight(). Scaling is not expensive, but it does not change either, and this avoids the need for a virtual method call. This cascades back to all GetCharacterHeight(FS_xxx) and FONT_HEIGHT_xxx calls. --- src/fontcache.cpp | 8 ++------ src/fontcache.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 1290777c0f..ce15233b7e 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -87,7 +87,6 @@ public: virtual void ClearFontCache(); virtual const Sprite *GetGlyph(GlyphID key); virtual uint GetGlyphWidth(GlyphID key); - virtual int GetHeight() const; virtual bool GetDrawGlyphShadow(); virtual GlyphID MapCharToGlyph(WChar key) { assert(IsPrintable(key)); return SPRITE_GLYPH | key; } virtual const void *GetFontTable(uint32 tag, size_t &length) { length = 0; return nullptr; } @@ -102,6 +101,7 @@ public: SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs), glyph_to_spriteid_map(nullptr) { this->InitializeUnicodeGlyphMap(); + this->height = ScaleFontTrad(this->GetDefaultFontHeight(this->fs)); } /** @@ -177,6 +177,7 @@ void SpriteFontCache::ClearGlyphToSpriteMap() void SpriteFontCache::ClearFontCache() { Layouter::ResetFontCache(this->fs); + this->height = ScaleFontTrad(this->GetDefaultFontHeight(this->fs)); } const Sprite *SpriteFontCache::GetGlyph(GlyphID key) @@ -193,11 +194,6 @@ uint SpriteFontCache::GetGlyphWidth(GlyphID key) return SpriteExists(sprite) ? GetSprite(sprite, ST_FONT)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; } -int SpriteFontCache::GetHeight() const -{ - return ScaleFontTrad(this->height); -} - bool SpriteFontCache::GetDrawGlyphShadow() { return false; diff --git a/src/fontcache.h b/src/fontcache.h index 73675cf44e..c3b20cb4f7 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -45,7 +45,7 @@ public: * Get the height of the font. * @return The height of the font. */ - virtual int GetHeight() const { return this->height; } + inline int GetHeight() const { return this->height; } /** * Get the ascender value of the font. From 40528db993e6883f7856c8d860ec0385e42e3bad Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 10:46:47 +0200 Subject: [PATCH 051/800] Fix #9152, Fix #9153: screenshot command showed error messages when successful --- src/screenshot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 06fae707a7..dc76996fbf 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -957,7 +957,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei if (t == SC_HEIGHTMAP) { SetDParamStr(0, _screenshot_name); SetDParam(1, _heightmap_highest_peak); - ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); } else { SetDParamStr(0, _screenshot_name); ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); From 2985277becdfd390d6116afab1fb2ada0d7940b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sat, 1 May 2021 12:11:07 +0200 Subject: [PATCH 052/800] Fix d4f0b6f4: [CMake] CMAKE_PROJECT_VERSION_XXX are not in CMake 3.9 (#9154) --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87d055047f..ecfbe408c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,9 +74,9 @@ add_custom_target(find_version ${CMAKE_COMMAND} -DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated -DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR} - -DREV_MAJOR=${CMAKE_PROJECT_VERSION_MAJOR} - -DREV_MINOR=${CMAKE_PROJECT_VERSION_MINOR} - -DREV_BUILD=${CMAKE_PROJECT_VERSION_PATCH} + -DREV_MAJOR=${PROJECT_VERSION_MAJOR} + -DREV_MINOR=${PROJECT_VERSION_MINOR} + -DREV_BUILD=${PROJECT_VERSION_PATCH} -P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} BYPRODUCTS ${GENERATED_SOURCE_FILES} From 0345f99180075e44d7c549e2207936a109a5451b Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 10:31:00 +0200 Subject: [PATCH 053/800] Feature: make the town directory horizontally resizable --- src/town_gui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 0629490393..a189c7ccb3 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -647,12 +647,12 @@ static const NWidgetPart _nested_town_directory_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TD_SORT_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), - NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(1, 0), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), + NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), EndContainer(), - NWidget(WWT_PANEL, COLOUR_BROWN, WID_TD_LIST), SetMinimalSize(196, 0), SetDataTip(0x0, STR_TOWN_DIRECTORY_LIST_TOOLTIP), - SetFill(1, 0), SetResize(0, 1), SetScrollbar(WID_TD_SCROLLBAR), EndContainer(), + NWidget(WWT_PANEL, COLOUR_BROWN, WID_TD_LIST), SetDataTip(0x0, STR_TOWN_DIRECTORY_LIST_TOOLTIP), + SetFill(1, 0), SetResize(1, 1), SetScrollbar(WID_TD_SCROLLBAR), EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN), - NWidget(WWT_TEXT, COLOUR_BROWN, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 2, 2), SetMinimalSize(196, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetDataTip(STR_TOWN_POPULATION, STR_NULL), + NWidget(WWT_TEXT, COLOUR_BROWN, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 2, 2), SetMinimalTextLines(1, 0), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TOWN_POPULATION, STR_NULL), EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), From 282d5d302dfe81e8a312c96732bb17439a8f8264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sat, 1 May 2021 16:18:41 +0200 Subject: [PATCH 054/800] Change: [Actions] Add a 2 minutes timeout for regression test (#9166) --- .github/workflows/ci-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 1aa7e17ccb..74677ee6d5 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -143,7 +143,7 @@ jobs: - name: Test run: | cd build - ctest -j $(nproc) + ctest -j $(nproc) --timeout 120 macos: name: Mac OS @@ -224,7 +224,7 @@ jobs: - name: Test run: | cd build - ctest -j $(sysctl -n hw.logicalcpu) + ctest -j $(sysctl -n hw.logicalcpu) --timeout 120 windows: name: Windows @@ -314,4 +314,4 @@ jobs: shell: bash run: | cd ${GITHUB_WORKSPACE}/build - ctest + ctest --timeout 120 From 376f2509ad5b35910ce2cb949f7ba84d86aed739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sat, 1 May 2021 16:19:14 +0200 Subject: [PATCH 055/800] Fix: Don't consider regression AIs when starting a random AI (#9164) --- regression/regression/info.nut | 1 + regression/stationlist/info.nut | 1 + 2 files changed, 2 insertions(+) diff --git a/regression/regression/info.nut b/regression/regression/info.nut index 340dcff5c3..50c9fa5146 100644 --- a/regression/regression/info.nut +++ b/regression/regression/info.nut @@ -7,6 +7,7 @@ class Regression extends AIInfo { function GetAPIVersion() { return "1.12"; } function GetDate() { return "2007-03-18"; } function CreateInstance() { return "Regression"; } + function UseAsRandomAI() { return false; } } RegisterAI(Regression()); diff --git a/regression/stationlist/info.nut b/regression/stationlist/info.nut index a58fd20ba8..0558ccc1fb 100644 --- a/regression/stationlist/info.nut +++ b/regression/stationlist/info.nut @@ -7,6 +7,7 @@ class StationList extends AIInfo { function GetAPIVersion() { return "1.12"; } function GetDate() { return "2007-03-18"; } function CreateInstance() { return "StationList"; } + function UseAsRandomAI() { return false; } } RegisterAI(StationList()); From 3bd416bfdba351d9d76a753a0c5b4abdd84fea39 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 13:54:30 +0200 Subject: [PATCH 056/800] Change: [Console] Show help when passing invalid company number --- src/console_cmds.cpp | 6 ++--- src/network/network.cpp | 41 ++++++++++++++++++++++++++++------ src/network/network_func.h | 2 +- src/network/network_internal.h | 2 +- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 401a52b1f9..71f2d4b7b0 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -901,8 +901,7 @@ DEF_CONSOLE_CMD(ConNetworkReconnect) /* Don't resolve the address first, just print it directly as it comes from the config file. */ IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined); - NetworkClientConnectGame(_settings_client.network.last_joined, playas); - return true; + return NetworkClientConnectGame(_settings_client.network.last_joined, playas); } DEF_CONSOLE_CMD(ConNetworkConnect) @@ -917,8 +916,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect) if (argc < 2) return false; if (_networking) NetworkDisconnect(); // we are in network-mode, first close it! - NetworkClientConnectGame(argv[1], COMPANY_NEW_COMPANY); - return true; + return NetworkClientConnectGame(argv[1], COMPANY_NEW_COMPANY); } /********************************* diff --git a/src/network/network.cpp b/src/network/network.cpp index c31a67487d..22ac5dc74c 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -713,7 +713,24 @@ public: } }; -void NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) +/** + * Join a client to the server at with the given connection string. + * The default for the passwords is \c nullptr. When the server or company needs a + * password and none is given, the user is asked to enter the password in the GUI. + * This function will return false whenever some information required to join is not + * correct such as the company number or the client's name, or when there is not + * networking avalabile at all. If the function returns false the connection with + * the existing server is not disconnected. + * It will return true when it starts the actual join process, i.e. when it + * actually shows the join status window. + * + * @param connection_string The IP address, port and company number to join as. + * @param default_company The company number to join as when none is given. + * @param join_server_password The password for the server. + * @param join_company_password The password for the company. + * @return Whether the join has started. + */ +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) { CompanyID join_as = default_company; NetworkAddress address = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT); @@ -721,18 +738,27 @@ void NetworkClientConnectGame(const std::string &connection_string, CompanyID de if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) { join_as--; if (join_as >= MAX_COMPANIES) { - return; + return false; } } - NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); + return NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); } -/* Used by clients, to connect to a server */ -void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password) +/** + * Join a client to the server at the given address. + * See the overloaded NetworkClientConnectGame for more details. + * + * @param address The network address of the server to join to. + * @param join_as The company number to join as. + * @param join_server_password The password for the server. + * @param join_company_password The password for the company. + * @return Whether the join has started. + */ +bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password) { - if (!_network_available) return; - if (!NetworkValidateClientName()) return; + if (!_network_available) return false; + if (!NetworkValidateClientName()) return false; strecpy(_settings_client.network.last_joined, address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); @@ -747,6 +773,7 @@ void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const ShowJoinStatusWindow(); new TCPClientConnecter(address); + return true; } static void NetworkInitGameInfo() diff --git a/src/network/network_func.h b/src/network/network_func.h index cd2b291bc7..252d207db5 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -51,7 +51,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); -void NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); void NetworkClientRequestMove(CompanyID company, const char *pass = ""); void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 683c954e82..be5b74a0f5 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -119,7 +119,7 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); -void NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port); NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port); From 39c51c35f4566553ec3c6c273c2642d796070521 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 13:55:39 +0200 Subject: [PATCH 057/800] Fix #6598: Do not disconnect before company number validation NetworkClientConnectGame already does a NetworkDisconnect, so no reason to do it here --- src/console_cmds.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 71f2d4b7b0..69a44e63de 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -914,7 +914,6 @@ DEF_CONSOLE_CMD(ConNetworkConnect) } if (argc < 2) return false; - if (_networking) NetworkDisconnect(); // we are in network-mode, first close it! return NetworkClientConnectGame(argv[1], COMPANY_NEW_COMPANY); } From 83985fe26f1ad87df709f122f74e5d50485095fa Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 14:21:33 +0200 Subject: [PATCH 058/800] Codechange: Move join information into a single structure --- src/network/network.cpp | 6 +++--- src/network/network_client.cpp | 21 ++++++++------------- src/network/network_client.h | 11 ++++++++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 22ac5dc74c..32fc4dec95 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -762,9 +762,9 @@ bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const strecpy(_settings_client.network.last_joined, address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); - _network_join_as = join_as; - _network_join_server_password = join_server_password; - _network_join_company_password = join_company_password; + _network_join.company = join_as; + _network_join.server_password = join_server_password; + _network_join.company_password = join_company_password; NetworkDisconnect(); NetworkInitialize(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index f73c8be528..ceb1463336 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -326,13 +326,8 @@ static uint8 _network_server_max_companies; /** Maximum number of spectators of the currently joined server. */ static uint8 _network_server_max_spectators; -/** Who would we like to join as. */ -CompanyID _network_join_as; - -/** Login password from -p argument */ -const char *_network_join_server_password = nullptr; -/** Company password from -P argument */ -const char *_network_join_company_password = nullptr; +/** Information about the game to join to. */ +NetworkJoinInfo _network_join; /** Make sure the server ID length is the same as a md5 hash. */ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1); @@ -372,7 +367,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin() p->Send_string(GetNetworkRevisionString()); p->Send_uint32(_openttd_newgrf_version); p->Send_string(_settings_client.network.client_name); // Client name - p->Send_uint8 (_network_join_as); // PlayAs + p->Send_uint8 (_network_join.company); // PlayAs p->Send_uint8 (0); // Used to be language my_client->SendPacket(p); return NETWORK_RECV_STATUS_OKAY; @@ -804,7 +799,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSW if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET; this->status = STATUS_AUTH_GAME; - const char *password = _network_join_server_password; + const char *password = _network_join.server_password; if (!StrEmpty(password)) { return SendGamePassword(password); } @@ -823,7 +818,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PA p->Recv_string(_password_server_id, sizeof(_password_server_id)); if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - const char *password = _network_join_company_password; + const char *password = _network_join.company_password; if (!StrEmpty(password)) { return SendCompanyPassword(password); } @@ -945,10 +940,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet /* New company/spectator (invalid company) or company we want to join is not active * Switch local company to spectator and await the server's judgement */ - if (_network_join_as == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join_as)) { + if (_network_join.company == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join.company)) { SetLocalCompany(COMPANY_SPECTATOR); - if (_network_join_as != COMPANY_SPECTATOR) { + if (_network_join.company != COMPANY_SPECTATOR) { /* We have arrived and ready to start playing; send a command to make a new company; * the server will give us a client-id and let us in */ _network_join_status = NETWORK_JOIN_STATUS_REGISTERING; @@ -957,7 +952,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet } } else { /* take control over an existing company */ - SetLocalCompany(_network_join_as); + SetLocalCompany(_network_join.company); } return NETWORK_RECV_STATUS_OKAY; diff --git a/src/network/network_client.h b/src/network/network_client.h index 40b8eedf92..28d2d00214 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -112,9 +112,14 @@ typedef ClientNetworkGameSocketHandler MyClient; void NetworkClient_Connected(); void NetworkClientSetCompanyPassword(const char *password); -extern CompanyID _network_join_as; +/** Information required to join a server. */ +struct NetworkJoinInfo { + NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {} + CompanyID company; ///< The company to join. + const char *server_password; ///< The password of the server to join. + const char *company_password; ///< The password of the company to join. +}; -extern const char *_network_join_server_password; -extern const char *_network_join_company_password; +extern NetworkJoinInfo _network_join; #endif /* NETWORK_CLIENT_H */ From 05394d5216f89c9a7e14487b571515e510828657 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 1 May 2021 14:41:25 +0200 Subject: [PATCH 059/800] Fix #6598: Prevent invalid memory accesses when abandoning a join from within a network game One could join a network game from within an already running network game. This would call a NetworkDisconnect, but keeps the UI alive. If, during that process the join is aborted, e.g. by cancelling on a password dialog, you would still be in your network game but also get shown the server list. Solve all the underlying problems by falling back to the main UI when (re)connecting to a(nother) server. --- src/network/network.cpp | 28 ++++++++++++++++++++++++---- src/network/network_client.h | 1 + src/network/network_func.h | 1 + src/openttd.cpp | 5 +++++ src/openttd.h | 1 + 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 32fc4dec95..ce79f4c514 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -760,20 +760,40 @@ bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const if (!_network_available) return false; if (!NetworkValidateClientName()) return false; - strecpy(_settings_client.network.last_joined, address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); - + _network_join.address = address; _network_join.company = join_as; _network_join.server_password = join_server_password; _network_join.company_password = join_company_password; + if (_game_mode == GM_MENU) { + /* From the menu we can immediately continue with the actual join. */ + NetworkClientJoinGame(); + } else { + /* When already playing a game, first go back to the main menu. This + * disconnects the user from the current game, meaning we can safely + * load in the new. After all, there is little point in continueing to + * play on a server if we are connecting to another one. + */ + _switch_mode = SM_JOIN_GAME; + } + return true; +} + +/** + * Actually perform the joining to the server. Use #NetworkClientConnectGame + * when you want to connect to a specific server/company. This function + * assumes _network_join is already fully set up. + */ +void NetworkClientJoinGame() +{ NetworkDisconnect(); NetworkInitialize(); + strecpy(_settings_client.network.last_joined, _network_join.address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); _network_join_status = NETWORK_JOIN_STATUS_CONNECTING; ShowJoinStatusWindow(); - new TCPClientConnecter(address); - return true; + new TCPClientConnecter(_network_join.address); } static void NetworkInitGameInfo() diff --git a/src/network/network_client.h b/src/network/network_client.h index 28d2d00214..81d5b720cd 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -115,6 +115,7 @@ void NetworkClientSetCompanyPassword(const char *password); /** Information required to join a server. */ struct NetworkJoinInfo { NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {} + NetworkAddress address; ///< The address of the server to join. CompanyID company; ///< The company to join. const char *server_password; ///< The password of the server to join. const char *company_password; ///< The password of the company to join. diff --git a/src/network/network_func.h b/src/network/network_func.h index 252d207db5..5f3e27c12f 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -52,6 +52,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +void NetworkClientJoinGame(); void NetworkClientRequestMove(CompanyID company, const char *pass = ""); void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); diff --git a/src/openttd.cpp b/src/openttd.cpp index fbeeba793e..234e3a4197 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1068,6 +1068,11 @@ void SwitchToMode(SwitchMode new_mode) break; } + case SM_JOIN_GAME: // Join a multiplayer game + LoadIntroGame(); + NetworkClientJoinGame(); + break; + case SM_MENU: // Switch to game intro menu LoadIntroGame(); if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback && SoundDriver::GetInstance()->HasOutput()) { diff --git a/src/openttd.h b/src/openttd.h index 77fafab1d1..2cd9cc1f09 100644 --- a/src/openttd.h +++ b/src/openttd.h @@ -36,6 +36,7 @@ enum SwitchMode { SM_START_HEIGHTMAP, ///< Load a heightmap and start a new game from it. SM_LOAD_HEIGHTMAP, ///< Load heightmap from scenario editor. SM_RESTART_HEIGHTMAP, ///< Load a heightmap and start a new game from it with current settings. + SM_JOIN_GAME, ///< Join a network game. }; /** Display Options */ From 520595ff87bc55042010a370ef1070f296ff07c0 Mon Sep 17 00:00:00 2001 From: Matt Kimber Date: Sat, 1 May 2021 18:14:50 +0100 Subject: [PATCH 060/800] Fix 3d7ab09: stopped trains not updating viewport hash when reversed for a second time (#9165) --- src/vehicle.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a9af24c55a..90accdd80e 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1639,13 +1639,19 @@ void Vehicle::UpdateBoundingBoxCoordinates(bool update_cache) const */ void Vehicle::UpdateViewport(bool dirty) { - Rect old_coord = this->sprite_cache.old_coord; + /* If the existing cache is invalid we should ignore it, as it will be set to the current coords by UpdateBoundingBoxCoordinates */ + bool ignore_cached_coords = this->sprite_cache.old_coord.left == INVALID_COORD; this->UpdateBoundingBoxCoordinates(true); - UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, old_coord.left, old_coord.top); + + if (ignore_cached_coords) { + UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, INVALID_COORD, INVALID_COORD); + } else { + UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top); + } if (dirty) { - if (old_coord.left == INVALID_COORD) { + if (ignore_cached_coords) { this->sprite_cache.is_viewport_candidate = this->MarkAllViewportsDirty(); } else { this->sprite_cache.is_viewport_candidate = ::MarkAllViewportsDirty( From 67063ceeb3832a7e0f608859ccbd5e79214e9853 Mon Sep 17 00:00:00 2001 From: Matt Kimber Date: Sat, 1 May 2021 18:15:22 +0100 Subject: [PATCH 061/800] Fix 3d7ab09: stopped trains not updating viewport hash when reversed for a second time (#9165) From 0eb17a70af86d11e49d9560088900c9d65cb07c1 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 30 Apr 2021 15:39:46 +0200 Subject: [PATCH 062/800] Codechange: rename NetworkError to ShowNetworkError --- src/network/core/tcp_listen.h | 2 +- src/network/network.cpp | 4 ++-- src/network/network_client.cpp | 2 +- src/network/network_internal.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h index 168f49f947..2ceea20aa9 100644 --- a/src/network/core/tcp_listen.h +++ b/src/network/core/tcp_listen.h @@ -151,7 +151,7 @@ public: if (sockets.size() == 0) { DEBUG(net, 0, "[server] could not start network: could not create listening socket"); - NetworkError(STR_NETWORK_ERROR_SERVER_START); + ShowNetworkError(STR_NETWORK_ERROR_SERVER_START); return false; } diff --git a/src/network/network.cpp b/src/network/network.cpp index ce79f4c514..af732facdb 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -277,7 +277,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs) /* There was a non-recoverable error, drop back to the main menu with a nice * error */ -void NetworkError(StringID error_string) +void ShowNetworkError(StringID error_string) { _switch_mode = SM_MENU; ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL); @@ -701,7 +701,7 @@ public: void OnFailure() override { - NetworkError(STR_NETWORK_ERROR_NOCONNECTION); + ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION); } void OnConnect(SOCKET s) override diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index ceb1463336..d288c71a6e 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -284,7 +284,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) #else if (_sync_seed_1 != _random.state[0]) { #endif - NetworkError(STR_NETWORK_ERROR_DESYNC); + ShowNetworkError(STR_NETWORK_ERROR_DESYNC); DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract); DEBUG(net, 0, "Sync error detected!"); my_client->ClientError(NETWORK_RECV_STATUS_DESYNC); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index be5b74a0f5..1fba1228a5 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -112,7 +112,7 @@ void NetworkExecuteLocalCommandQueue(); void NetworkFreeLocalCommandQueue(); void NetworkSyncCommandQueue(NetworkClientSocket *cs); -void NetworkError(StringID error_string); +void ShowNetworkError(StringID error_string); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0); uint NetworkCalculateLag(const NetworkClientSocket *cs); StringID GetNetworkErrorMsg(NetworkErrorCode err); From 22720332eb9922e20148c7aae1127f7304f6f7d3 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 30 Apr 2021 15:38:22 +0200 Subject: [PATCH 063/800] Codechange: encapsulate network error handling --- src/network/core/CMakeLists.txt | 1 + src/network/core/address.cpp | 24 +++--- src/network/core/core.cpp | 18 ---- src/network/core/os_abstraction.cpp | 125 ++++++++++++++++++++++++++++ src/network/core/os_abstraction.h | 52 +++++------- src/network/core/tcp.cpp | 22 ++--- src/network/core/tcp_http.cpp | 8 +- src/network/core/tcp_listen.h | 4 +- src/network/core/udp.cpp | 4 +- src/safeguards.h | 8 +- 10 files changed, 183 insertions(+), 83 deletions(-) create mode 100644 src/network/core/os_abstraction.cpp diff --git a/src/network/core/CMakeLists.txt b/src/network/core/CMakeLists.txt index 37cc3e1954..bf713be99c 100644 --- a/src/network/core/CMakeLists.txt +++ b/src/network/core/CMakeLists.txt @@ -8,6 +8,7 @@ add_files( game_info.h host.cpp host.h + os_abstraction.cpp os_abstraction.h packet.cpp packet.h diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index e91751c33f..d3e373ef76 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -317,7 +317,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp) SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (sock == INVALID_SOCKET) { - DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkError::GetLast().AsString()); return INVALID_SOCKET; } @@ -326,8 +326,8 @@ static SOCKET ConnectLoopProc(addrinfo *runp) if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed", type); int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen); - if (err != 0 && NetworkGetLastError() != EINPROGRESS) { - DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address.c_str(), family, NetworkGetLastErrorString()); + if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) { + DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address.c_str(), family, NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } @@ -343,7 +343,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp) tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS; int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv); if (n < 0) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } @@ -356,9 +356,9 @@ static SOCKET ConnectLoopProc(addrinfo *runp) } /* Retrieve last error, if any, on the socket. */ - err = GetSocketError(sock); - if (err != 0) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkGetErrorString(err)); + NetworkError socket_error = GetSocketError(sock); + if (socket_error.HasError()) { + DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), socket_error.AsString()); closesocket(sock); return INVALID_SOCKET; } @@ -393,7 +393,7 @@ static SOCKET ListenLoopProc(addrinfo *runp) SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (sock == INVALID_SOCKET) { - DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); return INVALID_SOCKET; } @@ -404,24 +404,24 @@ static SOCKET ListenLoopProc(addrinfo *runp) int on = 1; /* The (const char*) cast is needed for windows!! */ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); } #ifndef __OS2__ if (runp->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address.c_str(), NetworkError::GetLast().AsString()); } #endif if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) { - DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) { - DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address.c_str(), NetworkGetLastErrorString()); + DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } diff --git a/src/network/core/core.cpp b/src/network/core/core.cpp index 5c12cb2242..563deae963 100644 --- a/src/network/core/core.cpp +++ b/src/network/core/core.cpp @@ -13,7 +13,6 @@ #include "../../debug.h" #include "os_abstraction.h" #include "packet.h" -#include "../../string_func.h" #include "../../safeguards.h" @@ -48,20 +47,3 @@ void NetworkCoreShutdown() WSACleanup(); #endif } - -#if defined(_WIN32) -/** - * Return the string representation of the given error from the OS's network functions. - * @param error The error number (from \c NetworkGetLastError()). - * @return The error message, potentially an empty string but never \c nullptr. - */ -const char *NetworkGetErrorString(int error) -{ - static char buffer[512]; - if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) { - seprintf(buffer, lastof(buffer), "Unknown error %d", error); - } - return buffer; -} -#endif /* defined(_WIN32) */ diff --git a/src/network/core/os_abstraction.cpp b/src/network/core/os_abstraction.cpp new file mode 100644 index 0000000000..75f2224eb0 --- /dev/null +++ b/src/network/core/os_abstraction.cpp @@ -0,0 +1,125 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** + * @file os_abstraction.cpp OS specific implementations of functions of the OS abstraction layer for network stuff. + * + * The general idea is to have simple abstracting functions for things that + * require different implementations for different environments. + * In here the functions, and their documentation, are defined only once + * and the implementation contains the #ifdefs to change the implementation. + * Since Windows is usually different that is usually the first case, after + * that the behaviour is usually Unix/BSD-like with occasional variation. + */ + +#include "stdafx.h" +#include "os_abstraction.h" +#include "../../string_func.h" +#include + +#include "../../safeguards.h" + +/** + * Construct the network error with the given error code. + * @param error The error code. + */ +NetworkError::NetworkError(int error) : error(error) +{ +} + +/** + * Check whether this error describes that the operation would block. + * @return True iff the operation would block. + */ +bool NetworkError::WouldBlock() const +{ +#if defined(_WIN32) + return this->error == WSAEWOULDBLOCK; +#else + /* Usually EWOULDBLOCK and EAGAIN are the same, but sometimes they are not + * and the POSIX.1 specification states that either should be checked. */ + return this->error == EWOULDBLOCK || this->error == EAGAIN; +#endif +} + +/** + * Check whether this error describes a connection reset. + * @return True iff the connection is reset. + */ +bool NetworkError::IsConnectionReset() const +{ +#if defined(_WIN32) + return this->error == WSAECONNRESET; +#else + return this->error == ECONNRESET; +#endif +} + +/** + * Check whether this error describes a connect is in progress. + * @return True iff the connect is already in progress. + */ +bool NetworkError::IsConnectInProgress() const +{ +#if defined(_WIN32) + return this->error == WSAEWOULDBLOCK; +#else + return this->error == EINPROGRESS; +#endif +} + +/** + * Get the string representation of the error message. + * @return The string representation that will get overwritten by next calls. + */ +const char *NetworkError::AsString() const +{ + if (this->message.empty()) { +#if defined(_WIN32) + char buffer[512]; + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, this->error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) { + seprintf(buffer, lastof(buffer), "Unknown error %d", this->error); + } + this->message.assign(buffer); +#else + /* Make strerror thread safe by locking access to it. There is a thread safe strerror_r, however + * the non-POSIX variant is available due to defining _GNU_SOURCE meaning it is not portable. + * The problem with the non-POSIX variant is that it does not necessarily fill the buffer with + * the error message but can also return a pointer to a static bit of memory, whereas the POSIX + * variant always fills the buffer. This makes the behaviour too erratic to work with. */ + static std::mutex mutex; + std::lock_guard guard(mutex); + this->message.assign(strerror(this->error)); +#endif + } + return this->message.c_str(); +} + +/** + * Check whether an error was actually set. + * @return True iff an error was set. + */ +bool NetworkError::HasError() const +{ + return this->error != 0; +} + +/** + * Get the last network error. + * @return The network error. + */ +/* static */ NetworkError NetworkError::GetLast() +{ +#if defined(_WIN32) + return NetworkError(WSAGetLastError()); +#elif defined(__OS2__) + return NetworkError(sock_errno()); +#else + return NetworkError(errno); +#endif +} diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index 9bd0e321f7..e444bc78b4 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -14,6 +14,26 @@ #ifndef NETWORK_CORE_OS_ABSTRACTION_H #define NETWORK_CORE_OS_ABSTRACTION_H +/** + * Abstraction of a network error where all implementation details of the + * error codes are encapsulated in this class and the abstraction layer. + */ +class NetworkError { +private: + int error; ///< The underlying error number from errno or WSAGetLastError. + mutable std::string message; ///< The string representation of the error (set on first call to #AsString). +public: + NetworkError(int error); + + bool HasError() const; + bool WouldBlock() const; + bool IsConnectionReset() const; + bool IsConnectInProgress() const; + const char *AsString() const; + + static NetworkError GetLast(); +}; + /* Include standard stuff per OS */ /* Windows stuff */ @@ -23,21 +43,6 @@ #include #include -/** - * Get the last error code from any of the OS's network functions. - * What it returns and when it is reset, is implementation defined. - * @return The last error code. - */ -#define NetworkGetLastError() WSAGetLastError() -#undef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#undef ECONNRESET -#define ECONNRESET WSAECONNRESET -#undef EINPROGRESS -#define EINPROGRESS WSAEWOULDBLOCK - -const char *NetworkGetErrorString(int error); - /* Windows has some different names for some types */ typedef unsigned long in_addr_t; @@ -63,8 +68,6 @@ typedef unsigned long in_addr_t; # define INVALID_SOCKET -1 # define ioctlsocket ioctl # define closesocket close -# define NetworkGetLastError() (errno) -# define NetworkGetErrorString(error) (strerror(error)) /* Need this for FIONREAD on solaris */ # define BSD_COMP @@ -114,8 +117,6 @@ typedef unsigned long in_addr_t; # define INVALID_SOCKET -1 # define ioctlsocket ioctl # define closesocket close -# define NetworkGetLastError() (sock_errno()) -# define NetworkGetErrorString(error) (strerror(error)) /* Includes needed for OS/2 systems */ # include @@ -187,15 +188,6 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address } #endif -/** - * Return the string representation of the last error from the OS's network functions. - * @return The error message, potentially an empty string but never \c nullptr. - */ -static inline const char *NetworkGetLastErrorString() -{ - return NetworkGetErrorString(NetworkGetLastError()); -} - /** * Try to set the socket into non-blocking mode. * @param d The socket to set the non-blocking more for. @@ -237,13 +229,13 @@ static inline bool SetNoDelay(SOCKET d) * @param d The socket to get the error from. * @return The errno on the socket. */ -static inline int GetSocketError(SOCKET d) +static inline NetworkError GetSocketError(SOCKET d) { int err; socklen_t len = sizeof(err); getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len); - return err; + return NetworkError(err); } /* Make sure these structures have the size we expect them to be */ diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index f23b202c8b..842e1a89b9 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -86,11 +86,11 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down) while ((p = this->packet_queue) != nullptr) { res = p->TransferOut(send, this->sock, 0); if (res == -1) { - int err = NetworkGetLastError(); - if (err != EWOULDBLOCK) { + NetworkError err = NetworkError::GetLast(); + if (!err.WouldBlock()) { /* Something went wrong.. close client! */ if (!closing_down) { - DEBUG(net, 0, "send failed with error %s", NetworkGetErrorString(err)); + DEBUG(net, 0, "send failed with error %s", err.AsString()); this->CloseConnection(); } return SPS_CLOSED; @@ -136,10 +136,10 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() while (p->RemainingBytesToTransfer() != 0) { res = p->TransferIn(recv, this->sock, 0); if (res == -1) { - int err = NetworkGetLastError(); - if (err != EWOULDBLOCK) { - /* Something went wrong... (ECONNRESET is connection reset by peer) */ - if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err)); + NetworkError err = NetworkError::GetLast(); + if (!err.WouldBlock()) { + /* Something went wrong... */ + if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); this->CloseConnection(); return nullptr; } @@ -164,10 +164,10 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() while (p->RemainingBytesToTransfer() != 0) { res = p->TransferIn(recv, this->sock, 0); if (res == -1) { - int err = NetworkGetLastError(); - if (err != EWOULDBLOCK) { - /* Something went wrong... (ECONNRESET is connection reset by peer) */ - if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err)); + NetworkError err = NetworkError::GetLast(); + if (!err.WouldBlock()) { + /* Something went wrong... */ + if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); this->CloseConnection(); return nullptr; } diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index e0c269fafb..4f29df1912 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -225,10 +225,10 @@ int NetworkHTTPSocketHandler::Receive() for (;;) { ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0); if (res == -1) { - int err = NetworkGetLastError(); - if (err != EWOULDBLOCK) { - /* Something went wrong... (ECONNRESET is connection reset by peer) */ - if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err)); + NetworkError err = NetworkError::GetLast(); + if (!err.WouldBlock()) { + /* Something went wrong... */ + if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); return -1; } /* Connection would block, so stop for now */ diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h index 2ceea20aa9..e23ecae707 100644 --- a/src/network/core/tcp_listen.h +++ b/src/network/core/tcp_listen.h @@ -64,7 +64,7 @@ public: DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str()); if (p.TransferOut(send, s, 0) < 0) { - DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString()); + DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString()); } closesocket(s); break; @@ -81,7 +81,7 @@ public: p.PrepareToSend(); if (p.TransferOut(send, s, 0) < 0) { - DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString()); + DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString()); } closesocket(s); diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index ffc86d825f..e7b99a53e8 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -95,7 +95,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a /* Enable broadcast */ unsigned long val = 1; if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) { - DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkGetLastErrorString()); + DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkError::GetLast().AsString()); } } @@ -104,7 +104,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str()); /* Check for any errors, but ignore it otherwise */ - if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", send.GetAddressAsString().c_str(), NetworkGetLastErrorString()); + if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", send.GetAddressAsString().c_str(), NetworkError::GetLast().AsString()); if (!all) break; } diff --git a/src/safeguards.h b/src/safeguards.h index e3d6c4a3e4..aca461175f 100644 --- a/src/safeguards.h +++ b/src/safeguards.h @@ -70,15 +70,15 @@ #endif #if defined(NETWORK_CORE_OS_ABSTRACTION_H) && defined(_WIN32) -/* Use NetworkGetLastError() instead of errno, or do not (indirectly) include network/core/os_abstraction.h. - * Winsock does not set errno, but one should rather call WSAGetLastError. NetworkGetLastError abstracts that away. */ +/* Use NetworkError::GetLast() instead of errno, or do not (indirectly) include network/core/os_abstraction.h. + * Winsock does not set errno, but one should rather call WSAGetLastError. NetworkError::GetLast abstracts that away. */ #ifdef errno #undef errno #endif #define errno SAFEGUARD_DO_NOT_USE_THIS_METHOD -/* Use NetworkGetLastErrorString() instead of strerror, or do not (indirectly) include network/core/os_abstraction.h. - * Winsock errors are not handled by strerror, but one should rather call FormatMessage. NetworkGetLastErrorString abstracts that away. */ +/* Use NetworkError::AsString() instead of strerror, or do not (indirectly) include network/core/os_abstraction.h. + * Winsock errors are not handled by strerror, but one should rather call FormatMessage. NetworkError::AsString abstracts that away. */ #define strerror SAFEGUARD_DO_NOT_USE_THIS_METHOD #endif /* defined(NETWORK_CORE_OS_ABSTRACTION_H) && defined(_WIN32) */ From e097c83c83ac3be81041a67f8d641650045502fb Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 30 Apr 2021 19:21:02 +0200 Subject: [PATCH 064/800] Codechange: move some OS abstraction method implementations out of the header --- src/network/core/os_abstraction.cpp | 49 ++++++++++++++++++++++++++ src/network/core/os_abstraction.h | 53 ++--------------------------- 2 files changed, 52 insertions(+), 50 deletions(-) diff --git a/src/network/core/os_abstraction.cpp b/src/network/core/os_abstraction.cpp index 75f2224eb0..b2d3475d01 100644 --- a/src/network/core/os_abstraction.cpp +++ b/src/network/core/os_abstraction.cpp @@ -123,3 +123,52 @@ bool NetworkError::HasError() const return NetworkError(errno); #endif } + + +/** + * Try to set the socket into non-blocking mode. + * @param d The socket to set the non-blocking more for. + * @return True if setting the non-blocking mode succeeded, otherwise false. + */ +bool SetNonBlocking(SOCKET d) +{ +#if defined(_WIN32) + u_long nonblocking = 1; + return ioctlsocket(d, FIONBIO, &nonblocking) == 0; +#elif defined __EMSCRIPTEN__ + return true; +#else + int nonblocking = 1; + return ioctl(d, FIONBIO, &nonblocking) == 0; +#endif +} + +/** + * Try to set the socket to not delay sending. + * @param d The socket to disable the delaying for. + * @return True if disabling the delaying succeeded, otherwise false. + */ +bool SetNoDelay(SOCKET d) +{ +#ifdef __EMSCRIPTEN__ + return true; +#else + int flags = 1; + /* The (const char*) cast is needed for windows */ + return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char *)&flags, sizeof(flags)) == 0; +#endif +} + +/** + * Get the error from a socket, if any. + * @param d The socket to get the error from. + * @return The errno on the socket. + */ +NetworkError GetSocketError(SOCKET d) +{ + int err; + socklen_t len = sizeof(err); + getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len); + + return NetworkError(err); +} diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index e444bc78b4..55d7335017 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -66,7 +66,6 @@ typedef unsigned long in_addr_t; # endif # define SOCKET int # define INVALID_SOCKET -1 -# define ioctlsocket ioctl # define closesocket close /* Need this for FIONREAD on solaris */ # define BSD_COMP @@ -115,7 +114,6 @@ typedef unsigned long in_addr_t; #if defined(__OS2__) # define SOCKET int # define INVALID_SOCKET -1 -# define ioctlsocket ioctl # define closesocket close /* Includes needed for OS/2 systems */ @@ -188,55 +186,10 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address } #endif -/** - * Try to set the socket into non-blocking mode. - * @param d The socket to set the non-blocking more for. - * @return True if setting the non-blocking mode succeeded, otherwise false. - */ -static inline bool SetNonBlocking(SOCKET d) -{ -#ifdef __EMSCRIPTEN__ - return true; -#else -# ifdef _WIN32 - u_long nonblocking = 1; -# else - int nonblocking = 1; -# endif - return ioctlsocket(d, FIONBIO, &nonblocking) == 0; -#endif -} -/** - * Try to set the socket to not delay sending. - * @param d The socket to disable the delaying for. - * @return True if disabling the delaying succeeded, otherwise false. - */ -static inline bool SetNoDelay(SOCKET d) -{ -#ifdef __EMSCRIPTEN__ - return true; -#else - /* XXX should this be done at all? */ - int b = 1; - /* The (const char*) cast is needed for windows */ - return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0; -#endif -} - -/** - * Get the error from a socket, if any. - * @param d The socket to get the error from. - * @return The errno on the socket. - */ -static inline NetworkError GetSocketError(SOCKET d) -{ - int err; - socklen_t len = sizeof(err); - getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len); - - return NetworkError(err); -} +bool SetNonBlocking(SOCKET d); +bool SetNoDelay(SOCKET d); +NetworkError GetSocketError(SOCKET d); /* Make sure these structures have the size we expect them to be */ static_assert(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes. From f785a70a2bc08eaefcb1e2a43b8e6d36a154a00e Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 1 May 2021 23:58:18 +0100 Subject: [PATCH 065/800] Cleanup: Use std::vector in RealSpriteGroup. --- src/newgrf.cpp | 9 ++------- src/newgrf_airport.cpp | 4 ++-- src/newgrf_canal.cpp | 2 +- src/newgrf_cargo.cpp | 4 ++-- src/newgrf_engine.cpp | 6 +++--- src/newgrf_generic.cpp | 2 +- src/newgrf_railtype.cpp | 4 ++-- src/newgrf_roadtype.cpp | 4 ++-- src/newgrf_spritegroup.cpp | 6 ------ src/newgrf_spritegroup.h | 7 ++----- src/newgrf_station.cpp | 8 ++++---- 11 files changed, 21 insertions(+), 35 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 19cc436dd7..1d30cb2d75 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5181,23 +5181,18 @@ static void NewSpriteGroup(ByteReader *buf) group->nfo_line = _cur.nfo_line; act_group = group; - group->num_loaded = num_loaded; - group->num_loading = num_loading; - if (num_loaded > 0) group->loaded = CallocT(num_loaded); - if (num_loading > 0) group->loading = CallocT(num_loading); - grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading", setid, num_loaded, num_loading); for (uint i = 0; i < num_loaded; i++) { uint16 spriteid = buf->ReadWord(); - group->loaded[i] = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loaded.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid); } for (uint i = 0; i < num_loading; i++) { uint16 spriteid = buf->ReadWord(); - group->loading[i] = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loading.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid); } diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 61ad46ac0e..86b65fd0e3 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -223,8 +223,8 @@ void AirportOverrideManager::SetEntitySpec(AirportSpec *as) { /* Airport action 2s should always have only 1 "loaded" state, but some * times things don't follow the spec... */ - if (group->num_loaded > 0) return group->loaded[0]; - if (group->num_loading > 0) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; return nullptr; } diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 7295e5551b..6b3c9b3d42 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -111,7 +111,7 @@ struct CanalResolverObject : public ResolverObject { /* virtual */ const SpriteGroup *CanalResolverObject::ResolveReal(const RealSpriteGroup *group) const { - if (group->num_loaded == 0) return nullptr; + if (group->loaded.empty()) return nullptr; return group->loaded[0]; } diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index c2859b71ef..105a2b2524 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -29,8 +29,8 @@ struct CargoResolverObject : public ResolverObject { { /* Cargo action 2s should always have only 1 "loaded" state, but some * times things don't follow the spec... */ - if (group->num_loaded > 0) return group->loaded[0]; - if (group->num_loading > 0) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; return nullptr; } diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index cd12148558..e028b7a7d6 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -992,14 +992,14 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, const Vehicle *v = this->self_scope.v; if (v == nullptr) { - if (group->num_loading > 0) return group->loading[0]; - if (group->num_loaded > 0) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; return nullptr; } bool in_motion = !v->First()->current_order.IsType(OT_LOADING); - uint totalsets = in_motion ? group->num_loaded : group->num_loading; + uint totalsets = in_motion ? (uint)group->loaded.size() : (uint)group->loading.size(); if (totalsets == 0) return nullptr; diff --git a/src/newgrf_generic.cpp b/src/newgrf_generic.cpp index 6538b79b66..0a138f1d64 100644 --- a/src/newgrf_generic.cpp +++ b/src/newgrf_generic.cpp @@ -150,7 +150,7 @@ void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *g /* virtual */ const SpriteGroup *GenericResolverObject::ResolveReal(const RealSpriteGroup *group) const { - if (group->num_loaded == 0) return nullptr; + if (group->loaded.empty()) return nullptr; return group->loaded[0]; } diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 326ee80baf..407acc9844 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -60,8 +60,8 @@ /* virtual */ const SpriteGroup *RailTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const { - if (group->num_loading > 0) return group->loading[0]; - if (group->num_loaded > 0) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; return nullptr; } diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 025d03bb6a..9243bf77e3 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -60,8 +60,8 @@ /* virtual */ const SpriteGroup *RoadTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const { - if (group->num_loading > 0) return group->loading[0]; - if (group->num_loaded > 0) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; return nullptr; } diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 871108ec47..fb0d65c319 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -53,12 +53,6 @@ TemporaryStorageArray _temp_store; } } -RealSpriteGroup::~RealSpriteGroup() -{ - free(this->loaded); - free(this->loading); -} - DeterministicSpriteGroup::~DeterministicSpriteGroup() { free(this->adjusts); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 80f70df55d..a931597a03 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -78,7 +78,6 @@ public: * groups. */ struct RealSpriteGroup : SpriteGroup { RealSpriteGroup() : SpriteGroup(SGT_REAL) {} - ~RealSpriteGroup(); /* Loaded = in motion, loading = not moving * Each group contains several spritesets, for various loading stages */ @@ -87,10 +86,8 @@ struct RealSpriteGroup : SpriteGroup { * with small amount of cargo whilst loading is for stations with a lot * of da stuff. */ - byte num_loaded; ///< Number of loaded groups - byte num_loading; ///< Number of loading groups - const SpriteGroup **loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) - const SpriteGroup **loading; ///< List of loading groups (can be SpriteIDs or Callback results) + std::vector loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) + std::vector loading; ///< List of loading groups (can be SpriteIDs or Callback results) protected: const SpriteGroup *Resolve(ResolverObject &object) const; diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index fa3f831aa5..9aa3ad43be 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -523,13 +523,13 @@ uint32 Waypoint::GetNewGRFVariable(const ResolverObject &object, byte variable, cargo = std::min(0xfffu, cargo); if (cargo > this->station_scope.statspec->cargo_threshold) { - if (group->num_loading > 0) { - uint set = ((cargo - this->station_scope.statspec->cargo_threshold) * group->num_loading) / (4096 - this->station_scope.statspec->cargo_threshold); + if (!group->loading.empty()) { + uint set = ((cargo - this->station_scope.statspec->cargo_threshold) * (uint)group->loading.size()) / (4096 - this->station_scope.statspec->cargo_threshold); return group->loading[set]; } } else { - if (group->num_loaded > 0) { - uint set = (cargo * group->num_loaded) / (this->station_scope.statspec->cargo_threshold + 1); + if (!group->loaded.empty()) { + uint set = (cargo * (uint)group->loaded.size()) / (this->station_scope.statspec->cargo_threshold + 1); return group->loaded[set]; } } From 1aeaf399541c229973b576f2f2423fa8c4b49f65 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 2 May 2021 00:00:06 +0100 Subject: [PATCH 066/800] Cleanup: Use std::vector in DeterministicSpriteGroup. --- src/newgrf.cpp | 20 +++----------------- src/newgrf_spritegroup.cpp | 22 ++++++++-------------- src/newgrf_spritegroup.h | 7 ++----- 3 files changed, 13 insertions(+), 36 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 1d30cb2d75..ba5c098a2d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5024,16 +5024,13 @@ static void NewSpriteGroup(ByteReader *buf) case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break; } - static std::vector adjusts; - adjusts.clear(); - /* Loop through the var adjusts. Unfortunately we don't know how many we have * from the outset, so we shall have to keep reallocing. */ do { - DeterministicSpriteGroupAdjust &adjust = adjusts.emplace_back(); + DeterministicSpriteGroupAdjust &adjust = group->adjusts.emplace_back(); /* The first var adjust doesn't have an operation specified, so we set it to add. */ - adjust.operation = adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte(); + adjust.operation = group->adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte(); adjust.variable = buf->ReadByte(); if (adjust.variable == 0x7E) { /* Link subroutine group */ @@ -5058,10 +5055,6 @@ static void NewSpriteGroup(ByteReader *buf) /* Continue reading var adjusts while bit 5 is set. */ } while (HasBit(varadjust, 5)); - group->num_adjusts = (uint)adjusts.size(); - group->adjusts = MallocT(group->num_adjusts); - MemCpyT(group->adjusts, adjusts.data(), group->num_adjusts); - std::vector ranges; ranges.resize(buf->ReadByte()); for (uint i = 0; i < ranges.size(); i++) { @@ -5098,27 +5091,20 @@ static void NewSpriteGroup(ByteReader *buf) } assert(target.size() == bounds.size()); - std::vector optimised; for (uint j = 0; j < bounds.size(); ) { if (target[j] != group->default_group) { - DeterministicSpriteGroupRange r; + DeterministicSpriteGroupRange &r = group->ranges.emplace_back(); r.group = target[j]; r.low = bounds[j]; while (j < bounds.size() && target[j] == r.group) { j++; } r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX; - optimised.push_back(r); } else { j++; } } - group->num_ranges = (uint)optimised.size(); // cast is safe, there should never be 2**31 elements here - if (group->num_ranges > 0) { - group->ranges = MallocT(group->num_ranges); - MemCpyT(group->ranges, &optimised.front(), group->num_ranges); - } break; } diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index fb0d65c319..058baf334e 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -53,12 +53,6 @@ TemporaryStorageArray _temp_store; } } -DeterministicSpriteGroup::~DeterministicSpriteGroup() -{ - free(this->adjusts); - free(this->ranges); -} - RandomizedSpriteGroup::~RandomizedSpriteGroup() { free(this->groups); @@ -205,8 +199,8 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con ScopeResolver *scope = object.GetScope(this->var_scope); - for (i = 0; i < this->num_adjusts; i++) { - DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i]; + for (i = 0; i < this->adjusts.size(); i++) { + const DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i]; /* Try to get the variable. We shall assume it is available, unless told otherwise. */ bool available = true; @@ -250,16 +244,16 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con return &nvarzero; } - if (this->num_ranges > 4) { - DeterministicSpriteGroupRange *lower = std::lower_bound(this->ranges + 0, this->ranges + this->num_ranges, value, RangeHighComparator); - if (lower != this->ranges + this->num_ranges && lower->low <= value) { + if (this->ranges.size() > 4) { + const auto &lower = std::lower_bound(this->ranges.begin(), this->ranges.end(), value, RangeHighComparator); + if (lower != this->ranges.end() && lower->low <= value) { assert(lower->low <= value && value <= lower->high); return SpriteGroup::Resolve(lower->group, object, false); } } else { - for (i = 0; i < this->num_ranges; i++) { - if (this->ranges[i].low <= value && value <= this->ranges[i].high) { - return SpriteGroup::Resolve(this->ranges[i].group, object, false); + for (const auto &range : this->ranges) { + if (range.low <= value && value <= range.high) { + return SpriteGroup::Resolve(range.group, object, false); } } } diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index a931597a03..e91987dbb6 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -166,15 +166,12 @@ struct DeterministicSpriteGroupRange { struct DeterministicSpriteGroup : SpriteGroup { DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {} - ~DeterministicSpriteGroup(); VarSpriteGroupScope var_scope; DeterministicSpriteGroupSize size; - uint num_adjusts; - uint num_ranges; bool calculated_result; - DeterministicSpriteGroupAdjust *adjusts; - DeterministicSpriteGroupRange *ranges; // Dynamically allocated + std::vector adjusts; + std::vector ranges; // Dynamically allocated /* Dynamically allocated, this is the sole owner */ const SpriteGroup *default_group; From 913d8a7f28cade14577fc147e3bb42fa7d75cad7 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 2 May 2021 00:00:40 +0100 Subject: [PATCH 067/800] Cleanup: Use std::vector in RandomSpriteGroup. --- src/newgrf.cpp | 7 +++---- src/newgrf_spritegroup.cpp | 9 ++------- src/newgrf_spritegroup.h | 4 +--- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index ba5c098a2d..0377c0bc53 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5128,11 +5128,10 @@ static void NewSpriteGroup(ByteReader *buf) group->triggers = GB(triggers, 0, 7); group->cmp_mode = HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY; group->lowest_randbit = buf->ReadByte(); - group->num_groups = buf->ReadByte(); - group->groups = CallocT(group->num_groups); - for (uint i = 0; i < group->num_groups; i++) { - group->groups[i] = GetGroupFromGroupID(setid, type, buf->ReadWord()); + byte num_groups = buf->ReadByte(); + for (uint i = 0; i < num_groups; i++) { + group->groups.push_back(GetGroupFromGroupID(setid, type, buf->ReadWord())); } break; diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 058baf334e..eef531fb22 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -53,11 +53,6 @@ TemporaryStorageArray _temp_store; } } -RandomizedSpriteGroup::~RandomizedSpriteGroup() -{ - free(this->groups); -} - static inline uint32 GetVariable(const ResolverObject &object, ScopeResolver *scope, byte variable, uint32 parameter, bool *available) { uint32 value; @@ -272,11 +267,11 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject &object) const if (res) { object.used_triggers |= match; - object.reseed[this->var_scope] |= (this->num_groups - 1) << this->lowest_randbit; + object.reseed[this->var_scope] |= (this->groups.size() - 1) << this->lowest_randbit; } } - uint32 mask = (this->num_groups - 1) << this->lowest_randbit; + uint32 mask = ((uint)this->groups.size() - 1) << this->lowest_randbit; byte index = (scope->GetRandomBits() & mask) >> this->lowest_randbit; return SpriteGroup::Resolve(this->groups[index], object, false); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index e91987dbb6..b172667612 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -189,7 +189,6 @@ enum RandomizedSpriteGroupCompareMode { struct RandomizedSpriteGroup : SpriteGroup { RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {} - ~RandomizedSpriteGroup(); VarSpriteGroupScope var_scope; ///< Take this object: @@ -198,9 +197,8 @@ struct RandomizedSpriteGroup : SpriteGroup { byte count; byte lowest_randbit; ///< Look for this in the per-object randomized bitmask: - byte num_groups; ///< must be power of 2 - const SpriteGroup **groups; ///< Take the group with appropriate index: + std::vector groups; ///< Take the group with appropriate index: protected: const SpriteGroup *Resolve(ResolverObject &object) const; From 6b0b1bb3de17c92881d5a570736103d22c403368 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 2 May 2021 00:04:34 +0100 Subject: [PATCH 068/800] Cleanup: Use range iterator to evaluate DeterministicSpriteGroup. --- src/newgrf_spritegroup.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index eef531fb22..29080894ec 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -141,18 +141,18 @@ static inline uint32 GetVariable(const ResolverObject &object, ScopeResolver *sc /* Evaluate an adjustment for a variable of the given size. * U is the unsigned type and S is the signed type to use. */ template -static U EvalAdjustT(const DeterministicSpriteGroupAdjust *adjust, ScopeResolver *scope, U last_value, uint32 value) +static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver *scope, U last_value, uint32 value) { - value >>= adjust->shift_num; - value &= adjust->and_mask; + value >>= adjust.shift_num; + value &= adjust.and_mask; - switch (adjust->type) { - case DSGA_TYPE_DIV: value = ((S)value + (S)adjust->add_val) / (S)adjust->divmod_val; break; - case DSGA_TYPE_MOD: value = ((S)value + (S)adjust->add_val) % (S)adjust->divmod_val; break; + switch (adjust.type) { + case DSGA_TYPE_DIV: value = ((S)value + (S)adjust.add_val) / (S)adjust.divmod_val; break; + case DSGA_TYPE_MOD: value = ((S)value + (S)adjust.add_val) % (S)adjust.divmod_val; break; case DSGA_TYPE_NONE: break; } - switch (adjust->operation) { + switch (adjust.operation) { case DSGA_OP_ADD: return last_value + value; case DSGA_OP_SUB: return last_value - value; case DSGA_OP_SMIN: return std::min(last_value, value); @@ -190,17 +190,14 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con { uint32 last_value = 0; uint32 value = 0; - uint i; ScopeResolver *scope = object.GetScope(this->var_scope); - for (i = 0; i < this->adjusts.size(); i++) { - const DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i]; - + for (const auto &adjust : this->adjusts) { /* Try to get the variable. We shall assume it is available, unless told otherwise. */ bool available = true; - if (adjust->variable == 0x7E) { - const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, object, false); + if (adjust.variable == 0x7E) { + const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust.subroutine, object, false); if (subgroup == nullptr) { value = CALLBACK_FAILED; } else { @@ -208,10 +205,10 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con } /* Note: 'last_value' and 'reseed' are shared between the main chain and the procedure */ - } else if (adjust->variable == 0x7B) { - value = GetVariable(object, scope, adjust->parameter, last_value, &available); + } else if (adjust.variable == 0x7B) { + value = GetVariable(object, scope, adjust.parameter, last_value, &available); } else { - value = GetVariable(object, scope, adjust->variable, adjust->parameter, &available); + value = GetVariable(object, scope, adjust.variable, adjust.parameter, &available); } if (!available) { From 18fb1c386689f12d2a7e767d9372020c0a8d9fea Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 2 May 2021 00:34:17 +0100 Subject: [PATCH 069/800] Codechange: Warn if randomaction2 group count is not a power of 2. Previously noted by a comment, this does not need to be guarded against as non-powers of 2 will not cause issues beyond the choice of results being reduced. --- src/newgrf.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 0377c0bc53..a9727d38de 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5130,6 +5130,10 @@ static void NewSpriteGroup(ByteReader *buf) group->lowest_randbit = buf->ReadByte(); byte num_groups = buf->ReadByte(); + if (!HasExactlyOneBit(num_groups)) { + grfmsg(1, "NewSpriteGroup: Random Action 2 nrand should be power of 2"); + } + for (uint i = 0; i < num_groups; i++) { group->groups.push_back(GetGroupFromGroupID(setid, type, buf->ReadWord())); } From 256dbee25597f4da8726063084f94eb821babf14 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sun, 2 May 2021 10:21:27 +0100 Subject: [PATCH 070/800] Fix: Crash when extra viewport height is zero with sign in view. (#9175) If a viewport sign straddles the top of a viewport, a crash will occur if the viewport height is zero. This is resolved by simply not attempting to draw the viewport in this situation, consistent with other widgets. --- src/widget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widget.cpp b/src/widget.cpp index 68bc43d78f..5c1c0ae8fc 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -2029,6 +2029,8 @@ void NWidgetViewport::SetupSmallestSize(Window *w, bool init_array) void NWidgetViewport::Draw(const Window *w) { + if (this->current_x == 0 || this->current_y == 0) return; + if (this->disp_flags & ND_NO_TRANSPARENCY) { TransparencyOptionBits to_backup = _transparency_opt; _transparency_opt &= (1 << TO_SIGNS) | (1 << TO_LOADING); // Disable all transparency, except textual stuff From 18651dd8b13d8a427ae71d8af00792d52ad9ed60 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sun, 2 May 2021 10:43:14 +0100 Subject: [PATCH 071/800] Fix: Update text effect size when font zoom is changed. (#9174) --- src/saveload/afterload.cpp | 1 + src/texteff.cpp | 11 ++++++++++- src/texteff.hpp | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index d4b230dfd0..56680511cb 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -219,6 +219,7 @@ void UpdateAllVirtCoords() UpdateAllStationVirtCoords(); UpdateAllSignVirtCoords(); UpdateAllTownVirtCoords(); + UpdateAllTextEffectVirtCoords(); RebuildViewportKdtree(); } diff --git a/src/texteff.cpp b/src/texteff.cpp index f08701939f..e29326a90a 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -73,7 +73,16 @@ void UpdateTextEffect(TextEffectID te_id, StringID msg) te->params_1 = GetDParam(0); te->params_2 = GetDParam(1); - te->UpdatePosition(te->center, te->top, msg); + te->UpdatePosition(te->center, te->top, te->string_id, te->string_id - 1); +} + +void UpdateAllTextEffectVirtCoords() +{ + for (auto &te : _text_effects) { + SetDParam(0, te.params_1); + SetDParam(1, te.params_2); + te.UpdatePosition(te.center, te.top, te.string_id, te.string_id - 1); + } } void RemoveTextEffect(TextEffectID te_id) diff --git a/src/texteff.hpp b/src/texteff.hpp index 789b12d540..d122b17e9b 100644 --- a/src/texteff.hpp +++ b/src/texteff.hpp @@ -32,6 +32,7 @@ void InitTextEffects(); void DrawTextEffects(DrawPixelInfo *dpi); void UpdateTextEffect(TextEffectID effect_id, StringID msg); void RemoveTextEffect(TextEffectID effect_id); +void UpdateAllTextEffectVirtCoords(); /* misc_gui.cpp */ TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID colour); From 56aa6d0eddb60fac20cde82cd496005369ca1b8d Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 11:05:50 +0200 Subject: [PATCH 072/800] Fix: [Network] Reading beyond the length of the server's ID when hashing password Under normal circumstances the server's ID is 32 characters excluding '\0', however this can be changed at the server. This ID is sent to the server for company name hashing. The client reads it into a statically allocated buffer of 33 bytes, but fills only the bytes it received from the server. However, the hash assumes all 33 bytes are set, thus potentially reading uninitialized data, or a part of the server ID of a previous game in the hashing routine. It is still reading from memory assigned to the server ID, so nothing bad happens, except that company passwords might not work correctly. --- src/network/network.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index af732facdb..c00a3650fb 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -176,12 +176,15 @@ const char *GenerateCompanyPasswordHash(const char *password, const char *passwo if (StrEmpty(password)) return password; char salted_password[NETWORK_SERVER_ID_LENGTH]; + size_t password_length = strlen(password); + size_t password_server_id_length = strlen(password_server_id); - memset(salted_password, 0, sizeof(salted_password)); - seprintf(salted_password, lastof(salted_password), "%s", password); /* Add the game seed and the server's ID as the salt. */ for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) { - salted_password[i] ^= password_server_id[i] ^ (password_game_seed >> (i % 32)); + char password_char = (i < password_length ? password[i] : 0); + char server_id_char = (i < password_server_id_length ? password_server_id[i] : 0); + char seed_char = password_game_seed >> (i % 32); + salted_password[i] = password_char ^ server_id_char ^ seed_char; } Md5 checksum; From 84aa17cea6f677f2bd6cb0e1c33457dbdcda77dc Mon Sep 17 00:00:00 2001 From: frosch Date: Sat, 1 May 2021 23:59:53 +0200 Subject: [PATCH 073/800] Fix: [NewGRF] industry variables 65 and 66 ignored the parameter, and always used the north tile. --- src/newgrf_industries.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 5e59634e84..68f28148c7 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -281,13 +281,17 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout if (this->tile == INVALID_TILE) break; return GetClosestIndustry(this->tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), this->industry); /* Get town zone and Manhattan distance of closest town */ - case 0x65: + case 0x65: { if (this->tile == INVALID_TILE) break; - return GetTownRadiusGroup(this->industry->town, this->tile) << 16 | std::min(DistanceManhattan(this->tile, this->industry->town->xy), 0xFFFFu); + TileIndex tile = GetNearbyTile(parameter, this->tile, true); + return GetTownRadiusGroup(this->industry->town, tile) << 16 | std::min(DistanceManhattan(tile, this->industry->town->xy), 0xFFFFu); + } /* Get square of Euclidian distance of closes town */ - case 0x66: + case 0x66: { if (this->tile == INVALID_TILE) break; - return GetTownRadiusGroup(this->industry->town, this->tile) << 16 | std::min(DistanceSquare(this->tile, this->industry->town->xy), 0xFFFFu); + TileIndex tile = GetNearbyTile(parameter, this->tile, true); + return GetTownRadiusGroup(this->industry->town, tile) << 16 | std::min(DistanceSquare(tile, this->industry->town->xy), 0xFFFFu); + } /* Count of industry, distance of closest instance * 68 is the same as 67, but with a filtering on selected layout */ From 2cf5df2a50e9f28ef4ba93a765bfcf79afcbb20c Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 2 May 2021 00:01:06 +0200 Subject: [PATCH 074/800] Fix: [NewGRF] industry variable 66 and object variable 46 clamped the squared-euclidian distance to 16 bit, when they should not. --- src/newgrf_industries.cpp | 4 ++-- src/newgrf_object.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 68f28148c7..abae446040 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -286,11 +286,11 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout TileIndex tile = GetNearbyTile(parameter, this->tile, true); return GetTownRadiusGroup(this->industry->town, tile) << 16 | std::min(DistanceManhattan(tile, this->industry->town->xy), 0xFFFFu); } - /* Get square of Euclidian distance of closes town */ + /* Get square of Euclidian distance of closest town */ case 0x66: { if (this->tile == INVALID_TILE) break; TileIndex tile = GetNearbyTile(parameter, this->tile, true); - return GetTownRadiusGroup(this->industry->town, tile) << 16 | std::min(DistanceSquare(tile, this->industry->town->xy), 0xFFFFu); + return DistanceSquare(tile, this->industry->town->xy); } /* Count of industry, distance of closest instance diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 649a4b58a1..3c069f4c95 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -303,8 +303,8 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte local_id, uint32 grfid, /* Get town zone and Manhattan distance of closest town */ case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceManhattan(this->tile, t->xy), 0xFFFFu); - /* Get square of Euclidian distance of closes town */ - case 0x46: return GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceSquare(this->tile, t->xy), 0xFFFFu); + /* Get square of Euclidian distance of closest town */ + case 0x46: return DistanceSquare(this->tile, t->xy); /* Object colour */ case 0x47: return this->obj->colour; From 91b8ce073f54dff48cd61186c32d0a720a2abb4d Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 1 May 2021 19:39:03 +0200 Subject: [PATCH 075/800] Codechange: Generalise the delayed blitter change to a generic video driver command queue. --- src/gfxinit.cpp | 24 ++++++++++++++++++++++- src/video/video_driver.cpp | 26 +------------------------ src/video/video_driver.hpp | 39 ++++++++++++++++++++++++++++++-------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index b744eaa5ef..c0ba4c4d4d 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -244,6 +244,28 @@ static void LoadSpriteTables() } +static void RealChangeBlitter(const char *repl_blitter) +{ + const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName(); + if (strcmp(cur_blitter, repl_blitter) == 0) return; + + DEBUG(driver, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter); + Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter); + if (new_blitter == nullptr) NOT_REACHED(); + DEBUG(driver, 1, "Successfully switched to %s.", repl_blitter); + + if (!VideoDriver::GetInstance()->AfterBlitterChange()) { + /* Failed to switch blitter, let's hope we can return to the old one. */ + if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !VideoDriver::GetInstance()->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config"); + } + + /* Clear caches that might have sprites for another blitter. */ + VideoDriver::GetInstance()->ClearSystemSprites(); + ClearFontCache(); + GfxClearSpriteCache(); + ReInitAllWindows(false); +} + /** * Check blitter needed by NewGRF config and switch if needed. * @return False when nothing changed, true otherwise. @@ -309,7 +331,7 @@ static bool SwitchNewGRFBlitter() if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue; /* Inform the video driver we want to switch blitter as soon as possible. */ - VideoDriver::GetInstance()->ChangeBlitter(repl_blitter); + VideoDriver::GetInstance()->QueueOnMainThread(std::bind(&RealChangeBlitter, repl_blitter)); break; } diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index d8fbe0400a..2f8efc4ad4 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -97,27 +97,6 @@ void VideoDriver::StopGameThread() this->game_thread.join(); } -void VideoDriver::RealChangeBlitter(const char *repl_blitter) -{ - const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName(); - - DEBUG(driver, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter); - Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter); - if (new_blitter == nullptr) NOT_REACHED(); - DEBUG(driver, 1, "Successfully switched to %s.", repl_blitter); - - if (!this->AfterBlitterChange()) { - /* Failed to switch blitter, let's hope we can return to the old one. */ - if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !this->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config"); - } - - /* Clear caches that might have sprites for another blitter. */ - this->ClearSystemSprites(); - ClearFontCache(); - GfxClearSpriteCache(); - ReInitAllWindows(false); -} - void VideoDriver::Tick() { if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) { @@ -159,10 +138,7 @@ void VideoDriver::Tick() this->LockVideoBuffer(); - if (this->change_blitter != nullptr) { - this->RealChangeBlitter(this->change_blitter); - this->change_blitter = nullptr; - } + this->DrainCommandQueue(); while (this->PollEvent()) {} ::InputLoop(); diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index 4964e01cb3..db522a761d 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -22,6 +22,7 @@ #include #include #include +#include extern std::string _ini_videodriver; extern std::vector _resolutions; @@ -36,7 +37,7 @@ class VideoDriver : public Driver { const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height. public: - VideoDriver() : fast_forward_key_pressed(false), fast_forward_via_key(false), is_game_threaded(true), change_blitter(nullptr) {} + VideoDriver() : fast_forward_key_pressed(false), fast_forward_via_key(false), is_game_threaded(true) {} /** * Mark a particular area dirty. @@ -178,12 +179,16 @@ public: } /** - * Queue a request to change the blitter. This is not executed immediately, - * but instead on the next draw-tick. + * Queue a function to be called on the main thread with game state + * lock held and video buffer locked. Queued functions will be + * executed on the next draw tick. + * @param func Function to call. */ - void ChangeBlitter(const char *new_blitter) + void QueueOnMainThread(std::function &&func) { - this->change_blitter = new_blitter; + std::lock_guard lock(this->cmd_queue_mutex); + + this->cmd_queue.emplace_back(std::forward>(func)); } void GameLoopPause(); @@ -328,11 +333,29 @@ protected: static void GameThreadThunk(VideoDriver *drv); private: + std::mutex cmd_queue_mutex; + std::vector> cmd_queue; + + /** Execute all queued commands. */ + void DrainCommandQueue() + { + std::vector> cmds{}; + + { + /* Exchange queue with an empty one to limit the time we + * hold the mutex. This also ensures that queued functions can + * add new functions to the queue without everything blocking. */ + std::lock_guard lock(this->cmd_queue_mutex); + cmds.swap(this->cmd_queue); + } + + for (auto &f : cmds) { + f(); + } + } + void GameLoop(); void GameThread(); - void RealChangeBlitter(const char *repl_blitter); - - const char *change_blitter; ///< Request to change the blitter. nullptr if no pending request. }; #endif /* VIDEO_VIDEO_DRIVER_HPP */ From 1f159f79de7428cbaa6133ec9cf06ce559980ea6 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 1 May 2021 19:55:46 +0200 Subject: [PATCH 076/800] Fix #9147: Delay making screenshots until the next draw tick as we may not access the video buffer from the game thread. --- src/console_cmds.cpp | 2 +- src/screenshot.cpp | 38 ++++++++++++++++++++++++++++++-------- src/screenshot.h | 2 +- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 69a44e63de..99b3b54582 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1416,7 +1416,7 @@ DEF_CONSOLE_CMD(ConScreenShot) ScreenshotType type = SC_VIEWPORT; uint32 width = 0; uint32 height = 0; - const char *name = nullptr; + std::string name{}; uint32 arg_index = 1; if (argc > arg_index) { diff --git a/src/screenshot.cpp b/src/screenshot.cpp index dc76996fbf..0e3bf3d8e2 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -864,7 +864,7 @@ static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the curre */ static void ScreenshotConfirmationCallback(Window *w, bool confirmed) { - if (confirmed) MakeScreenshot(_confirmed_screenshot_type, nullptr); + if (confirmed) MakeScreenshot(_confirmed_screenshot_type, {}); } /** @@ -890,24 +890,20 @@ void MakeScreenshotWithConfirm(ScreenshotType t) ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback); } else { /* Less than 64M pixels, just do it */ - MakeScreenshot(t, nullptr); + MakeScreenshot(t, {}); } } /** * Make a screenshot. - * Unconditionally take a screenshot of the requested type. * @param t the type of screenshot to make. * @param name the name to give to the screenshot. * @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). * @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). * @return true iff the screenshot was made successfully - * @see MakeScreenshotWithConfirm */ -bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 height) +static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height) { - VideoDriver::VideoBufferLocker lock; - if (t == SC_VIEWPORT) { /* First draw the dirty parts of the screen and only then change the name * of the screenshot. This way the screenshot will always show the name @@ -918,7 +914,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei } _screenshot_name[0] = '\0'; - if (name != nullptr) strecpy(_screenshot_name, name, lastof(_screenshot_name)); + if (!name.empty()) strecpy(_screenshot_name, name.c_str(), lastof(_screenshot_name)); bool ret; switch (t) { @@ -969,6 +965,32 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei return ret; } +/** + * Schedule making a screenshot. + * Unconditionally take a screenshot of the requested type. + * @param t the type of screenshot to make. + * @param name the name to give to the screenshot. + * @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). + * @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). + * @return true iff the screenshot was successfully made. + * @see MakeScreenshotWithConfirm + */ +bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height) +{ + if (t == SC_CRASHLOG) { + /* Video buffer might or might not be locked. */ + VideoDriver::VideoBufferLocker lock; + + return RealMakeScreenshot(t, name, width, height); + } + + VideoDriver::GetInstance()->QueueOnMainThread([=] { // Capture by value to not break scope. + RealMakeScreenshot(t, name, width, height); + }); + + return true; +} + /** * Return the owner of a tile to display it with in the small map in mode "Owner". diff --git a/src/screenshot.h b/src/screenshot.h index 148c018e1e..e65813573f 100644 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -28,7 +28,7 @@ enum ScreenshotType { void SetupScreenshotViewport(ScreenshotType t, struct Viewport *vp, uint32 width = 0, uint32 height = 0); bool MakeHeightmapScreenshot(const char *filename); void MakeScreenshotWithConfirm(ScreenshotType t); -bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width = 0, uint32 height = 0); +bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width = 0, uint32 height = 0); bool MakeMinimapWorldScreenshot(); extern char _screenshot_format_name[8]; From bd1a20f6eee6758f6a812af18fbe5b41b491b5c4 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 1 May 2021 18:07:47 +0100 Subject: [PATCH 077/800] Codechange: Use std::vector for NewGRF station platform layouts. This avoids the need to custom memory management and additional members. This also resolves use-after-free if modifying copied layouts, so presumably nobody has ever done that. --- src/newgrf.cpp | 79 +++++++++++--------------------------------- src/newgrf_station.h | 22 +++++++----- src/station_cmd.cpp | 14 ++++---- src/waypoint_cmd.cpp | 2 +- 4 files changed, 42 insertions(+), 75 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index a9727d38de..9e8bbda190 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -218,6 +218,19 @@ protected: public: ByteReader(byte *data, byte *end) : data(data), end(end) { } + inline byte *ReadBytes(size_t size) + { + if (data + size >= end) { + /* Put data at the end, as would happen if every byte had been individually read. */ + data = end; + throw OTTDByteReaderSignal(); + } + + byte *ret = data; + data += size; + return ret; + } + inline byte ReadByte() { if (data < end) return *(data)++; @@ -1883,7 +1896,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte StationSpec **spec = &_cur.grffile->stations[stid + i]; /* Property 0x08 is special; it is where the station is allocated */ - if (*spec == nullptr) *spec = CallocT(1); + if (*spec == nullptr) *spec = new StationSpec(); /* Swap classid because we read it in BE meaning WAYP or DFLT */ uint32 classid = buf->ReadDWord(); @@ -1966,54 +1979,17 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte break; case 0x0E: // Define custom layout - statspec->copied_layouts = false; - while (buf->HasData()) { byte length = buf->ReadByte(); byte number = buf->ReadByte(); - StationLayout layout; - uint l, p; if (length == 0 || number == 0) break; - if (length > statspec->lengths) { - byte diff_length = length - statspec->lengths; - statspec->platforms = ReallocT(statspec->platforms, length); - memset(statspec->platforms + statspec->lengths, 0, diff_length); + if (statspec->layouts.size() < length) statspec->layouts.resize(length); + if (statspec->layouts[length - 1].size() < number) statspec->layouts[length - 1].resize(number); - statspec->layouts = ReallocT(statspec->layouts, length); - memset(statspec->layouts + statspec->lengths, 0, diff_length * sizeof(*statspec->layouts)); - - statspec->lengths = length; - } - l = length - 1; // index is zero-based - - if (number > statspec->platforms[l]) { - statspec->layouts[l] = ReallocT(statspec->layouts[l], number); - /* We expect nullptr being 0 here, but C99 guarantees that. */ - memset(statspec->layouts[l] + statspec->platforms[l], 0, - (number - statspec->platforms[l]) * sizeof(**statspec->layouts)); - - statspec->platforms[l] = number; - } - - p = 0; - layout = MallocT(length * number); - try { - for (l = 0; l < length; l++) { - for (p = 0; p < number; p++) { - layout[l * number + p] = buf->ReadByte(); - } - } - } catch (...) { - free(layout); - throw; - } - - l--; - p--; - free(statspec->layouts[l][p]); - statspec->layouts[l][p] = layout; + const byte *layout = buf->ReadBytes(length * number); + statspec->layouts[length - 1][number - 1].assign(layout, layout + length * number); } break; @@ -2026,10 +2002,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte continue; } - statspec->lengths = srcstatspec->lengths; - statspec->platforms = srcstatspec->platforms; - statspec->layouts = srcstatspec->layouts; - statspec->copied_layouts = true; + statspec->layouts = srcstatspec->layouts; break; } @@ -8399,20 +8372,8 @@ static void ResetCustomStations() delete[] statspec->renderdata; - /* Release platforms and layouts */ - if (!statspec->copied_layouts) { - for (uint l = 0; l < statspec->lengths; l++) { - for (uint p = 0; p < statspec->platforms[l]; p++) { - free(statspec->layouts[l][p]); - } - free(statspec->layouts[l]); - } - free(statspec->layouts); - free(statspec->platforms); - } - /* Release this station */ - free(statspec); + delete statspec; } /* Free and reset the station data */ diff --git a/src/newgrf_station.h b/src/newgrf_station.h index fac5d64ddd..4c4a5831be 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -109,12 +109,13 @@ enum StationRandomTrigger { SRT_PATH_RESERVATION, ///< Trigger platform when train reserves path. }; -/* Station layout for given dimensions - it is a two-dimensional array - * where index is computed as (x * platforms) + platform. */ -typedef byte *StationLayout; - /** Station specification. */ struct StationSpec { + StationSpec() : cls_id(STAT_CLASS_DFLT), name(0), + disallowed_platforms(0), disallowed_lengths(0), tiles(0), + renderdata(nullptr), cargo_threshold(0), cargo_triggers(0), + callback_mask(0), flags(0), pylons(0), wires(0), blocked(0), + animation({0, 0, 0, 0}) {} /** * Properties related the the grf file. * NUM_CARGO real cargo plus three pseudo cargo sprite groups. @@ -165,10 +166,15 @@ struct StationSpec { AnimationInfo animation; - byte lengths; - byte *platforms; - StationLayout **layouts; - bool copied_layouts; + /** + * Custom platform layouts. + * This is a 2D array containing an array of tiles. + * 1st layer is platform lengths. + * 2nd layer is tracks (width). + * These can be sparsely populated, and the upper limit is not defined but + * limited to 255. + */ + std::vector>> layouts; }; /** Struct containing information relating to station classes. */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 482b954625..ac78064d49 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1109,13 +1109,13 @@ static inline byte *CreateMulti(byte *layout, int n, byte b) * @param plat_len The length of the platforms. * @param statspec The specification of the station to (possibly) get the layout from. */ -void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec) +void GetStationLayout(byte *layout, uint numtracks, uint plat_len, const StationSpec *statspec) { - if (statspec != nullptr && statspec->lengths >= plat_len && - statspec->platforms[plat_len - 1] >= numtracks && - statspec->layouts[plat_len - 1][numtracks - 1]) { + if (statspec != nullptr && statspec->layouts.size() >= plat_len && + statspec->layouts[plat_len - 1].size() >= numtracks && + !statspec->layouts[plat_len - 1][numtracks - 1].empty()) { /* Custom layout defined, follow it. */ - memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1], + memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1].data(), plat_len * numtracks); return; } @@ -1124,9 +1124,9 @@ void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSp CreateSingle(layout, numtracks); } else { if (numtracks & 1) layout = CreateSingle(layout, plat_len); - numtracks >>= 1; + int n = numtracks >> 1; - while (--numtracks >= 0) { + while (--n >= 0) { layout = CreateMulti(layout, plat_len, 4); layout = CreateMulti(layout, plat_len, 6); } diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 01cdbc16e0..e8e9e69455 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -153,7 +153,7 @@ static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID * return CommandCost(); } -extern void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec); +extern void GetStationLayout(byte *layout, uint numtracks, uint plat_len, const StationSpec *statspec); extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp); extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis axis); From a3e49178d1d5d65e3ce91328d743d1642f324961 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 1 May 2021 20:28:23 +0100 Subject: [PATCH 078/800] Codechange: Use std::vector for NewGRF station tile sprite layouts. --- src/newgrf.cpp | 38 +++++++++++++++++++------------------- src/newgrf_station.cpp | 4 ++-- src/newgrf_station.h | 7 +++---- src/station_cmd.cpp | 4 ++-- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 9e8bbda190..a2671eff27 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1904,13 +1904,13 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte break; } - case 0x09: // Define sprite layout - statspec->tiles = buf->ReadExtendedByte(); - delete[] statspec->renderdata; // delete earlier loaded stuff - statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles]; + case 0x09: { // Define sprite layout + uint16 tiles = buf->ReadExtendedByte(); + statspec->renderdata.clear(); // delete earlier loaded stuff + statspec->renderdata.reserve(tiles); - for (uint t = 0; t < statspec->tiles; t++) { - NewGRFSpriteLayout *dts = &statspec->renderdata[t]; + for (uint t = 0; t < tiles; t++) { + NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back(); dts->consistent_max_offset = UINT16_MAX; // Spritesets are unknown, so no limit. if (buf->HasData(4) && *(uint32*)buf->Data() == 0) { @@ -1946,6 +1946,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte dts->Clone(tmp_layout.data()); } break; + } case 0x0A: { // Copy sprite layout byte srcid = buf->ReadByte(); @@ -1956,12 +1957,12 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte continue; } - delete[] statspec->renderdata; // delete earlier loaded stuff + statspec->renderdata.clear(); // delete earlier loaded stuff + statspec->renderdata.reserve(srcstatspec->renderdata.size()); - statspec->tiles = srcstatspec->tiles; - statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles]; - for (uint t = 0; t < statspec->tiles; t++) { - statspec->renderdata[t].Clone(&srcstatspec->renderdata[t]); + for (const auto &it : srcstatspec->renderdata) { + NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back(); + dts->Clone(&it); } break; } @@ -2047,18 +2048,19 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte statspec->animation.triggers = buf->ReadWord(); break; - case 0x1A: // Advanced sprite layout - statspec->tiles = buf->ReadExtendedByte(); - delete[] statspec->renderdata; // delete earlier loaded stuff - statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles]; + case 0x1A: { // Advanced sprite layout + uint16 tiles = buf->ReadExtendedByte(); + statspec->renderdata.clear(); // delete earlier loaded stuff + statspec->renderdata.reserve(tiles); - for (uint t = 0; t < statspec->tiles; t++) { - NewGRFSpriteLayout *dts = &statspec->renderdata[t]; + for (uint t = 0; t < tiles; t++) { + NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back(); uint num_building_sprites = buf->ReadByte(); /* On error, bail out immediately. Temporary GRF data was already freed */ if (ReadSpriteLayout(buf, num_building_sprites, false, GSF_STATIONS, true, false, dts)) return CIR_DISABLED; } break; + } default: ret = CIR_UNKNOWN; @@ -8370,8 +8372,6 @@ static void ResetCustomStations() if (stations[i] == nullptr) continue; StationSpec *statspec = stations[i]; - delete[] statspec->renderdata; - /* Release this station */ delete statspec; } diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 9aa3ad43be..eff5ef2b2c 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -798,10 +798,10 @@ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID const NewGRFSpriteLayout *layout = nullptr; DrawTileSprites tmp_rail_layout; - if (statspec->renderdata == nullptr) { + if (statspec->renderdata.empty()) { sprites = GetStationTileLayout(STATION_RAIL, tile + axis); } else { - layout = &statspec->renderdata[(tile < statspec->tiles) ? tile + axis : (uint)axis]; + layout = &statspec->renderdata[(tile < statspec->renderdata.size()) ? tile + axis : (uint)axis]; if (!layout->NeedsPreprocessing()) { sprites = layout; layout = nullptr; diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 4c4a5831be..5273625ae6 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -112,8 +112,8 @@ enum StationRandomTrigger { /** Station specification. */ struct StationSpec { StationSpec() : cls_id(STAT_CLASS_DFLT), name(0), - disallowed_platforms(0), disallowed_lengths(0), tiles(0), - renderdata(nullptr), cargo_threshold(0), cargo_triggers(0), + disallowed_platforms(0), disallowed_lengths(0), + cargo_threshold(0), cargo_triggers(0), callback_mask(0), flags(0), pylons(0), wires(0), blocked(0), animation({0, 0, 0, 0}) {} /** @@ -145,8 +145,7 @@ struct StationSpec { * 4-5 = platform with roof, left side * 6-7 = platform with roof, right side */ - uint tiles; - NewGRFSpriteLayout *renderdata; ///< Array of tile layouts. + std::vector renderdata; ///< Array of tile layouts. /** * Cargo threshold for choosing between little and lots of cargo diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index ac78064d49..f642a914f6 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2844,8 +2844,8 @@ static void DrawTile_Station(TileInfo *ti) } /* Ensure the chosen tile layout is valid for this custom station */ - if (statspec->renderdata != nullptr) { - layout = &statspec->renderdata[tile_layout < statspec->tiles ? tile_layout : (uint)GetRailStationAxis(ti->tile)]; + if (!statspec->renderdata.empty()) { + layout = &statspec->renderdata[tile_layout < statspec->renderdata.size() ? tile_layout : (uint)GetRailStationAxis(ti->tile)]; if (!layout->NeedsPreprocessing()) { t = layout; layout = nullptr; From 756034fa279bb6c3b81efbe13385583eb8a42d0f Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 2 May 2021 10:47:05 +0100 Subject: [PATCH 079/800] Codechange: Validate custom station platform layout tiles are permitted values only. --- src/newgrf.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index a2671eff27..3a4fe12619 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1991,6 +1991,14 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte const byte *layout = buf->ReadBytes(length * number); statspec->layouts[length - 1][number - 1].assign(layout, layout + length * number); + + /* Validate tile values are only the permitted 00, 02, 04 and 06. */ + for (auto &tile : statspec->layouts[length - 1][number - 1]) { + if ((tile & 6) != tile) { + grfmsg(1, "StationChangeInfo: Invalid tile %u in layout %ux%u", tile, length, number); + tile &= 6; + } + } } break; From 20762f9117c8dfbc5cc72771926563b4893592c0 Mon Sep 17 00:00:00 2001 From: Milek7 Date: Sun, 2 May 2021 20:10:07 +0200 Subject: [PATCH 080/800] Codechange: Acquire video buffer before taking game state lock to prevent erratic fast forward behaviour (#9140) --- src/video/video_driver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index 2f8efc4ad4..0af716f05e 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -131,13 +131,14 @@ void VideoDriver::Tick() this->fast_forward_via_key = false; } + /* Locking video buffer can block (especially with vsync enabled), do it before taking game state lock. */ + this->LockVideoBuffer(); + { /* Tell the game-thread to stop so we can have a go. */ std::lock_guard lock_wait(this->game_thread_wait_mutex); std::lock_guard lock_state(this->game_state_mutex); - this->LockVideoBuffer(); - this->DrainCommandQueue(); while (this->PollEvent()) {} From 1a1def99dc0913d8887a04b8132f308934cd57ee Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 2 May 2021 18:15:54 +0000 Subject: [PATCH 081/800] Update: Translations from eints norwegian (bokmal): 24 changes by Anolitt russian: 8 changes by Ln-Wolf dutch: 46 changes by Afoklala spanish: 43 changes by MontyMontana french: 44 changes by arikover --- src/lang/dutch.txt | 50 ++++++++++++++++++++++++++++++++--- src/lang/french.txt | 46 ++++++++++++++++++++++++++++++-- src/lang/norwegian_bokmal.txt | 26 ++++++++++++++++-- src/lang/russian.txt | 8 ++++++ src/lang/spanish.txt | 45 +++++++++++++++++++++++++++++-- 5 files changed, 165 insertions(+), 10 deletions(-) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index ae1af9673a..9e54ba3fdb 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -953,7 +953,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Maleisische Rin STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Links rijden STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Rechts rijden -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Plaatsnamen +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Plaatsnamen: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Stijl voor plaatsnamen kiezen ############ start of townname region @@ -993,6 +993,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Iedere 12 maand STR_GAME_OPTIONS_LANGUAGE :{BLACK}Taal STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Taal selecteren voor gebruikersscherm +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% voltooid) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Volledig scherm STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Vink dit vakje aan om OpenTTD in het volledige scherm te spelen @@ -1990,6 +1991,8 @@ STR_FACE_TIE :Stropdas: STR_FACE_EARRING :Oorbel: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Verander das of oorbel +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privé +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Openbaar # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Netwerkspel @@ -2046,13 +2049,15 @@ STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Vul je n STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Voer het IP-adres van de server in # Start new multiplayer server -STR_NETWORK_START_SERVER_CAPTION :{WHITE}Start nieuw multiplayerspel +STR_NETWORK_START_SERVER_CAPTION :{WHITE}Nieuw spel met meerdere spelers starten STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Spelnaam: -STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het multiplayerspelselectiemenu +STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het spelselectiemenu voor meerdere spelers STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Wachtwoord instellen STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beveilig je spel met een wachtwoord als je niet wilt dat dit algemeen toegankelijk is +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Zichtbaarheid +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Bepaalt of andere mensen je server kunnen zien in de openbare lijst STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} speler{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximumaantal spelers: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Kies het maximaal aantal toegestane spelers. Niet alle posities hoeven gebruikt te worden. @@ -2116,11 +2121,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server i STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Bedrijf is beveiligd. Voer wachtwoord in # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelerslijst +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelers online # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Meerdere spelers +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Naam +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}De naam van de server waar je speelt +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}De naam van je server bewerken +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Servernaam +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Zichtbaarheid +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Bepaalt of andere mensen je server kunnen zien in de openbare lijst +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Speler +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Naam +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Je spelernaam +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Je spelernaam bewerken +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Je spelernaam +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Beheeracties die nodig zijn voor deze client +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Beheeracties die nodig zijn voor dit bedrijf +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Meedoen met dit bedrijf +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Een bericht sturen naar deze speler +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Een bericht versturen naar alle spelers van dit bedrijf +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Een bericht sturen naar alle toeschouwers +STR_NETWORK_CLIENT_LIST_SPECTATORS :Toeschouwers +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nieuw bedrijf) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Een nieuw bedrijf maken en meedoen +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dit ben jij +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dit is de host van het spel +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Eruit schoppen +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannen +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Verwijderen +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Wachtwoord ontgrendelen +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Beheeractie +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Weet je zeker dat je de speler '{STRING}' eruit wilt schoppen? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Weet je zeker dat je de speler '{STRING}' wilt bannen? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Weet je zeker dat je het bedrijf '{COMPANY}' wilt verwijderen? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Weet je zeker dat je het wachtwoord voor bedrijf '{COMPANY}' wilt terugstellen? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Speler @@ -2165,6 +2203,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Kan serv STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kan geen verbinding maken STR_NETWORK_ERROR_TIMEOUT :{WHITE}Verbinding nr. {NUM} kostte te veel tijd STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Er is een protocolfout gedetecteerd en de verbinding werd gesloten +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Je spelernaam is nog niet ingesteld. Je stelt de naam in bovenin het venster Meerdere spelers STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}De revisie van deze client komt niet overeen met de revisie van de server STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Ongeldig wachtwoord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}De server is vol @@ -2177,6 +2216,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Het invo STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Uw computer is te traag om de server bij te houden STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Uw computer deed er te lang over om de kaart te downloaden STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Uw computer deed er te lang over om met de server te verbinden +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Je spelernaam is niet geldig ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :algemene fout @@ -2199,6 +2239,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :wachtwoord niet STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :algemene time-out STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :downloaden van de kaart duurde te lang STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :verwerken van de kaart duurde te lang +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :ongeldige clientnaam ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Mogelijk verbinding verbroken @@ -3038,6 +3079,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Waarschuwi STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fout: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatale fout: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Een fatale NewGRF-fout is ontstaan:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Er is een NewGRF-fout opgetreden:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} werkt niet met de TTDPatch-versie die is opgegeven door OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} is voor versie {STRING} van TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} is ontwikkeld voor {STRING} diff --git a/src/lang/french.txt b/src/lang/french.txt index a578ea2739..b0491a80cb 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysian Ringg STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Conduite à gauche STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Conduite à droite -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Noms des villes +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nom des villes{NBSP}: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Sélectionner la nationalité des noms des villes ############ start of townname region @@ -994,6 +994,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Tous les 12 moi STR_GAME_OPTIONS_LANGUAGE :{BLACK}Langue STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Sélectionner la langue à utiliser pour l'interface +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}{NBSP}% terminé{P "" s}) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Plein écran STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Cocher cette case pour jouer à OpenTTD en plein écran @@ -1991,6 +1992,8 @@ STR_FACE_TIE :Cravate{NBSP}: STR_FACE_EARRING :Boucle d'oreille{NBSP}: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Modifier la cravate ou la boucle d'oreille +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privé +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Public # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijoueurs @@ -2054,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Les autr STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Choisir le mot de passe STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protégez votre partie avec un mot de passe si vous ne souhaitez pas que d'autres l'utilisent +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilité +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Possibilité pour les autres personnes de vous voir dans la liste publique STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Nombre de clients maximum{NBSP}: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Choisir un nombre maximum de clients. Tous les emplacements n'auront pas besoin d'être remplis @@ -2117,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Le serve STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}La compagnie est protégée. Entrez le mot de passe # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste des clients +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Joueurs en ligne # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijoueur +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Serveur +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nom +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nom du serveur sur lequel vous jouez +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Éditer le nom de votre serveur +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nom du serveur +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilité +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Possibilité pour les autres personnes de voir votre serveur dans la liste publique +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Joueur +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nom +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Votre nom de jeu +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Éditer votre nom +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Votre nom de jeu +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Actions administratives à accomplir pour ce client +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Actions administratives à accomplir pour cette compagnie +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Rejoindre cette compagnie +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Envoyer un message à cette personne +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Envoyer un message à tous les joueurs de cette compagnie +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Envoyer un message à tous les spectateurs +STR_NETWORK_CLIENT_LIST_SPECTATORS :Spectateurs +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nouvelle compagnie) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Créer une nouvelle compagnie et la rejoindre +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}C'est vous +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}C'est l'hôte du jeu +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Exclure +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannir +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Supprimer +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Débloquer le mot de passe +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Action administrative +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Êtes-vous sûr de vouloir exclure '{STRING}'{NBSP}? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Êtes-vous sûr de vouloir bannir '{STRING}'{NBSP}? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Êtes-vous sûr de vouloir supprimer la compagnie '{COMPANY}'{NBSP}? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Êtes-vous sûr de vouloir réinitialiser le mot de passe de la compagnie '{COMPANY}'? STR_NETWORK_SERVER :Serveur STR_NETWORK_CLIENT :Client @@ -2166,6 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Le serve STR_NETWORK_ERROR_CLIENT_START :{WHITE}Échec de la connexion STR_NETWORK_ERROR_TIMEOUT :{WHITE}La connexion n°{NBSP}{NUM} a dépassé le temps d'attente STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Une erreur de protocole a été détectée et la connexion a été fermée +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Vous n'avez pas de nom. Il doit être entré en haut de la fenêtre Multijoueur STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Le numéro de version/révision de ce client ne correspond pas à celui du serveur STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Mot de passe incorrect STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Le serveur est complet @@ -2178,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Vous ave STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Votre ordinateur est trop lent pour suivre le serveur STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Votre ordinateur a mis trop de temps pour télécharger la carte STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Votre ordinateur a mis trop de temps pour rejoindre le serveur +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Votre nom n'est pas valide ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erreur générale @@ -2200,6 +2240,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :aucun mot de pa STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :délai dépassé STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :télécharger la carte a pris trop de temps STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :le traitement de la carte a pris trop de temps +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nom client invalide ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possible perte de connexion @@ -3039,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Attention{ STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erreur{NBSP}: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Erreur fatale{NBSP}: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Une erreur NewGRF fatale est survenue{NBSP}:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Une erreur NewGRF est survenue{NBSP}:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} ne fonctionnera pas avec la version de TTDPatch rapportée par OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} est conçu pour la version {STRING} de TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} est conçu pour être utilisé avec {STRING} diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index b79089f237..1cbf14fbec 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -955,7 +955,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk Ringg STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Venstrekjøring STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Høyrekjøring -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Bynavn +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Bynavn: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Velg nasjonalitet på bynavn ############ start of townname region @@ -1994,6 +1994,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Ørering: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Endre slips eller ørering +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privat STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Offentlig # Network server list @@ -2059,6 +2060,7 @@ STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Sett pas STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskytt ditt spill med et passord hvis du ikke vil at hvem som helst skal bli med på det STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Synlighet +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Om andre mennesker kan se serveren din i den offentlige oppføringen STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maks antall klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS.small :dra og slipp @@ -2123,24 +2125,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Tjeneren STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firmaet er beskyttet. Skriv inn passord # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste over klienter +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Påloggede spillere # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Flerspiller +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Navn +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Navnet på serveren du spiller på +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Rediger navnet på serveren +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Servernavn +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Synlighet STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Om andre mennesker kan se serveren din i den offentlige oppføringen STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Spiller STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Navn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ditt spillernavn STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Rediger ditt spillernavn STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ditt spillernavn STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrative handlinger å utføre for denne klienten +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrative tiltak å utføre for dette firmaet STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Bli med i dette firmaet +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send en melding til denne spilleren STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send en melding til alle spillerne i dette firmaet STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send en melding til alle tilskuerne +STR_NETWORK_CLIENT_LIST_SPECTATORS :Tilskuere +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt firma) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Opprett et nytt firma og bli med i det +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dette er deg +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dette er verten for spillet STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Spark +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Utesteng +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Slett +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Låse opp passord +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Administratorhandling +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Er du sikker på at du vil utestenge spiller '{STRING}'? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Er du sikker på at du vil utestenge spiller '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Er du sikker på at du vil slette firmaet '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Er du sikker på at du vil tilbakestille passordet til firma '{COMPANY}'? STR_NETWORK_SERVER :Tjener STR_NETWORK_CLIENT :Klient diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 1a8d94e9d1..bf9666d409 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2142,6 +2142,8 @@ STR_FACE_TIE :Галстук: STR_FACE_EARRING :Серьга: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Изменить галстук или серьгу +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Публичный +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Частный # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Сетевая игра @@ -2205,6 +2207,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Назв STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Установить пароль STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Защитите вашу игру паролем, если не хотите, чтобы к ней могли подключиться посторонние. +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Видимость +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Видимость вашего сервера в публичном списке STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" а ов} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. количество клиентов: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места должны быть заняты @@ -2271,6 +2275,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Комп STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список клиентов # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Сетевая игра +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Имя +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ваше игровое имя +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ваше игровое имя STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Действия администратора, применимые к этому клиенту STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Отключить diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 1af0a7fc4f..3ff09a3674 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit malasio STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Conducir por la izquierda STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Conducir por la derecha -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de municipios +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de municipios: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Selección del estilo del nombre de los municipios ############ start of townname region @@ -1992,6 +1992,8 @@ STR_FACE_TIE :Corbata: STR_FACE_EARRING :Pendientes: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o pendientes +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador @@ -2055,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}La parti STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Establecer contraseña STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protege tu partida con una contraseña si no quieres que sea universalmente accesible +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilidad +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Establece si otras personas pueden ver el servidor en la lista de servidores públicos STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Número máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Selecciona el número máximo de clientes. No es necesario ocupar todos los espacios @@ -2118,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduce la contraseña # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jugadores en línea # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijugador +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nombre +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nombre del servidor en el que estás jugando +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Modifica el nombre de tu servidor +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nombre del servidor +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidad +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Establece si otras personas pueden ver el servidor en la lista de servidores públicos +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nombre +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Tu nombre de jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Modifica tu nombre de jugador +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Tu nombre de jugador +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Acciones de administrador a realizar para este cliente +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Acciones de administrador a realizar para esta compañía +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Unirse a esta compañía +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Manda un mensaje a este jugador +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Manda un mensaje a todos los jugadores de esta compañía +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Manda un mensaje a todos los observadores +STR_NETWORK_CLIENT_LIST_SPECTATORS :Observadores +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva compañía) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crea una nueva companía y te une a ella +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Éste eres tú +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Éste es el servidor de la partida +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Prohibir el acceso +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Eliminar +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Eliminar contraseña +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Acción de administrador +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}¿Estás seguro de que deseas expulsar al jugador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}¿Estás seguro de que deseas prohibir el acceso al jugador '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}¿Estás seguro de que quieres eliminar la compañía '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}¿Estás seguro de que quieres eliminar la contraseña de la compañía '{COMPANY}'? STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente @@ -2167,6 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}No se ha STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pudo conectar STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se ha producido un error de protocolo y la conexión ha sido cerrada +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No se ha establecido tu nombre de jugador. El nombre se puede establecer en la parte superior de la ventana de Multijugador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo @@ -2179,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Has tard STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Su ordenador es demasiado lento para seguir la velocidad del servidor STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Su ordenador necesitó demasiado tiempo para descargar el mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Su ordenador necesitó demasiado tiempo para conectar al servidor +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Tu nombre de jugador no es válido ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :error general @@ -2201,6 +2240,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :no se ha recibi STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :tiempo agotado en general STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :la descarga del mapa ha necesitado demasiado tiempo STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :el procesado del mapa ha necesitado demasiado tiempo +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nombre de cliente inválido ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Posible pérdida de conexión @@ -3040,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atención: STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Error Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ha ocurrido un error fatal de NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ha ocurrido un error de NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionará con la con la versión de TTDPatch informada por OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} es para la versión {STRING} de TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} está diseñado para ser usado con {STRING} From ece9a356dcae3c9f7fe85a0f7dab87e06d8eb299 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 3 May 2021 15:03:25 +0100 Subject: [PATCH 082/800] Fix #9113: Assertion failure when removing airport with order backup (#9182) --- src/station_cmd.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index f642a914f6..451dedbad4 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2394,9 +2394,9 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) if (flags & DC_EXEC) { for (uint i = 0; i < st->airport.GetNumHangars(); ++i) { - DeleteWindowById( - WC_VEHICLE_DEPOT, st->airport.GetHangarTile(i) - ); + TileIndex tile_cur = st->airport.GetHangarTile(i); + OrderBackup::Reset(tile_cur, false); + DeleteWindowById(WC_VEHICLE_DEPOT, tile_cur); } const AirportSpec *as = st->airport.GetSpec(); @@ -2418,7 +2418,6 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]); if (flags & DC_EXEC) { - if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false); DeleteAnimatedTile(tile_cur); DoClearSquare(tile_cur); DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur); From 0bc6f3234664cbd71dab89ddf75b14616cced160 Mon Sep 17 00:00:00 2001 From: PeterN Date: Mon, 3 May 2021 15:12:47 +0100 Subject: [PATCH 083/800] Fix #9174: Don't update text effect if it has been reset. (#9183) --- src/texteff.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/texteff.cpp b/src/texteff.cpp index e29326a90a..1c4722ae61 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -79,6 +79,7 @@ void UpdateTextEffect(TextEffectID te_id, StringID msg) void UpdateAllTextEffectVirtCoords() { for (auto &te : _text_effects) { + if (te.string_id == INVALID_STRING_ID) continue; SetDParam(0, te.params_1); SetDParam(1, te.params_2); te.UpdatePosition(te.center, te.top, te.string_id, te.string_id - 1); From 08781d96ed385158a5b452be1779260a92204e4e Mon Sep 17 00:00:00 2001 From: PeterN Date: Mon, 3 May 2021 16:39:20 +0100 Subject: [PATCH 084/800] Fix: Query windows may be partially drawn initially. (#9184) Query window was not marked dirty after being moved on init. It was then marked dirty once the white border flash completed. --- src/misc_gui.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index b2de451404..e9ee7b193b 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -1162,12 +1162,9 @@ struct QueryWindow : public Window { this->caption = caption; this->message = message; this->proc = callback; + this->parent = parent; this->InitNested(WN_CONFIRM_POPUP_QUERY); - - this->parent = parent; - this->left = parent->left + (parent->width / 2) - (this->width / 2); - this->top = parent->top + (parent->height / 2) - (this->height / 2); } ~QueryWindow() @@ -1175,6 +1172,14 @@ struct QueryWindow : public Window { if (this->proc != nullptr) this->proc(this->parent, false); } + void FindWindowPlacementAndResize(int def_width, int def_height) override + { + /* Position query window over the calling window, ensuring it's within screen bounds. */ + this->left = Clamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width); + this->top = Clamp(parent->top + (parent->height / 2) - (this->height / 2), 0, _screen.height - this->height); + this->SetDirty(); + } + void SetStringParameters(int widget) const override { switch (widget) { From 6bd7f8816dfee1a5e697d18e30aad4b5ef7e320f Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 3 May 2021 17:40:19 +0200 Subject: [PATCH 085/800] Fix #9117, 04ce1f07: [Fluidsynth] Infinite wait when stopping song (#9181) In FluidSynth 2.2.0 an extra state was added to denote stopping. To transition from this state to a stopped state the rendering needs to be running. Since 04ce1f07 locking was added that skipped the rendering when something else held a lock, so the state would never get to stopped and join would never return. --- src/music/fluidsynth.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index 000432e1da..b5cbf46aa1 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -163,14 +163,21 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song) void MusicDriver_FluidSynth::StopSong() { - std::lock_guard lock{ _midi.synth_mutex }; + { + std::lock_guard lock{ _midi.synth_mutex }; - if (!_midi.player) return; + if (!_midi.player) return; - fluid_player_stop(_midi.player); + fluid_player_stop(_midi.player); + } + + /* The join must be run without lock as the Music rendering needs to be + * running so FluidSynth's internals can actually stop the playing. */ if (fluid_player_join(_midi.player) != FLUID_OK) { DEBUG(driver, 0, "Could not join player"); } + + std::lock_guard lock{ _midi.synth_mutex }; delete_fluid_player(_midi.player); fluid_synth_system_reset(_midi.synth); fluid_synth_all_sounds_off(_midi.synth, -1); From 8228021afea409ad41268f995ce6ab629f3cbc0d Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 3 May 2021 15:50:01 +0000 Subject: [PATCH 086/800] Update: Translations from eints norwegian (bokmal): 1 change by Anolitt spanish (mexican): 1 change by absay korean: 1 change by telk5093 russian: 48 changes by Ln-Wolf catalan: 1 change by J0anJosep portuguese: 1 change by azulcosta portuguese (brazilian): 1 change by Vimerum --- src/lang/brazilian_portuguese.txt | 1 + src/lang/catalan.txt | 1 + src/lang/korean.txt | 1 + src/lang/norwegian_bokmal.txt | 1 + src/lang/portuguese.txt | 1 + src/lang/russian.txt | 71 +++++++++++++++++++++---------- src/lang/spanish_MX.txt | 1 + 7 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 96e9fbbd1c..3cf4a64be0 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Seu comp STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Seu computador demorou demais para baixar o mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Seu computador demorou demais para entrar no servidor STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Seu nome de jogador não é válido +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}O servidor requisitado é muito antigo para esse cliente ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 34b6cfb0b4..bc89f55f40 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}El teu o STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}El teu ordinador ha tardat massa a descarregar el mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}El teu ordinador ha tardat massa a unir-se al servidor STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}El vostre nom de jugador no és vàlid. +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}El servidor és massa antic per a aquest client. ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :error general diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 2a51f3dfcc..78a46e95eb 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}사용 STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}지도 다운로드 시간을 초과하였습니다 STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}서버 접속 시간을 초과하였습니다 STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}사용할 수 없는 이름입니다 +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}검색한 서버는 현재 버전에 비해 너무 오래된 서버입니다 ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :일반 오류 diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 1cbf14fbec..882605dcea 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -2221,6 +2221,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Din data STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Din datamaskin brukte for lang tid på å laste ned kartet STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Din datamaskin brukte for lang tid på å koble til tjeneren STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Spillernavnet ditt er ugyldig +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Den forespurte serveren er for gammel for denne klienten ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :generell feil diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index d97e52569a..4473b1cb39 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}O seu co STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}O seu computador demorou demasiado a transferir o mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}O seu computador demorou demasiado a ligar ao servidor STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}O seu nome de jogador não é válido +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}O servidor consultado é muito antigo para este cliente ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral diff --git a/src/lang/russian.txt b/src/lang/russian.txt index bf9666d409..337d79ce9c 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -390,7 +390,7 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}Если STR_BUTTON_DEFAULT :{BLACK}По умолчанию STR_BUTTON_CANCEL :{BLACK}Отмена STR_BUTTON_OK :{BLACK}OK -STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть ваш пароль. +STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть текст, введённый в это поле. # On screen keyboard window STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ . @@ -924,7 +924,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Отоб STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Показать последнее сообщение или новость STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * ПАУЗА * * -STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * ПАУЗА (ожидает обновления графы ссылок) * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * ПАУЗА (ожидает обновления графа распределения) * * STR_STATUSBAR_AUTOSAVE :{RED}АВТОСОХРАНЕНИЕ STR_STATUSBAR_SAVING_GAME :{RED}* * СОХРАНЕНИЕ ИГРЫ * * @@ -2162,7 +2162,7 @@ STR_NETWORK_SERVER_LIST_DATE_CAPTION :{BLACK}Дата STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP :{BLACK}Текущая дата STR_NETWORK_SERVER_LIST_YEARS_CAPTION :{BLACK}Года STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP :{BLACK}Количество лет{}в игре -STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и т.п. +STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и{NBSP}т.{NBSP}п. STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT :{BLACK}Выберите игру из списка STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER :{BLACK}Последний сервер, к которому вы подключались: @@ -2177,20 +2177,20 @@ STR_NETWORK_SERVER_LIST_SERVER_VERSION :{SILVER}Вер STR_NETWORK_SERVER_LIST_SERVER_ADDRESS :{SILVER}Адрес сервера: {WHITE}{STRING} STR_NETWORK_SERVER_LIST_START_DATE :{SILVER}Дата начала: {WHITE}{DATE_SHORT} STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Текущая дата: {WHITE}{DATE_SHORT} -STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищено паролем! -STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЕН +STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищён паролем! +STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЁН STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}СЕРВЕР ЗАПОЛНЕН STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ВЕРСИЯ НЕ ПОДХОДИТ STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}НЕ СОВПАДАЕТ НАБОР NEWGRF STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Присоединиться -STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Обновить сервер +STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Обновить информацию STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Обновить информацию о сервере STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Искать в интернете -STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK} Искать в Интернете общедоступные серверы -STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Искать LAN -STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK} Поиск серверов в локальной сети +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Поиск общедоступных серверов в интернете +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Искать в ЛВС +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Поиск серверов в локальной сети STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Добавить сервер STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Добавить сервер в список, который будет автоматически проверяться на идущие игры STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Запуск сервера @@ -2211,13 +2211,13 @@ STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Види STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Видимость вашего сервера в публичном списке STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" а ов} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. количество клиентов: -STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места должны быть заняты +STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места обязательно должны быть заняты. STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} компани{P я и й} STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Макс. количество компаний: STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ограничить максимальное количество компаний на сервере -STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} наблюдател{P ь я ей} -STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество наблюдателей: -STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество наблюдателей на сервере +STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} зрител{P ь я ей} +STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество зрителей: +STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество зрителей на сервере STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Язык общения: STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Другие игроки будут знать, на каком языке общаются на сервере @@ -2227,7 +2227,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE :{BLACK}Введ STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Состояние сетевой игры STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Подготовка соединения: {ORANGE}{STRING} -STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к существующей или основать новую, если есть свободный слот +STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к одной из существующих или основать новую, если есть свободная позиция. STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}ИНФОРМАЦИЯ О КОМПАНИИ STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Название компании: {WHITE}{STRING} @@ -2272,25 +2272,48 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Серв STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Компания защищена. Введите пароль. # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список клиентов +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список игроков # Network client list STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Сетевая игра +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Сервер +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Название +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Название вашего сервера +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Сменить название сервера +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Название сервера +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Видимость +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Видимость вашего сервера в публичном списке +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Игрок STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Имя STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ваше игровое имя +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Изменить имя игрока STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ваше игровое имя -STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Действия администратора, применимые к этому клиенту +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Административные действия, применимые к этому игроку +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Административные действия, применимые к этой компании +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Присоединиться к этой компании +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Отправить сообщение этому игроку +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Послать сообщение всем игрокам этой компании +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Послать сообщение всем зрителям +STR_NETWORK_CLIENT_LIST_SPECTATORS :Зрители +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Новая компания) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Основать новую транспортную компанию и присоединиться к ней +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Это вы! +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Это организатор игры STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Отключить STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Заблокировать +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Удалить +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Сбросить пароль STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Подтверждение действия STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Отключить игрока «{STRING}»? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Заблокировать игрока «{STRING}»? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Удалить компанию «{COMPANY}»? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Сбросить пароль у компании «{COMPANY}»? STR_NETWORK_SERVER :Сервер STR_NETWORK_CLIENT :Клиент -STR_NETWORK_SPECTATORS :Наблюдатели +STR_NETWORK_SPECTATORS :Зрители # Network set password STR_COMPANY_PASSWORD_CANCEL :{BLACK}Не сохранять пароль @@ -2335,8 +2358,8 @@ STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Не у STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Версия этого клиента не совместима с версией сервера STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неверный пароль STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен -STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере -STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры +STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас заблокировали на этом сервере +STR_NETWORK_ERROR_KICKED :{WHITE}Вас отключили от игры STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING} STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд @@ -2345,6 +2368,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Ваш STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Ваш компьютер тратит много времени на загрузку карты STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Ваш компьютер тратит много времени на подключение к серверу STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Неверно указано имя игрока +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}На сервере запущена устаревшая версия игры ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :общая ошибка @@ -2387,13 +2411,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :количес STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :подключение клиентов STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :вручную STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :игровой скрипт -STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графы ссылок +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графа распределения ############ End of leave-in-this-order -STR_NETWORK_MESSAGE_CLIENT_LEAVING :покинул +STR_NETWORK_MESSAGE_CLIENT_LEAVING :отключение STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} подключился к игре STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} подключился к игре (клиент #{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} подключился к компании #{2:NUM} -STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился наблюдателем +STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился в качестве зрителя STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} основал новую компанию (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} покинул игру ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} изменил имя на {STRING} @@ -3231,6 +3255,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Внима STR_NEWGRF_ERROR_MSG_ERROR :{RED}Ошибка: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Критическая ошибка: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ошибка при работе с NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ошибка, связанная с модулем NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} не будет работать с версией TTDPatch, сообщенной OpenTTD. STR_NEWGRF_ERROR_DOS_OR_WINDOWS :Файл {1:STRING} требует {STRING}-версию TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} сделан для использования совместно с {STRING} @@ -5344,7 +5369,7 @@ STR_DEFAULT_SIGN_NAME :Табличк STR_COMPANY_SOMEONE :кто-то STR_SAVEGAME_NAME_DEFAULT :{COMPANY}, {STRING} -STR_SAVEGAME_NAME_SPECTATOR :Наблюдатель, {1:STRING} +STR_SAVEGAME_NAME_SPECTATOR :Зритель, {1:STRING} # Viewport strings STR_VIEWPORT_TOWN_POP :{WHITE}{TOWN} ({COMMA}) diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 08d5bdea6b..6cae2f782f 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tu compu STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Tu computadora tardó demasiado en descargar el mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Tu computadora tardó demasiado en conectarse al servidor STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Tu nombre de jugador no es válido +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}El servidor es demasiado viejo para este cliente ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :error general From ba409e8c4502cc435d0d3f4bec7ba5f5fe28b658 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 21:25:52 +0200 Subject: [PATCH 087/800] Add: [Network] Writing std::string to a packet --- src/network/core/packet.cpp | 9 ++++----- src/network/core/packet.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 644490e0fb..6f56e4a567 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -178,12 +178,11 @@ void Packet::Send_uint64(uint64 data) * the string + '\0'. No size-byte or something. * @param data The string to send */ -void Packet::Send_string(const char *data) +void Packet::Send_string(const std::string_view data) { - assert(data != nullptr); - /* Length of the string + 1 for the '\0' termination. */ - assert(this->CanWriteToPacket(strlen(data) + 1)); - while (this->buffer.emplace_back(*data++) != '\0') {} + assert(this->CanWriteToPacket(data.size() + 1)); + this->buffer.insert(this->buffer.end(), data.begin(), data.end()); + this->buffer.emplace_back('\0'); } /** diff --git a/src/network/core/packet.h b/src/network/core/packet.h index bc7bab6c4f..0f58d3be84 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -71,7 +71,7 @@ public: void Send_uint16(uint16 data); void Send_uint32(uint32 data); void Send_uint64(uint64 data); - void Send_string(const char *data); + void Send_string(const std::string_view data); size_t Send_bytes (const byte *begin, const byte *end); /* Reading/receiving of packets */ From 7bcc472f73c774163285f71c235852ba0911e88e Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 08:43:11 +0200 Subject: [PATCH 088/800] Add: [Network] Reading std::string from a packet --- src/network/core/packet.cpp | 29 +++++++++++++++++++++++++++++ src/network/core/packet.h | 1 + 2 files changed, 30 insertions(+) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 6f56e4a567..7369707910 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -396,6 +396,35 @@ void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings set str_validate(bufp, last, settings); } +/** + * Reads characters (bytes) from the packet until it finds a '\0', or reaches a + * maximum of \c length characters. + * When the '\0' has not been reached in the first \c length read characters, + * more characters are read from the packet until '\0' has been reached. However, + * these characters will not end up in the returned string. + * The length of the returned string will be at most \c length - 1 characters. + * @param length The maximum length of the string including '\0'. + * @param settings The string validation settings. + * @return The validated string. + */ +std::string Packet::Recv_string(size_t length, StringValidationSettings settings) +{ + assert(length > 1); + + /* Both loops with Recv_uint8 terminate when reading past the end of the + * packet as Recv_uint8 then closes the connection and returns 0. */ + std::string str; + char character; + while (--length > 0 && (character = this->Recv_uint8()) != '\0') str.push_back(character); + + if (length == 0) { + /* The string in the packet was longer. Read until the termination. */ + while (this->Recv_uint8() != '\0') {} + } + + return str_validate(str, settings); +} + /** * Get the amount of bytes that are still available for the Transfer functions. * @return The number of bytes that still have to be transfered. diff --git a/src/network/core/packet.h b/src/network/core/packet.h index 0f58d3be84..21a88e3ea9 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -88,6 +88,7 @@ public: uint32 Recv_uint32(); uint64 Recv_uint64(); void Recv_string(char *buffer, size_t size, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); + std::string Recv_string(size_t length, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); size_t RemainingBytesToTransfer() const; From 34215f7faa2de08d767b4f6945443a8f3175acbf Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 30 Apr 2021 01:13:50 +0200 Subject: [PATCH 089/800] Codechange: Replace FOR_ALL_TARS with range-based for loops --- src/fileio.cpp | 9 ++++----- src/game/game_text.cpp | 11 +++++------ src/script/script_scanner.cpp | 9 ++++----- src/tar_type.h | 2 -- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index f2a2b14f3a..651fddff90 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1345,12 +1345,12 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s * @param extension the extension of files to search for. * @param tar the tar to search in. */ -static uint ScanTar(FileScanner *fs, const char *extension, TarFileList::iterator tar) +static uint ScanTar(FileScanner *fs, const char *extension, const TarFileList::value_type &tar) { uint num = 0; - const auto &filename = (*tar).first; + const auto &filename = tar.first; - if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, 0, (*tar).second.tar_filename)) num++; + if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, 0, tar.second.tar_filename)) num++; return num; } @@ -1369,7 +1369,6 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r this->subdir = sd; Searchpath sp; - TarFileList::iterator tar; uint num = 0; FOR_ALL_SEARCHPATHS(sp) { @@ -1381,7 +1380,7 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r } if (tars && sd != NO_DIRECTORY) { - FOR_ALL_TARS(tar, sd) { + for (const auto &tar : _tar_filelist[sd]) { num += ScanTar(this, extension, tar); } } diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 24f41c93ac..ce20c1ee70 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -249,16 +249,15 @@ GameStrings *LoadTranslations() if (!tar_filename.empty() && (iter = _tar_list[GAME_DIR].find(tar_filename)) != _tar_list[GAME_DIR].end()) { /* The main script is in a tar file, so find all files that * are in the same tar and add them to the langfile scanner. */ - TarFileList::iterator tar; - FOR_ALL_TARS(tar, GAME_DIR) { + for (const auto &tar : _tar_filelist[GAME_DIR]) { /* Not in the same tar. */ - if (tar->second.tar_filename != iter->first) continue; + if (tar.second.tar_filename != iter->first) continue; /* Check the path and extension. */ - if (tar->first.size() <= ldir.size() || tar->first.compare(0, ldir.size(), ldir) != 0) continue; - if (tar->first.compare(tar->first.size() - 4, 4, ".txt") != 0) continue; + if (tar.first.size() <= ldir.size() || tar.first.compare(0, ldir.size(), ldir) != 0) continue; + if (tar.first.compare(tar.first.size() - 4, 4, ".txt") != 0) continue; - scanner.AddFile(tar->first, 0, tar_filename); + scanner.AddFile(tar.first, 0, tar_filename); } } else { /* Scan filesystem */ diff --git a/src/script/script_scanner.cpp b/src/script/script_scanner.cpp index 8b48809bf7..bdde99f6c3 100644 --- a/src/script/script_scanner.cpp +++ b/src/script/script_scanner.cpp @@ -224,16 +224,15 @@ static bool IsSameScript(const ContentInfo *ci, bool md5sum, ScriptInfo *info, S if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) { /* The main script is in a tar file, so find all files that * are in the same tar and add them to the MD5 checksumming. */ - TarFileList::iterator tar; - FOR_ALL_TARS(tar, dir) { + for (const auto &tar : _tar_filelist[dir]) { /* Not in the same tar. */ - if (tar->second.tar_filename != iter->first) continue; + if (tar.second.tar_filename != iter->first) continue; /* Check the extension. */ - const char *ext = strrchr(tar->first.c_str(), '.'); + const char *ext = strrchr(tar.first.c_str(), '.'); if (ext == nullptr || strcasecmp(ext, ".nut") != 0) continue; - checksum.AddFile(tar->first, 0, tar_filename); + checksum.AddFile(tar.first, 0, tar_filename); } } else { char path[MAX_PATH]; diff --git a/src/tar_type.h b/src/tar_type.h index c4e72df851..4266f23623 100644 --- a/src/tar_type.h +++ b/src/tar_type.h @@ -28,6 +28,4 @@ typedef std::map TarFileList; extern std::array _tar_list; extern TarFileList _tar_filelist[NUM_SUBDIRS]; -#define FOR_ALL_TARS(tar, sd) for (tar = _tar_filelist[sd].begin(); tar != _tar_filelist[sd].end(); tar++) - #endif /* TAR_TYPE_H */ From 983c7ade60f82a49d8c23c1f295add1fd9a913b0 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 30 Apr 2021 15:41:58 +0200 Subject: [PATCH 090/800] Codechange: Replace FOR_ALL_SEARCHPATHS with range-based for loops --- src/fileio.cpp | 29 +++++++++++++++++------------ src/fileio_func.h | 12 ++---------- src/fios.cpp | 3 +-- src/script/script_instance.cpp | 3 +-- src/strings.cpp | 4 +--- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 651fddff90..810f3f34ef 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -241,6 +241,7 @@ static_assert(lengthof(_subdirs) == NUM_SUBDIRS); * current operating system. */ std::array _searchpaths; +std::vector _valid_searchpaths; std::array _tar_list; TarFileList _tar_filelist[NUM_SUBDIRS]; @@ -252,11 +253,19 @@ static TarLinkList _tar_linklist[NUM_SUBDIRS]; ///< List of directory links * @param sp the search path to check * @return true if the search path is valid */ -bool IsValidSearchPath(Searchpath sp) +static bool IsValidSearchPath(Searchpath sp) { return sp < _searchpaths.size() && !_searchpaths[sp].empty(); } +static void FillValidSearchPaths() +{ + _valid_searchpaths.clear(); + for (Searchpath sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) { + if (IsValidSearchPath(sp)) _valid_searchpaths.emplace_back(sp); + } +} + /** * Check whether the given file exists * @param filename the file to try for existence. @@ -298,10 +307,9 @@ void FioFCloseFile(FILE *f) */ std::string FioFindFullPath(Subdirectory subdir, const char *filename) { - Searchpath sp; assert(subdir < NUM_SUBDIRS); - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { std::string buf = FioGetDirectory(sp, subdir); buf += filename; if (FileExists(buf)) return buf; @@ -326,10 +334,8 @@ std::string FioGetDirectory(Searchpath sp, Subdirectory subdir) std::string FioFindDirectory(Subdirectory subdir) { - Searchpath sp; - /* Find and return the first valid directory */ - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { std::string ret = FioGetDirectory(sp, subdir); if (FileExists(ret)) return ret; } @@ -406,11 +412,10 @@ FILE *FioFOpenFileTar(const TarFileListEntry &entry, size_t *filesize) FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize) { FILE *f = nullptr; - Searchpath sp; assert(subdir < NUM_SUBDIRS || subdir == NO_DIRECTORY); - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { f = FioFOpenFileSp(filename, mode, sp, subdir, filesize); if (f != nullptr || subdir == NO_DIRECTORY) break; } @@ -1130,6 +1135,7 @@ std::string _personal_dir; void DeterminePaths(const char *exe) { DetermineBasePaths(exe); + FillValidSearchPaths(); #ifdef USE_XDG std::string config_home; @@ -1148,8 +1154,7 @@ void DeterminePaths(const char *exe) AppendPathSeparator(config_home); #endif - Searchpath sp; - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; DEBUG(misc, 4, "%s added as search path", _searchpaths[sp].c_str()); } @@ -1222,6 +1227,7 @@ void DeterminePaths(const char *exe) /* If we have network we make a directory for the autodownloading of content */ _searchpaths[SP_AUTODOWNLOAD_DIR] = _personal_dir + "content_download" PATHSEP; FioCreateDirectory(_searchpaths[SP_AUTODOWNLOAD_DIR]); + FillValidSearchPaths(); /* Create the directory for each of the types of content */ const Subdirectory dirs[] = { SCENARIO_DIR, HEIGHTMAP_DIR, BASESET_DIR, NEWGRF_DIR, AI_DIR, AI_LIBRARY_DIR, GAME_DIR, GAME_LIBRARY_DIR }; @@ -1368,10 +1374,9 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r { this->subdir = sd; - Searchpath sp; uint num = 0; - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { /* Don't search in the working directory */ if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; diff --git a/src/fileio_func.h b/src/fileio_func.h index 1428356506..4b9b2dd9ee 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -13,6 +13,7 @@ #include "core/enum_type.hpp" #include "fileio_type.h" #include +#include void FioSeekTo(size_t pos, int mode); void FioSeekToFile(uint8 slot, size_t pos); @@ -26,16 +27,6 @@ void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir); void FioReadBlock(void *ptr, size_t size); void FioSkipBytes(int n); -/** - * Checks whether the given search path is a valid search path - * @param sp the search path to check - * @return true if the search path is valid - */ -bool IsValidSearchPath(Searchpath sp); - -/** Iterator for all the search paths */ -#define FOR_ALL_SEARCHPATHS(sp) for (sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) if (IsValidSearchPath(sp)) - void FioFCloseFile(FILE *f); FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); bool FioCheckFileExists(const std::string &filename, Subdirectory subdir); @@ -54,6 +45,7 @@ bool FileExists(const std::string &filename); bool ExtractTar(const std::string &tar_filename, Subdirectory subdir); extern std::string _personal_dir; ///< custom directory for personal settings, saves, newgrf, etc. +extern std::vector _valid_searchpaths; /** Helper for scanning for files with a given name */ class FileScanner { diff --git a/src/fios.cpp b/src/fios.cpp index 8528e8c622..3b11bcbe02 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -582,8 +582,7 @@ static FiosType FiosGetHeightmapListCallback(SaveLoadOperation fop, const std::s * collections of NewGRFs or 32 bpp graphics replacement PNGs. */ bool match = false; - Searchpath sp; - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { std::string buf = FioGetDirectory(sp, HEIGHTMAP_DIR); if (buf.compare(0, buf.size(), it->second.tar_filename, 0, buf.size()) == 0) { diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index f7f9de4fc8..fadbba70dd 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -116,8 +116,7 @@ bool ScriptInstance::LoadCompatibilityScripts(const char *api_version, Subdirect { char script_name[32]; seprintf(script_name, lastof(script_name), "compat_%s.nut", api_version); - Searchpath sp; - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { std::string buf = FioGetDirectory(sp, dir); buf += script_name; if (!FileExists(buf)) continue; diff --git a/src/strings.cpp b/src/strings.cpp index e340a2b1c4..0489714590 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1949,9 +1949,7 @@ static void GetLanguageList(const char *path) */ void InitializeLanguagePacks() { - Searchpath sp; - - FOR_ALL_SEARCHPATHS(sp) { + for (Searchpath sp : _valid_searchpaths) { std::string path = FioGetDirectory(sp, LANG_DIR); GetLanguageList(path.c_str()); } From 2feb801e56f5f36121bcc44d04cb46937987c490 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 30 Apr 2021 17:01:26 +0200 Subject: [PATCH 091/800] Codechange: Replace FOR_ALL_ROADTRAMTYPES with range-based for loops --- src/road.h | 2 +- src/road_cmd.cpp | 6 +++--- src/saveload/afterload.cpp | 2 +- src/saveload/company_sl.cpp | 6 +++--- src/station_cmd.cpp | 6 +++--- src/tunnelbridge_cmd.cpp | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/road.h b/src/road.h index becbf40512..6a2af6698f 100644 --- a/src/road.h +++ b/src/road.h @@ -32,7 +32,7 @@ enum RoadTramTypes : uint8 { }; DECLARE_ENUM_AS_BIT_SET(RoadTramTypes) -#define FOR_ALL_ROADTRAMTYPES(x) for (RoadTramType x : { RTT_ROAD, RTT_TRAM }) +static const RoadTramType _roadtramtypes[] = { RTT_ROAD, RTT_TRAM }; /** Roadtype flags. Starts with RO instead of R because R is used for rails */ enum RoadTypeFlags { diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 830f9dd4fc..82e944f6e6 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1238,7 +1238,7 @@ static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlag flags) /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */ if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !(flags & DC_AUTO)) { CommandCost ret(EXPENSES_CONSTRUCTION); - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue; CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true); @@ -2203,7 +2203,7 @@ static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owne Company::Get(new_owner)->infrastructure.road[rt] += 2; SetTileOwner(tile, new_owner); - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { if (GetRoadOwner(tile, rtt) == old_owner) { SetRoadOwner(tile, rtt, new_owner); } @@ -2213,7 +2213,7 @@ static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owne return; } - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rtt) == old_owner) { RoadType rt = GetRoadType(tile, rtt); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 56680511cb..7fd2204943 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1855,7 +1855,7 @@ bool AfterLoadGame() } } else if (IsTileType(t, MP_ROAD)) { /* works for all RoadTileType */ - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { /* update even non-existing road types to update tile owner too */ Owner o = GetRoadOwner(t, rtt); if (o < MAX_COMPANIES && !Company::IsValidID(o)) SetRoadOwner(t, rtt, OWNER_NONE); diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index fb2742a186..5770f9791e 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -128,7 +128,7 @@ void AfterLoadCompanyStats() } /* Iterate all present road types as each can have a different owner. */ - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt)); @@ -151,7 +151,7 @@ void AfterLoadCompanyStats() case STATION_BUS: case STATION_TRUCK: { /* Iterate all present road types as each can have a different owner. */ - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(GetRoadOwner(tile, rtt)); @@ -209,7 +209,7 @@ void AfterLoadCompanyStats() case TRANSPORT_ROAD: { /* Iterate all present road types as each can have a different owner. */ - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(GetRoadOwner(tile, rtt)); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 451dedbad4..39efb710e6 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2029,7 +2029,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags) } /* Update company infrastructure counts. */ - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { RoadType rt = GetRoadType(tile, rtt); UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), -static_cast(ROAD_STOP_TRACKBIT_FACTOR)); } @@ -2110,7 +2110,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui RoadType road_type[] = { INVALID_ROADTYPE, INVALID_ROADTYPE }; Owner road_owner[] = { OWNER_NONE, OWNER_NONE }; if (IsDriveThroughStopTile(cur_tile)) { - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { road_type[rtt] = GetRoadType(cur_tile, rtt); if (road_type[rtt] == INVALID_ROADTYPE) continue; road_owner[rtt] = GetRoadOwner(cur_tile, rtt); @@ -4178,7 +4178,7 @@ void DeleteOilRig(TileIndex tile) static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner) { if (IsRoadStopTile(tile)) { - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rtt) == old_owner) { RoadType rt = GetRoadType(tile, rtt); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 2f76dbcef9..dd8d731ee9 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1811,7 +1811,7 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner * don't want to update the infrastructure counts twice. */ uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0; - FOR_ALL_ROADTRAMTYPES(rtt) { + for (RoadTramType rtt : _roadtramtypes) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rtt) == old_owner) { RoadType rt = GetRoadType(tile, rtt); From 176d65b47240be9be0fece2c56019f66cf4b8692 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Tue, 4 May 2021 07:28:01 -0400 Subject: [PATCH 092/800] Change: Use gender-neutral pronouns in english.txt (#9189) --- src/lang/english.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index f8e3618e51..f0ac1df382 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2269,7 +2269,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {RAW_STRING STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {RAW_STRING} has joined spectators STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {RAW_STRING} has started a new company (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {RAW_STRING} has left the game ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {RAW_STRING} has changed his/her name to {RAW_STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {RAW_STRING} has changed their name to {RAW_STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {RAW_STRING} gave {2:CURRENCY_LONG} to {1:RAW_STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}The server closed the session STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}The server is restarting...{}Please wait... From fa206bf2e3fb7869af7797be008d7b35704d8177 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 4 May 2021 18:58:09 +0000 Subject: [PATCH 093/800] Update: Translations from eints english (us): 1 change by 2TallTyler estonian: 49 changes by siimsoni korean: 1 change by telk5093 hungarian: 45 changes by baliball finnish: 12 changes by hpiirai spanish: 1 change by JohnBoyFan --- src/lang/english_US.txt | 1 + src/lang/estonian.txt | 50 ++++++++++++++++++++++++++++++++++++++++- src/lang/finnish.txt | 23 ++++++++++--------- src/lang/hungarian.txt | 47 ++++++++++++++++++++++++++++++++++++-- src/lang/korean.txt | 2 +- src/lang/spanish.txt | 1 + 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index dd81df78e3..14ad4e9aae 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -2217,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your com STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Your computer took too long to download the map STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Your computer took too long to join the server STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your player name is not valid +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}The queried server is too old for this client ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :general error diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index d4b7d94dbe..c9acfd0e7d 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -1050,6 +1050,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :12 kuud STR_GAME_OPTIONS_LANGUAGE :{BLACK}Keel STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Valib kasutajaliideses kasutatava keele +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% valmis) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Täisekraan STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Märgi see kast, et OpenTTD täisekraanirežiimis mängida @@ -1063,6 +1064,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Riistvar STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Märkides selle ruudu, lubad OpenTTD-l üritada kasutada riistvarakiirendust. Muudetud seade omab mõju pärast mängu taaskäivitust STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Seade omab mõju alles pärast mängu taaskäivitust +STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync +STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Märgi, et ekraani v-sync sisse lülitada. Seade kohaldub alles pärast mängu taaskäivitust. Töötab vaid, kui riistvarakiirendus on peal STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Liidese suurus STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Vali kasutatav liideseelementide suurus @@ -1196,6 +1199,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Seaded STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Märksõna: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Ava kõik STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Sulge kõik +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Nulli kõik väärtused STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(seletus puudub) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Vaikeväärtus: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Seade liik: {ORANGE}{STRING} @@ -1204,6 +1208,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Mängu seade (s STR_CONFIG_SETTING_TYPE_GAME_INGAME :Mängu seaded (hoitakse salvestuses; mõjutab ainult praegust mängu) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Ettevõtte seaded (hoitakse salvestuses; mõjutab ainult uusi mänge) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Ettevõtte seaded (hoitakse salvestuses; mõjutab ainult praegust ettevõtet) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Ettevaatust! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}See toiming nullib kõik mänguseaded.{}Oled sa kindel, et jätkata? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Jagu: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Liik: @@ -2042,6 +2048,8 @@ STR_FACE_TIE :Lips: STR_FACE_EARRING :Kõrvarõngas: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Vaheta kraed või kõrvarõngast +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privaatne +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Avalik # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Mitmikmäng @@ -2105,6 +2113,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Serveril STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Määra salasõna STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Et server ei oleks avalik, kaitse oma mäng salasõnaga +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Nähtavus +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Kas sinu server on kõikidele teistele avalikult nähtav STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Kliente kuni: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS.in :sees @@ -2169,11 +2179,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server o STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Ettevõte on kaitstud. Sisesta salasõna # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klientide nimekiri +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Ühendatud mängijad # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Mitmikmäng +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nimi +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Serveri nimi, kus sa mängid +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Muuda oma serveri nime +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Serveri nimi +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Nähtavus +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Kas sinu server on kõikidele teistele avalikult nähtav +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Mängija +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nimi +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Sinu mängija nimi +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Muuda oma mängija nime +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Sinu mängija nimi +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Haldustegevused, mida teha selle ettevõtte peal +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Haldustegevused, mida teha selle ettevõtte peal +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Liitu selle ettevõttega +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Saada sellele mängijale sõnum +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Saada sõnum igale selle ettevõtte mängijale +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Saada sõnum igale vaatlejale +STR_NETWORK_CLIENT_LIST_SPECTATORS :Vaatlejad +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Uus ettevõte) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Loo uus ettevõte ja liitu sellega +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tema oled sina +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Tema on mängu korraldaja +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Viska välja +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Keela +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Kustuta +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Salasõnaga avamine +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Haldustoiming +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Kas oled kindel, et välja visata mängija '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Kas oled kindel, et sa tahad keelata mängija '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Kas oled kindel, et tahad kustutada ettevõtte '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Kas oled kindel, et soovid nullida ettevõtte '{COMPANY}' salasõna? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient @@ -2218,6 +2261,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Ei saa u STR_NETWORK_ERROR_CLIENT_START :{WHITE}Ei õnnestu ühendada STR_NETWORK_ERROR_TIMEOUT :{WHITE}Ühendus nr {NUM} aegus STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Tekkis protokolliviga ja ühendus katkes +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Sinu mängijale ei ole nime määratud. Nime saab määrata mitmikmägu akna ülaosas STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Kliendi osa ei vasta serveri osaga STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Vale salasõna STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Server on täis @@ -2230,6 +2274,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Sisestas STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Arvutil võttis liitumisega liiga kaua aega STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Kaardi allalaadimine võttis liiga kaua aega STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Serveriga liitumine võttis liiga kaua aega +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Sinu mängija nimi ei vasta nõuetele +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Päritud server kasutab liiga vana versiooni ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :üldine viga @@ -2252,6 +2298,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :ei saanud õige STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :üldine aegumine STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :kaardi laadimine võttis liiga kaua aega STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :kaardi töötlemine võttis liiga kaua aega +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :kliendinimi ei vasta nõuetele ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Võimalik ühenduse katkemine @@ -3091,6 +3138,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Hoiatus: { STR_NEWGRF_ERROR_MSG_ERROR :{RED}Viga: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Saatuslik viga: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Esines raske NewGRF-i tõrge:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Esines viga NewGRF-iga:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :OpenTTD väitel {1:STRING} ei tööta selle TTDPatch versiooniga. STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} on {STRING} TTD osa jaoks. STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} on mõeldud kasutamiseks {STRING} diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 4435cca260..8f1b82c784 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1170,9 +1170,9 @@ STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :Pelin asetukset STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Pelin asetukset (tallennetaan pelitallenteeseen; vaikuttavat vain nykyiseen peliin) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Yhtiön asetukset (tallennetaan pelitallenteisiin; vaikuttavat vain uusiin peleihin) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Yhtiön asetukset (tallennetaan pelitallenteeseen; vaikuttavat ainoastaan nykyiseen yhtiöön) -STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Näytä kaikki tulokset muuttamalla{}{SILVER}Kategoriaksi {WHITE}{STRING} +STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Näytä kaikki tulokset muuttamalla{}{SILVER}kategoriaksi {WHITE}{STRING} STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}Näytä kaikki hakutulokset muuttamalla{}{SILVER}Tyypiksi {WHITE}Kaikki asetustyypit -STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Näytä kaikki tulokset muuttamalla{}{SILVER}Kategoriaksi {WHITE}{STRING} {BLACK}ja {SILVER}Tyypiksi {WHITE}Kaikki asetustyypit +STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Näytä kaikki tulokset muuttamalla{}{SILVER}kategoriaksi {WHITE}{STRING} {BLACK}ja {SILVER}tyypiksi {WHITE}kaikki asetustyypit STR_CONFIG_SETTINGS_NONE :{WHITE}- Ei mitään - STR_CONFIG_SETTING_OFF :pois @@ -1334,7 +1334,7 @@ STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Suhteellinen ik STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE :{COMMA} kuukau{P 0 si tta} ennen kulkuneuvon käyttöiän loppua STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :{COMMA} kuukau{P 0 si tta} jälkeen kulkuneuvon käyttöiän lopun STR_CONFIG_SETTING_AUTORENEW_MONEY :Vähimmäisrahamäärä kulkuneuvon automaattiseen uudistukseen: {STRING} -STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Pienin rahamäärä, joka on oltava pankissa ennen kulkuneuvojen automaattista uudistamista +STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Vähimmäisrahamäärä, jonka on jäätävä pankkiin kulkuneuvoja automaattisesti uudistettaessa STR_CONFIG_SETTING_ERRMSG_DURATION :Virheilmoitusten näyttöaika: {STRING} STR_CONFIG_SETTING_ERRMSG_DURATION_HELPTEXT :Aika virheilmoitusten näyttämiseen punaisessa ikkunassa. Huomaa, että jotkut (kriittiset) virheilmoitukset eivät sulkeudu automaattisesti tämän ajan jälkeen, vaan ne on suljettava käsin STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE :{COMMA} sekunti{P 0 "" a} @@ -1458,7 +1458,7 @@ STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Mikäli käytö STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Salli pelin ollessa pysäytettynä: {STRING} STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Valitse käytössä olevat toiminnot pelin ollessa pysäytettynä STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Ei mitään toimintoja -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Kaikki ei-rakennustoiminnot +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Kaikki paitsi rakennustoiminnot STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Kaikki paitsi maastonmuokkaustoiminnot STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Kaikki toiminnot STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Käytä ryhmiä kulkuneuvolistassa: {STRING} @@ -1595,7 +1595,7 @@ STR_CONFIG_SETTING_NEWS_MESSAGES_SUMMARY :Tiivistelmä STR_CONFIG_SETTING_NEWS_MESSAGES_FULL :Täysi STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Värilliset uutiset ilmestyvät: {STRING} -STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Vuosi, jonka jälkeen sanomalehdet ovat värillisiä. Ennen tätä vuotta sanomalehdet käyttävät mustavalkoisia kuvia +STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Vuosi, josta alkaen sanomalehdet painetaan värillisinä. Ennen tätä vuotta lehdet ovat mustavalkoiset. STR_CONFIG_SETTING_STARTING_YEAR :Aloitusvuosi: {STRING} STR_CONFIG_SETTING_ENDING_YEAR :Pistelaskun päättymisvuosi: {STRING} STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Pelin päättymisvuosi pisteiden laskemista varten. Tämän vuoden lopussa talletetaan yhtiön pistemäärä ja näytetään ennätysluettelo; pelaajat voivat jatkaa pelaamista tämän jälkeenkin.{}Jos päättymisvuosi on ennen alkamisvuotta, ennätyksiä ei näytetä koskaan. @@ -1771,7 +1771,7 @@ STR_CONFIG_SETTING_INTERFACE :{ORANGE}Käytt STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}Yleinen STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Näkymät STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Rakentaminen -STR_CONFIG_SETTING_ADVISORS :{ORANGE}Uutiset / Neuvonantajat +STR_CONFIG_SETTING_ADVISORS :{ORANGE}Uutiset ja neuvonantajat STR_CONFIG_SETTING_COMPANY :{ORANGE}Yhtiö STR_CONFIG_SETTING_ACCOUNTING :{ORANGE}Talous STR_CONFIG_SETTING_VEHICLES :{ORANGE}Kulkuneuvot @@ -1876,7 +1876,7 @@ STR_QUIT_NO :{BLACK}Ei # Abandon game STR_ABANDON_GAME_CAPTION :{WHITE}Pelin lopetus STR_ABANDON_GAME_QUERY :{YELLOW}Lopetetaanko peli? -STR_ABANDON_SCENARIO_QUERY :{YELLOW}Lopetetaanko skenaario? +STR_ABANDON_SCENARIO_QUERY :{YELLOW}Haluatko varmasti hylätä tämän skenaarion? # Cheat window STR_CHEATS :{WHITE}Huijaukset @@ -2207,7 +2207,7 @@ STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Et ole a STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Tämän asiakkaan versio ei vastaa palvelimen versiota STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Väärä salasana STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Palvelin on täynnä -STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Sinut on kielletty palvelimelta +STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Sinut on estetty palvelimelta STR_NETWORK_ERROR_KICKED :{WHITE}Sinut potkittiin pihalle palvelimelta STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Syy: {STRING} STR_NETWORK_ERROR_CHEATER :{WHITE}Huijaaminen ei ole sallittua tällä palvelimella @@ -2217,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tietokon STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Kartan lataus kesti liian kauan STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Palvelimelle liittyminen kesti liian kauan STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Pelaajanimesi ei kelpaa +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Kysytty palvelin on liian vanha tälle asiakkaalle ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :yleinen virhe @@ -2800,7 +2801,7 @@ STR_LAI_OBJECT_DESCRIPTION_COMPANY_OWNED_LAND :Yhtiön omistam STR_ABOUT_OPENTTD :{WHITE}Tietoja OpenTTD:stä STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Alkuperäiset oikeudet {COPYRIGHT} 1995 Chris Sawyer, kaikki oikeudet pidätetään STR_ABOUT_VERSION :{BLACK}OpenTTD-versio {REV} -STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-{STRING} The OpenTTD team +STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002–{STRING} The OpenTTD team # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}Kuvataajuus @@ -3502,8 +3503,8 @@ STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Tarvitse STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} odottamassa{STRING} -STR_CONFIG_GAME_PRODUCTION :{WHITE}Muokkaa tuotantoa (8:n kerroin, 2040 asti) -STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Muuta tuotantotasoa (prosentteina, 800{NBSP}% asti) +STR_CONFIG_GAME_PRODUCTION :{WHITE}Muokkaa tuotantoa (8:n kerroin, 2040:een asti) +STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Muuta tuotantotasoa (prosentteina, 800{NBSP}%:iin asti) # Vehicle lists STR_VEHICLE_LIST_TRAIN_CAPTION :{WHITE}{STRING} – {COMMA} juna{P "" a} diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 5aa64101a3..b34b36e94a 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -1017,7 +1017,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Maláj ringgit STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Balra hajtás STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Jobbra hajtás -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Városnevek +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Városnevek: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}A városnevek stílusának kiválasztása ############ start of townname region @@ -1057,6 +1057,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :12 havonta STR_GAME_OPTIONS_LANGUAGE :{BLACK}Nyelv STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Válassz nyelvet +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% teljesítve) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Teljes képernyő STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Jelöld be ezt, ha teljes képernyős módban szeretnél játszani az OpenTTD-vel @@ -2054,6 +2055,8 @@ STR_FACE_TIE :Nyakkendő: STR_FACE_EARRING :Fülbevaló: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Nyakkendő vagy fülbevaló cseréje +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privát +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Nyilvános # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Hálózati játék @@ -2117,6 +2120,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}A játé STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Jelszó beállítása STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Védd le a játékodat jelszóval, ha nem akarod hogy illetéktelenek csatlakozzanak +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Láthatóság +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Mások láthassák-e a szerveredet a publikus listában STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} kliens STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Játékosok max. száma: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}A maximálisan felcsatlakozható kliensek számának kiválasztása. Nem szükséges pont ennyi embernek éppen kapcsolódva lennie @@ -2180,11 +2185,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}A szerve STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}A vállalat jelszóval van védve. Írd be # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Kliens lista +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online játékosok # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Többjátékos +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Szerver +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Név +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}A szerver neve amin játszol +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}A szervered nevének szerkesztése +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Szerver neve +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Láthatóság +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Mások láthassák-e a szerveredet a publikus listában +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Játékos +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Név +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}A játékos neved +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}A játékos neved szerkesztése +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Játékos neve +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Adminisztrátori műveletek ehhez a vállalathoz +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Adminisztrátori műveletek ehhez a vállalathoz +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :Csatlakozz ehhez a vállalathoz +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Üzenet küldése ennek a játékosnak +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Üzenet küldése az összes játékosnak ebben a vállalatban +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Üzenet küldése az összes megfigyelőnek +STR_NETWORK_CLIENT_LIST_SPECTATORS :Megfigyelők +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Új vállalat) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Hozz létre egy új vállalatot és csatlakozz +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Ez vagy te +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Ez a játék elindítója +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kirúgás +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Tiltás +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Törlés +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Jelszó feloldása +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Adminisztrátori művelet +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Biztos ki akarod rúgni ezt a játékost: '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Biztos ki akarod tiltani ezt a játékost: '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Biztos ki akarod törölni a '{COMPANY}' vállalatot? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Biztos vissza akarod állítani a '{COMPANY}' vállalat jelszavát? STR_NETWORK_SERVER :Szerver STR_NETWORK_CLIENT :Kliens @@ -2229,6 +2267,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Nem tudt STR_NETWORK_ERROR_CLIENT_START :{WHITE}Nem tudtam kapcsolódni STR_NETWORK_ERROR_TIMEOUT :{WHITE}A(z) {NUM}. játékos kapcsolata elveszett STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Protokoll-hiba keletkezett és megszakadt a kapcsolat +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}A játékos neved nem lett megadva. A nevet a többjátékos ablak tetején tudod beállítani. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A gépeden és a szerveren lévő programnak nem egyezik meg a verziója STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Rossz jelszó STR_NETWORK_ERROR_SERVER_FULL :{WHITE}A szerver tele van @@ -2241,6 +2280,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Túl sok STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}A számítógéped túl lassú, hogy tartsa a szerver sebességét STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Túl sokáig tartott a térkép letöltése a számítógépednek STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Túl sokáig tartott a szerverhez való csatlakozása a számítógépednek +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}A játékos neved nem megfelelő +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}A lekérdezett szerver túl régi ehhez a klienshez ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :általános hiba @@ -2263,6 +2304,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :nem érkezett j STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :általános időtúllépés STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :térkép letöltés túl sokáig tartott STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :térkép feldolgozás túl sokáig tartott +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :Érvénytelen kliens név ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Lehetséges, hogy elveszett a kapcsolat @@ -3102,6 +3144,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Figyelmezt STR_NEWGRF_ERROR_MSG_ERROR :{RED}Hiba: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Végzetes hiba: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Egy végzetes NewGRF hiba történt:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF hiba történt:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} nem fog működni az OpenTTD által jelentett TTDPatch verzióval STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} a TTD {STRING} verziójához van STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} úgy lett tervezve, hogy együtt lesz használva ezzel: {STRING} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 78a46e95eb..6bf90700c5 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -397,7 +397,7 @@ STR_SETTINGS_MENU_SIGNS_DISPLAYED :팻말을 표 STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :경쟁사의 팻말과 역 이름을 표시 STR_SETTINGS_MENU_FULL_ANIMATION :완전한 애니메이션 STR_SETTINGS_MENU_FULL_DETAIL :그래픽을 아주 상세하게 -STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS :건물 숨기기 +STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS :건물 감추기 STR_SETTINGS_MENU_TRANSPARENT_SIGNS :역명판 감추기 ############ range ends here diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 3ff09a3674..e891400928 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Su orden STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Su ordenador necesitó demasiado tiempo para descargar el mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Su ordenador necesitó demasiado tiempo para conectar al servidor STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Tu nombre de jugador no es válido +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}El servidor es demasiado antiguo para este cliente. ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :error general From a432009f06321009ee1c480ec4034f5faffde75c Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 4 May 2021 20:50:52 +0200 Subject: [PATCH 094/800] Cleanup: [Fluidsynth] Comply better with the coding style --- src/music/fluidsynth.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index b5cbf46aa1..061ade3456 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -18,9 +18,9 @@ #include static struct { - fluid_settings_t* settings; ///< FluidSynth settings handle - fluid_synth_t* synth; ///< FluidSynth synthesizer handle - fluid_player_t* player; ///< FluidSynth MIDI player handle + fluid_settings_t *settings; ///< FluidSynth settings handle + fluid_synth_t *synth; ///< FluidSynth synthesizer handle + fluid_player_t *player; ///< FluidSynth MIDI player handle std::mutex synth_mutex; ///< Guard mutex for synth access } _midi; ///< Metadata about the midi we're playing. @@ -54,7 +54,7 @@ static void RenderMusicStream(int16 *buffer, size_t samples) { std::unique_lock lock{ _midi.synth_mutex, std::try_to_lock }; - if (!lock.owns_lock() || !_midi.synth || !_midi.player) return; + if (!lock.owns_lock() || _midi.synth == nullptr || _midi.player == nullptr) return; fluid_synth_write_s16(_midi.synth, samples, buffer, 0, 2, buffer, 1, 2); } @@ -69,7 +69,7 @@ const char *MusicDriver_FluidSynth::Start(const StringList ¶m) /* Create the settings. */ _midi.settings = new_fluid_settings(); - if (!_midi.settings) return "Could not create midi settings"; + if (_midi.settings == nullptr) return "Could not create midi settings"; /* Don't try to lock sample data in memory, OTTD usually does not run with privileges allowing that */ fluid_settings_setint(_midi.settings, "synth.lock-memory", 0); @@ -80,11 +80,11 @@ const char *MusicDriver_FluidSynth::Start(const StringList ¶m) /* Create the synthesizer. */ _midi.synth = new_fluid_synth(_midi.settings); - if (!_midi.synth) return "Could not open synth"; + if (_midi.synth == nullptr) return "Could not open synth"; /* Load a SoundFont and reset presets (so that new instruments * get used from the SoundFont) */ - if (!sfont_name) { + if (sfont_name == nullptr) { sfont_id = FLUID_FAILED; /* Try loading the default soundfont registered with FluidSynth. */ @@ -142,7 +142,7 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song) std::lock_guard lock{ _midi.synth_mutex }; _midi.player = new_fluid_player(_midi.synth); - if (!_midi.player) { + if (_midi.player == nullptr) { DEBUG(driver, 0, "Could not create midi player"); return; } @@ -166,7 +166,7 @@ void MusicDriver_FluidSynth::StopSong() { std::lock_guard lock{ _midi.synth_mutex }; - if (!_midi.player) return; + if (_midi.player == nullptr) return; fluid_player_stop(_midi.player); } @@ -187,7 +187,7 @@ void MusicDriver_FluidSynth::StopSong() bool MusicDriver_FluidSynth::IsSongPlaying() { std::lock_guard lock{ _midi.synth_mutex }; - if (!_midi.player) return false; + if (_midi.player == nullptr) return false; return fluid_player_get_status(_midi.player) == FLUID_PLAYER_PLAYING; } From 605bd246746b0d6b47e54bbdb1f2a96b782fb371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Wed, 5 May 2021 16:32:41 +0200 Subject: [PATCH 095/800] Cleanup: Leftover static const variable from a3b356e (#9194) --- src/newgrf_config.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index d7919e32ae..a4ec52f0f8 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -835,9 +835,6 @@ char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last) return dst; } -/** Base GRF ID for OpenTTD's base graphics GRFs. */ -static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400); - /** * Search a textfile file next to this NewGRF. * @param type The type of the textfile to search for. From 24e7cb494738a8e0117dbd8c4a148a9ee532e129 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 5 May 2021 18:58:22 +0000 Subject: [PATCH 096/800] Update: Translations from eints english (us): 1 change by 2TallTyler russian: 1 change by Ln-Wolf finnish: 4 changes by hpiirai --- src/lang/english_US.txt | 2 +- src/lang/finnish.txt | 8 ++++---- src/lang/russian.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 14ad4e9aae..4aebf0230f 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -2269,7 +2269,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} ha STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} has joined spectators STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} has started a new company (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} has left the game ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} has changed his/her name to {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} has changed their name to {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} gave {2:CURRENCY_LONG} to {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}The server closed the session STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}The server is restarting...{}Please wait... diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 8f1b82c784..b8a219fb5e 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1711,13 +1711,13 @@ STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manuaalinen STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :epäsymmetrinen STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :symmetrinen STR_CONFIG_SETTING_DISTRIBUTION_PAX :Matkustajien jakautuminen: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :"symmetrinen" tarkoittaa, että suunnilleen sama määrä matkustajia kulkee asemalta A asemalle B kuin asemalta B asemalle A. "epäsymmetrinen" tarkoittaa, että eri suuntiin voi kulkea eriävä määrä matkustajia. "manuaalinen" tarkoittaa, että automaattinen rahdin jakautuminen on pois käytöstä matkustajilla. +STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :”Symmetrinen” tarkoittaa, että suunnilleen sama määrä matkustajia kulkee asemalta A asemalle B kuin asemalta B asemalle A. ”Epäsymmetrinen” tarkoittaa, että eri suuntiin voi kulkea eriävä määrä matkustajia. ”Manuaalinen” tarkoittaa, että automaattinen rahdin jakautuminen on pois käytöstä matkustajilla. STR_CONFIG_SETTING_DISTRIBUTION_MAIL :Postin jakautuminen: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :"symmetrinen" tarkoittaa, että suunnilleen sama määrä postia lähetetään asemalta A asemalle B kuin asemalta B asemalle A. "epäsymmetrinen" tarkoittaa, että eri suuntiin voidaan lähettää eriävä määrä postia. "manuaalinen" tarkoittaa, että automaattinen rahdin jakautuminen on pois käytöstä postilla. +STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :”Symmetrinen” tarkoittaa, että suunnilleen sama määrä postia lähetetään asemalta A asemalle B kuin asemalta B asemalle A. ”Epäsymmetrinen” tarkoittaa, että eri suuntiin voidaan lähettää eriävä määrä postia. ”Manuaalinen” tarkoittaa, että automaattinen rahdin jakautuminen on pois käytöstä postilla. STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :Arvokuljetusten jakautuminen: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Arvokuljetuksiin kuuluvat arvotavarat lauhkeassa ilmastossa, timantit subtrooppisessa ilmastossa ja kulta pohjoisessa ilmastossa. NewGRF:t voivat kuitenkin muuttaa näitä rahteja. "symmetrinen" tarkoittaa, että suunnilleen sama määrä rahtia lähetetään asemalta A asemalle B kuin asemalta B asemalle A. "epäsymmetrinen" tarkoittaa, että eri suuntiin voidaan lähettää eriävä määrä rahtia. "manuaalinen" tarkoittaa, että automaattinen rahdin jakautuminen on poistettu käytöstä rahdilta. Suositeltavia asetuksia ovat "epäsymmetrinen" tai "manuaalinen" pelattaessa pohjoisessa ilmastossa, sillä pankit eivät lähetä kultaa takaisin kaivoksille. Lauhkeassa ja subtrooppisessa ilmastossa pelatessa voidaan myös valita "symmetrinen", sillä pankit lähettävät arvotavaroita takaisin alkuperäiselle pankille. +STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Arvokuljetuksiin kuuluvat arvotavarat lauhkeassa ilmastossa, timantit subtrooppisessa ilmastossa ja kulta pohjoisessa ilmastossa. NewGRF:t voivat kuitenkin muuttaa näitä rahteja. ”Symmetrinen” tarkoittaa, että suunnilleen sama määrä rahtia lähetetään asemalta A asemalle B kuin asemalta B asemalle A. ”Epäsymmetrinen” tarkoittaa, että eri suuntiin voidaan lähettää eriävä määrä rahtia. ”Manuaalinen” tarkoittaa, että automaattinen rahdin jakautuminen on poistettu käytöstä rahdilta. Suositeltavia asetuksia ovat ”epäsymmetrinen” tai ”manuaalinen” pelattaessa pohjoisessa ilmastossa, sillä pankit eivät lähetä kultaa takaisin kaivoksille. Lauhkeassa ja subtrooppisessa ilmastossa pelatessa voidaan myös valita ”symmetrinen”, sillä pankit lähettävät arvotavaroita takaisin alkuperäiselle pankille. STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Muiden rahtityyppien jakautuminen: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"epäsymmetrinen" tarkoittaa, että eri suuntiin voidaan lähettää eriäviä määriä rahtia. "manuaalinen" tarkoittaa, että automaattinen jakautuminen ei ole käytössä rahdille. +STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :”Epäsymmetrinen” tarkoittaa, että eri suuntiin voidaan lähettää eriäviä määriä rahtia. ”Manuaalinen” tarkoittaa, että automaattinen jakautuminen ei ole käytössä rahdille. STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Jakautumisen tarkkuus: {STRING} STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Mitä suuremmaksi tämä asetus on määritetty, sitä enemmän prosessoriaikaa yhteyskuvaajan laskemiseen kuluu. Mikäli tähän kuluu liian paljon aikaa, saatat havaita pelin nykimistä. Jos arvo on määritetty liian pieneksi, jakauman laskeminen ei ole tarkka ja rahtia ei välttämättä lähetetä odotetuille asemille. STR_CONFIG_SETTING_DEMAND_DISTANCE :Välimatkan vaikutus kysyntään: {STRING} diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 337d79ce9c..49828c53e5 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2420,7 +2420,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} п STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился в качестве зрителя STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} основал новую компанию (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} покинул игру ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} изменил имя на {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} сменил(а) имя на {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** Компания «{STRING}» передала «{STRING}» {CURRENCY_LONG} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Сервер закрыл сессию STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Сервер перезапускается...{}Пожалуйста, подождите... From 72bd62fd705c495d90f08adc964ff8d7f84c6cc1 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 5 May 2021 19:15:37 +0200 Subject: [PATCH 097/800] Codechange: [Network] Use a single NetworkServerGameInfo object at server side and serialize that for the clients --- src/network/core/game_info.cpp | 48 +++++++++++++++++----------------- src/network/core/game_info.h | 30 ++++++++++----------- src/network/network_gui.cpp | 2 +- src/network/network_server.cpp | 5 +--- src/network/network_udp.cpp | 5 +--- 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index 55b5d1749a..e5e85105e3 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -122,30 +122,30 @@ void CheckGameCompatibility(NetworkGameInfo &ngi) } /** - * Fill a NetworkGameInfo structure with the latest information of the server. - * @param ngi the NetworkGameInfo struct to fill with data. + * Get the NetworkServerGameInfo structure with the latest information of the server. + * @return The current NetworkServerGameInfo. */ -void FillNetworkGameInfo(NetworkGameInfo &ngi) +const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo() { - /* Update some game_info */ - ngi.clients_on = _network_game_info.clients_on; - ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); + _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; - ngi.use_password = !StrEmpty(_settings_client.network.server_password); - ngi.clients_max = _settings_client.network.max_clients; - ngi.companies_on = (byte)Company::GetNumItems(); - ngi.companies_max = _settings_client.network.max_companies; - ngi.spectators_on = NetworkSpectatorCount(); - ngi.spectators_max = _settings_client.network.max_spectators; - ngi.game_date = _date; - ngi.map_width = MapSizeX(); - ngi.map_height = MapSizeY(); - ngi.map_set = _settings_game.game_creation.landscape; - ngi.dedicated = _network_dedicated; - ngi.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)); - strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name)); - strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision)); + /* 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; } /** @@ -179,7 +179,7 @@ static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) * @param p the packet to write the data to. * @param info the NetworkGameInfo struct to serialize from. */ -void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info) +void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info) { p->Send_uint8 (NETWORK_GAME_INFO_VERSION); @@ -232,7 +232,7 @@ void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info) p->Send_string(""); // Used to be map-name. p->Send_uint16(info->map_width); p->Send_uint16(info->map_height); - p->Send_uint8 (info->map_set); + p->Send_uint8 (info->landscape); p->Send_bool (info->dedicated); } @@ -302,10 +302,10 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) while (p->Recv_uint8() != 0) {} // Used to contain the map-name. info->map_width = p->Recv_uint16(); info->map_height = p->Recv_uint16(); - info->map_set = p->Recv_uint8 (); + info->landscape = p->Recv_uint8 (); info->dedicated = p->Recv_bool (); - if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0; + if (info->landscape >= NETWORK_NUM_LANDSCAPES) info->landscape = 0; } } diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index 324c6ea4aa..10f922f318 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -57,17 +57,9 @@ */ /** - * The game information that is not generated on-the-fly and has to - * be sent to the clients. + * The game information that is sent from the server to the client. */ struct NetworkServerGameInfo { - byte clients_on; ///< Current count of clients on server -}; - -/** - * The game information that is sent from the server to the clients. - */ -struct NetworkGameInfo : NetworkServerGameInfo { GRFConfig *grfconfig; ///< List of NewGRF files used Date start_date; ///< When the game started Date game_date; ///< Current date @@ -76,16 +68,24 @@ struct NetworkGameInfo : NetworkServerGameInfo { char server_name[NETWORK_NAME_LENGTH]; ///< Server name char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) bool dedicated; ///< Is this a dedicated server? - 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 bool use_password; ///< Is this server passworded? - byte game_info_version; ///< Version of the game info + byte clients_on; ///< Current count of clients on server byte clients_max; ///< Max clients allowed on server byte companies_on; ///< How many started companies do we have byte companies_max; ///< Max companies allowed on server byte spectators_on; ///< How many spectators do we have? byte spectators_max; ///< Max spectators allowed on server - byte map_set; ///< Graphical set + byte landscape; ///< The used landscape +}; + +/** + * The game information that is sent from the server to the clients + * with extra information only required at the client side. + */ +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; @@ -94,12 +94,12 @@ const char *GetNetworkRevisionString(); bool IsNetworkCompatibleVersion(const char *other); void CheckGameCompatibility(NetworkGameInfo &ngi); -void FillNetworkGameInfo(NetworkGameInfo &ngi); +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 NetworkGameInfo *info); +void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info); #endif /* NETWORK_CORE_GAME_INFO_H */ diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index b2feacc955..ac86b868c6 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -633,7 +633,7 @@ public: DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS); y += FONT_HEIGHT_NORMAL; - SetDParam(0, STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE + sel->info.map_set); + SetDParam(0, STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE + sel->info.landscape); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_LANDSCAPE); // landscape y += FONT_HEIGHT_NORMAL; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index fd69a8d37a..905290bfc5 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -356,11 +356,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientIn /** Send the client information about the server. */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfo() { - NetworkGameInfo ngi; - FillNetworkGameInfo(ngi); - Packet *p = new Packet(PACKET_SERVER_GAME_INFO); - SerializeNetworkGameInfo(p, &ngi); + SerializeNetworkGameInfo(p, GetCurrentNetworkServerGameInfo()); this->SendPacket(p); diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index bb71e5ceaa..de69e4a9af 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -170,11 +170,8 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ return; } - NetworkGameInfo ngi; - FillNetworkGameInfo(ngi); - Packet packet(PACKET_UDP_SERVER_RESPONSE); - SerializeNetworkGameInfo(&packet, &ngi); + SerializeNetworkGameInfo(&packet, GetCurrentNetworkServerGameInfo()); /* Let the client know that we are here */ this->SendPacket(&packet, client_addr); From e7581fd42d9740ca68adfc2ec55edb49d51af237 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 5 May 2021 19:21:12 +0200 Subject: [PATCH 098/800] 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. --- src/network/core/game_info.cpp | 13 ++++++++++--- src/network/core/game_info.h | 1 + src/network/network.cpp | 1 + src/network/network_func.h | 1 + src/network/network_server.cpp | 6 ++++++ src/openttd.cpp | 29 +++++++++++++++++++---------- src/settings.cpp | 2 ++ src/table/settings.ini | 2 ++ 8 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index e5e85105e3..9f4d23b3b4 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -122,10 +122,10 @@ void CheckGameCompatibility(NetworkGameInfo &ngi) } /** - * 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); @@ -140,7 +140,14 @@ const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo() 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(); diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index 10f922f318..7c84d7b154 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -94,6 +94,7 @@ const char *GetNetworkRevisionString(); bool IsNetworkCompatibleVersion(const char *other); void CheckGameCompatibility(NetworkGameInfo &ngi); +void FillStaticNetworkServerGameInfo(); const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo(); void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf); diff --git a/src/network/network.cpp b/src/network/network.cpp index c00a3650fb..4708151865 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -805,6 +805,7 @@ static void NetworkInitGameInfo() 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; diff --git a/src/network/network_func.h b/src/network/network_func.h index 5f3e27c12f..ba26e06c09 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -68,6 +68,7 @@ void NetworkServerDailyLoop(); void NetworkServerMonthlyLoop(); void NetworkServerYearlyLoop(); void NetworkServerSendConfigUpdate(); +void NetworkServerUpdateGameInfo(); void NetworkServerShowStatusToConsole(); bool NetworkServerStart(); void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 905290bfc5..1a9ddecfbc 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1992,6 +1992,12 @@ void NetworkServerSendConfigUpdate() } } +/** 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. diff --git a/src/openttd.cpp b/src/openttd.cpp index 234e3a4197..d4c7da6e4c 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -832,15 +832,30 @@ void HandleExitGameRequest() } } +/** + * 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; } @@ -858,9 +873,7 @@ static void MakeNewGameDone() _company_colours[c->index] = (Colours)c->colour; } - IConsoleCmdExec("exec scripts/game_start.scr 0"); - - SetLocalCompany(COMPANY_FIRST); + OnStartGame(false); InitializeRailGUI(); InitializeRoadGUI(); @@ -1032,11 +1045,7 @@ void SwitchToMode(SwitchMode new_mode) /* 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); } diff --git a/src/settings.cpp b/src/settings.cpp index c5819297fc..c0b0dd8edd 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1416,6 +1416,7 @@ static bool UpdateServerPassword(int32 p1) _settings_client.network.server_password[0] = '\0'; } + NetworkServerUpdateGameInfo(); return true; } @@ -1430,6 +1431,7 @@ static bool UpdateRconPassword(int32 p1) static bool UpdateClientConfigValues(int32 p1) { + NetworkServerUpdateGameInfo(); if (_network_server) NetworkServerSendConfigUpdate(); return true; diff --git a/src/table/settings.ini b/src/table/settings.ini index 4e64bd0326..d12f58236d 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3962,6 +3962,7 @@ 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] @@ -4029,6 +4030,7 @@ guiflags = SGF_NETWORK_ONLY def = 25 min = 2 max = MAX_CLIENTS +proc = UpdateClientConfigValues cat = SC_BASIC [SDTC_VAR] From ead30dc725c60cac8bc13c86d18b179dac684bec Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 5 May 2021 20:38:18 +0200 Subject: [PATCH 099/800] Cleanup: [Network] Remove variable from NetworkGameInfo that is only used during deserialisation --- src/network/core/game_info.cpp | 6 +++--- src/network/core/game_info.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index 9f4d23b3b4..47e6f221ef 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -252,7 +252,7 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) { static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11 - info->game_info_version = p->Recv_uint8(); + byte game_info_version = p->Recv_uint8(); /* * Please observe the order. @@ -262,7 +262,7 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) /* Update the documentation in game_info.h on changes * to the NetworkGameInfo wire-protocol! */ - switch (info->game_info_version) { + switch (game_info_version) { case 4: { GRFConfig **dst = &info->grfconfig; uint i; @@ -302,7 +302,7 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) info->clients_max = p->Recv_uint8 (); info->clients_on = p->Recv_uint8 (); info->spectators_on = p->Recv_uint8 (); - if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier + if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; } diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index 7c84d7b154..ef83e4d053 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -85,7 +85,6 @@ 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; From f94fb9377910c63fc8e1ea0ede1d96603e4d8862 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 5 May 2021 23:21:14 +0200 Subject: [PATCH 100/800] Codechange: use connection_string in favour of NetworkAddress (#9197) We now resolve the connection_string to a NetworkAddress in a much later state. This means there are fewer places constructing a NetworkAddress. The main benefit of this is in later PRs that introduce different types of NetworkAddresses. Storing this in things like NetworkGameList is rather complex, especially as NetworkAddress has to be mutable at all times. Additionally, the NetworkAddress is a complex object to store simple information: how to connect to this server. --- src/network/core/tcp.h | 2 +- src/network/core/tcp_connect.cpp | 10 +++-- src/network/core/tcp_http.cpp | 4 +- src/network/core/tcp_http.h | 16 +++---- src/network/network.cpp | 75 +++++++++++++++----------------- src/network/network_client.cpp | 4 +- src/network/network_client.h | 12 ++--- src/network/network_content.cpp | 7 ++- src/network/network_gamelist.cpp | 13 +++--- src/network/network_gamelist.h | 14 +++--- src/network/network_gui.cpp | 21 ++++----- src/network/network_internal.h | 4 +- src/network/network_udp.cpp | 24 +++++----- src/network/network_udp.h | 2 +- 14 files changed, 101 insertions(+), 107 deletions(-) diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index ffa231497e..5acf9d12e6 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -77,7 +77,7 @@ protected: NetworkAddress address; public: - TCPConnecter(const NetworkAddress &address); + TCPConnecter(const std::string &connection_string, uint16 default_port); /** Silence the warnings */ virtual ~TCPConnecter() {} diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index b4485cfe96..81c4d8c264 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -13,6 +13,7 @@ #include "../../thread.h" #include "tcp.h" +#include "../network_internal.h" #include "../../safeguards.h" @@ -21,15 +22,16 @@ static std::vector _tcp_connecters; /** * Create a new connecter for the given address - * @param address the (un)resolved address to connect to + * @param connection_string the address to connect to */ -TCPConnecter::TCPConnecter(const NetworkAddress &address) : +TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port) : connected(false), aborted(false), killed(false), - sock(INVALID_SOCKET), - address(address) + sock(INVALID_SOCKET) { + this->address = ParseConnectionString(connection_string, default_port); + _tcp_connecters.push_back(this); if (!StartNewThread(nullptr, "ottd:tcp", &TCPConnecter::ThreadEntry, this)) { this->Connect(); diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index 4f29df1912..3b7579fcea 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -203,11 +203,9 @@ int NetworkHTTPSocketHandler::HandleHeader() *url = '\0'; - NetworkAddress address = ParseConnectionString(hname, 80); - /* Restore the URL. */ *url = '/'; - new NetworkHTTPContentConnecter(address, callback, url, data, depth); + new NetworkHTTPContentConnecter(hname, callback, url, data, depth); return 0; } diff --git a/src/network/core/tcp_http.h b/src/network/core/tcp_http.h index 1a1edaf87a..cc9a3adac2 100644 --- a/src/network/core/tcp_http.h +++ b/src/network/core/tcp_http.h @@ -81,16 +81,14 @@ class NetworkHTTPContentConnecter : TCPConnecter { public: /** * Start the connecting. - * @param address the address to connect to - * @param callback the callback for HTTP retrieval - * @param url the url at the server - * @param data the data to send - * @param depth the depth (redirect recursion) of the queries + * @param connection_string The address to connect to. + * @param callback The callback for HTTP retrieval. + * @param url The url at the server. + * @param data The data to send. + * @param depth The depth (redirect recursion) of the queries. */ - NetworkHTTPContentConnecter(const NetworkAddress &address, - HTTPCallback *callback, const char *url, - const char *data = nullptr, int depth = 0) : - TCPConnecter(address), + NetworkHTTPContentConnecter(const std::string &connection_string, HTTPCallback *callback, const char *url, const char *data = nullptr, int depth = 0) : + TCPConnecter(connection_string, 80), callback(callback), url(stredup(url)), data(data), diff --git a/src/network/network.cpp b/src/network/network.cpp index 4708151865..98b49e81fe 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -515,7 +515,7 @@ NetworkAddress ParseConnectionString(const std::string &connection_string, int d * @param default_port The default port to set port to if not in connection_string. * @return A valid NetworkAddress of the parsed information. */ -NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port) +static NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port) { char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string)); @@ -524,7 +524,20 @@ NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string & const char *company_s = nullptr; ParseFullConnectionString(&company_s, &port_s, internal_connection_string); - if (company_s != nullptr) *company = (CompanyID)atoi(company_s); + if (company_s != nullptr) { + uint company_value = atoi(company_s); + + if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) { + if (company_value > MAX_COMPANIES || company_value == 0) { + *company = COMPANY_SPECTATOR; + } else { + /* "#1" means the first company, which has index 0. */ + *company = (CompanyID)(company_value - 1); + } + } else { + *company = (CompanyID)company_value; + } + } int port = port_s != nullptr ? atoi(port_s) : default_port; return NetworkAddress(internal_connection_string, port); @@ -607,9 +620,10 @@ static void NetworkInitialize(bool close_admins = true) class TCPQueryConnecter : TCPConnecter { private: bool request_company_info; + std::string connection_string; public: - TCPQueryConnecter(const NetworkAddress &address, bool request_company_info) : TCPConnecter(address), request_company_info(request_company_info) {} + TCPQueryConnecter(const std::string &connection_string, bool request_company_info) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), request_company_info(request_company_info), connection_string(connection_string) {} void OnFailure() override { @@ -619,24 +633,24 @@ public: void OnConnect(SOCKET s) override { _networking = true; - new ClientNetworkGameSocketHandler(s, address); + new ClientNetworkGameSocketHandler(s, this->connection_string); MyClient::SendInformationQuery(request_company_info); } }; /** * Query a server to fetch his game-info. - * @param address the address to query. + * @param connection_string the address to query. * @param request_company_info Whether to request company info too. */ -void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info) +void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info) { if (!_network_available) return; NetworkDisconnect(); NetworkInitialize(); - new TCPQueryConnecter(address, request_company_info); + new TCPQueryConnecter(connection_string, request_company_info); } /** @@ -650,20 +664,18 @@ NetworkGameList *NetworkAddServer(const std::string &connection_string) { if (connection_string.empty()) return nullptr; - NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT); - /* Ensure the item already exists in the list */ - NetworkGameList *item = NetworkGameListAddItem(address); + NetworkGameList *item = NetworkGameListAddItem(connection_string); if (StrEmpty(item->info.server_name)) { ClearGRFConfigList(&item->info.grfconfig); - address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name)); + strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name)); item->manually = true; NetworkRebuildHostList(); UpdateNetworkGameWindow(); } - NetworkTCPQueryServer(address); + NetworkTCPQueryServer(connection_string); return item; } @@ -693,14 +705,17 @@ void NetworkRebuildHostList() _network_host_list.clear(); for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) { - if (item->manually) _network_host_list.emplace_back(item->address.GetAddressAsString(false)); + if (item->manually) _network_host_list.emplace_back(item->connection_string); } } /** Non blocking connection create to actually connect to servers */ class TCPClientConnecter : TCPConnecter { +private: + std::string connection_string; + public: - TCPClientConnecter(const NetworkAddress &address) : TCPConnecter(address) {} + TCPClientConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {} void OnFailure() override { @@ -710,7 +725,7 @@ public: void OnConnect(SOCKET s) override { _networking = true; - new ClientNetworkGameSocketHandler(s, this->address); + new ClientNetworkGameSocketHandler(s, this->connection_string); IConsoleCmdExec("exec scripts/on_client.scr 0"); NetworkClient_Connected(); } @@ -736,34 +751,12 @@ public: bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) { CompanyID join_as = default_company; - NetworkAddress address = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT); + std::string resolved_connection_string = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT).GetAddressAsString(false); - if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) { - join_as--; - if (join_as >= MAX_COMPANIES) { - return false; - } - } - - return NetworkClientConnectGame(address, join_as, join_server_password, join_company_password); -} - -/** - * Join a client to the server at the given address. - * See the overloaded NetworkClientConnectGame for more details. - * - * @param address The network address of the server to join to. - * @param join_as The company number to join as. - * @param join_server_password The password for the server. - * @param join_company_password The password for the company. - * @return Whether the join has started. - */ -bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password) -{ if (!_network_available) return false; if (!NetworkValidateClientName()) return false; - _network_join.address = address; + _network_join.connection_string = resolved_connection_string; _network_join.company = join_as; _network_join.server_password = join_server_password; _network_join.company_password = join_company_password; @@ -792,11 +785,11 @@ void NetworkClientJoinGame() NetworkDisconnect(); NetworkInitialize(); - strecpy(_settings_client.network.last_joined, _network_join.address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); + strecpy(_settings_client.network.last_joined, _network_join.connection_string.c_str(), lastof(_settings_client.network.last_joined)); _network_join_status = NETWORK_JOIN_STATUS_CONNECTING; ShowJoinStatusWindow(); - new TCPClientConnecter(_network_join.address); + new TCPClientConnecter(_network_join.connection_string); } static void NetworkInitGameInfo() diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index d288c71a6e..190bb29450 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -145,7 +145,7 @@ void ClientNetworkEmergencySave() * Create a new socket for the client side of the game connection. * @param s The socket to connect with. */ -ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address) : NetworkGameSocketHandler(s), address(address), savegame(nullptr), status(STATUS_INACTIVE) +ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string), savegame(nullptr), status(STATUS_INACTIVE) { assert(ClientNetworkGameSocketHandler::my_client == nullptr); ClientNetworkGameSocketHandler::my_client = this; @@ -581,7 +581,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe NetworkGameList *item = GetLobbyGameInfo(); if (item == nullptr) { /* This is not the lobby, so add it to the game list. */ - item = NetworkGameListAddItem(this->address); + item = NetworkGameListAddItem(this->connection_string); } /* Clear any existing GRFConfig chain. */ diff --git a/src/network/network_client.h b/src/network/network_client.h index 81d5b720cd..ddc0e362c8 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -15,7 +15,7 @@ /** Class for handling the client side of the game connection. */ class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler { private: - NetworkAddress address; ///< Address we are connected to. + std::string connection_string; ///< Address we are connected to. struct PacketReader *savegame; ///< Packet reader for reading the savegame. byte token; ///< The token we need to send back to the server to prove we're the right client. @@ -76,7 +76,7 @@ protected: static NetworkRecvStatus SendMapOk(); void CheckConnection(); public: - ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address); + ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string); ~ClientNetworkGameSocketHandler(); NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override; @@ -115,10 +115,10 @@ void NetworkClientSetCompanyPassword(const char *password); /** Information required to join a server. */ struct NetworkJoinInfo { NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {} - NetworkAddress address; ///< The address of the server to join. - CompanyID company; ///< The company to join. - const char *server_password; ///< The password of the server to join. - const char *company_password; ///< The password of the company to join. + std::string connection_string; ///< The address of the server to join. + CompanyID company; ///< The company to join. + const char *server_password; ///< The password of the server to join. + const char *company_password; ///< The password of the company to join. }; extern NetworkJoinInfo _network_join; diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index a208f3c6e2..528b7bd777 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -343,8 +343,7 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentHTTP(const Conten this->http_response_index = -1; - NetworkAddress address(NETWORK_CONTENT_MIRROR_HOST, NETWORK_CONTENT_MIRROR_PORT); - new NetworkHTTPContentConnecter(address, this, NETWORK_CONTENT_MIRROR_URL, content_request); + new NetworkHTTPContentConnecter(NETWORK_CONTENT_MIRROR_HOST, this, NETWORK_CONTENT_MIRROR_URL, content_request); /* NetworkHTTPContentConnecter takes over freeing of content_request! */ } @@ -744,7 +743,7 @@ public: * Initiate the connecting. * @param address The address of the server. */ - NetworkContentConnecter(const NetworkAddress &address) : TCPConnecter(address) {} + NetworkContentConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_CONTENT_SERVER_PORT) {} void OnFailure() override { @@ -770,7 +769,7 @@ void ClientNetworkContentSocketHandler::Connect() { if (this->sock != INVALID_SOCKET || this->isConnecting) return; this->isConnecting = true; - new NetworkContentConnecter(NetworkAddress(NETWORK_CONTENT_SERVER_HOST, NETWORK_CONTENT_SERVER_PORT, AF_UNSPEC)); + new NetworkContentConnecter(NETWORK_CONTENT_SERVER_HOST); } /** diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index 12dbbce615..1edbafc328 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -44,7 +44,7 @@ static void NetworkGameListHandleDelayedInsert() while (ins_item != nullptr && !_network_game_delayed_insertion_list.compare_exchange_weak(ins_item, ins_item->next, std::memory_order_acq_rel)) {} if (ins_item == nullptr) break; // No item left. - NetworkGameList *item = NetworkGameListAddItem(ins_item->address); + NetworkGameList *item = NetworkGameListAddItem(ins_item->connection_string); if (item != nullptr) { if (StrEmpty(item->info.server_name)) { @@ -67,19 +67,22 @@ static void NetworkGameListHandleDelayedInsert() * @param address the address of the to-be added item * @return a point to the newly added or already existing item */ -NetworkGameList *NetworkGameListAddItem(NetworkAddress address) +NetworkGameList *NetworkGameListAddItem(const std::string &connection_string) { NetworkGameList *item, *prev_item; + /* Parse the connection string to ensure the default port is there. */ + const std::string resolved_connection_string = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT).GetAddressAsString(false); + prev_item = nullptr; for (item = _network_game_list; item != nullptr; item = item->next) { - if (item->address == address) return item; + if (item->connection_string == resolved_connection_string) return item; prev_item = item; } item = CallocT(1); item->next = nullptr; - item->address = address; + item->connection_string = resolved_connection_string; if (prev_item == nullptr) { _network_game_list = item; @@ -141,7 +144,7 @@ void NetworkGameListRequery() /* item gets mostly zeroed by NetworkUDPQueryServer */ uint8 retries = item->retries; - NetworkUDPQueryServer(item->address); + NetworkUDPQueryServer(item->connection_string); item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries; } } diff --git a/src/network/network_gamelist.h b/src/network/network_gamelist.h index ce35c01d8b..31b3bc3e64 100644 --- a/src/network/network_gamelist.h +++ b/src/network/network_gamelist.h @@ -16,19 +16,19 @@ /** Structure with information shown in the game list (GUI) */ struct NetworkGameList { - NetworkGameInfo info; ///< The game information of this server - NetworkAddress address; ///< The connection info of the game server - bool online; ///< False if the server did not respond (default status) - bool manually; ///< True if the server was added manually - uint8 retries; ///< Number of retries (to stop requerying) - NetworkGameList *next; ///< Next pointer to make a linked game list + NetworkGameInfo info; ///< The game information of this server + std::string connection_string; ///< Address of the server + bool online; ///< False if the server did not respond (default status) + bool manually; ///< True if the server was added manually + uint8 retries; ///< Number of retries (to stop requerying) + NetworkGameList *next; ///< Next pointer to make a linked game list }; /** Game list of this client */ extern NetworkGameList *_network_game_list; void NetworkGameListAddItemDelayed(NetworkGameList *item); -NetworkGameList *NetworkGameListAddItem(NetworkAddress address); +NetworkGameList *NetworkGameListAddItem(const std::string &connection_string); void NetworkGameListRemoveItem(NetworkGameList *remove); void NetworkGameListRequery(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index ac86b868c6..526f141cde 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -272,7 +272,9 @@ protected: static bool NGameNameSorter(NetworkGameList * const &a, NetworkGameList * const &b) { int r = strnatcmp(a->info.server_name, b->info.server_name, true); // Sort by name (natural sorting). - return r == 0 ? a->address.CompareTo(b->address) < 0: r < 0; + if (r == 0) r = a->connection_string.compare(b->connection_string); + + return r < 0; } /** @@ -646,8 +648,7 @@ public: DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version y += FONT_HEIGHT_NORMAL; - std::string address = sel->address.GetAddressAsString(); - SetDParamStr(0, address.c_str()); + SetDParamStr(0, sel->connection_string.c_str()); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address y += FONT_HEIGHT_NORMAL; @@ -751,7 +752,7 @@ public: break; case WID_NG_REFRESH: // Refresh - if (this->server != nullptr) NetworkTCPQueryServer(this->server->address); + if (this->server != nullptr) NetworkTCPQueryServer(this->server->connection_string); break; case WID_NG_NEWGRF: // NewGRF Settings @@ -1471,22 +1472,22 @@ struct NetworkLobbyWindow : public Window { case WID_NL_JOIN: // Join company /* Button can be clicked only when it is enabled. */ - NetworkClientConnectGame(this->server->address, this->company); + NetworkClientConnectGame(this->server->connection_string, this->company); break; case WID_NL_NEW: // New company - NetworkClientConnectGame(this->server->address, COMPANY_NEW_COMPANY); + NetworkClientConnectGame(this->server->connection_string, COMPANY_NEW_COMPANY); break; case WID_NL_SPECTATE: // Spectate game - NetworkClientConnectGame(this->server->address, COMPANY_SPECTATOR); + NetworkClientConnectGame(this->server->connection_string, COMPANY_SPECTATOR); break; case WID_NL_REFRESH: // Refresh /* Clear the information so removed companies don't remain */ for (auto &company : this->company_info) company = {}; - NetworkTCPQueryServer(this->server->address, true); + NetworkTCPQueryServer(this->server->connection_string, true); break; } } @@ -1554,9 +1555,9 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); - strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined)); + strecpy(_settings_client.network.last_joined, ngl->connection_string.c_str(), lastof(_settings_client.network.last_joined)); - NetworkTCPQueryServer(ngl->address, true); + NetworkTCPQueryServer(ngl->connection_string, true); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 1fba1228a5..ef414c46a3 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -87,7 +87,7 @@ extern uint8 _network_reconnect; extern CompanyMask _network_company_passworded; -void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info = false); +void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info = false); void GetBindAddresses(NetworkAddressList *addresses, uint16 port); struct NetworkGameList *NetworkAddServer(const std::string &connection_string); @@ -119,8 +119,6 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); -bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port); -NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port); #endif /* NETWORK_INTERNAL_H */ diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index de69e4a9af..558b51f993 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -83,35 +83,36 @@ static UDPSocket _udp_master("Master"); ///< udp master socket /** * Helper function doing the actual work for querying the server. - * @param address The address of the server. + * @param connection_string The address of the server. * @param needs_mutex Whether we need to acquire locks when sending the packet or not. * @param manually Whether the address was entered manually. */ -static void DoNetworkUDPQueryServer(NetworkAddress &address, bool needs_mutex, bool manually) +static void DoNetworkUDPQueryServer(const std::string &connection_string, bool needs_mutex, bool manually) { /* Clear item in gamelist */ NetworkGameList *item = CallocT(1); - address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name)); - item->address = address; + strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name)); + item->connection_string = connection_string; item->manually = manually; NetworkGameListAddItemDelayed(item); std::unique_lock lock(_udp_client.mutex, std::defer_lock); if (needs_mutex) lock.lock(); /* Init the packet */ + NetworkAddress address = NetworkAddress(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT)); Packet p(PACKET_UDP_CLIENT_FIND_SERVER); if (_udp_client.socket != nullptr) _udp_client.socket->SendPacket(&p, &address); } /** * Query a specific server. - * @param address The address of the server. + * @param connection_string The address of the server. * @param manually Whether the address was entered manually. */ -void NetworkUDPQueryServer(NetworkAddress address, bool manually) +void NetworkUDPQueryServer(const std::string &connection_string, bool manually) { - if (address.IsResolved() || !StartNewThread(nullptr, "ottd:udp-query", &DoNetworkUDPQueryServer, std::move(address), true, std::move(manually))) { - DoNetworkUDPQueryServer(address, true, manually); + if (!StartNewThread(nullptr, "ottd:udp-query", &DoNetworkUDPQueryServer, std::move(connection_string), true, std::move(manually))) { + DoNetworkUDPQueryServer(connection_string, true, manually); } } @@ -318,7 +319,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd DEBUG(net, 4, "[udp] server response from %s", client_addr->GetAddressAsString().c_str()); /* Find next item */ - item = NetworkGameListAddItem(*client_addr); + item = NetworkGameListAddItem(client_addr->GetAddressAsString(false)); /* Clear any existing GRFConfig chain. */ ClearGRFConfigList(&item->info.grfconfig); @@ -357,7 +358,8 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd SerializeGRFIdentifier(&packet, &in_request[i]->ident); } - this->SendPacket(&packet, &item->address); + NetworkAddress address = NetworkAddress(ParseConnectionString(item->connection_string, NETWORK_DEFAULT_PORT)); + this->SendPacket(&packet, &address); } } @@ -398,7 +400,7 @@ void ClientNetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST(Packet *p, Netw /* Somehow we reached the end of the packet */ if (this->HasClientQuit()) return; - DoNetworkUDPQueryServer(addr, false, false); + DoNetworkUDPQueryServer(addr.GetAddressAsString(false), false, false); } } } diff --git a/src/network/network_udp.h b/src/network/network_udp.h index 189657bc87..ced949cd32 100644 --- a/src/network/network_udp.h +++ b/src/network/network_udp.h @@ -15,7 +15,7 @@ void NetworkUDPInitialize(); void NetworkUDPSearchGame(); void NetworkUDPQueryMasterServer(); -void NetworkUDPQueryServer(NetworkAddress address, bool manually = false); +void NetworkUDPQueryServer(const std::string &connection_string, bool manually = false); void NetworkUDPAdvertise(); void NetworkUDPRemoveAdvertise(bool blocking); void NetworkUDPClose(); From dc0591728739c2c8fa68dbfeb418239fbfb39383 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 07:14:19 +0200 Subject: [PATCH 101/800] Add: [[nodiscard]] to std::string str_validate --- src/string_func.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string_func.h b/src/string_func.h index 4fe9d7b825..787fd6413e 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -40,7 +40,7 @@ int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2); -std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +[[nodiscard]] std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void ValidateString(const char *str); void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2); From dcef3209a61acf818f3114d07e3378bc7e61a9c1 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 4 May 2021 19:30:25 +0200 Subject: [PATCH 102/800] Codechange: [Network] Use new/delete instead of calloc/free for NetworkGameList --- src/network/network_gamelist.cpp | 9 +++------ src/network/network_gamelist.h | 17 +++++++++++------ src/network/network_udp.cpp | 4 +--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index 1edbafc328..e4e2d17412 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -57,7 +57,7 @@ static void NetworkGameListHandleDelayedInsert() if (item->manually) NetworkRebuildHostList(); UpdateNetworkGameWindow(); } - free(ins_item); + delete ins_item; } } @@ -80,9 +80,7 @@ NetworkGameList *NetworkGameListAddItem(const std::string &connection_string) prev_item = item; } - item = CallocT(1); - item->next = nullptr; - item->connection_string = resolved_connection_string; + item = new NetworkGameList(resolved_connection_string); if (prev_item == nullptr) { _network_game_list = item; @@ -112,8 +110,7 @@ void NetworkGameListRemoveItem(NetworkGameList *remove) /* Remove GRFConfig information */ ClearGRFConfigList(&remove->info.grfconfig); - free(remove); - remove = nullptr; + delete remove; DEBUG(net, 4, "[gamelist] removed server from list"); NetworkRebuildHostList(); diff --git a/src/network/network_gamelist.h b/src/network/network_gamelist.h index 31b3bc3e64..6ef9d8e41f 100644 --- a/src/network/network_gamelist.h +++ b/src/network/network_gamelist.h @@ -16,12 +16,17 @@ /** Structure with information shown in the game list (GUI) */ struct NetworkGameList { - NetworkGameInfo info; ///< The game information of this server - std::string connection_string; ///< Address of the server - bool online; ///< False if the server did not respond (default status) - bool manually; ///< True if the server was added manually - uint8 retries; ///< Number of retries (to stop requerying) - NetworkGameList *next; ///< Next pointer to make a linked game list + NetworkGameList(const std::string &connection_string, bool manually = false) : + connection_string(connection_string), manually(manually) + { + } + + NetworkGameInfo info = {}; ///< The game information of this server + std::string connection_string; ///< Address of the server + bool online = false; ///< False if the server did not respond (default status) + bool manually = false; ///< True if the server was added manually + uint8 retries = 0; ///< Number of retries (to stop requerying) + NetworkGameList *next = nullptr; ///< Next pointer to make a linked game list }; /** Game list of this client */ diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 558b51f993..4e4f4a37e7 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -90,10 +90,8 @@ static UDPSocket _udp_master("Master"); ///< udp master socket static void DoNetworkUDPQueryServer(const std::string &connection_string, bool needs_mutex, bool manually) { /* Clear item in gamelist */ - NetworkGameList *item = CallocT(1); + NetworkGameList *item = new NetworkGameList(connection_string, manually); strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name)); - item->connection_string = connection_string; - item->manually = manually; NetworkGameListAddItemDelayed(item); std::unique_lock lock(_udp_client.mutex, std::defer_lock); From 6c4a65eeb80431ce35e91affee865419e7d7af34 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 4 May 2021 19:31:12 +0200 Subject: [PATCH 103/800] Codechange: [Network] Use std::string for NetworkAddress' host name --- src/network/core/address.cpp | 24 +++++++++++++----------- src/network/core/address.h | 23 ++++++++++------------- src/network/core/udp.cpp | 6 +++--- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index d3e373ef76..d40a72420b 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -23,11 +23,13 @@ static const int DEFAULT_CONNECT_TIMEOUT_SECONDS = 3; ///< Allow connect() three */ const char *NetworkAddress::GetHostname() { - if (StrEmpty(this->hostname) && this->address.ss_family != AF_UNSPEC) { + if (this->hostname.empty() && this->address.ss_family != AF_UNSPEC) { assert(this->address_length != 0); - getnameinfo((struct sockaddr *)&this->address, this->address_length, this->hostname, sizeof(this->hostname), nullptr, 0, NI_NUMERICHOST); + char buffer[NETWORK_HOSTNAME_LENGTH]; + getnameinfo((struct sockaddr *)&this->address, this->address_length, buffer, sizeof(buffer), nullptr, 0, NI_NUMERICHOST); + this->hostname = buffer; } - return this->hostname; + return this->hostname.c_str(); } /** @@ -234,32 +236,32 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList * /* Setting both hostname to nullptr and port to 0 is not allowed. * As port 0 means bind to any port, the other must mean that * we want to bind to 'all' IPs. */ - if (StrEmpty(this->hostname) && this->address_length == 0 && this->GetPort() == 0) { + if (this->hostname.empty() && this->address_length == 0 && this->GetPort() == 0) { reset_hostname = true; int fam = this->address.ss_family; if (fam == AF_UNSPEC) fam = family; - strecpy(this->hostname, fam == AF_INET ? "0.0.0.0" : "::", lastof(this->hostname)); + this->hostname = fam == AF_INET ? "0.0.0.0" : "::"; } static bool _resolve_timeout_error_message_shown = false; auto start = std::chrono::steady_clock::now(); - int e = getaddrinfo(StrEmpty(this->hostname) ? nullptr : this->hostname, port_name, &hints, &ai); + int e = getaddrinfo(this->hostname.empty() ? nullptr : this->hostname.c_str(), port_name, &hints, &ai); auto end = std::chrono::steady_clock::now(); std::chrono::seconds duration = std::chrono::duration_cast(end - start); if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) { DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s took %i seconds", - this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), (int)duration.count()); + this->hostname.c_str(), port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), (int)duration.count()); DEBUG(net, 0, " this is likely an issue in the DNS name resolver's configuration causing it to time out"); _resolve_timeout_error_message_shown = true; } - if (reset_hostname) strecpy(this->hostname, "", lastof(this->hostname)); + if (reset_hostname) this->hostname.clear(); if (e != 0) { if (func != ResolveLoopProc) { DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s", - this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str()); + this->hostname.c_str(), port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str()); } return INVALID_SOCKET; } @@ -442,11 +444,11 @@ void NetworkAddress::Listen(int socktype, SocketList *sockets) { assert(sockets != nullptr); - /* Setting both hostname to nullptr and port to 0 is not allowed. + /* Setting both hostname to "" and port to 0 is not allowed. * As port 0 means bind to any port, the other must mean that * we want to bind to 'all' IPs. */ if (this->address_length == 0 && this->address.ss_family == AF_UNSPEC && - StrEmpty(this->hostname) && this->GetPort() == 0) { + this->hostname.empty() && this->GetPort() == 0) { this->Resolve(AF_INET, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc); this->Resolve(AF_INET6, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc); } else { diff --git a/src/network/core/address.h b/src/network/core/address.h index 65546818b2..b4364c95ab 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -28,10 +28,10 @@ typedef SmallMap SocketList; ///< Type for a mapping */ class NetworkAddress { private: - char hostname[NETWORK_HOSTNAME_LENGTH]; ///< The hostname - int address_length; ///< The length of the resolved address - sockaddr_storage address; ///< The resolved address - bool resolved; ///< Whether the address has been (tried to be) resolved + std::string hostname; ///< The hostname + int address_length; ///< The length of the resolved address + sockaddr_storage address; ///< The resolved address + bool resolved; ///< Whether the address has been (tried to be) resolved /** * Helper function to resolve something to a socket. @@ -52,7 +52,6 @@ public: address(address), resolved(address_length != 0) { - *this->hostname = '\0'; } /** @@ -64,7 +63,6 @@ public: address_length(address_length), resolved(address_length != 0) { - *this->hostname = '\0'; memset(&this->address, 0, sizeof(this->address)); memcpy(&this->address, address, address_length); } @@ -75,16 +73,15 @@ public: * @param port the port * @param family the address family */ - NetworkAddress(const char *hostname = "", uint16 port = 0, int family = AF_UNSPEC) : + NetworkAddress(std::string_view hostname = "", uint16 port = 0, int family = AF_UNSPEC) : address_length(0), resolved(false) { - /* Also handle IPv6 bracket enclosed hostnames */ - if (StrEmpty(hostname)) hostname = ""; - if (*hostname == '[') hostname++; - strecpy(this->hostname, StrEmpty(hostname) ? "" : hostname, lastof(this->hostname)); - char *tmp = strrchr(this->hostname, ']'); - if (tmp != nullptr) *tmp = '\0'; + if (!hostname.empty() && hostname.front() == '[' && hostname.back() == ']') { + hostname.remove_prefix(1); + hostname.remove_suffix(1); + } + this->hostname = hostname; memset(&this->address, 0, sizeof(this->address)); this->address.ss_family = family; diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index e7b99a53e8..c4d448f268 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -28,11 +28,11 @@ NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind) this->bind.push_back(addr); } } else { - /* As hostname nullptr and port 0/nullptr don't go well when + /* As an empty hostname and port 0 don't go well when * resolving it we need to add an address for each of * the address families we support. */ - this->bind.emplace_back(nullptr, 0, AF_INET); - this->bind.emplace_back(nullptr, 0, AF_INET6); + this->bind.emplace_back("", 0, AF_INET); + this->bind.emplace_back("", 0, AF_INET6); } } From 3d91eee919de2ecec11102b4ba1f4caafa4d7a83 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 4 May 2021 19:32:37 +0200 Subject: [PATCH 104/800] Codechange: [Network] Move connection string parsing away from C-strings --- src/network/network.cpp | 112 +++++++++++++++------------------ src/network/network_func.h | 2 +- src/network/network_internal.h | 2 +- src/openttd.cpp | 11 ++-- 4 files changed, 57 insertions(+), 70 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 98b49e81fe..a90f8197e7 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -33,6 +33,7 @@ #include "../core/pool_func.hpp" #include "../gfx_func.h" #include "../error.h" +#include #include "../safeguards.h" @@ -453,36 +454,51 @@ static void CheckPauseOnJoin() * Converts a string to ip/port/company * Format: IP:port#company * - * connection_string will be re-terminated to separate out the hostname, port will - * be set to the port strings given by the user, inside the memory area originally - * occupied by connection_string. Similar for company, if set. + * Returns the IP part as a string view into the passed string. This view is + * valid as long the passed connection string is valid. If there is no port + * present in the connection string, the port reference will not be touched. + * When there is no company ID present in the connection string or company_id + * is nullptr, then company ID will not be touched. + * + * @param connection_string The string with the connection data. + * @param port The port reference to set. + * @param company_id The company ID to set, if available. + * @return A std::string_view into the connection string with the (IP) address part. */ -void ParseFullConnectionString(const char **company, const char **port, char *connection_string) +std::string_view ParseFullConnectionString(const std::string &connection_string, uint16 &port, CompanyID *company_id) { - bool ipv6 = (strchr(connection_string, ':') != strrchr(connection_string, ':')); - for (char *p = connection_string; *p != '\0'; p++) { - switch (*p) { - case '[': - ipv6 = true; - break; + std::string_view ip = connection_string; + if (company_id != nullptr) { + size_t offset = ip.find_last_of('#'); + if (offset != std::string::npos) { + std::string_view company_string = ip.substr(offset + 1); + ip = ip.substr(0, offset); - case ']': - ipv6 = false; - break; - - case '#': - if (company == nullptr) continue; - *company = p + 1; - *p = '\0'; - break; - - case ':': - if (ipv6) break; - *port = p + 1; - *p = '\0'; - break; + uint8 company_value; + auto [_, err] = std::from_chars(company_string.data(), company_string.data() + company_string.size(), company_value); + if (err == std::errc()) { + if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) { + if (company_value > MAX_COMPANIES || company_value == 0) { + *company_id = COMPANY_SPECTATOR; + } else { + /* "#1" means the first company, which has index 0. */ + *company_id = (CompanyID)(company_value - 1); + } + } else { + *company_id = (CompanyID)company_value; + } + } } } + + size_t port_offset = ip.find_last_of(':'); + size_t ipv6_close = ip.find_last_of(']'); + if (port_offset != std::string::npos && (ipv6_close == std::string::npos || ipv6_close < port_offset)) { + std::string_view port_string = ip.substr(port_offset + 1); + ip = ip.substr(0, port_offset); + std::from_chars(port_string.data(), port_string.data() + port_string.size(), port); + } + return ip; } /** @@ -493,16 +509,11 @@ void ParseFullConnectionString(const char **company, const char **port, char *co * @param default_port The default port to set port to if not in connection_string. * @return A valid NetworkAddress of the parsed information. */ -NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port) +NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port) { - char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH]; - strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string)); - - const char *port = nullptr; - ParseFullConnectionString(nullptr, &port, internal_connection_string); - - int rport = port != nullptr ? atoi(port) : default_port; - return NetworkAddress(internal_connection_string, rport); + uint16 port = default_port; + std::string_view ip = ParseFullConnectionString(connection_string, port); + return NetworkAddress(ip, port); } /** @@ -510,37 +521,16 @@ NetworkAddress ParseConnectionString(const std::string &connection_string, int d * NetworkAddress, where the string can be postfixed with "#company" to * indicate the requested company. * - * @param company Pointer to the company variable to set iff indicted. * @param connection_string The string to parse. * @param default_port The default port to set port to if not in connection_string. + * @param company Pointer to the company variable to set iff indicted. * @return A valid NetworkAddress of the parsed information. */ -static NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port) +static NetworkAddress ParseGameConnectionString(const std::string &connection_string, uint16 default_port, CompanyID *company) { - char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company - strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string)); - - const char *port_s = nullptr; - const char *company_s = nullptr; - ParseFullConnectionString(&company_s, &port_s, internal_connection_string); - - if (company_s != nullptr) { - uint company_value = atoi(company_s); - - if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) { - if (company_value > MAX_COMPANIES || company_value == 0) { - *company = COMPANY_SPECTATOR; - } else { - /* "#1" means the first company, which has index 0. */ - *company = (CompanyID)(company_value - 1); - } - } else { - *company = (CompanyID)company_value; - } - } - - int port = port_s != nullptr ? atoi(port_s) : default_port; - return NetworkAddress(internal_connection_string, port); + uint16 port = default_port; + std::string_view ip = ParseFullConnectionString(connection_string, port, company); + return NetworkAddress(ip, port); } /** @@ -751,7 +741,7 @@ public: bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) { CompanyID join_as = default_company; - std::string resolved_connection_string = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT).GetAddressAsString(false); + std::string resolved_connection_string = ParseGameConnectionString(connection_string, NETWORK_DEFAULT_PORT, &join_as).GetAddressAsString(false); if (!_network_available) return false; if (!NetworkValidateClientName()) return false; diff --git a/src/network/network_func.h b/src/network/network_func.h index ba26e06c09..ef81b0fb16 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -45,7 +45,7 @@ void NetworkReboot(); void NetworkDisconnect(bool blocking = false, bool close_admins = true); void NetworkGameLoop(); void NetworkBackgroundLoop(); -void ParseFullConnectionString(const char **company, const char **port, char *connection_string); +std::string_view ParseFullConnectionString(const std::string &connection_string, uint16 &port, CompanyID *company_id = nullptr); void NetworkStartDebugLog(const std::string &connection_string); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index ef414c46a3..2a2024bac5 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -119,6 +119,6 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); -NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port); +NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port); #endif /* NETWORK_INTERNAL_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index d4c7da6e4c..d9e0b835e0 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -405,7 +405,7 @@ void OpenBrowser(const char *url) struct AfterNewGRFScan : NewGRFScanCallback { Year startyear; ///< The start year. uint32 generation_seed; ///< Seed for the new game. - char *dedicated_host; ///< Hostname for the dedicated server. + std::string dedicated_host; ///< Hostname for the dedicated server. uint16 dedicated_port; ///< Port for the dedicated server. char *network_conn; ///< Information about the server to connect to, or nullptr. const char *join_server_password; ///< The password to join the server with. @@ -417,7 +417,7 @@ struct AfterNewGRFScan : NewGRFScanCallback { */ AfterNewGRFScan() : startyear(INVALID_YEAR), generation_seed(GENERATE_NEW_SEED), - dedicated_host(nullptr), dedicated_port(0), network_conn(nullptr), + dedicated_port(0), network_conn(nullptr), join_server_password(nullptr), join_company_password(nullptr), save_config(true) { @@ -458,7 +458,7 @@ struct AfterNewGRFScan : NewGRFScanCallback { if (startyear != INVALID_YEAR) IConsoleSetSetting("game_creation.starting_year", startyear); if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed; - if (dedicated_host != nullptr) { + if (!dedicated_host.empty()) { _network_bind_list.clear(); _network_bind_list.emplace_back(dedicated_host); } @@ -565,10 +565,7 @@ int openttd_main(int argc, char *argv[]) dedicated = true; SetDebugString("net=6"); if (mgo.opt != nullptr) { - const char *port = nullptr; - ParseFullConnectionString(nullptr, &port, mgo.opt); - if (!StrEmpty(mgo.opt)) scanner->dedicated_host = mgo.opt; - if (port != nullptr) scanner->dedicated_port = atoi(port); + scanner->dedicated_host = ParseFullConnectionString(mgo.opt, scanner->dedicated_port); } break; case 'f': _dedicated_forks = true; break; From f313a539a54efe09850bcab0680d281e3cc54444 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 6 May 2021 18:59:49 +0000 Subject: [PATCH 105/800] Update: Translations from eints portuguese: 1 change by azulcosta --- src/lang/portuguese.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 4473b1cb39..2e7f686ac2 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -2270,7 +2270,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} en STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} entrou como espectador STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} iniciou uma nova empresa (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} deixou o jogo ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} mudou o seu nome para {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} mudou o nome para {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} deu {2:CURRENCY_LONG} a {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}O servidor fechou a sessão STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}O servidor está a reiniciar...{}Por favor espere... From 6bca9e090dc6637fd7b6ed6a5a37d65f151849e9 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 20:58:17 +0200 Subject: [PATCH 106/800] Codechange: add SetDParamStr that accepts std::string& --- src/fios.cpp | 2 +- src/fios_gui.cpp | 2 +- src/industry_gui.cpp | 2 +- src/music_gui.cpp | 2 +- src/newgrf_gui.cpp | 12 ++++++------ src/settings.cpp | 2 +- src/settings_gui.cpp | 8 ++++---- src/strings.cpp | 11 +++++++++++ src/strings_func.h | 1 + src/town_gui.cpp | 4 ++-- src/widgets/dropdown.cpp | 2 +- 11 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/fios.cpp b/src/fios.cpp index 3b11bcbe02..c56e505fa0 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -392,7 +392,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c fios->mtime = 0; strecpy(fios->name, d_name, lastof(fios->name)); std::string dirname = std::string(d_name) + PATHSEP; - SetDParamStr(0, dirname.c_str()); + SetDParamStr(0, dirname); GetString(fios->title, STR_SAVELOAD_DIRECTORY, lastof(fios->title)); str_validate(fios->title, lastof(fios->title)); } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 8de6235d62..e4de1acaaa 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -537,7 +537,7 @@ public: const CompanyProperties &c = *pair.second; if (!c.name.empty()) { SetDParam(1, STR_JUST_RAW_STRING); - SetDParamStr(2, c.name.c_str()); + SetDParamStr(2, c.name); } else { SetDParam(1, c.name_1); SetDParam(2, c.name_2); diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index aa4d86da6c..d0c916ef7c 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -972,7 +972,7 @@ public: } if (!i->text.empty()) { - SetDParamStr(0, i->text.c_str()); + SetDParamStr(0, i->text); y += WD_PAR_VSEP_WIDE; y = DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK); } diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 28cb6ce4e1..16245a0b24 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -462,7 +462,7 @@ struct MusicTrackSelectionWindow : public Window { SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist); break; case WID_MTS_CAPTION: - SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str()); + SetDParamStr(0, BaseMusic::GetUsedSet()->name); break; } } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 6316a7c4bf..9e86a575f0 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -51,9 +51,9 @@ void ShowNewGRFError() if (c->error == nullptr || (c->error->severity != STR_NEWGRF_ERROR_MSG_FATAL && c->error->severity != STR_NEWGRF_ERROR_MSG_ERROR)) continue; SetDParam (0, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING); - SetDParamStr(1, c->error->custom_message.c_str()); + SetDParamStr(1, c->error->custom_message); SetDParamStr(2, c->filename); - SetDParamStr(3, c->error->data.c_str()); + SetDParamStr(3, c->error->data); for (uint i = 0; i < lengthof(c->error->param_value); i++) { SetDParam(4 + i, c->error->param_value[i]); } @@ -70,9 +70,9 @@ static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint right, uint { if (c->error != nullptr) { char message[512]; - SetDParamStr(0, c->error->custom_message.c_str()); // is skipped by built-in messages + SetDParamStr(0, c->error->custom_message); // is skipped by built-in messages SetDParamStr(1, c->filename); - SetDParamStr(2, c->error->data.c_str()); + SetDParamStr(2, c->error->data); for (uint i = 0; i < lengthof(c->error->param_value); i++) { SetDParam(3 + i, c->error->param_value[i]); } @@ -750,7 +750,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { case WID_NS_PRESET_LIST: { Dimension d = GetStringBoundingBox(STR_NUM_CUSTOM); for (const auto &i : this->grf_presets) { - SetDParamStr(0, i.c_str()); + SetDParamStr(0, i); d = maxdim(d, GetStringBoundingBox(STR_JUST_RAW_STRING)); } d.width += padding.width; @@ -783,7 +783,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { SetDParam(0, STR_NUM_CUSTOM); } else { SetDParam(0, STR_JUST_RAW_STRING); - SetDParamStr(1, this->grf_presets[this->preset].c_str()); + SetDParamStr(1, this->grf_presets[this->preset]); } break; } diff --git a/src/settings.cpp b/src/settings.cpp index c0b0dd8edd..855bedd18d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1631,7 +1631,7 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN); } - SetDParamStr(0, StrEmpty(filename) ? item->name.c_str() : filename); + SetDParamStr(0, StrEmpty(filename) ? item->name : filename); ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, WL_CRITICAL); delete c; continue; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 34c073fe92..9935d596c0 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -123,7 +123,7 @@ struct BaseSetTextfileWindow : public TextfileWindow { { if (widget == WID_TF_CAPTION) { SetDParam(0, content_type); - SetDParamStr(1, this->baseset->name.c_str()); + SetDParamStr(1, this->baseset->name); } } }; @@ -304,10 +304,10 @@ struct GameOptionsWindow : Window { case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break; case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[_gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom_cfg + 1 : 0]); break; case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[_font_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _font_zoom_cfg + 1 : 0]); break; - case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name.c_str()); break; + case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break; case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break; - case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name.c_str()); break; - case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str()); break; + case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name); break; + case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name); break; case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break; case WID_GO_REFRESH_RATE_DROPDOWN: SetDParam(0, _settings_client.gui.refresh_rate); break; case WID_GO_RESOLUTION_DROPDOWN: { diff --git a/src/strings.cpp b/src/strings.cpp index 0489714590..2b6dbc3ef9 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -296,6 +296,17 @@ void SetDParamStr(uint n, const char *str) SetDParam(n, (uint64)(size_t)str); } +/** + * This function is used to "bind" the C string of a std::string to a OpenTTD dparam slot. + * The caller has to ensure that the std::string reference remains valid while the string is shown. + * @param n slot of the string + * @param str string to bind + */ +void SetDParamStr(uint n, const std::string &str) +{ + SetDParamStr(n, str.c_str()); +} + /** * Shift the string parameters in the global string parameter array by \a amount positions, making room at the beginning. * @param amount Number of positions to shift. diff --git a/src/strings_func.h b/src/strings_func.h index e4b7791052..be59b091a2 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -205,6 +205,7 @@ void SetDParamMaxValue(uint n, uint64 max_value, uint min_count = 0, FontSize si void SetDParamMaxDigits(uint n, uint count, FontSize size = FS_NORMAL); void SetDParamStr(uint n, const char *str); +void SetDParamStr(uint n, const std::string &str); void CopyInDParam(int offs, const uint64 *src, int num); void CopyOutDParam(uint64 *dst, int offs, int num); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index a189c7ccb3..22f8b757f8 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -435,7 +435,7 @@ public: } if (!this->town->text.empty()) { - SetDParamStr(0, this->town->text.c_str()); + SetDParamStr(0, this->town->text); DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y += FONT_HEIGHT_NORMAL, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK); } } @@ -517,7 +517,7 @@ public: if (_settings_game.economy.station_noise_level) aimed_height += FONT_HEIGHT_NORMAL; if (!this->town->text.empty()) { - SetDParamStr(0, this->town->text.c_str()); + SetDParamStr(0, this->town->text); aimed_height += GetStringHeight(STR_JUST_RAW_STRING, width - WD_FRAMERECT_LEFT - WD_FRAMERECT_RIGHT); } diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 8f4a8634ee..4b89b48092 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -65,7 +65,7 @@ StringID DropDownListParamStringItem::String() const StringID DropDownListCharStringItem::String() const { - SetDParamStr(0, this->raw_string.c_str()); + SetDParamStr(0, this->raw_string); return this->string; } From cb89d22cf248841f93d257983770a08aa0a64561 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Thu, 6 May 2021 16:32:57 +0200 Subject: [PATCH 107/800] Codechange: add DrawString(Multiline) that accepts std::string& --- src/gfx.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/gfx_func.h | 2 ++ src/industry_gui.cpp | 4 ++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 1f4b40a54c..a4bac6e13f 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -656,6 +656,28 @@ int DrawString(int left, int right, int top, const char *str, TextColour colour, return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true); } +/** + * Draw string, possibly truncated to make it fit in its allocated space + * + * @param left The left most position to draw on. + * @param right The right most position to draw on. + * @param top The top most position to draw on. + * @param str String to draw. + * @param colour Colour used for drawing the string, for details see _string_colourmap in + * table/palettes.h or docs/ottd-colourtext-palette.png or the enum TextColour in gfx_type.h + * @param align The alignment of the string when drawing left-to-right. In the + * case a right-to-left language is chosen this is inverted so it + * will be drawn in the right direction. + * @param underline Whether to underline what has been drawn or not. + * @param fontsize The size of the initial characters. + * @return In case of left or center alignment the right most pixel we have drawn to. + * In case of right alignment the left most pixel we have drawn to. + */ +int DrawString(int left, int right, int top, const std::string &str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize) +{ + return DrawString(left, right, top, str.c_str(), colour, align, underline, fontsize); +} + /** * Draw string, possibly truncated to make it fit in its allocated space * @@ -806,6 +828,28 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, const char *st return ((align & SA_VERT_MASK) == SA_BOTTOM) ? first_line : last_line; } + +/** + * Draw string, possibly over multiple lines. + * + * @param left The left most position to draw on. + * @param right The right most position to draw on. + * @param top The top most position to draw on. + * @param bottom The bottom most position to draw on. + * @param str String to draw. + * @param colour Colour used for drawing the string, for details see _string_colourmap in + * table/palettes.h or docs/ottd-colourtext-palette.png or the enum TextColour in gfx_type.h + * @param align The horizontal and vertical alignment of the string. + * @param underline Whether to underline all strings + * @param fontsize The size of the initial characters. + * + * @return If \a align is #SA_BOTTOM, the top to where we have written, else the bottom to where we have written. + */ +int DrawStringMultiLine(int left, int right, int top, int bottom, const std::string &str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize) +{ + return DrawStringMultiLine(left, right, top, bottom, str.c_str(), colour, align, underline, fontsize); +} + /** * Draw string, possibly over multiple lines. * diff --git a/src/gfx_func.h b/src/gfx_func.h index 18b1966f9b..3deb4f3eb6 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -92,8 +92,10 @@ void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSpri void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI); int DrawString(int left, int right, int top, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL); +int DrawString(int left, int right, int top, const std::string &str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL); int DrawString(int left, int right, int top, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL); int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL); +int DrawStringMultiLine(int left, int right, int top, int bottom, const std::string &str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL); int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL); void DrawCharCentered(WChar c, const Rect &r, TextColour colour); diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index d0c916ef7c..147d4dc777 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -572,12 +572,12 @@ public: /* Draw the accepted cargoes, if any. Otherwise, will print "Nothing". */ GetAllCargoSuffixes(CARGOSUFFIX_IN, CST_FUND, nullptr, this->selected_type, indsp, indsp->accepts_cargo, cargo_suffix); std::string cargostring = this->MakeCargoListString(indsp->accepts_cargo, cargo_suffix, lengthof(indsp->accepts_cargo), STR_INDUSTRY_VIEW_REQUIRES_N_CARGO); - y = DrawStringMultiLine(left, right, y, bottom, cargostring.c_str()); + y = DrawStringMultiLine(left, right, y, bottom, cargostring); /* Draw the produced cargoes, if any. Otherwise, will print "Nothing". */ GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_FUND, nullptr, this->selected_type, indsp, indsp->produced_cargo, cargo_suffix); cargostring = this->MakeCargoListString(indsp->produced_cargo, cargo_suffix, lengthof(indsp->produced_cargo), STR_INDUSTRY_VIEW_PRODUCES_N_CARGO); - y = DrawStringMultiLine(left, right, y, bottom, cargostring.c_str()); + y = DrawStringMultiLine(left, right, y, bottom, cargostring); /* Get the additional purchase info text, if it has not already been queried. */ if (HasBit(indsp->callback_mask, CBM_IND_FUND_MORE_TEXT)) { From f1dfa661a1898cde06a38ab4cb230c95912b245b Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Thu, 6 May 2021 16:19:00 +0200 Subject: [PATCH 108/800] Codechange: [Network] Use std::string for NetworkGameInfo --- src/network/core/game_info.cpp | 10 +++++----- src/network/core/game_info.h | 32 ++++++++++++++++---------------- src/network/network.cpp | 6 +++--- src/network/network_gamelist.cpp | 6 +++--- src/network/network_gui.cpp | 6 +++--- src/network/network_udp.cpp | 4 ++-- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index 47e6f221ef..f7044a3fce 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -112,7 +112,7 @@ bool IsNetworkCompatibleVersion(const char *other) void CheckGameCompatibility(NetworkGameInfo &ngi) { /* Check if we are allowed on this server based on the revision-check. */ - ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision); + ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision.c_str()); ngi.compatible = ngi.version_compatible; /* Check if we have all the GRFs on the client-system too. */ @@ -138,8 +138,8 @@ void FillStaticNetworkServerGameInfo() _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)); + _network_game_info.server_name = _settings_client.network.server_name; + _network_game_info.server_revision = GetNetworkRevisionString(); } /** @@ -295,8 +295,8 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info) FALLTHROUGH; case 1: - p->Recv_string(info->server_name, sizeof(info->server_name)); - p->Recv_string(info->server_revision, sizeof(info->server_revision)); + info->server_name = p->Recv_string(NETWORK_NAME_LENGTH); + info->server_revision = p->Recv_string(NETWORK_REVISION_LENGTH); p->Recv_uint8 (); // Used to contain server-lang. info->use_password = p->Recv_bool (); info->clients_max = p->Recv_uint8 (); diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index ef83e4d053..668b9801da 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -60,22 +60,22 @@ * The game information that is sent from the server to the client. */ struct NetworkServerGameInfo { - GRFConfig *grfconfig; ///< List of NewGRF files used - Date start_date; ///< When the game started - Date game_date; ///< Current date - uint16 map_width; ///< Map width - uint16 map_height; ///< Map height - char server_name[NETWORK_NAME_LENGTH]; ///< Server name - char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) - bool dedicated; ///< Is this a dedicated server? - bool use_password; ///< Is this server passworded? - byte clients_on; ///< Current count of clients on server - byte clients_max; ///< Max clients allowed on server - byte companies_on; ///< How many started companies do we have - byte companies_max; ///< Max companies allowed on server - byte spectators_on; ///< How many spectators do we have? - byte spectators_max; ///< Max spectators allowed on server - byte landscape; ///< The used landscape + GRFConfig *grfconfig; ///< List of NewGRF files used + Date start_date; ///< When the game started + Date game_date; ///< Current date + uint16 map_width; ///< Map width + uint16 map_height; ///< Map height + std::string server_name; ///< Server name + std::string server_revision; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) + bool dedicated; ///< Is this a dedicated server? + bool use_password; ///< Is this server passworded? + byte clients_on; ///< Current count of clients on server + byte clients_max; ///< Max clients allowed on server + byte companies_on; ///< How many started companies do we have + byte companies_max; ///< Max companies allowed on server + byte spectators_on; ///< How many spectators do we have? + byte spectators_max; ///< Max spectators allowed on server + byte landscape; ///< The used landscape }; /** diff --git a/src/network/network.cpp b/src/network/network.cpp index a90f8197e7..83a93a22ea 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -656,9 +656,9 @@ NetworkGameList *NetworkAddServer(const std::string &connection_string) /* Ensure the item already exists in the list */ NetworkGameList *item = NetworkGameListAddItem(connection_string); - if (StrEmpty(item->info.server_name)) { + if (item->info.server_name.empty()) { ClearGRFConfigList(&item->info.grfconfig); - strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name)); + item->info.server_name = connection_string; item->manually = true; NetworkRebuildHostList(); @@ -1163,7 +1163,7 @@ void NetworkStartUp() /* Generate an server id when there is none yet */ if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateServerId(); - memset(&_network_game_info, 0, sizeof(_network_game_info)); + _network_game_info = {}; NetworkInitialize(); DEBUG(net, 3, "[core] network online, multiplayer available"); diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index e4e2d17412..20fbb19a7c 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -47,10 +47,10 @@ static void NetworkGameListHandleDelayedInsert() NetworkGameList *item = NetworkGameListAddItem(ins_item->connection_string); if (item != nullptr) { - if (StrEmpty(item->info.server_name)) { + if (item->info.server_name.empty()) { ClearGRFConfigList(&item->info.grfconfig); - memset(&item->info, 0, sizeof(item->info)); - strecpy(item->info.server_name, ins_item->info.server_name, lastof(item->info.server_name)); + item->info = {}; + item->info.server_name = ins_item->info.server_name; item->online = false; } item->manually |= ins_item->manually; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 526f141cde..cf16d06b13 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -271,7 +271,7 @@ protected: /** Sort servers by name. */ static bool NGameNameSorter(NetworkGameList * const &a, NetworkGameList * const &b) { - int r = strnatcmp(a->info.server_name, b->info.server_name, true); // Sort by name (natural sorting). + int r = strnatcmp(a->info.server_name.c_str(), b->info.server_name.c_str(), true); // Sort by name (natural sorting). if (r == 0) r = a->connection_string.compare(b->connection_string); return r < 0; @@ -324,7 +324,7 @@ protected: static bool NGameAllowedSorter(NetworkGameList * const &a, NetworkGameList * const &b) { /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */ - int r = StrEmpty(a->info.server_revision) - StrEmpty(b->info.server_revision); + int r = a->info.server_revision.empty() - b->info.server_revision.empty(); /* Reverse default as we are interested in version-compatible clients first */ if (r == 0) r = b->info.version_compatible - a->info.version_compatible; @@ -361,7 +361,7 @@ protected: assert((*item) != nullptr); sf.ResetState(); - sf.AddLine((*item)->info.server_name); + sf.AddLine((*item)->info.server_name.c_str()); return sf.GetState(); } diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 4e4f4a37e7..8a95596c17 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -91,7 +91,7 @@ static void DoNetworkUDPQueryServer(const std::string &connection_string, bool n { /* Clear item in gamelist */ NetworkGameList *item = new NetworkGameList(connection_string, manually); - strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name)); + item->info.server_name = connection_string; NetworkGameListAddItemDelayed(item); std::unique_lock lock(_udp_client.mutex, std::defer_lock); @@ -362,7 +362,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd } if (client_addr->GetAddress()->ss_family == AF_INET6) { - strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name)); + item->info.server_name.append(" (IPv6)"); } UpdateNetworkGameWindow(); From f7e390bdc084a20462fe833373087fd9106c5972 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 6 May 2021 23:13:35 +0200 Subject: [PATCH 109/800] Feature: use Happy Eyeballs to make network connections (TCP-only) (#9199) Hostnames like "content.openttd.org" resolve into multiple IPv4 and IPv6. It is possible that either of the IPs is not working, either due to a poorly configured OS (having IPv6 but no valid route), broken network paths, or a service that is temporary unavailable. Instead of trying the IPs one by one, waiting for a 3s timeout between each, be a bit more like browsers, and stack attempts on top of each other with slight delays. This is called Happy Eyebells. Initially, try the first IPv6 address. If within 250ms there is no connection yet, try the first IPv4 address. 250ms later, try the second IPv6 address, etc, till all addresses are tried. If any connection is created, abort all the other (pending) connections and use the one that is created. If all fail 3s after the last connect(), trigger a timeout for all. --- src/network/core/address.cpp | 91 ++-------- src/network/core/address.h | 2 +- src/network/core/tcp.h | 28 +-- src/network/core/tcp_connect.cpp | 301 +++++++++++++++++++++++++++---- src/network/core/tcp_http.cpp | 4 +- src/network/core/tcp_http.h | 10 +- src/network/network.cpp | 43 +++-- src/network/network_internal.h | 1 + 8 files changed, 334 insertions(+), 146 deletions(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index d40a72420b..205b5df224 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -14,8 +14,6 @@ #include "../../safeguards.h" -static const int DEFAULT_CONNECT_TIMEOUT_SECONDS = 3; ///< Allow connect() three seconds to connect. - /** * Get the hostname; in case it wasn't given the * IPv4 dotted representation is given. @@ -306,82 +304,6 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList * return sock; } -/** - * Helper function to resolve a connected socket. - * @param runp information about the socket to try not - * @return the opened socket or INVALID_SOCKET - */ -static SOCKET ConnectLoopProc(addrinfo *runp) -{ - const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype); - const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family); - std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(); - - SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); - if (sock == INVALID_SOCKET) { - DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkError::GetLast().AsString()); - return INVALID_SOCKET; - } - - if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type); - - if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed", type); - - int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen); - if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) { - DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address.c_str(), family, NetworkError::GetLast().AsString()); - closesocket(sock); - return INVALID_SOCKET; - } - - fd_set write_fd; - struct timeval tv; - - FD_ZERO(&write_fd); - FD_SET(sock, &write_fd); - - /* Wait for connect() to either connect, timeout or fail. */ - tv.tv_usec = 0; - tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS; - int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv); - if (n < 0) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkError::GetLast().AsString()); - closesocket(sock); - return INVALID_SOCKET; - } - - /* If no fd is selected, the timeout has been reached. */ - if (n == 0) { - DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address.c_str()); - closesocket(sock); - return INVALID_SOCKET; - } - - /* Retrieve last error, if any, on the socket. */ - NetworkError socket_error = GetSocketError(sock); - if (socket_error.HasError()) { - DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), socket_error.AsString()); - closesocket(sock); - return INVALID_SOCKET; - } - - /* Connection succeeded. */ - DEBUG(net, 1, "[%s] connected to %s", type, address.c_str()); - - return sock; -} - -/** - * Connect to the given address. - * @return the connected socket or INVALID_SOCKET. - */ -SOCKET NetworkAddress::Connect() -{ - DEBUG(net, 1, "Connecting to %s", this->GetAddressAsString().c_str()); - - return this->Resolve(AF_UNSPEC, SOCK_STREAM, AI_ADDRCONFIG, nullptr, ConnectLoopProc); -} - /** * Helper function to resolve a listening. * @param runp information about the socket to try not @@ -486,3 +408,16 @@ void NetworkAddress::Listen(int socktype, SocketList *sockets) default: return "unsupported"; } } + +/** + * Get the peer name of a socket in string format. + * @param sock The socket to get the peer name of. + * @return The string representation of the peer name. + */ +/* static */ const std::string NetworkAddress::GetPeerName(SOCKET sock) +{ + sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + getpeername(sock, (sockaddr *)&addr, &addr_len); + return NetworkAddress(addr, addr_len).GetAddressAsString(); +} diff --git a/src/network/core/address.h b/src/network/core/address.h index b4364c95ab..c3f95b4925 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -171,11 +171,11 @@ public: return this->CompareTo(address) < 0; } - SOCKET Connect(); void Listen(int socktype, SocketList *sockets); static const char *SocketTypeAsString(int socktype); static const char *AddressFamilyAsString(int family); + static const std::string GetPeerName(SOCKET sock); }; #endif /* NETWORK_CORE_ADDRESS_H */ diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index 5acf9d12e6..b90ce0232c 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -15,6 +15,7 @@ #include "address.h" #include "packet.h" +#include #include /** The states of sending the packets. */ @@ -63,23 +64,28 @@ public: */ class TCPConnecter { private: - std::atomic connected;///< Whether we succeeded in making the connection - std::atomic aborted; ///< Whether we bailed out (i.e. connection making failed) - bool killed; ///< Whether we got killed - SOCKET sock; ///< The socket we're connecting with + addrinfo *ai = nullptr; ///< getaddrinfo() allocated linked-list of resolved addresses. + std::vector addresses; ///< Addresses we can connect to. + size_t current_address = 0; ///< Current index in addresses we are trying. - void Connect(); + std::vector sockets; ///< Pending connect() attempts. + std::chrono::steady_clock::time_point last_attempt; ///< Time we last tried to connect. - static void ThreadEntry(TCPConnecter *param); + std::atomic is_resolved = false; ///< Whether resolving is done. -protected: - /** Address we're connecting to */ - NetworkAddress address; + void Resolve(); + void OnResolved(addrinfo *ai); + bool TryNextAddress(); + void Connect(addrinfo *address); + bool CheckActivity(); + + static void ResolveThunk(TCPConnecter *connecter); public: + std::string connection_string; ///< Current address we are connecting to (before resolving). + TCPConnecter(const std::string &connection_string, uint16 default_port); - /** Silence the warnings */ - virtual ~TCPConnecter() {} + virtual ~TCPConnecter(); /** * Callback when the connection succeeded. diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index 81c4d8c264..cca9f09b71 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -15,6 +15,8 @@ #include "tcp.h" #include "../network_internal.h" +#include + #include "../../safeguards.h" /** List of connections that are currently being created */ @@ -24,38 +26,271 @@ static std::vector _tcp_connecters; * Create a new connecter for the given address * @param connection_string the address to connect to */ -TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port) : - connected(false), - aborted(false), - killed(false), - sock(INVALID_SOCKET) +TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port) { - this->address = ParseConnectionString(connection_string, default_port); + this->connection_string = NormalizeConnectionString(connection_string, default_port); _tcp_connecters.push_back(this); - if (!StartNewThread(nullptr, "ottd:tcp", &TCPConnecter::ThreadEntry, this)) { - this->Connect(); + + if (!StartNewThread(nullptr, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) { + this->Resolve(); } } -/** The actual connection function */ -void TCPConnecter::Connect() +TCPConnecter::~TCPConnecter() { - this->sock = this->address.Connect(); - if (this->sock == INVALID_SOCKET) { - this->aborted = true; - } else { - this->connected = true; + for (const auto &socket : this->sockets) { + close(socket); } + + freeaddrinfo(this->ai); } /** - * Entry point for the new threads. - * @param param the TCPConnecter instance to call Connect on. + * Start a connection to the indicated address. + * @param address The address to connection to. */ -/* static */ void TCPConnecter::ThreadEntry(TCPConnecter *param) +void TCPConnecter::Connect(addrinfo *address) { - param->Connect(); + SOCKET sock = socket(address->ai_family, address->ai_socktype, address->ai_protocol); + if (sock == INVALID_SOCKET) { + DEBUG(net, 0, "Could not create %s %s socket: %s", NetworkAddress::SocketTypeAsString(address->ai_socktype), NetworkAddress::AddressFamilyAsString(address->ai_family), NetworkError::GetLast().AsString()); + return; + } + + if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); + if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed"); + + NetworkAddress network_address = NetworkAddress(address->ai_addr, (int)address->ai_addrlen); + DEBUG(net, 4, "Attempting to connect to %s", network_address.GetAddressAsString().c_str()); + + int err = connect(sock, address->ai_addr, (int)address->ai_addrlen); + if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) { + closesocket(sock); + + DEBUG(net, 1, "Could not connect to %s: %s", network_address.GetAddressAsString().c_str(), NetworkError::GetLast().AsString()); + return; + } + + this->sockets.push_back(sock); +} + +/** + * Start the connect() for the next address in the list. + * @return True iff a new connect() is attempted. + */ +bool TCPConnecter::TryNextAddress() +{ + if (this->current_address >= this->addresses.size()) return false; + + this->last_attempt = std::chrono::steady_clock::now(); + this->Connect(this->addresses[this->current_address++]); + + return true; +} + +void TCPConnecter::OnResolved(addrinfo *ai) +{ + std::deque addresses_ipv4, addresses_ipv6; + + /* Apply "Happy Eyeballs" if it is likely IPv6 is functional. */ + + /* Detect if IPv6 is likely to succeed or not. */ + bool seen_ipv6 = false; + bool resort = true; + for (addrinfo *runp = ai; runp != nullptr; runp = runp->ai_next) { + if (runp->ai_family == AF_INET6) { + seen_ipv6 = true; + } else if (!seen_ipv6) { + /* We see an IPv4 before an IPv6; this most likely means there is + * no IPv6 available on the system, so keep the order of this + * list. */ + resort = false; + break; + } + } + + /* Convert the addrinfo into NetworkAddresses. */ + for (addrinfo *runp = ai; runp != nullptr; runp = runp->ai_next) { + if (resort) { + if (runp->ai_family == AF_INET6) { + addresses_ipv6.emplace_back(runp); + } else { + addresses_ipv4.emplace_back(runp); + } + } else { + this->addresses.emplace_back(runp); + } + } + + /* If we want to resort, make the list like IPv6 / IPv4 / IPv6 / IPv4 / .. + * for how ever many (round-robin) DNS entries we have. */ + if (resort) { + while (!addresses_ipv4.empty() || !addresses_ipv6.empty()) { + if (!addresses_ipv6.empty()) { + this->addresses.push_back(addresses_ipv6.front()); + addresses_ipv6.pop_front(); + } + if (!addresses_ipv4.empty()) { + this->addresses.push_back(addresses_ipv4.front()); + addresses_ipv4.pop_front(); + } + } + } + + if (_debug_net_level >= 5) { + DEBUG(net, 5, "%s resolved in:", this->connection_string.c_str()); + for (const auto &address : this->addresses) { + DEBUG(net, 5, "- %s", NetworkAddress(address->ai_addr, (int)address->ai_addrlen).GetAddressAsString().c_str()); + } + } + + this->current_address = 0; +} + +void TCPConnecter::Resolve() +{ + /* Port is already guaranteed part of the connection_string. */ + NetworkAddress address = ParseConnectionString(this->connection_string, 0); + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + char port_name[6]; + seprintf(port_name, lastof(port_name), "%u", address.GetPort()); + + static bool getaddrinfo_timeout_error_shown = false; + auto start = std::chrono::steady_clock::now(); + + addrinfo *ai; + int e = getaddrinfo(address.GetHostname(), port_name, &hints, &ai); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + if (!getaddrinfo_timeout_error_shown && duration >= std::chrono::seconds(5)) { + DEBUG(net, 0, "getaddrinfo() for address \"%s\" took %i seconds", this->connection_string.c_str(), (int)duration.count()); + DEBUG(net, 0, " This is likely an issue in the DNS name resolver's configuration causing it to time out"); + getaddrinfo_timeout_error_shown = true; + } + + if (e != 0) { + DEBUG(misc, 0, "Failed to resolve DNS for %s", this->connection_string.c_str()); + this->OnFailure(); + return; + } + + this->ai = ai; + this->OnResolved(ai); + this->is_resolved = true; +} + +/* static */ void TCPConnecter::ResolveThunk(TCPConnecter *connecter) +{ + connecter->Resolve(); +} + +/** + * Check if there was activity for this connecter. + * @return True iff the TCPConnecter is done and can be cleaned up. + */ +bool TCPConnecter::CheckActivity() +{ + if (!this->is_resolved.load()) return false; + + /* If there are no attempts pending, connect to the next. */ + if (this->sockets.empty()) { + if (!this->TryNextAddress()) { + /* There were no more addresses to try, so we failed. */ + this->OnFailure(); + return true; + } + return false; + } + + fd_set write_fd; + FD_ZERO(&write_fd); + for (const auto &socket : this->sockets) { + FD_SET(socket, &write_fd); + } + + timeval tv; + tv.tv_usec = 0; + tv.tv_sec = 0; + int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv); + /* select() failed; hopefully next try it doesn't. */ + if (n < 0) { + /* select() normally never fails; so hopefully it works next try! */ + DEBUG(net, 1, "select() failed with %s", NetworkError::GetLast().AsString()); + return false; + } + + /* No socket updates. */ + if (n == 0) { + /* Wait 250ms between attempting another address. */ + if (std::chrono::steady_clock::now() < this->last_attempt + std::chrono::milliseconds(250)) return false; + + /* Try the next address in the list. */ + if (this->TryNextAddress()) return false; + + /* Wait up to 3 seconds since the last connection we started. */ + if (std::chrono::steady_clock::now() < this->last_attempt + std::chrono::milliseconds(3000)) return false; + + /* More than 3 seconds no socket reported activity, and there are no + * more address to try. Timeout the attempt. */ + DEBUG(net, 0, "Timeout while connecting to %s", this->connection_string.c_str()); + + for (const auto &socket : this->sockets) { + closesocket(socket); + } + this->OnFailure(); + return true; + } + + /* Check for errors on any of the sockets. */ + for (auto it = this->sockets.begin(); it != this->sockets.end(); /* nothing */) { + NetworkError socket_error = GetSocketError(*it); + if (socket_error.HasError()) { + DEBUG(net, 1, "Could not connect to %s: %s", NetworkAddress::GetPeerName(*it).c_str(), socket_error.AsString()); + closesocket(*it); + it = this->sockets.erase(it); + } else { + it++; + } + } + + /* In case all sockets had an error, queue a new one. */ + if (this->sockets.empty()) { + if (!this->TryNextAddress()) { + /* There were no more addresses to try, so we failed. */ + this->OnFailure(); + return true; + } + return false; + } + + /* At least one socket is connected. The first one that does is the one + * we will be using, and we close all other sockets. */ + SOCKET connected_socket = INVALID_SOCKET; + for (auto it = this->sockets.begin(); it != this->sockets.end(); /* nothing */) { + if (connected_socket == INVALID_SOCKET && FD_ISSET(*it, &write_fd)) { + connected_socket = *it; + } else { + closesocket(*it); + } + it = this->sockets.erase(it); + } + assert(connected_socket != INVALID_SOCKET); + + DEBUG(net, 1, "Connected to %s", this->connection_string.c_str()); + if (_debug_net_level >= 5) { + DEBUG(net, 5, "- using %s", NetworkAddress::GetPeerName(connected_socket).c_str()); + } + + this->OnConnect(connected_socket); + return true; } /** @@ -68,32 +303,22 @@ void TCPConnecter::Connect() { for (auto iter = _tcp_connecters.begin(); iter < _tcp_connecters.end(); /* nothing */) { TCPConnecter *cur = *iter; - const bool connected = cur->connected.load(); - const bool aborted = cur->aborted.load(); - if ((connected || aborted) && cur->killed) { + + if (cur->CheckActivity()) { iter = _tcp_connecters.erase(iter); - if (cur->sock != INVALID_SOCKET) closesocket(cur->sock); delete cur; - continue; + } else { + iter++; } - if (connected) { - iter = _tcp_connecters.erase(iter); - cur->OnConnect(cur->sock); - delete cur; - continue; - } - if (aborted) { - iter = _tcp_connecters.erase(iter); - cur->OnFailure(); - delete cur; - continue; - } - iter++; } } /** Kill all connection attempts. */ /* static */ void TCPConnecter::KillAll() { - for (TCPConnecter *conn : _tcp_connecters) conn->killed = true; + for (auto iter = _tcp_connecters.begin(); iter < _tcp_connecters.end(); /* nothing */) { + TCPConnecter *cur = *iter; + iter = _tcp_connecters.erase(iter); + delete cur; + } } diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index 3b7579fcea..ccad120aec 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -203,9 +203,11 @@ int NetworkHTTPSocketHandler::HandleHeader() *url = '\0'; + std::string hostname = std::string(hname); + /* Restore the URL. */ *url = '/'; - new NetworkHTTPContentConnecter(hname, callback, url, data, depth); + new NetworkHTTPContentConnecter(hostname, callback, url, data, depth); return 0; } diff --git a/src/network/core/tcp_http.h b/src/network/core/tcp_http.h index cc9a3adac2..d7be0c327b 100644 --- a/src/network/core/tcp_http.h +++ b/src/network/core/tcp_http.h @@ -73,6 +73,7 @@ public: /** Connect with a HTTP server and do ONE query. */ class NetworkHTTPContentConnecter : TCPConnecter { + std::string hostname; ///< Hostname we are connecting to. HTTPCallback *callback; ///< Callback to tell that we received some data (or won't). const char *url; ///< The URL we want to get at the server. const char *data; ///< The data to send @@ -81,14 +82,15 @@ class NetworkHTTPContentConnecter : TCPConnecter { public: /** * Start the connecting. - * @param connection_string The address to connect to. + * @param hostname The hostname to connect to. * @param callback The callback for HTTP retrieval. * @param url The url at the server. * @param data The data to send. * @param depth The depth (redirect recursion) of the queries. */ - NetworkHTTPContentConnecter(const std::string &connection_string, HTTPCallback *callback, const char *url, const char *data = nullptr, int depth = 0) : - TCPConnecter(connection_string, 80), + NetworkHTTPContentConnecter(const std::string &hostname, HTTPCallback *callback, const char *url, const char *data = nullptr, int depth = 0) : + TCPConnecter(hostname, 80), + hostname(hostname), callback(callback), url(stredup(url)), data(data), @@ -110,7 +112,7 @@ public: void OnConnect(SOCKET s) override { - new NetworkHTTPSocketHandler(s, this->callback, this->address.GetHostname(), this->url, this->data, this->depth); + new NetworkHTTPSocketHandler(s, this->callback, this->hostname.c_str(), this->url, this->data, this->depth); /* We've relinquished control of data now. */ this->data = nullptr; } diff --git a/src/network/network.cpp b/src/network/network.cpp index 83a93a22ea..bbf6bb5deb 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -501,6 +501,19 @@ std::string_view ParseFullConnectionString(const std::string &connection_string, return ip; } +/** + * Normalize a connection string. That is, ensure there is a port in the string. + * @param connection_string The connection string to normalize. + * @param default_port The port to use if none is given. + * @return The normalized connection string. + */ +std::string NormalizeConnectionString(const std::string &connection_string, uint16 default_port) +{ + uint16 port = default_port; + std::string_view ip = ParseFullConnectionString(connection_string, port); + return std::string(ip) + ":" + std::to_string(port); +} + /** * Convert a string containing either "hostname" or "hostname:ip" to a * NetworkAddress. @@ -1131,23 +1144,27 @@ static void NetworkGenerateServerId() seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output); } -void NetworkStartDebugLog(const std::string &connection_string) -{ - extern SOCKET _debug_socket; // Comes from debug.c +class TCPNetworkDebugConnecter : TCPConnecter { +public: + TCPNetworkDebugConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT) {} - NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT); - - DEBUG(net, 0, "Redirecting DEBUG() to %s", address.GetAddressAsString().c_str()); - - SOCKET s = address.Connect(); - if (s == INVALID_SOCKET) { - DEBUG(net, 0, "Failed to open socket for redirection DEBUG()"); - return; + void OnFailure() override + { + DEBUG(net, 0, "Failed to open connection to %s for redirecting DEBUG()", this->connection_string.c_str()); } - _debug_socket = s; + void OnConnect(SOCKET s) override + { + DEBUG(net, 0, "Redirecting DEBUG() to %s", this->connection_string.c_str()); - DEBUG(net, 0, "DEBUG() is now redirected"); + extern SOCKET _debug_socket; + _debug_socket = s; + } +}; + +void NetworkStartDebugLog(const std::string &connection_string) +{ + new TCPNetworkDebugConnecter(connection_string); } /** This tries to launch the network for a given OS */ diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 2a2024bac5..88af965cfc 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -120,5 +120,6 @@ bool NetworkFindName(char *new_name, const char *last); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port); +std::string NormalizeConnectionString(const std::string &connection_string, uint16 default_port); #endif /* NETWORK_INTERNAL_H */ From b56c03b12009e2356af0ff01c028132e36c97b5d Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 7 May 2021 18:59:46 +0000 Subject: [PATCH 110/800] Update: Translations from eints dutch: 2 changes by Afoklala --- src/lang/dutch.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 9e54ba3fdb..c1f03eab95 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -2217,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Uw compu STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Uw computer deed er te lang over om de kaart te downloaden STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Uw computer deed er te lang over om met de server te verbinden STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Je spelernaam is niet geldig +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}De opgevraagde server is te oud voor deze client ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :algemene fout @@ -2268,7 +2269,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} he STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} kijkt nu toe STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} heeft een nieuw bedrijf opgericht (nr. {2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} heeft het spel verlaten ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} heeft zijn/haar naam gewijzigd naar {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} heeft diens naam gewijzigd in {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} gaf {2:CURRENCY_LONG} aan {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}De server heeft de sessie gesloten STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}De server wordt opnieuw gestart...{}Wacht alstublieft... From a87999601294af97d8d914db232f24525d9248ce Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 8 May 2021 03:43:17 -0400 Subject: [PATCH 111/800] Fix: [Emscripten] Use non-XDG directories to simplify lolac storage (#9207) --- src/stdafx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdafx.h b/src/stdafx.h index 819eb0e614..937c053f2f 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -347,7 +347,7 @@ typedef unsigned char byte; #endif /* Define the the platforms that use XDG */ -#if defined(WITH_PERSONAL_DIR) && defined(UNIX) && !defined(__APPLE__) +#if defined(WITH_PERSONAL_DIR) && defined(UNIX) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__) # define USE_XDG #endif From e2774354b4f64a46992a74b399fb882aa075cfac Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 8 May 2021 10:19:42 +0200 Subject: [PATCH 112/800] Codechange: [Network] Change ChatMessage's message to std::string and simplify some code --- src/network/network.cpp | 2 +- src/network/network_chat_gui.cpp | 15 +++------------ src/network/network_func.h | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index bbf6bb5deb..3965c200fd 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -262,7 +262,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, DEBUG(desync, 1, "msg: %08x; %02x; %s", _date, _date_fract, message); IConsolePrintF(colour, "%s", message); - NetworkAddChatMessage((TextColour)colour, _settings_client.gui.network_chat_timeout, "%s", message); + NetworkAddChatMessage((TextColour)colour, _settings_client.gui.network_chat_timeout, message); } /* Calculate the frame-lag of a client */ diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 14edc15032..e8fbf0f124 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -39,7 +39,7 @@ static const uint NETWORK_CHAT_LINE_SPACING = 3; /** Container for a message. */ struct ChatMessage { - char message[DRAW_STRING_BUFFER]; ///< The action message. + std::string message; ///< The action message. TextColour colour; ///< The colour of the message. std::chrono::steady_clock::time_point remove_time; ///< The time to remove the message. }; @@ -87,23 +87,14 @@ static inline bool HaveChatMessages(bool show_all) * @param duration The duration of the chat message in seconds * @param message message itself in printf() style */ -void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) +void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message) { - char buf[DRAW_STRING_BUFFER]; - va_list va; - - va_start(va, message); - vseprintf(buf, lastof(buf), message, va); - va_end(va); - - Utf8TrimString(buf, DRAW_STRING_BUFFER); - if (_chatmsg_list.size() == MAX_CHAT_MESSAGES) { _chatmsg_list.pop_back(); } ChatMessage *cmsg = &_chatmsg_list.emplace_front(); - strecpy(cmsg->message, buf, lastof(cmsg->message)); + cmsg->message = message; cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE; cmsg->remove_time = std::chrono::steady_clock::now() + std::chrono::seconds(duration); diff --git a/src/network/network_func.h b/src/network/network_func.h index ef81b0fb16..e7709d3075 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -84,7 +84,7 @@ uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason); uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason); void NetworkInitChatMessage(); -void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) WARN_FORMAT(3, 4); +void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message); void NetworkUndrawChatMessage(); void NetworkChatMessageLoop(); From 8321ef0061fa898cfb215e57c67aebd7411475e1 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 6 May 2021 01:36:56 +0100 Subject: [PATCH 113/800] Codechange: Set specific widgets dirty instead of window. --- src/misc_gui.cpp | 2 +- src/music_gui.cpp | 2 +- src/settings_gui.cpp | 9 +++++---- src/window.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e9ee7b193b..a40bf50139 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -557,7 +557,7 @@ struct AboutWindow : public Window { if (this->text_position < (int)(this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) { this->text_position = this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget(WID_A_SCROLLING_TEXT)->current_y; } - this->SetDirty(); + this->SetWidgetDirty(WID_A_SCROLLING_TEXT); } } }; diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 16245a0b24..80d55eb4ba 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -789,7 +789,7 @@ struct MusicWindow : public Window { byte &vol = (widget == WID_M_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; if (ClickVolumeSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, vol)) { if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(vol); - this->SetDirty(); + this->SetWidgetDirty(widget); SetWindowClassesDirty(WC_GAME_OPTIONS); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 9935d596c0..15c6a887e9 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -446,17 +446,18 @@ struct GameOptionsWindow : Window { ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR); } this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen); - this->SetDirty(); + this->SetWidgetDirty(WID_GO_FULLSCREEN_BUTTON); break; case WID_GO_VIDEO_ACCEL_BUTTON: _video_hw_accel = !_video_hw_accel; ShowErrorMessage(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART, INVALID_STRING_ID, WL_INFO); this->SetWidgetLoweredState(WID_GO_VIDEO_ACCEL_BUTTON, _video_hw_accel); + this->SetWidgetDirty(WID_GO_VIDEO_ACCEL_BUTTON); #ifndef __APPLE__ this->SetWidgetDisabledState(WID_GO_VIDEO_VSYNC_BUTTON, !_video_hw_accel); + this->SetWidgetDirty(WID_GO_VIDEO_VSYNC_BUTTON); #endif - this->SetDirty(); break; case WID_GO_VIDEO_VSYNC_BUTTON: @@ -466,7 +467,7 @@ struct GameOptionsWindow : Window { VideoDriver::GetInstance()->ToggleVsync(_video_vsync); this->SetWidgetLoweredState(WID_GO_VIDEO_VSYNC_BUTTON, _video_vsync); - this->SetDirty(); + this->SetWidgetDirty(WID_GO_VIDEO_VSYNC_BUTTON); break; case WID_GO_BASE_SFX_VOLUME: @@ -474,7 +475,7 @@ struct GameOptionsWindow : Window { byte &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; if (ClickVolumeSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, vol)) { if (widget == WID_GO_BASE_MUSIC_VOLUME) MusicDriver::GetInstance()->SetVolume(vol); - this->SetDirty(); + this->SetWidgetDirty(widget); SetWindowClassesDirty(WC_MUSIC_WINDOW); } diff --git a/src/window.cpp b/src/window.cpp index a409726002..20c7ffbddf 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2438,8 +2438,8 @@ static EventState HandleActiveWidget() if (w->mouse_capture_widget >= 0) { /* Abort if no button is clicked any more. */ if (!_left_button_down) { + w->SetWidgetDirty(w->mouse_capture_widget); w->mouse_capture_widget = -1; - w->SetDirty(); return ES_HANDLED; } From 52b16237ad863ce30746ac7efc46a9ece7e3bdd2 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 7 May 2021 12:36:08 +0100 Subject: [PATCH 114/800] Codechange: Don't update window contents if scrollbar position has not moved. --- src/widget.cpp | 17 ++++++++++++----- src/widget_type.h | 12 ++++++++---- src/window.cpp | 9 +++------ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/widget.cpp b/src/widget.cpp index 5c1c0ae8fc..93a5afe953 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -108,6 +108,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in int pos; int button_size; bool rtl = false; + bool changed = false; if (sb->type == NWID_HSCROLLBAR) { pos = x; @@ -122,7 +123,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in SetBit(sb->disp_flags, NDB_SCROLLBAR_UP); if (_scroller_click_timeout <= 1) { _scroller_click_timeout = 3; - sb->UpdatePosition(rtl ? 1 : -1); + changed = sb->UpdatePosition(rtl ? 1 : -1); } w->mouse_capture_widget = sb->index; } else if (pos >= ma - button_size) { @@ -131,16 +132,16 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in if (_scroller_click_timeout <= 1) { _scroller_click_timeout = 3; - sb->UpdatePosition(rtl ? -1 : 1); + changed = sb->UpdatePosition(rtl ? -1 : 1); } w->mouse_capture_widget = sb->index; } else { Point pt = HandleScrollbarHittest(sb, mi, ma, sb->type == NWID_HSCROLLBAR); if (pos < pt.x) { - sb->UpdatePosition(rtl ? 1 : -1, Scrollbar::SS_BIG); + changed = sb->UpdatePosition(rtl ? 1 : -1, Scrollbar::SS_BIG); } else if (pos > pt.y) { - sb->UpdatePosition(rtl ? -1 : 1, Scrollbar::SS_BIG); + changed = sb->UpdatePosition(rtl ? -1 : 1, Scrollbar::SS_BIG); } else { _scrollbar_start_pos = pt.x - mi - button_size; _scrollbar_size = ma - mi - button_size * 2; @@ -149,7 +150,13 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in } } - w->SetDirty(); + if (changed) { + /* Position changed so refresh the window */ + w->SetDirty(); + } else { + /* No change so only refresh this scrollbar */ + sb->SetDirty(w); + } } /** diff --git a/src/widget_type.h b/src/widget_type.h index 2007113565..c50a263d68 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -737,12 +737,15 @@ public: /** * Sets the position of the first visible element * @param position the position of the element + * @return true iff the position has changed */ - void SetPosition(int position) + bool SetPosition(int position) { assert(position >= 0); assert(this->count <= this->cap ? (position == 0) : (position + this->cap <= this->count)); + uint16 old_pos = this->pos; this->pos = position; + return this->pos != old_pos; } /** @@ -750,16 +753,17 @@ public: * If the position would be too low or high it will be clamped appropriately * @param difference the amount of change requested * @param unit The stepping unit of \a difference + * @return true iff the position has changed */ - void UpdatePosition(int difference, ScrollbarStepping unit = SS_SMALL) + bool UpdatePosition(int difference, ScrollbarStepping unit = SS_SMALL) { - if (difference == 0) return; + if (difference == 0) return false; switch (unit) { case SS_SMALL: difference *= this->stepsize; break; case SS_BIG: difference *= this->cap; break; default: break; } - this->SetPosition(Clamp(this->pos + difference, 0, std::max(this->count - this->cap, 0))); + return this->SetPosition(Clamp(this->pos + difference, 0, std::max(this->count - this->cap, 0))); } /** diff --git a/src/window.cpp b/src/window.cpp index 20c7ffbddf..d69a34144e 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -849,8 +849,7 @@ static void DispatchMouseWheelEvent(Window *w, NWidgetCore *nwid, int wheel) if (nwid->type == NWID_VSCROLLBAR) { NWidgetScrollbar *sb = static_cast(nwid); if (sb->GetCount() > sb->GetCapacity()) { - sb->UpdatePosition(wheel); - w->SetDirty(); + if (sb->UpdatePosition(wheel)) w->SetDirty(); } return; } @@ -858,8 +857,7 @@ static void DispatchMouseWheelEvent(Window *w, NWidgetCore *nwid, int wheel) /* Scroll the widget attached to the scrollbar. */ Scrollbar *sb = (nwid->scrollbar_index >= 0 ? w->GetScrollbar(nwid->scrollbar_index) : nullptr); if (sb != nullptr && sb->GetCount() > sb->GetCapacity()) { - sb->UpdatePosition(wheel); - w->SetDirty(); + if (sb->UpdatePosition(wheel)) w->SetDirty(); } } @@ -2413,8 +2411,7 @@ static void HandleScrollbarScrolling(Window *w) if (sb->disp_flags & ND_SCROLLBAR_BTN) { if (_scroller_click_timeout == 1) { _scroller_click_timeout = 3; - sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1); - w->SetDirty(); + if (sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1)) w->SetDirty(); } return; } From d8e06e590aff56c837b29ddbba3764292ea08d85 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 4 May 2021 00:24:14 +0100 Subject: [PATCH 115/800] Codechange: Make GetCurrentRect() conform to usual Rect bounds, and reuse it. Similar code is already repeated in other locations. --- src/station_gui.cpp | 4 ++-- src/widget.cpp | 18 +++--------------- src/widget_type.h | 4 ++-- src/widgets/dropdown.cpp | 6 +----- src/window.cpp | 5 +---- 5 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 98b44c6f98..cf3f455bc9 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1440,7 +1440,7 @@ struct StationViewWindow : public Window { if (!this->IsShaded()) { /* Draw 'accepted cargo' or 'cargo ratings'. */ const NWidgetBase *wid = this->GetWidget(WID_SV_ACCEPT_RATING_LIST); - const Rect r = {(int)wid->pos_x, (int)wid->pos_y, (int)(wid->pos_x + wid->current_x - 1), (int)(wid->pos_y + wid->current_y - 1)}; + const Rect r = wid->GetCurrentRect(); if (this->GetWidget(WID_SV_ACCEPTS_RATINGS)->widget_data == STR_STATION_VIEW_RATINGS_BUTTON) { int lines = this->DrawAcceptedCargo(r); if (lines > this->accepts_lines) { // Resize the widget, and perform re-initialization of the window. @@ -1468,7 +1468,7 @@ struct StationViewWindow : public Window { /* Draw waiting cargo. */ NWidgetBase *nwi = this->GetWidget(WID_SV_WAITING); - Rect waiting_rect = { (int)nwi->pos_x, (int)nwi->pos_y, (int)(nwi->pos_x + nwi->current_x - 1), (int)(nwi->pos_y + nwi->current_y - 1)}; + Rect waiting_rect = nwi->GetCurrentRect(); this->DrawEntries(&cargo, waiting_rect, pos, maxrows, 0); scroll_to_row = INT_MAX; } diff --git a/src/widget.cpp b/src/widget.cpp index 93a5afe953..aaa00d4d79 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1964,11 +1964,7 @@ void NWidgetBackground::Draw(const Window *w) { if (this->current_x == 0 || this->current_y == 0) return; - Rect r; - r.left = this->pos_x; - r.right = this->pos_x + this->current_x - 1; - r.top = this->pos_y; - r.bottom = this->pos_y + this->current_y - 1; + Rect r = this->GetCurrentRect(); const DrawPixelInfo *dpi = _cur_dpi; if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top) return; @@ -2232,11 +2228,7 @@ void NWidgetScrollbar::Draw(const Window *w) { if (this->current_x == 0 || this->current_y == 0) return; - Rect r; - r.left = this->pos_x; - r.right = this->pos_x + this->current_x - 1; - r.top = this->pos_y; - r.bottom = this->pos_y + this->current_y - 1; + Rect r = this->GetCurrentRect(); const DrawPixelInfo *dpi = _cur_dpi; if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top) return; @@ -2615,11 +2607,7 @@ void NWidgetLeaf::Draw(const Window *w) DrawPixelInfo *old_dpi = _cur_dpi; _cur_dpi = &new_dpi; - Rect r; - r.left = this->pos_x; - r.right = this->pos_x + this->current_x - 1; - r.top = this->pos_y; - r.bottom = this->pos_y + this->current_y - 1; + Rect r = this->GetCurrentRect(); bool clicked = this->IsLowered(); switch (this->type) { diff --git a/src/widget_type.h b/src/widget_type.h index c50a263d68..a5bd988492 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -167,8 +167,8 @@ public: Rect r; r.left = this->pos_x; r.top = this->pos_y; - r.right = this->pos_x + this->current_x; - r.bottom = this->pos_y + this->current_y; + r.right = this->pos_x + this->current_x - 1; + r.bottom = this->pos_y + this->current_y - 1; return r; } diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 4b89b48092..b6f7de3c18 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -448,12 +448,8 @@ void ShowDropDownList(Window *w, DropDownList &&list, int selected, int button, { /* Our parent's button widget is used to determine where to place the drop * down list window. */ - Rect wi_rect; NWidgetCore *nwi = w->GetWidget(button); - wi_rect.left = nwi->pos_x; - wi_rect.right = nwi->pos_x + nwi->current_x - 1; - wi_rect.top = nwi->pos_y; - wi_rect.bottom = nwi->pos_y + nwi->current_y - 1; + Rect wi_rect = nwi->GetCurrentRect(); Colours wi_colour = nwi->colour; if ((nwi->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) { diff --git a/src/window.cpp b/src/window.cpp index d69a34144e..3fcda7d42d 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2097,10 +2097,7 @@ static void EnsureVisibleCaption(Window *w, int nx, int ny) Rect caption_rect; const NWidgetBase *caption = w->nested_root->GetWidgetOfType(WWT_CAPTION); if (caption != nullptr) { - caption_rect.left = caption->pos_x; - caption_rect.right = caption->pos_x + caption->current_x; - caption_rect.top = caption->pos_y; - caption_rect.bottom = caption->pos_y + caption->current_y; + caption_rect = caption->GetCurrentRect(); /* Make sure the window doesn't leave the screen */ nx = Clamp(nx, MIN_VISIBLE_TITLE_BAR - caption_rect.right, _screen.width - MIN_VISIBLE_TITLE_BAR - caption_rect.left); From dd41de89315156cf7c5e43872de0863d4c539a95 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 7 May 2021 22:33:48 +0100 Subject: [PATCH 116/800] Codechange: Slider widget used different range for drawing vs setting. Using the same range for setting means that no workaround for setting the extremes is necessary. --- src/widgets/slider.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/widgets/slider.cpp b/src/widgets/slider.cpp index 6d6d732884..67c4c372d2 100644 --- a/src/widgets/slider.cpp +++ b/src/widgets/slider.cpp @@ -16,6 +16,7 @@ #include "../safeguards.h" +static const int SLIDER_WIDTH = 3; /** * Draw a volume slider widget with know at given value @@ -24,8 +25,6 @@ */ void DrawVolumeSliderWidget(Rect r, byte value) { - static const int slider_width = 3; - /* Draw a wedge indicating low to high volume level. */ const int ha = (r.bottom - r.top) / 5; int wx1 = r.left, wx2 = r.right; @@ -40,7 +39,7 @@ void DrawVolumeSliderWidget(Rect r, byte value) GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow); /* Draw a slider handle indicating current volume level. */ - const int sw = ScaleGUITrad(slider_width); + const int sw = ScaleGUITrad(SLIDER_WIDTH); if (_current_text_dir == TD_RTL) value = 127 - value; const int x = r.left + (value * (r.right - r.left - sw) / 127); DrawFrameRect(x, r.top, x + sw, r.bottom, COLOUR_GREY, FR_NONE); @@ -55,12 +54,10 @@ void DrawVolumeSliderWidget(Rect r, byte value) */ bool ClickVolumeSliderWidget(Rect r, Point pt, byte &value) { - byte new_vol = Clamp((pt.x - r.left) * 127 / (r.right - r.left), 0, 127); + const int sw = ScaleGUITrad(SLIDER_WIDTH); + byte new_vol = Clamp((pt.x - r.left - sw / 2) * 127 / (r.right - r.left - sw), 0, 127); if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol; - /* Clamp to make sure min and max are properly settable */ - if (new_vol > 124) new_vol = 127; - if (new_vol < 3) new_vol = 0; if (new_vol != value) { value = new_vol; return true; From 8c3fa2a3bf079424529a49b58f0466e4285d5874 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sat, 8 May 2021 09:54:32 +0100 Subject: [PATCH 117/800] Fix #9209: Excessive time resizing highscore/news window when screen is too small. (#9210) If the highscore/news window panel size, which is now scaled by GUI zoom, is larger than the screen size, a loop will be entered where the window is repeatedly resized. This is resolved by removing the minimal size from the panel, as the window is always resized to cover the screen anyway. This means the screen size can never be too small. --- src/highscore_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index b1c428a768..356235fa03 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -205,7 +205,7 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow { }; static const NWidgetPart _nested_highscore_widgets[] = { - NWidget(WWT_PANEL, COLOUR_BROWN, WID_H_BACKGROUND), SetMinimalSize(641, 481), SetResize(1, 1), EndContainer(), + NWidget(WWT_PANEL, COLOUR_BROWN, WID_H_BACKGROUND), SetResize(1, 1), EndContainer(), }; static WindowDesc _highscore_desc( From f187708b3b6bcb95a0d92908f8a90c1431ca2578 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 8 May 2021 11:57:41 +0200 Subject: [PATCH 118/800] Fix f7e390bd: getpeername() doesn't work on closed sockets (#9213) --- src/network/core/tcp.h | 4 +++- src/network/core/tcp_connect.cpp | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index b90ce0232c..624555649d 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -15,8 +15,9 @@ #include "address.h" #include "packet.h" -#include #include +#include +#include /** The states of sending the packets. */ enum SendPacketsState { @@ -66,6 +67,7 @@ class TCPConnecter { private: addrinfo *ai = nullptr; ///< getaddrinfo() allocated linked-list of resolved addresses. std::vector addresses; ///< Addresses we can connect to. + std::map sock_to_address; ///< Mapping of a socket to the real address it is connecting to. USed for DEBUG statements. size_t current_address = 0; ///< Current index in addresses we are trying. std::vector sockets; ///< Pending connect() attempts. diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index cca9f09b71..a1e369295a 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -40,8 +40,10 @@ TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_ TCPConnecter::~TCPConnecter() { for (const auto &socket : this->sockets) { - close(socket); + closesocket(socket); } + this->sockets.clear(); + this->sock_to_address.clear(); freeaddrinfo(this->ai); } @@ -72,6 +74,7 @@ void TCPConnecter::Connect(addrinfo *address) return; } + this->sock_to_address[sock] = network_address; this->sockets.push_back(sock); } @@ -245,6 +248,9 @@ bool TCPConnecter::CheckActivity() for (const auto &socket : this->sockets) { closesocket(socket); } + this->sockets.clear(); + this->sock_to_address.clear(); + this->OnFailure(); return true; } @@ -253,8 +259,9 @@ bool TCPConnecter::CheckActivity() for (auto it = this->sockets.begin(); it != this->sockets.end(); /* nothing */) { NetworkError socket_error = GetSocketError(*it); if (socket_error.HasError()) { - DEBUG(net, 1, "Could not connect to %s: %s", NetworkAddress::GetPeerName(*it).c_str(), socket_error.AsString()); + DEBUG(net, 1, "Could not connect to %s: %s", this->sock_to_address[*it].GetAddressAsString().c_str(), socket_error.AsString()); closesocket(*it); + this->sock_to_address.erase(*it); it = this->sockets.erase(it); } else { it++; @@ -280,6 +287,7 @@ bool TCPConnecter::CheckActivity() } else { closesocket(*it); } + this->sock_to_address.erase(*it); it = this->sockets.erase(it); } assert(connected_socket != INVALID_SOCKET); From 881e1da51d47bde0b6ddf86be1da55aceced7839 Mon Sep 17 00:00:00 2001 From: William Davis Date: Sat, 8 May 2021 06:02:30 -0400 Subject: [PATCH 119/800] Change: Use gender-neutral pronouns in console command messages (and comments) (#9203) --- src/console_cmds.cpp | 8 ++++---- src/economy.cpp | 2 +- src/industry_cmd.cpp | 2 +- src/network/network_client.cpp | 8 ++++---- src/network/network_server.cpp | 8 ++++---- src/network/network_server.h | 2 +- src/openttd.cpp | 2 +- src/order_cmd.cpp | 2 +- src/roadveh_cmd.cpp | 2 +- src/saveload/ai_sl.cpp | 2 +- src/saveload/game_sl.cpp | 2 +- src/saveload/saveload.h | 2 +- src/script/api/script_companymode.hpp | 2 +- src/script/api/script_event_types.hpp | 2 +- src/script/api/script_execmode.hpp | 2 +- src/script/api/script_stationlist.hpp | 2 +- src/script/api/script_testmode.hpp | 2 +- src/script/squirrel_class.hpp | 4 ++-- src/town_cmd.cpp | 2 +- 19 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 99b3b54582..01c35ecf88 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -485,7 +485,7 @@ static bool ConKickOrBan(const char *argv, bool ban, const char *reason) * would be reading from and writing to after returning. So we would read or write data * from freed memory up till the segfault triggers. */ if (client_id == CLIENT_ID_SERVER || client_id == _redirect_console_to_client) { - IConsolePrintF(CC_ERROR, "ERROR: Silly boy, you can not %s yourself!", ban ? "ban" : "kick"); + IConsolePrintF(CC_ERROR, "ERROR: You can not %s yourself!", ban ? "ban" : "kick"); return true; } @@ -544,7 +544,7 @@ DEF_CONSOLE_CMD(ConBan) if (argc == 0) { IConsoleHelp("Ban a client from a network game. Usage: 'ban []'"); IConsoleHelp("For client-id's, see the command 'clients'"); - IConsoleHelp("If the client is no longer online, you can still ban his/her IP"); + IConsoleHelp("If the client is no longer online, you can still ban their IP"); return true; } @@ -806,12 +806,12 @@ DEF_CONSOLE_CMD(ConMoveClient) } if (ci->client_id == CLIENT_ID_SERVER && _network_dedicated) { - IConsoleError("Silly boy, you cannot move the server!"); + IConsoleError("You cannot move the server!"); return true; } if (ci->client_playas == company_id) { - IConsoleError("You cannot move someone to where he/she already is!"); + IConsoleError("You cannot move someone to where they already are!"); return true; } diff --git a/src/economy.cpp b/src/economy.cpp index 9982e79e02..ae289a51da 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -607,7 +607,7 @@ static void CompanyCheckBankrupt(Company *c) if (!_networking && _local_company == c->index) { /* If we are in singleplayer mode, leave the company playing. Eg. there * is no THE-END, otherwise mark the client as spectator to make sure - * he/she is no long in control of this company. However... when you + * they are no longer in control of this company. However... when you * join another company (cheat) the "unowned" company can bankrupt. */ c->bankrupt_asked = MAX_UVALUE(CompanyMask); break; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 37bbd915c3..f9e75ed880 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2579,7 +2579,7 @@ static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accept /** * Compute who can service the industry. * - * Here, 'can service' means that he/she has trains and stations close enough + * Here, 'can service' means that they have trains and stations close enough * to the industry with the right cargo type and the right orders (ie has the * technical means). * diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 190bb29450..f827c57351 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -194,8 +194,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvSta */ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) { - /* First, send a CLIENT_ERROR to the server, so he knows we are - * disconnection (and why!) */ + /* First, send a CLIENT_ERROR to the server, so it knows we are + * disconnected (and why!) */ NetworkErrorCode errorno; /* We just want to close the connection.. */ @@ -293,7 +293,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) /* If this is the first time we have a sync-frame, we * need to let the server know that we are ready and at the same - * frame as he is.. so we can start playing! */ + * frame as it is.. so we can start playing! */ if (_network_first_time) { _network_first_time = false; SendAck(); @@ -1399,7 +1399,7 @@ void NetworkClientSetCompanyPassword(const char *password) } /** - * Tell whether the client has team members where he/she can chat to. + * Tell whether the client has team members who they can chat to. * @param cio client to check members of. * @return true if there is at least one team member. */ diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 1a9ddecfbc..e8266a84fc 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1027,7 +1027,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet * InvalidateWindowData(WC_CLIENT_LIST, 0); /* Mark the client as pre-active, and wait for an ACK - * so we know he is done loading and in sync with us */ + * so we know it is done loading and in sync with us */ this->status = STATUS_PRE_ACTIVE; NetworkHandleCommandQueue(this); this->SendFrame(); @@ -1199,7 +1199,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p) /* The client is not yet caught up? */ if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY; - /* Now he is! Unpause the game */ + /* Now it is! Unpause the game */ this->status = STATUS_ACTIVE; this->last_token_frame = _frame_counter; @@ -1855,14 +1855,14 @@ void NetworkServer_Tick(bool send_frame) case NetworkClientSocket::STATUS_MAP_WAIT: /* Send every two seconds a packet to the client, to make sure - * he knows the server is still there; just someone else is + * it knows the server is still there; just someone else is * still receiving the map. */ if (std::chrono::steady_clock::now() > cs->last_packet + std::chrono::seconds(2)) { cs->SendWait(); /* We need to reset the timer, as otherwise we will be * spamming the client. Strictly speaking this variable * tracks when we last received a packet from the client, - * but as he is waiting, he will not send us any till we + * but as it is waiting, it will not send us any till we * start sending him data. */ cs->last_packet = std::chrono::steady_clock::now(); } diff --git a/src/network/network_server.h b/src/network/network_server.h index e72377e824..fb4c4f63eb 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -72,7 +72,7 @@ public: size_t receive_limit; ///< Amount of bytes that we can receive at this moment struct PacketWriter *savegame; ///< Writer used to write the savegame. - NetworkAddress client_address; ///< IP-address of the client (so he can be banned) + NetworkAddress client_address; ///< IP-address of the client (so they can be banned) ServerNetworkGameSocketHandler(SOCKET s); ~ServerNetworkGameSocketHandler(); diff --git a/src/openttd.cpp b/src/openttd.cpp index d9e0b835e0..d8b197466a 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -652,7 +652,7 @@ int openttd_main(int argc, char *argv[]) } if (i == -2 || mgo.numleft > 0) { - /* Either the user typed '-h', he made an error, or he added unrecognized command line arguments. + /* Either the user typed '-h', they made an error, or they added unrecognized command line arguments. * In all cases, print the help, and exit. * * The next two functions are needed to list the graphics sets. We can't do them earlier diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 082ec1ae33..c4793fa33b 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -660,7 +660,7 @@ static inline bool OrderGoesToStation(const Vehicle *v, const Order *o) * Delete all news items regarding defective orders about a vehicle * This could kill still valid warnings (for example about void order when just * another order gets added), but assume the company will notice the problems, - * when (s)he's changing the orders. + * when they're changing the orders. */ static void DeleteOrderWarnings(const Vehicle *v) { diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 1a4e4e0852..d44a37c872 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1257,7 +1257,7 @@ again: tile = v->tile; start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM; } else { - /* The company can build on the next tile, so wait till (s)he does. */ + /* The company can build on the next tile, so wait till they do. */ v->cur_speed = 0; return false; } diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index 9b58aea11c..0ece819813 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -98,7 +98,7 @@ static void Load_AIPL() DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version); DEBUG(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible."); } - /* Make sure the AI doesn't get the saveload data, as he was not the + /* Make sure the AI doesn't get the saveload data, as it was not the * writer of the saveload data in the first place */ _ai_saveload_version = -1; } diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index e134843850..b570d1054d 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -90,7 +90,7 @@ static void Load_GSDT() DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible."); } - /* Make sure the GameScript doesn't get the saveload data, as he was not the + /* Make sure the GameScript doesn't get the saveload data, as it was not the * writer of the saveload data in the first place */ _game_saveload_version = -1; } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index cda6af82b6..28513c70c1 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -313,7 +313,7 @@ enum SaveLoadVersion : uint16 { * cannot digest. But, this gives for ugly errors. As we have plenty of * versions anyway, we simply skip the versions we know belong to * patchpacks. This way we can present the user with a clean error - * indicate he is loading a savegame from a patchpack. + * indicate they are loading a savegame from a patchpack. * For future patchpack creators: please follow a system like JGRPP, where * the version is masked with 0x8000, and the true version is stored in * its own chunk with feature toggles. diff --git a/src/script/api/script_companymode.hpp b/src/script/api/script_companymode.hpp index 4eba2dd9f7..e00cc7bfb0 100644 --- a/src/script/api/script_companymode.hpp +++ b/src/script/api/script_companymode.hpp @@ -37,7 +37,7 @@ public: * Creating instance of this class switches the company used for queries * and commands. * @param company The new company to switch to. - * @note When the instance is destroyed, he restores the company that was + * @note When the instance is destroyed, it restores the company that was * current when the instance was created! */ ScriptCompanyMode(int company); diff --git a/src/script/api/script_event_types.hpp b/src/script/api/script_event_types.hpp index f0487f48a0..1d514389b5 100644 --- a/src/script/api/script_event_types.hpp +++ b/src/script/api/script_event_types.hpp @@ -968,7 +968,7 @@ public: private: uint16 uniqueid; ///< The uniqueid of the question. ScriptCompany::CompanyID company; ///< The company given the answer. - ScriptGoal::QuestionButton button; ///< The button he pressed. + ScriptGoal::QuestionButton button; ///< The button that was pressed. }; /** diff --git a/src/script/api/script_execmode.hpp b/src/script/api/script_execmode.hpp index 8e4fd71578..f7ea55a1f6 100644 --- a/src/script/api/script_execmode.hpp +++ b/src/script/api/script_execmode.hpp @@ -34,7 +34,7 @@ protected: public: /** * Creating instance of this class switches the build mode to Execute. - * @note When the instance is destroyed, he restores the mode that was + * @note When the instance is destroyed, it restores the mode that was * current when the instance was created! */ ScriptExecMode(); diff --git a/src/script/api/script_stationlist.hpp b/src/script/api/script_stationlist.hpp index ee862cb935..8628dbb4a3 100644 --- a/src/script/api/script_stationlist.hpp +++ b/src/script/api/script_stationlist.hpp @@ -279,7 +279,7 @@ public: class ScriptStationList_Vehicle : public ScriptList { public: /** - * @param vehicle_id The vehicle to get the list of stations he has in its orders from. + * @param vehicle_id The vehicle to get the list of stations it has in its orders from. */ ScriptStationList_Vehicle(VehicleID vehicle_id); }; diff --git a/src/script/api/script_testmode.hpp b/src/script/api/script_testmode.hpp index eddd9340a7..956a25e2d6 100644 --- a/src/script/api/script_testmode.hpp +++ b/src/script/api/script_testmode.hpp @@ -36,7 +36,7 @@ protected: public: /** * Creating instance of this class switches the build mode to Testing. - * @note When the instance is destroyed, he restores the mode that was + * @note When the instance is destroyed, it restores the mode that was * current when the instance was created! */ ScriptTestMode(); diff --git a/src/script/squirrel_class.hpp b/src/script/squirrel_class.hpp index b600839d4d..8794e2441a 100644 --- a/src/script/squirrel_class.hpp +++ b/src/script/squirrel_class.hpp @@ -48,7 +48,7 @@ public: /** * This defines a method inside a class for Squirrel with defined params. - * @note If you define nparam, make sure that he first param is always 'x', + * @note If you define nparam, make sure that the first param is always 'x', * which is the 'this' inside the function. This is hidden from the rest * of the code, but without it calling your function will fail! */ @@ -81,7 +81,7 @@ public: /** * This defines a static method inside a class for Squirrel with defined params. - * @note If you define nparam, make sure that he first param is always 'x', + * @note If you define nparam, make sure that the first param is always 'x', * which is the 'this' inside the function. This is hidden from the rest * of the code, but without it calling your function will fail! */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index a0f5df23ed..01331a269e 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -3209,7 +3209,7 @@ static CommandCost TownActionFundBuildings(Town *t, DoCommandFlag flags) * than 1 house per 2 * TOWN_GROWTH_TICKS ticks. * Also emulate original behaviour when town was only growing in * TOWN_GROWTH_TICKS intervals, to make sure that it's not too - * tick-perfect and gives player some time window where he can + * tick-perfect and gives player some time window where they can * spam funding with the exact same efficiency. */ t->grow_counter = std::min(t->grow_counter, 2 * TOWN_GROWTH_TICKS - (t->growth_rate - t->grow_counter) % TOWN_GROWTH_TICKS); From 69e5da0b544e83ed445cf500938c24602230fa2c Mon Sep 17 00:00:00 2001 From: PeterN Date: Sat, 8 May 2021 11:36:39 +0100 Subject: [PATCH 120/800] Codechange: Don't save unused NewGRF override mappings. (#9202) --- src/newgrf_commons.h | 1 + src/saveload/newgrf_sl.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index ed18aaa9e2..b86e3d10af 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -218,6 +218,7 @@ public: inline uint16 GetMaxMapping() const { return max_new_entities; } inline uint16 GetMaxOffset() const { return max_offset; } + inline bool IsValidID(uint16 entity_id) const { return entity_overrides[entity_id] != invalid_ID; } }; diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index b2d2b0df99..f7f6ab72e0 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -30,6 +30,7 @@ static const SaveLoad _newgrf_mapping_desc[] = { void Save_NewGRFMapping(const OverrideManagerBase &mapping) { for (uint i = 0; i < mapping.GetMaxMapping(); i++) { + if (!mapping.IsValidID(i)) continue; SlSetArrayIndex(i); SlObject(&mapping.mapping_ID[i], _newgrf_mapping_desc); } From 8e0b1b5d1a4cc8c72e662416a9de58066e9ceb37 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 13 Apr 2021 21:36:01 +0200 Subject: [PATCH 121/800] Add: concept of a RandomAccessFile to replace the FIO slot functions --- src/CMakeLists.txt | 2 + src/random_access_file.cpp | 156 ++++++++++++++++++++++++++++++++++ src/random_access_file_type.h | 58 +++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 src/random_access_file.cpp create mode 100644 src/random_access_file_type.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0af799994..2d4fffc8c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -309,6 +309,8 @@ add_files( rail_gui.h rail_map.h rail_type.h + random_access_file.cpp + random_access_file_type.h rev.h road.cpp road.h diff --git a/src/random_access_file.cpp b/src/random_access_file.cpp new file mode 100644 index 0000000000..2fd6a64b64 --- /dev/null +++ b/src/random_access_file.cpp @@ -0,0 +1,156 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + + /** @file random_access_file.cpp Actual implementation of the RandomAccessFile class. */ + +#include "stdafx.h" +#include "random_access_file_type.h" + +#include "debug.h" +#include "fileio_func.h" +#include "string_func.h" + +#include "safeguards.h" + +/** + * Create the RandomAccesFile. + * @param filename Name of the file at the disk. + * @param subdir The sub directory to search this file in. + */ +RandomAccessFile::RandomAccessFile(const std::string &filename, Subdirectory subdir) : filename(filename) +{ + this->file_handle = FioFOpenFile(filename, "rb", subdir); + if (this->file_handle == nullptr) usererror("Cannot open file '%s'", filename.c_str()); + + /* When files are in a tar-file, the begin of the file might not be at 0. */ + long pos = ftell(this->file_handle); + if (pos < 0) usererror("Cannot read file '%s'", filename.c_str()); + + /* Store the filename without path and extension */ + auto t = filename.rfind(PATHSEPCHAR); + std::string name_without_path = filename.substr(t != std::string::npos ? t + 1 : 0); + this->simplified_filename = name_without_path.substr(0, name_without_path.rfind('.')); + strtolower(this->simplified_filename); + + this->SeekTo((size_t)pos, SEEK_SET); +} + +/** + * Close the file's file handle. + */ +RandomAccessFile::~RandomAccessFile() +{ + fclose(this->file_handle); +} + +/** + * Get the filename of the opened file with the path from the SubDirectory and the extension. + * @return Name of the file. + */ +const std::string& RandomAccessFile::GetFilename() const +{ + return this->filename; +} + +/** + * Get the simplified filename of the opened file. The simplified filename is the name of the + * file without the SubDirectory or extension in lower case. + * @return Name of the file. + */ +const std::string& RandomAccessFile::GetSimplifiedFilename() const +{ + return this->simplified_filename; +} + +/** + * Get position in the file. + * @return Position in the file. + */ +size_t RandomAccessFile::GetPos() const +{ + return this->pos + (this->buffer - this->buffer_end); +} + +/** + * Seek in the current file. + * @param pos New position. + * @param mode Type of seek (\c SEEK_CUR means \a pos is relative to current position, \c SEEK_SET means \a pos is absolute). + */ +void RandomAccessFile::SeekTo(size_t pos, int mode) +{ + if (mode == SEEK_CUR) pos += this->GetPos(); + + this->pos = pos; + if (fseek(this->file_handle, this->pos, SEEK_SET) < 0) { + DEBUG(misc, 0, "Seeking in %s failed", this->filename.c_str()); + } + + /* Reset the buffer, so the next ReadByte will read bytes from the file. */ + this->buffer = this->buffer_end = this->buffer_start; +} + +/** + * Read a byte from the file. + * @return Read byte. + */ +byte RandomAccessFile::ReadByte() +{ + if (this->buffer == this->buffer_end) { + this->buffer = this->buffer_start; + size_t size = fread(this->buffer, 1, RandomAccessFile::BUFFER_SIZE, this->file_handle); + this->pos += size; + this->buffer_end = this->buffer_start + size; + + if (size == 0) return 0; + } + return *this->buffer++; +} + +/** + * Read a word (16 bits) from the file (in low endian format). + * @return Read word. + */ +uint16 RandomAccessFile::ReadWord() +{ + byte b = this->ReadByte(); + return (this->ReadByte() << 8) | b; +} + +/** + * Read a double word (32 bits) from the file (in low endian format). + * @return Read word. + */ +uint32 RandomAccessFile::ReadDword() +{ + uint b = this->ReadWord(); + return (this->ReadWord() << 16) | b; +} + +/** + * Read a block. + * @param ptr Destination buffer. + * @param size Number of bytes to read. + */ +void RandomAccessFile::ReadBlock(void *ptr, size_t size) +{ + this->SeekTo(this->GetPos(), SEEK_SET); + this->pos += fread(ptr, 1, size, this->file_handle); +} + +/** + * Skip \a n bytes ahead in the file. + * @param n Number of bytes to skip reading. + */ +void RandomAccessFile::SkipBytes(int n) +{ + int remaining = this->buffer_end - this->buffer; + if (n <= remaining) { + this->buffer += n; + } else { + this->SeekTo(n, SEEK_CUR); + } +} diff --git a/src/random_access_file_type.h b/src/random_access_file_type.h new file mode 100644 index 0000000000..ce0e9e3584 --- /dev/null +++ b/src/random_access_file_type.h @@ -0,0 +1,58 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + + /** @file random_access_file_type.h Class related to random access to files. */ + +#ifndef RANDOM_ACCESS_FILE_TYPE_H +#define RANDOM_ACCESS_FILE_TYPE_H + +#include "fileio_type.h" +#include + +/** + * A file from which bytes, words and double words are read in (potentially) a random order. + * + * This is mostly intended to be used for things that can be read from GRFs when needed, so + * the graphics but also the sounds. This also ties into the spritecache as it uses these + * files to load the sprites from when needed. + */ +class RandomAccessFile { + /** The number of bytes to allocate for the buffer. */ + static constexpr int BUFFER_SIZE = 512; + + std::string filename; ///< Full name of the file; relative path to subdir plus the extension of the file. + std::string simplified_filename; ///< Simplified lowecase name of the file; only the name, no path or extension. + + FILE *file_handle; ///< File handle of the open file. + size_t pos; ///< Position in the file of the end of the read buffer. + + byte *buffer; ///< Current position within the local buffer. + byte *buffer_end; ///< Last valid byte of buffer. + byte buffer_start[BUFFER_SIZE]; ///< Local buffer when read from file. + +public: + RandomAccessFile(const std::string &filename, Subdirectory subdir); + RandomAccessFile(const RandomAccessFile&) = delete; + void operator=(const RandomAccessFile&) = delete; + + virtual ~RandomAccessFile(); + + const std::string &GetFilename() const; + const std::string &GetSimplifiedFilename() const; + + size_t GetPos() const; + void SeekTo(size_t pos, int mode); + + byte ReadByte(); + uint16 ReadWord(); + uint32 ReadDword(); + + void ReadBlock(void *ptr, size_t size); + void SkipBytes(int n); +}; + +#endif /* RANDOM_ACCESS_FILE_TYPE_H */ From b144e56b2c4d92baa868435818a99faa8ed06439 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 13 Apr 2021 21:36:24 +0200 Subject: [PATCH 122/800] Codechange: use the new RandomAccessFile as backend for the FIO slot functions --- src/fileio.cpp | 109 ++++++++----------------------------- src/random_access_file.cpp | 4 +- 2 files changed, 24 insertions(+), 89 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 810f3f34ef..465e713048 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "fileio_func.h" +#include "random_access_file_type.h" #include "debug.h" #include "fios.h" #include "string_func.h" @@ -29,22 +30,8 @@ #include "safeguards.h" -/** Size of the #Fio data buffer. */ -#define FIO_BUFFER_SIZE 512 - -/** Structure for keeping several open files with just one data buffer. */ -struct Fio { - byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer - byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file - size_t pos; ///< current (system) position in file - FILE *cur_fh; ///< current file handle - std::string filename; ///< current filename - std::array handles; ///< array of file handles we can have open - std::array filenames; ///< array of filenames we (should) have open - std::array shortnames;///< array of short names for spriteloader's use -}; - -static Fio _fio; ///< #Fio instance. +static RandomAccessFile *_fio_current_file; ///< current file handle for the Fio functions +static std::array _fio_files; ///< array of random access files we can have open /** Whether the working directory should be scanned. */ static bool _do_scan_working_directory = true; @@ -58,7 +45,7 @@ extern std::string _highscore_file; */ size_t FioGetPos() { - return _fio.pos + (_fio.buffer - _fio.buffer_end); + return _fio_current_file->GetPos(); } /** @@ -68,7 +55,7 @@ size_t FioGetPos() */ const char *FioGetFilename(uint8 slot) { - return _fio.shortnames[slot].c_str(); + return _fio_current_file->GetSimplifiedFilename().c_str(); } /** @@ -78,12 +65,7 @@ const char *FioGetFilename(uint8 slot) */ void FioSeekTo(size_t pos, int mode) { - if (mode == SEEK_CUR) pos += FioGetPos(); - _fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE; - _fio.pos = pos; - if (fseek(_fio.cur_fh, _fio.pos, SEEK_SET) < 0) { - DEBUG(misc, 0, "Seeking in %s failed", _fio.filename.c_str()); - } + _fio_current_file->SeekTo(pos, mode); } /** @@ -93,11 +75,10 @@ void FioSeekTo(size_t pos, int mode) */ void FioSeekToFile(uint8 slot, size_t pos) { - FILE *f = _fio.handles[slot]; - assert(f != nullptr); - _fio.cur_fh = f; - _fio.filename = _fio.filenames[slot]; - FioSeekTo(pos, SEEK_SET); + RandomAccessFile *raf = _fio_files[slot]; + assert(raf != nullptr); + _fio_current_file = raf; + _fio_current_file->SeekTo(pos, SEEK_SET); } /** @@ -106,15 +87,7 @@ void FioSeekToFile(uint8 slot, size_t pos) */ byte FioReadByte() { - if (_fio.buffer == _fio.buffer_end) { - _fio.buffer = _fio.buffer_start; - size_t size = fread(_fio.buffer, 1, FIO_BUFFER_SIZE, _fio.cur_fh); - _fio.pos += size; - _fio.buffer_end = _fio.buffer_start + size; - - if (size == 0) return 0; - } - return *_fio.buffer++; + return _fio_current_file->ReadByte(); } /** @@ -123,14 +96,7 @@ byte FioReadByte() */ void FioSkipBytes(int n) { - for (;;) { - int m = std::min(_fio.buffer_end - _fio.buffer, n); - _fio.buffer += m; - n -= m; - if (n == 0) break; - FioReadByte(); - n--; - } + return _fio_current_file->SkipBytes(n); } /** @@ -139,8 +105,7 @@ void FioSkipBytes(int n) */ uint16 FioReadWord() { - byte b = FioReadByte(); - return (FioReadByte() << 8) | b; + return _fio_current_file->ReadWord(); } /** @@ -149,8 +114,7 @@ uint16 FioReadWord() */ uint32 FioReadDword() { - uint b = FioReadWord(); - return (FioReadWord() << 16) | b; + return _fio_current_file->ReadDword(); } /** @@ -160,30 +124,15 @@ uint32 FioReadDword() */ void FioReadBlock(void *ptr, size_t size) { - FioSeekTo(FioGetPos(), SEEK_SET); - _fio.pos += fread(ptr, 1, size, _fio.cur_fh); -} - -/** - * Close the file at the given slot number. - * @param slot File index to close. - */ -static inline void FioCloseFile(int slot) -{ - if (_fio.handles[slot] != nullptr) { - fclose(_fio.handles[slot]); - - _fio.shortnames[slot].clear(); - - _fio.handles[slot] = nullptr; - } + _fio_current_file->ReadBlock(ptr, size); } /** Close all slotted open files. */ void FioCloseAll() { - for (int i = 0; i != lengthof(_fio.handles); i++) { - FioCloseFile(i); + for (int i = 0; i != lengthof(_fio_files); i++) { + delete _fio_files[i]; + _fio_files[i] = nullptr; } } @@ -195,24 +144,10 @@ void FioCloseAll() */ void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir) { - FILE *f; - - f = FioFOpenFile(filename, "rb", subdir); - if (f == nullptr) usererror("Cannot open file '%s'", filename.c_str()); - long pos = ftell(f); - if (pos < 0) usererror("Cannot read file '%s'", filename.c_str()); - - FioCloseFile(slot); // if file was opened before, close it - _fio.handles[slot] = f; - _fio.filenames[slot] = filename; - - /* Store the filename without path and extension */ - auto t = filename.rfind(PATHSEPCHAR); - std::string sn = filename.substr(t != std::string::npos ? t + 1 : 0); - _fio.shortnames[slot] = sn.substr(0, sn.rfind('.')); - strtolower(_fio.shortnames[slot]); - - FioSeekToFile(slot, (size_t)pos); + RandomAccessFile *raf = new RandomAccessFile(filename, subdir); + delete _fio_files[slot]; + _fio_files[slot] = raf; + _fio_current_file = raf; } static const char * const _subdirs[] = { diff --git a/src/random_access_file.cpp b/src/random_access_file.cpp index 2fd6a64b64..72f2078377 100644 --- a/src/random_access_file.cpp +++ b/src/random_access_file.cpp @@ -51,7 +51,7 @@ RandomAccessFile::~RandomAccessFile() * Get the filename of the opened file with the path from the SubDirectory and the extension. * @return Name of the file. */ -const std::string& RandomAccessFile::GetFilename() const +const std::string &RandomAccessFile::GetFilename() const { return this->filename; } @@ -61,7 +61,7 @@ const std::string& RandomAccessFile::GetFilename() const * file without the SubDirectory or extension in lower case. * @return Name of the file. */ -const std::string& RandomAccessFile::GetSimplifiedFilename() const +const std::string &RandomAccessFile::GetSimplifiedFilename() const { return this->simplified_filename; } From c097bc9d7d610b613f76152b3cdcb9be2af7a1c7 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 13 Apr 2021 21:58:56 +0200 Subject: [PATCH 123/800] Codechange: let NewGRF sounds make use of RandomAccessFile instead of the FIO slot functions --- src/fileio.cpp | 8 ++++++ src/fileio_func.h | 1 + src/fios.h | 2 -- src/newgrf.cpp | 2 +- src/newgrf_sound.cpp | 63 +++++++++++++++++++++--------------------- src/sound.cpp | 65 ++++++++++++++++++++++++-------------------- src/sound_type.h | 2 +- 7 files changed, 79 insertions(+), 64 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 465e713048..6b13e30890 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -39,6 +39,14 @@ static bool _do_scan_working_directory = true; extern std::string _config_file; extern std::string _highscore_file; +/** + * Transition helper to get the RandomAccessFile associated with a given slot. + */ +RandomAccessFile *FioGetRandomAccessFile(int slot) +{ + return _fio_files[slot]; +} + /** * Get position in the current file. * @return Position in the file. diff --git a/src/fileio_func.h b/src/fileio_func.h index 4b9b2dd9ee..55fac39efd 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -26,6 +26,7 @@ void FioCloseAll(); void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir); void FioReadBlock(void *ptr, size_t size); void FioSkipBytes(int n); +class RandomAccessFile *FioGetRandomAccessFile(int slot); void FioFCloseFile(FILE *f); FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); diff --git a/src/fios.h b/src/fios.h index 28a1cc6aa5..5029d4862f 100644 --- a/src/fios.h +++ b/src/fios.h @@ -91,8 +91,6 @@ enum FileSlots { * and thus cannot be used for files, which are continuously accessed during a game. */ CONFIG_SLOT = 0, - /** Slot for the sound. */ - SOUND_SLOT = 1, /** First slot usable for (New)GRFs used during the game. */ FIRST_GRF_SLOT = 2, /** Maximum number of slots. */ diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 3a4fe12619..b51a18b437 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7553,7 +7553,7 @@ static void LoadGRFSound(size_t offs, SoundEntry *sound) if (offs != SIZE_MAX) { /* Sound is present in the NewGRF. */ - sound->file_slot = _cur.file_index; + sound->file = FioGetRandomAccessFile(_cur.file_index); sound->file_offset = offs; sound->grf_container_ver = _cur.grf_container_ver; } diff --git a/src/newgrf_sound.cpp b/src/newgrf_sound.cpp index aead090016..523b210d1c 100644 --- a/src/newgrf_sound.cpp +++ b/src/newgrf_sound.cpp @@ -14,7 +14,7 @@ #include "newgrf_sound.h" #include "vehicle_base.h" #include "sound_func.h" -#include "fileio_func.h" +#include "random_access_file_type.h" #include "debug.h" #include "settings_type.h" @@ -65,56 +65,57 @@ uint GetNumSounds() */ bool LoadNewGRFSound(SoundEntry *sound) { - if (sound->file_offset == SIZE_MAX || sound->file_slot == 0) return false; + if (sound->file_offset == SIZE_MAX || sound->file == nullptr) return false; - FioSeekToFile(sound->file_slot, sound->file_offset); + RandomAccessFile &file = *sound->file; + file.SeekTo(sound->file_offset, SEEK_SET); /* Skip ID for container version >= 2 as we only look at the first * entry and ignore any further entries with the same ID. */ - if (sound->grf_container_ver >= 2) FioReadDword(); + if (sound->grf_container_ver >= 2) file.ReadDword(); /* Format: '\0' */ - uint32 num = sound->grf_container_ver >= 2 ? FioReadDword() : FioReadWord(); - if (FioReadByte() != 0xFF) return false; - if (FioReadByte() != 0xFF) return false; + uint32 num = sound->grf_container_ver >= 2 ? file.ReadDword() : file.ReadWord(); + if (file.ReadByte() != 0xFF) return false; + if (file.ReadByte() != 0xFF) return false; - uint8 name_len = FioReadByte(); + uint8 name_len = file.ReadByte(); char *name = AllocaM(char, name_len + 1); - FioReadBlock(name, name_len + 1); + file.ReadBlock(name, name_len + 1); /* Test string termination */ if (name[name_len] != 0) { - DEBUG(grf, 2, "LoadNewGRFSound [%s]: Name not properly terminated", FioGetFilename(sound->file_slot)); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: Name not properly terminated", file.GetSimplifiedFilename().c_str()); return false; } - DEBUG(grf, 2, "LoadNewGRFSound [%s]: Sound name '%s'...", FioGetFilename(sound->file_slot), name); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: Sound name '%s'...", file.GetSimplifiedFilename().c_str(), name); - if (FioReadDword() != BSWAP32('RIFF')) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Missing RIFF header", FioGetFilename(sound->file_slot)); + if (file.ReadDword() != BSWAP32('RIFF')) { + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Missing RIFF header", file.GetSimplifiedFilename().c_str()); return false; } - uint32 total_size = FioReadDword(); + uint32 total_size = file.ReadDword(); uint header_size = 11; if (sound->grf_container_ver >= 2) header_size++; // The first FF in the sprite is only counted for container version >= 2. if (total_size + name_len + header_size > num) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF was truncated", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF was truncated", file.GetSimplifiedFilename().c_str()); return false; } - if (FioReadDword() != BSWAP32('WAVE')) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF type", FioGetFilename(sound->file_slot)); + if (file.ReadDword() != BSWAP32('WAVE')) { + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF type", file.GetSimplifiedFilename().c_str()); return false; } while (total_size >= 8) { - uint32 tag = FioReadDword(); - uint32 size = FioReadDword(); + uint32 tag = file.ReadDword(); + uint32 size = file.ReadDword(); total_size -= 8; if (total_size < size) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF", file.GetSimplifiedFilename().c_str()); return false; } total_size -= size; @@ -122,15 +123,15 @@ bool LoadNewGRFSound(SoundEntry *sound) switch (tag) { case ' tmf': // 'fmt ' /* Audio format, must be 1 (PCM) */ - if (size < 16 || FioReadWord() != 1) { - DEBUG(grf, 1, "LoadGRFSound [%s]: Invalid audio format", FioGetFilename(sound->file_slot)); + if (size < 16 || file.ReadWord() != 1) { + DEBUG(grf, 1, "LoadGRFSound [%s]: Invalid audio format", file.GetSimplifiedFilename().c_str()); return false; } - sound->channels = FioReadWord(); - sound->rate = FioReadDword(); - FioReadDword(); - FioReadWord(); - sound->bits_per_sample = FioReadWord(); + sound->channels = file.ReadWord(); + sound->rate = file.ReadDword(); + file.ReadDword(); + file.ReadWord(); + sound->bits_per_sample = file.ReadWord(); /* The rest will be skipped */ size -= 16; @@ -138,9 +139,9 @@ bool LoadNewGRFSound(SoundEntry *sound) case 'atad': // 'data' sound->file_size = size; - sound->file_offset = FioGetPos(); + sound->file_offset = file.GetPos(); - DEBUG(grf, 2, "LoadNewGRFSound [%s]: channels %u, sample rate %u, bits per sample %u, length %u", FioGetFilename(sound->file_slot), sound->channels, sound->rate, sound->bits_per_sample, size); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: channels %u, sample rate %u, bits per sample %u, length %u", file.GetSimplifiedFilename().c_str(), sound->channels, sound->rate, sound->bits_per_sample, size); return true; // the fmt chunk has to appear before data, so we are finished default: @@ -149,10 +150,10 @@ bool LoadNewGRFSound(SoundEntry *sound) } /* Skip rest of chunk */ - if (size > 0) FioSkipBytes(size); + if (size > 0) file.SkipBytes(size); } - DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF does not contain any sound data", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF does not contain any sound data", file.GetSimplifiedFilename().c_str()); /* Clear everything that was read */ MemSetT(sound, 0); diff --git a/src/sound.cpp b/src/sound.cpp index d91476729b..413c70af2a 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -11,7 +11,7 @@ #include "landscape.h" #include "mixer.h" #include "newgrf_sound.h" -#include "fios.h" +#include "random_access_file_type.h" #include "window_gui.h" #include "vehicle_base.h" @@ -25,14 +25,20 @@ static SoundEntry _original_sounds[ORIGINAL_SAMPLE_COUNT]; static void OpenBankFile(const char *filename) { + /** + * The sound file for the original sounds, i.e. those not defined/overridden by a NewGRF. + * Needs to be kept alive during the game as _original_sounds[n].file refers to this. + */ + static std::unique_ptr original_sound_file; + memset(_original_sounds, 0, sizeof(_original_sounds)); /* If there is no sound file (nosound set), don't load anything */ if (filename == nullptr) return; - FioOpenFile(SOUND_SLOT, filename, BASESET_DIR); - size_t pos = FioGetPos(); - uint count = FioReadDword(); + original_sound_file.reset(new RandomAccessFile(filename, BASESET_DIR)); + size_t pos = original_sound_file->GetPos(); + uint count = original_sound_file->ReadDword(); /* The new format has the highest bit always set */ bool new_format = HasBit(count, 31); @@ -48,43 +54,43 @@ static void OpenBankFile(const char *filename) return; } - FioSeekTo(pos, SEEK_SET); + original_sound_file->SeekTo(pos, SEEK_SET); for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) { - _original_sounds[i].file_slot = SOUND_SLOT; - _original_sounds[i].file_offset = GB(FioReadDword(), 0, 31) + pos; - _original_sounds[i].file_size = FioReadDword(); + _original_sounds[i].file = original_sound_file.get(); + _original_sounds[i].file_offset = GB(original_sound_file->ReadDword(), 0, 31) + pos; + _original_sounds[i].file_size = original_sound_file->ReadDword(); } for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) { SoundEntry *sound = &_original_sounds[i]; char name[255]; - FioSeekTo(sound->file_offset, SEEK_SET); + original_sound_file->SeekTo(sound->file_offset, SEEK_SET); /* Check for special case, see else case */ - FioReadBlock(name, FioReadByte()); // Read the name of the sound + original_sound_file->ReadBlock(name, original_sound_file->ReadByte()); // Read the name of the sound if (new_format || strcmp(name, "Corrupt sound") != 0) { - FioSeekTo(12, SEEK_CUR); // Skip past RIFF header + original_sound_file->SeekTo(12, SEEK_CUR); // Skip past RIFF header /* Read riff tags */ for (;;) { - uint32 tag = FioReadDword(); - uint32 size = FioReadDword(); + uint32 tag = original_sound_file->ReadDword(); + uint32 size = original_sound_file->ReadDword(); if (tag == ' tmf') { - FioReadWord(); // wFormatTag - sound->channels = FioReadWord(); // wChannels - sound->rate = FioReadDword(); // samples per second - if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate. - FioReadDword(); // avg bytes per second - FioReadWord(); // alignment - sound->bits_per_sample = FioReadByte(); // bits per sample - FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR); + original_sound_file->ReadWord(); // wFormatTag + sound->channels = original_sound_file->ReadWord(); // wChannels + sound->rate = original_sound_file->ReadDword(); // samples per second + if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate. + original_sound_file->ReadDword(); // avg bytes per second + original_sound_file->ReadWord(); // alignment + sound->bits_per_sample = original_sound_file->ReadByte(); // bits per sample + original_sound_file->SeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR); } else if (tag == 'atad') { sound->file_size = size; - sound->file_slot = SOUND_SLOT; - sound->file_offset = FioGetPos(); + sound->file = original_sound_file.get(); + sound->file_offset = original_sound_file->GetPos(); break; } else { sound->file_size = 0; @@ -100,8 +106,8 @@ static void OpenBankFile(const char *filename) sound->channels = 1; sound->rate = 11025; sound->bits_per_sample = 8; - sound->file_slot = SOUND_SLOT; - sound->file_offset = FioGetPos(); + sound->file = original_sound_file.get(); + sound->file_offset = original_sound_file->GetPos(); } } } @@ -119,8 +125,9 @@ static bool SetBankSource(MixerChannel *mc, const SoundEntry *sound) mem[sound->file_size ] = 0; mem[sound->file_size + 1] = 0; - FioSeekToFile(sound->file_slot, sound->file_offset); - FioReadBlock(mem, sound->file_size); + RandomAccessFile *file = sound->file; + file->SeekTo(sound->file_offset, SEEK_SET); + file->ReadBlock(mem, sound->file_size); /* 16-bit PCM WAV files should be signed by default */ if (sound->bits_per_sample == 8) { @@ -163,10 +170,10 @@ static void StartSound(SoundID sound_id, float pan, uint volume) if (sound == nullptr) return; /* NewGRF sound that wasn't loaded yet? */ - if (sound->rate == 0 && sound->file_slot != 0) { + if (sound->rate == 0 && sound->file != nullptr) { if (!LoadNewGRFSound(sound)) { /* Mark as invalid. */ - sound->file_slot = 0; + sound->file = nullptr; return; } } diff --git a/src/sound_type.h b/src/sound_type.h index e8d4b7becb..02bfc4f835 100644 --- a/src/sound_type.h +++ b/src/sound_type.h @@ -11,7 +11,7 @@ #define SOUND_TYPE_H struct SoundEntry { - uint8 file_slot; + class RandomAccessFile *file; size_t file_offset; size_t file_size; uint16 rate; From 0dd339ecd8fab0ae3a4901e0ad185798e04cccf3 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 14 Apr 2021 06:49:46 +0200 Subject: [PATCH 124/800] Codechange: lets music make use of RandomAccessFile instead of the FIO slot functions --- src/music.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/music.cpp b/src/music.cpp index 66ac2b511b..62a9482337 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -15,7 +15,7 @@ #include "base_media_func.h" #include "safeguards.h" -#include "fios.h" +#include "random_access_file_type.h" /** @@ -29,15 +29,15 @@ char *GetMusicCatEntryName(const char *filename, size_t entrynum) { if (!FioCheckFileExists(filename, BASESET_DIR)) return nullptr; - FioOpenFile(CONFIG_SLOT, filename, BASESET_DIR); - uint32 ofs = FioReadDword(); + RandomAccessFile file(filename, BASESET_DIR); + uint32 ofs = file.ReadDword(); size_t entry_count = ofs / 8; if (entrynum < entry_count) { - FioSeekTo(entrynum * 8, SEEK_SET); - FioSeekTo(FioReadDword(), SEEK_SET); - byte namelen = FioReadByte(); + file.SeekTo(entrynum * 8, SEEK_SET); + file.SeekTo(file.ReadDword(), SEEK_SET); + byte namelen = file.ReadByte(); char *name = MallocT(namelen + 1); - FioReadBlock(name, namelen); + file.ReadBlock(name, namelen); name[namelen] = '\0'; return name; } @@ -57,17 +57,17 @@ byte *GetMusicCatEntryData(const char *filename, size_t entrynum, size_t &entryl entrylen = 0; if (!FioCheckFileExists(filename, BASESET_DIR)) return nullptr; - FioOpenFile(CONFIG_SLOT, filename, BASESET_DIR); - uint32 ofs = FioReadDword(); + RandomAccessFile file(filename, BASESET_DIR); + uint32 ofs = file.ReadDword(); size_t entry_count = ofs / 8; if (entrynum < entry_count) { - FioSeekTo(entrynum * 8, SEEK_SET); - size_t entrypos = FioReadDword(); - entrylen = FioReadDword(); - FioSeekTo(entrypos, SEEK_SET); - FioSkipBytes(FioReadByte()); + file.SeekTo(entrynum * 8, SEEK_SET); + size_t entrypos = file.ReadDword(); + entrylen = file.ReadDword(); + file.SeekTo(entrypos, SEEK_SET); + file.SkipBytes(file.ReadByte()); byte *data = MallocT(entrylen); - FioReadBlock(data, entrylen); + file.ReadBlock(data, entrylen); return data; } return nullptr; From fdc11a9f943bcbd674b8b69a2bb0895414928028 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 14 Apr 2021 17:20:39 +0200 Subject: [PATCH 125/800] Codechange: introduce SpriteFile to be used by the sprite loader instead of the global FIO slot functionality --- src/fileio.cpp | 26 ++--- src/fileio_func.h | 4 +- src/gfx_func.h | 2 - src/gfxinit.cpp | 42 ++++---- src/newgrf.cpp | 95 ++++++----------- src/newgrf.h | 2 - src/newgrf_debug_gui.cpp | 4 +- src/spritecache.cpp | 144 ++++++++++++++++---------- src/spritecache.h | 12 ++- src/spriteloader/CMakeLists.txt | 2 + src/spriteloader/grf.cpp | 103 +++++++++--------- src/spriteloader/grf.hpp | 2 +- src/spriteloader/sprite_file.cpp | 50 +++++++++ src/spriteloader/sprite_file_type.hpp | 46 ++++++++ src/spriteloader/spriteloader.hpp | 3 +- 15 files changed, 317 insertions(+), 220 deletions(-) create mode 100644 src/spriteloader/sprite_file.cpp create mode 100644 src/spriteloader/sprite_file_type.hpp diff --git a/src/fileio.cpp b/src/fileio.cpp index 6b13e30890..6d5e2da287 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -9,7 +9,7 @@ #include "stdafx.h" #include "fileio_func.h" -#include "random_access_file_type.h" +#include "spriteloader/spriteloader.hpp" #include "debug.h" #include "fios.h" #include "string_func.h" @@ -30,8 +30,8 @@ #include "safeguards.h" -static RandomAccessFile *_fio_current_file; ///< current file handle for the Fio functions -static std::array _fio_files; ///< array of random access files we can have open +static SpriteFile *_fio_current_file; ///< current file handle for the Fio functions +static std::array _fio_files; ///< array of random access files we can have open /** Whether the working directory should be scanned. */ static bool _do_scan_working_directory = true; @@ -40,9 +40,9 @@ extern std::string _config_file; extern std::string _highscore_file; /** - * Transition helper to get the RandomAccessFile associated with a given slot. + * Transition helper to get the SpriteFile associated with a given slot. */ -RandomAccessFile *FioGetRandomAccessFile(int slot) +SpriteFile *FioGetSpriteFile(int slot) { return _fio_files[slot]; } @@ -83,9 +83,9 @@ void FioSeekTo(size_t pos, int mode) */ void FioSeekToFile(uint8 slot, size_t pos) { - RandomAccessFile *raf = _fio_files[slot]; - assert(raf != nullptr); - _fio_current_file = raf; + SpriteFile *file = _fio_files[slot]; + assert(file != nullptr); + _fio_current_file = file; _fio_current_file->SeekTo(pos, SEEK_SET); } @@ -149,13 +149,15 @@ void FioCloseAll() * @param slot Index to assign. * @param filename Name of the file at the disk. * @param subdir The sub directory to search this file in. + * @param palette_remap Whether palette remapping needs to take place. */ -void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir) +SpriteFile &FioOpenFile(int slot, const std::string &filename, Subdirectory subdir, bool palette_remap) { - RandomAccessFile *raf = new RandomAccessFile(filename, subdir); + SpriteFile *file = new SpriteFile(filename, subdir, palette_remap); delete _fio_files[slot]; - _fio_files[slot] = raf; - _fio_current_file = raf; + _fio_files[slot] = file; + _fio_current_file = file; + return *file; } static const char * const _subdirs[] = { diff --git a/src/fileio_func.h b/src/fileio_func.h index 55fac39efd..b3ed9e138d 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -23,10 +23,10 @@ byte FioReadByte(); uint16 FioReadWord(); uint32 FioReadDword(); void FioCloseAll(); -void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir); +class SpriteFile &FioOpenFile(int slot, const std::string &filename, Subdirectory subdir, bool palette_remap = false); void FioReadBlock(void *ptr, size_t size); void FioSkipBytes(int n); -class RandomAccessFile *FioGetRandomAccessFile(int slot); +class SpriteFile *FioGetSpriteFile(int slot); void FioFCloseFile(FILE *f); FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); diff --git a/src/gfx_func.h b/src/gfx_func.h index 3deb4f3eb6..6363a699d9 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -178,8 +178,6 @@ TextColour GetContrastColour(uint8 background, uint8 threshold = 128); */ extern byte _colour_gradient[COLOUR_END][8]; -extern bool _palette_remap_grf[]; - /** * Return the colour for a particular greyscale level. * @param level Intensity, 0 = black, 15 = white diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index c0ba4c4d4d..3bacc5af65 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -26,9 +26,6 @@ #include "safeguards.h" -/** Whether the given NewGRFs must get a palette remap from windows to DOS or not. */ -bool _palette_remap_grf[MAX_FILE_SLOTS]; - #include "table/landscape_sprite.h" /** Offsets for loading the different "replacement" sprites in the files. */ @@ -43,27 +40,28 @@ static const SpriteID * const _landscape_spriteindexes[] = { * @param filename The name of the file to open. * @param load_index The offset of the first sprite. * @param file_index The Fio offset to load the file in. + * @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @return The number of loaded sprites. */ -static uint LoadGrfFile(const char *filename, uint load_index, int file_index) +static uint LoadGrfFile(const char *filename, uint load_index, int file_index, bool needs_palette_remap) { uint load_index_org = load_index; uint sprite_id = 0; - FioOpenFile(file_index, filename, BASESET_DIR); + SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); DEBUG(sprite, 2, "Reading grf-file '%s'", filename); - byte container_ver = GetGRFContainerVersion(); + byte container_ver = file.GetContainerVersion(); if (container_ver == 0) usererror("Base grf '%s' is corrupt", filename); - ReadGRFSpriteOffsets(container_ver); + ReadGRFSpriteOffsets(file); if (container_ver >= 2) { /* Read compression. */ - byte compression = FioReadByte(); + byte compression = file.ReadByte(); if (compression != 0) usererror("Unsupported compression format"); } - while (LoadNextSprite(load_index, file_index, sprite_id, container_ver)) { + while (LoadNextSprite(load_index, file, sprite_id)) { load_index++; sprite_id++; if (load_index >= MAX_SPRITES) { @@ -80,23 +78,24 @@ static uint LoadGrfFile(const char *filename, uint load_index, int file_index) * @param filename The name of the file to open. * @param index_tbl The offsets of each of the sprites. * @param file_index The Fio offset to load the file in. + * @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @return The number of loaded sprites. */ -static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, int file_index) +static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, int file_index, bool needs_palette_remap) { uint start; uint sprite_id = 0; - FioOpenFile(file_index, filename, BASESET_DIR); + SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename); - byte container_ver = GetGRFContainerVersion(); + byte container_ver = file.GetContainerVersion(); if (container_ver == 0) usererror("Base grf '%s' is corrupt", filename); - ReadGRFSpriteOffsets(container_ver); + ReadGRFSpriteOffsets(file); if (container_ver >= 2) { /* Read compression. */ - byte compression = FioReadByte(); + byte compression = file.ReadByte(); if (compression != 0) usererror("Unsupported compression format"); } @@ -104,7 +103,7 @@ static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, uint end = *index_tbl++; do { - bool b = LoadNextSprite(start, file_index, sprite_id, container_ver); + bool b = LoadNextSprite(start, file, sprite_id); (void)b; // Unused without asserts assert(b); sprite_id++; @@ -162,12 +161,10 @@ void CheckExternalFiles() /** Actually load the sprite tables. */ static void LoadSpriteTables() { - memset(_palette_remap_grf, 0, sizeof(_palette_remap_grf)); uint i = FIRST_GRF_SLOT; const GraphicsSet *used_set = BaseGraphics::GetUsedSet(); - _palette_remap_grf[i] = (PAL_DOS != used_set->palette); - LoadGrfFile(used_set->files[GFT_BASE].filename, 0, i++); + LoadGrfFile(used_set->files[GFT_BASE].filename, 0, i++, (PAL_DOS != used_set->palette)); /* * The second basic file always starts at the given location and does @@ -175,8 +172,7 @@ static void LoadSpriteTables() * has a few sprites less. However, we do not care about those missing * sprites as they are not shown anyway (logos in intro game). */ - _palette_remap_grf[i] = (PAL_DOS != used_set->palette); - LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, i++); + LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, i++, (PAL_DOS != used_set->palette)); /* * Load additional sprites for climates other than temperate. @@ -184,11 +180,11 @@ static void LoadSpriteTables() * and the ground sprites. */ if (_settings_game.game_creation.landscape != LT_TEMPERATE) { - _palette_remap_grf[i] = (PAL_DOS != used_set->palette); LoadGrfFileIndexed( used_set->files[GFT_ARCTIC + _settings_game.game_creation.landscape - 1].filename, _landscape_spriteindexes[_settings_game.game_creation.landscape - 1], - i++ + i++, + (PAL_DOS != used_set->palette) ); } @@ -230,7 +226,7 @@ static void LoadSpriteTables() LoadNewGRF(SPR_NEWGRFS_BASE, i, 2); uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE; - _missing_extra_graphics = GetSpriteCountForSlot(i, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); + _missing_extra_graphics = GetSpriteCountForFile(used_set->files[GFT_EXTRA].filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); DEBUG(sprite, 1, "%u extra sprites, %u from baseset, %u from fallback", total_extra_graphics, total_extra_graphics - _missing_extra_graphics, _missing_extra_graphics); /* The original baseset extra graphics intentionally make use of the fallback graphics. diff --git a/src/newgrf.cpp b/src/newgrf.cpp index b51a18b437..aadd1a3a92 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -99,11 +99,10 @@ public: SpriteID spriteid; ///< First available SpriteID for loading realsprites. /* Local state in the file */ - uint file_index; ///< File index of currently processed GRF file. + SpriteFile *file; ///< File of currently processed GRF file. GRFFile *grffile; ///< Currently processed GRF file. GRFConfig *grfconfig; ///< Config of the currently processed GRF file. uint32 nfo_line; ///< Currently processed pseudo sprite number in the GRF. - byte grf_container_ver; ///< Container format of the current GRF file. /* Kind of return values when processing certain actions */ int skip_sprites; ///< Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file) @@ -4884,7 +4883,7 @@ static void NewSpriteSet(ByteReader *buf) for (int i = 0; i < num_sets * num_ents; i++) { _cur.nfo_line++; - LoadNextSprite(_cur.spriteid++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver); + LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line); } } @@ -6120,16 +6119,16 @@ static void GraphicsNew(ByteReader *buf) /* Special not-TTDP-compatible case used in openttd.grf * Missing shore sprites and initialisation of SPR_SHORE_BASE */ grfmsg(2, "GraphicsNew: Loading 10 missing shore sprites from extra grf."); - LoadNextSprite(SPR_SHORE_BASE + 0, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_STEEP_S - LoadNextSprite(SPR_SHORE_BASE + 5, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_STEEP_W - LoadNextSprite(SPR_SHORE_BASE + 7, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_WSE - LoadNextSprite(SPR_SHORE_BASE + 10, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_STEEP_N - LoadNextSprite(SPR_SHORE_BASE + 11, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_NWS - LoadNextSprite(SPR_SHORE_BASE + 13, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_ENW - LoadNextSprite(SPR_SHORE_BASE + 14, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_SEN - LoadNextSprite(SPR_SHORE_BASE + 15, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_STEEP_E - LoadNextSprite(SPR_SHORE_BASE + 16, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_EW - LoadNextSprite(SPR_SHORE_BASE + 17, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver); // SLOPE_NS + LoadNextSprite(SPR_SHORE_BASE + 0, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_S + LoadNextSprite(SPR_SHORE_BASE + 5, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_W + LoadNextSprite(SPR_SHORE_BASE + 7, *_cur.file, _cur.nfo_line++); // SLOPE_WSE + LoadNextSprite(SPR_SHORE_BASE + 10, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_N + LoadNextSprite(SPR_SHORE_BASE + 11, *_cur.file, _cur.nfo_line++); // SLOPE_NWS + LoadNextSprite(SPR_SHORE_BASE + 13, *_cur.file, _cur.nfo_line++); // SLOPE_ENW + LoadNextSprite(SPR_SHORE_BASE + 14, *_cur.file, _cur.nfo_line++); // SLOPE_SEN + LoadNextSprite(SPR_SHORE_BASE + 15, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_E + LoadNextSprite(SPR_SHORE_BASE + 16, *_cur.file, _cur.nfo_line++); // SLOPE_EW + LoadNextSprite(SPR_SHORE_BASE + 17, *_cur.file, _cur.nfo_line++); // SLOPE_NS if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ONLY_NEW; return; } @@ -6177,7 +6176,7 @@ static void GraphicsNew(ByteReader *buf) for (; num > 0; num--) { _cur.nfo_line++; - LoadNextSprite(replace == 0 ? _cur.spriteid++ : replace++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver); + LoadNextSprite(replace == 0 ? _cur.spriteid++ : replace++, *_cur.file, _cur.nfo_line); } _cur.skip_sprites = skip_num; @@ -6397,7 +6396,7 @@ static void CfgApply(ByteReader *buf) /* Preload the next sprite */ size_t pos = FioGetPos(); - uint32 num = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord(); + uint32 num = _cur.file->GetContainerVersion() >= 2 ? FioReadDword() : FioReadWord(); uint8 type = FioReadByte(); byte *preload_sprite = nullptr; @@ -6758,7 +6757,7 @@ static void SpriteReplace(ByteReader *buf) for (uint j = 0; j < num_sprites; j++) { int load_index = first_sprite + j; _cur.nfo_line++; - LoadNextSprite(load_index, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver); // XXX + LoadNextSprite(load_index, *_cur.file, _cur.nfo_line); // XXX /* Shore sprites now located at different addresses. * So detect when the old ones get replaced. */ @@ -7553,9 +7552,9 @@ static void LoadGRFSound(size_t offs, SoundEntry *sound) if (offs != SIZE_MAX) { /* Sound is present in the NewGRF. */ - sound->file = FioGetRandomAccessFile(_cur.file_index); + sound->file = _cur.file; sound->file_offset = offs; - sound->grf_container_ver = _cur.grf_container_ver; + sound->grf_container_ver = _cur.file->GetContainerVersion(); } } @@ -7587,10 +7586,11 @@ static void GRFSound(ByteReader *buf) size_t offs = FioGetPos(); - uint32 len = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord(); + byte grf_container_version = _cur.file->GetContainerVersion(); + uint32 len = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); byte type = FioReadByte(); - if (_cur.grf_container_ver >= 2 && type == 0xFD) { + if (grf_container_version >= 2 && type == 0xFD) { /* Reference to sprite section. */ if (invalid) { grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)"); @@ -7608,7 +7608,7 @@ static void GRFSound(ByteReader *buf) if (type != 0xFF) { grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping"); FioSkipBytes(7); - SkipSpriteData(type, len - 8); + SkipSpriteData(*_cur.file, type, len - 8); continue; } @@ -7622,7 +7622,7 @@ static void GRFSound(ByteReader *buf) case 0xFF: /* Allocate sound only in init stage. */ if (_cur.stage == GLS_INIT) { - if (_cur.grf_container_ver >= 2) { + if (grf_container_version >= 2) { grfmsg(1, "GRFSound: Inline sounds are not supported for container version >= 2"); } else { LoadGRFSound(offs, sound + i); @@ -7688,7 +7688,7 @@ static void LoadFontGlyph(ByteReader *buf) for (uint c = 0; c < num_char; c++) { if (size < FS_END) SetUnicodeGlyph(size, base_char + c, _cur.spriteid); _cur.nfo_line++; - LoadNextSprite(_cur.spriteid++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver); + LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line); } } } @@ -9269,32 +9269,6 @@ static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage) } -/** Signature of a container version 2 GRF. */ -extern const byte _grf_cont_v2_sig[8] = {'G', 'R', 'F', 0x82, 0x0D, 0x0A, 0x1A, 0x0A}; - -/** - * Get the container version of the currently opened GRF file. - * @return Container version of the GRF file or 0 if the file is corrupt/no GRF file. - */ -byte GetGRFContainerVersion() -{ - size_t pos = FioGetPos(); - - if (FioReadWord() == 0) { - /* Check for GRF container version 2, which is identified by the bytes - * '47 52 46 82 0D 0A 1A 0A' at the start of the file. */ - for (uint i = 0; i < lengthof(_grf_cont_v2_sig); i++) { - if (FioReadByte() != _grf_cont_v2_sig[i]) return 0; // Invalid format - } - - return 2; - } - - /* Container version 1 has no header, rewind to start. */ - FioSeekTo(pos, SEEK_SET); - return 1; -} - /** * Load a particular NewGRF. * @param config The configuration of the to be loaded NewGRF. @@ -9329,16 +9303,13 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S return; } - FioOpenFile(file_index, filename, subdir); - _cur.file_index = file_index; // XXX - _palette_remap_grf[_cur.file_index] = (config->palette & GRFP_USE_MASK); - + _cur.file = &FioOpenFile(file_index, filename, subdir, config->palette & GRFP_USE_MASK); _cur.grfconfig = config; DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", filename); - _cur.grf_container_ver = GetGRFContainerVersion(); - if (_cur.grf_container_ver == 0) { + byte grf_container_version = _cur.file->GetContainerVersion(); + if (grf_container_version == 0) { DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); return; } @@ -9346,13 +9317,13 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S if (stage == GLS_INIT || stage == GLS_ACTIVATION) { /* We need the sprite offsets in the init stage for NewGRF sounds * and in the activation stage for real sprites. */ - ReadGRFSpriteOffsets(_cur.grf_container_ver); + ReadGRFSpriteOffsets(*_cur.file); } else { /* Skip sprite section offset if present. */ - if (_cur.grf_container_ver >= 2) FioReadDword(); + if (grf_container_version >= 2) FioReadDword(); } - if (_cur.grf_container_ver >= 2) { + if (grf_container_version >= 2) { /* Read compression value. */ byte compression = FioReadByte(); if (compression != 0) { @@ -9364,7 +9335,7 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S /* Skip the first sprite; we don't care about how many sprites this * does contain; newest TTDPatches and George's longvehicles don't * neither, apparently. */ - uint32 num = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord(); + uint32 num = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); if (num == 4 && FioReadByte() == 0xFF) { FioReadDword(); } else { @@ -9376,7 +9347,7 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S ReusableBuffer buf; - while ((num = (_cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord())) != 0) { + while ((num = (grf_container_version >= 2 ? FioReadDword() : FioReadWord())) != 0) { byte type = FioReadByte(); _cur.nfo_line++; @@ -9398,12 +9369,12 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S break; } - if (_cur.grf_container_ver >= 2 && type == 0xFD) { + if (grf_container_version >= 2 && type == 0xFD) { /* Reference to data section. Container version >= 2 only. */ FioSkipBytes(num); } else { FioSkipBytes(7); - SkipSpriteData(type, num - 8); + SkipSpriteData(*_cur.file, type, num - 8); } } diff --git a/src/newgrf.h b/src/newgrf.h index d9c8a4da58..477bfa892c 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -192,8 +192,6 @@ static inline bool HasGrfMiscBit(GrfMiscBit bit) /* Indicates which are the newgrf features currently loaded ingame */ extern GRFLoadedFeatures _loaded_newgrf_features; -byte GetGRFContainerVersion(); - void LoadNewGRFFile(struct GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir); void LoadNewGRF(uint load_index, uint file_index, uint num_baseset); void ReloadNewGRFData(); // in saveload/afterload.cpp diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 3a5e05a77b..0d9fae8a48 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -11,7 +11,7 @@ #include #include "window_gui.h" #include "window_func.h" -#include "fileio_func.h" +#include "random_access_file_type.h" #include "spritecache.h" #include "string_func.h" #include "strings_func.h" @@ -828,7 +828,7 @@ struct SpriteAlignerWindow : Window { switch (widget) { case WID_SA_CAPTION: SetDParam(0, this->current_sprite); - SetDParamStr(1, FioGetFilename(GetOriginFileSlot(this->current_sprite))); + SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename().c_str()); break; case WID_SA_OFFSETS_ABS: diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 288f74af43..f2840c1b02 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -8,7 +8,7 @@ /** @file spritecache.cpp Caching of sprites. */ #include "stdafx.h" -#include "fileio_func.h" +#include "random_access_file_type.h" #include "spriteloader/grf.hpp" #include "gfx_func.h" #include "error.h" @@ -31,18 +31,17 @@ uint _sprite_cache_size = 4; struct SpriteCache { void *ptr; size_t file_pos; + SpriteFile *file; ///< The file the sprite in this entry can be found in. uint32 id; - uint16 file_slot; int16 lru; SpriteType type; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble. bool warned; ///< True iff the user has been warned about incorrect use of this sprite - byte container_ver; ///< Container version of the GRF the sprite is from. }; static uint _spritecache_items = 0; static SpriteCache *_spritecache = nullptr; - +static std::vector> _sprite_files; static inline SpriteCache *GetSpriteCache(uint index) { @@ -72,6 +71,37 @@ static SpriteCache *AllocateSpriteCache(uint index) return GetSpriteCache(index); } +/** + * Get the cached SpriteFile given the name of the file. + * @param filename The name of the file at the disk. + * @return The SpriteFile or \c null. + */ +static SpriteFile *GetCachedSpriteFileByName(const std::string &filename) { + for (auto &f : _sprite_files) { + if (f->GetFilename() == filename) { + return f.get(); + } + } + return nullptr; +} + +/** + * Open/get the SpriteFile that is cached for use in the sprite cache. + * @param filename Name of the file at the disk. + * @param subdir The sub directory to search this file in. + * @param palette_remap Whether a palette remap needs to be performed for this file. + * @return The reference to the SpriteCache. + */ +SpriteFile &OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap) +{ + SpriteFile *file = GetCachedSpriteFileByName(filename); + if (file == nullptr) { + file = _sprite_files.emplace_back(new SpriteFile(filename, subdir, palette_remap)).get(); + } else { + file->SeekToBegin(); + } + return *file; +} struct MemBlock { size_t size; @@ -92,22 +122,22 @@ static void *AllocSprite(size_t mem_req); * @param num the amount of sprites to skip * @return true if the data could be correctly skipped. */ -bool SkipSpriteData(byte type, uint16 num) +bool SkipSpriteData(SpriteFile &file, byte type, uint16 num) { if (type & 2) { - FioSkipBytes(num); + file.SkipBytes(num); } else { while (num > 0) { - int8 i = FioReadByte(); + int8 i = file.ReadByte(); if (i >= 0) { int size = (i == 0) ? 0x80 : i; if (size > num) return false; num -= size; - FioSkipBytes(size); + file.SkipBytes(size); } else { i = -(i >> 3); num -= i; - FioReadByte(); + file.ReadByte(); } } } @@ -121,7 +151,7 @@ bool SpriteExists(SpriteID id) /* Special case for Sprite ID zero -- its position is also 0... */ if (id == 0) return true; - return !(GetSpriteCache(id)->file_pos == 0 && GetSpriteCache(id)->file_slot == 0); + return !(GetSpriteCache(id)->file_pos == 0 && GetSpriteCache(id)->file == nullptr); } /** @@ -136,14 +166,14 @@ SpriteType GetSpriteType(SpriteID sprite) } /** - * Get the (FIOS) file slot of a given sprite. + * Get the SpriteFile of a given sprite. * @param sprite The sprite to look at. - * @return the FIOS file slot + * @return The SpriteFile. */ -uint GetOriginFileSlot(SpriteID sprite) +SpriteFile *GetOriginFile(SpriteID sprite) { - if (!SpriteExists(sprite)) return 0; - return GetSpriteCache(sprite)->file_slot; + if (!SpriteExists(sprite)) return nullptr; + return GetSpriteCache(sprite)->file; } /** @@ -158,19 +188,22 @@ uint32 GetSpriteLocalID(SpriteID sprite) } /** - * Count the sprites which originate from a specific file slot in a range of SpriteIDs. - * @param file_slot FIOS file slot. + * Count the sprites which originate from a specific file in a range of SpriteIDs. + * @param file The loaded SpriteFile. * @param begin First sprite in range. * @param end First sprite not in range. * @return Number of sprites. */ -uint GetSpriteCountForSlot(uint file_slot, SpriteID begin, SpriteID end) +uint GetSpriteCountForFile(const std::string &filename, SpriteID begin, SpriteID end) { + SpriteFile *file = GetCachedSpriteFileByName(filename); + if (file == nullptr) return 0; + uint count = 0; for (SpriteID i = begin; i != end; i++) { if (SpriteExists(i)) { SpriteCache *sc = GetSpriteCache(i); - if (sc->file_slot == file_slot) count++; + if (sc->file == file) count++; } } return count; @@ -348,7 +381,7 @@ static bool PadSprites(SpriteLoader::Sprite *sprite, uint8 sprite_avail, SpriteE return true; } -static bool ResizeSprites(SpriteLoader::Sprite *sprite, uint8 sprite_avail, uint32 file_slot, uint32 file_pos, SpriteEncoder *encoder) +static bool ResizeSprites(SpriteLoader::Sprite *sprite, uint8 sprite_avail, SpriteEncoder *encoder) { /* Create a fully zoomed image if it does not exist */ ZoomLevel first_avail = static_cast(FIND_FIRST_BIT(sprite_avail)); @@ -379,11 +412,11 @@ static bool ResizeSprites(SpriteLoader::Sprite *sprite, uint8 sprite_avail, uint /** * Load a recolour sprite into memory. - * @param file_slot GRF we're reading from. + * @param file GRF we're reading from. * @param num Size of the sprite in the GRF. * @return Sprite data. */ -static void *ReadRecolourSprite(uint16 file_slot, uint num) +static void *ReadRecolourSprite(SpriteFile &file, uint num) { /* "Normal" recolour sprites are ALWAYS 257 bytes. Then there is a small * number of recolour sprites that are 17 bytes that only exist in DOS @@ -392,19 +425,19 @@ static void *ReadRecolourSprite(uint16 file_slot, uint num) static const uint RECOLOUR_SPRITE_SIZE = 257; byte *dest = (byte *)AllocSprite(std::max(RECOLOUR_SPRITE_SIZE, num)); - if (_palette_remap_grf[file_slot]) { + if (file.NeedsPaletteRemap()) { byte *dest_tmp = AllocaM(byte, std::max(RECOLOUR_SPRITE_SIZE, num)); /* Only a few recolour sprites are less than 257 bytes */ if (num < RECOLOUR_SPRITE_SIZE) memset(dest_tmp, 0, RECOLOUR_SPRITE_SIZE); - FioReadBlock(dest_tmp, num); + file.ReadBlock(dest_tmp, num); /* The data of index 0 is never used; "literal 00" according to the (New)GRF specs. */ for (uint i = 1; i < RECOLOUR_SPRITE_SIZE; i++) { dest[i] = _palmap_w2d[dest_tmp[_palmap_d2w[i - 1] + 1]]; } } else { - FioReadBlock(dest, num); + file.ReadBlock(dest, num); } return dest; @@ -424,7 +457,7 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty /* Use current blitter if no other sprite encoder is given. */ if (encoder == nullptr) encoder = BlitterFactory::GetCurrentBlitter(); - uint8 file_slot = sc->file_slot; + SpriteFile &file = *sc->file; size_t file_pos = sc->file_pos; assert(sprite_type != ST_RECOLOUR); @@ -437,13 +470,13 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty uint8 sprite_avail = 0; sprite[ZOOM_LVL_NORMAL].type = sprite_type; - SpriteLoaderGrf sprite_loader(sc->container_ver); + SpriteLoaderGrf sprite_loader(file.GetContainerVersion()); if (sprite_type != ST_MAPGEN && encoder->Is32BppSupported()) { /* Try for 32bpp sprites first. */ - sprite_avail = sprite_loader.LoadSprite(sprite, file_slot, file_pos, sprite_type, true); + sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, true); } if (sprite_avail == 0) { - sprite_avail = sprite_loader.LoadSprite(sprite, file_slot, file_pos, sprite_type, false); + sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, false); } if (sprite_avail == 0) { @@ -480,7 +513,7 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty return s; } - if (!ResizeSprites(sprite, sprite_avail, file_slot, sc->id, encoder)) { + if (!ResizeSprites(sprite, sprite_avail, encoder)) { if (id == SPR_IMG_QUERY) usererror("Okay... something went horribly wrong. I couldn't resize the fallback sprite. What should I do?"); return (void*)GetRawSprite(SPR_IMG_QUERY, ST_NORMAL, allocator, encoder); } @@ -516,27 +549,27 @@ size_t GetGRFSpriteOffset(uint32 id) * Parse the sprite section of GRFs. * @param container_version Container version of the GRF we're currently processing. */ -void ReadGRFSpriteOffsets(byte container_version) +void ReadGRFSpriteOffsets(SpriteFile &file) { _grf_sprite_offsets.clear(); - if (container_version >= 2) { + if (file.GetContainerVersion() >= 2) { /* Seek to sprite section of the GRF. */ - size_t data_offset = FioReadDword(); - size_t old_pos = FioGetPos(); - FioSeekTo(data_offset, SEEK_CUR); + size_t data_offset = file.ReadDword(); + size_t old_pos = file.GetPos(); + file.SeekTo(data_offset, SEEK_CUR); /* Loop over all sprite section entries and store the file * offset for each newly encountered ID. */ uint32 id, prev_id = 0; - while ((id = FioReadDword()) != 0) { - if (id != prev_id) _grf_sprite_offsets[id] = FioGetPos() - 4; + while ((id = file.ReadDword()) != 0) { + if (id != prev_id) _grf_sprite_offsets[id] = file.GetPos() - 4; prev_id = id; - FioSkipBytes(FioReadDword()); + file.SkipBytes(file.ReadDword()); } /* Continue processing the data section. */ - FioSeekTo(old_pos, SEEK_SET); + file.SeekTo(old_pos, SEEK_SET); } } @@ -544,19 +577,19 @@ void ReadGRFSpriteOffsets(byte container_version) /** * Load a real or recolour sprite. * @param load_index Global sprite index. - * @param file_slot GRF to load from. + * @param file GRF to load from. * @param file_sprite_id Sprite number in the GRF. * @param container_version Container version of the GRF. * @return True if a valid sprite was loaded, false on any error. */ -bool LoadNextSprite(int load_index, byte file_slot, uint file_sprite_id, byte container_version) +bool LoadNextSprite(int load_index, SpriteFile &file, uint file_sprite_id) { - size_t file_pos = FioGetPos(); + size_t file_pos = file.GetPos(); /* Read sprite header. */ - uint32 num = container_version >= 2 ? FioReadDword() : FioReadWord(); + uint32 num = file.GetContainerVersion() >= 2 ? file.ReadDword() : file.ReadWord(); if (num == 0) return false; - byte grf_type = FioReadByte(); + byte grf_type = file.ReadByte(); SpriteType type; void *data = nullptr; @@ -564,25 +597,25 @@ bool LoadNextSprite(int load_index, byte file_slot, uint file_sprite_id, byte co /* Some NewGRF files have "empty" pseudo-sprites which are 1 * byte long. Catch these so the sprites won't be displayed. */ if (num == 1) { - FioReadByte(); + file.ReadByte(); return false; } type = ST_RECOLOUR; - data = ReadRecolourSprite(file_slot, num); - } else if (container_version >= 2 && grf_type == 0xFD) { + data = ReadRecolourSprite(file, num); + } else if (file.GetContainerVersion() >= 2 && grf_type == 0xFD) { if (num != 4) { /* Invalid sprite section include, ignore. */ - FioSkipBytes(num); + file.SkipBytes(num); return false; } /* It is not an error if no sprite with the provided ID is found in the sprite section. */ - file_pos = GetGRFSpriteOffset(FioReadDword()); + file_pos = GetGRFSpriteOffset(file.ReadDword()); type = ST_NORMAL; } else { - FioSkipBytes(7); - type = SkipSpriteData(grf_type, num - 8) ? ST_NORMAL : ST_INVALID; + file.SkipBytes(7); + type = SkipSpriteData(file, grf_type, num - 8) ? ST_NORMAL : ST_INVALID; /* Inline sprites are not supported for container version >= 2. */ - if (container_version >= 2) return false; + if (file.GetContainerVersion() >= 2) return false; } if (type == ST_INVALID) return false; @@ -599,14 +632,13 @@ bool LoadNextSprite(int load_index, byte file_slot, uint file_sprite_id, byte co } SpriteCache *sc = AllocateSpriteCache(load_index); - sc->file_slot = file_slot; + sc->file = &file; sc->file_pos = file_pos; sc->ptr = data; sc->lru = 0; sc->id = file_sprite_id; sc->type = type; sc->warned = false; - sc->container_ver = container_version; return true; } @@ -617,13 +649,12 @@ void DupSprite(SpriteID old_spr, SpriteID new_spr) SpriteCache *scnew = AllocateSpriteCache(new_spr); // may reallocate: so put it first SpriteCache *scold = GetSpriteCache(old_spr); - scnew->file_slot = scold->file_slot; + scnew->file = scold->file; scnew->file_pos = scold->file_pos; scnew->ptr = nullptr; scnew->id = scold->id; scnew->type = scold->type; scnew->warned = false; - scnew->container_ver = scold->container_ver; } /** @@ -967,6 +998,7 @@ void GfxInitSpriteMem() _spritecache = nullptr; _compact_cache_counter = 0; + _sprite_files.clear(); } /** diff --git a/src/spritecache.h b/src/spritecache.h index 00503c4535..367d690951 100644 --- a/src/spritecache.h +++ b/src/spritecache.h @@ -31,9 +31,9 @@ void *GetRawSprite(SpriteID sprite, SpriteType type, AllocatorProc *allocator = bool SpriteExists(SpriteID sprite); SpriteType GetSpriteType(SpriteID sprite); -uint GetOriginFileSlot(SpriteID sprite); +SpriteFile *GetOriginFile(SpriteID sprite); uint32 GetSpriteLocalID(SpriteID sprite); -uint GetSpriteCountForSlot(uint file_slot, SpriteID begin, SpriteID end); +uint GetSpriteCountForFile(const std::string &filename, SpriteID begin, SpriteID end); uint GetMaxSpriteID(); @@ -53,10 +53,12 @@ void GfxInitSpriteMem(); void GfxClearSpriteCache(); void IncreaseSpriteLRU(); -void ReadGRFSpriteOffsets(byte container_version); +SpriteFile &OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap); + +void ReadGRFSpriteOffsets(SpriteFile &file); size_t GetGRFSpriteOffset(uint32 id); -bool LoadNextSprite(int load_index, byte file_index, uint file_sprite_id, byte container_version); -bool SkipSpriteData(byte type, uint16 num); +bool LoadNextSprite(int load_index, SpriteFile &file, uint file_sprite_id); +bool SkipSpriteData(SpriteFile &file, byte type, uint16 num); void DupSprite(SpriteID old_spr, SpriteID new_spr); #endif /* SPRITECACHE_H */ diff --git a/src/spriteloader/CMakeLists.txt b/src/spriteloader/CMakeLists.txt index 5d6a2f865e..804bb1a2ee 100644 --- a/src/spriteloader/CMakeLists.txt +++ b/src/spriteloader/CMakeLists.txt @@ -1,5 +1,7 @@ add_files( grf.cpp grf.hpp + sprite_file.cpp + sprite_file_type.hpp spriteloader.hpp ) diff --git a/src/spriteloader/grf.cpp b/src/spriteloader/grf.cpp index 30ea094443..fae87b87fc 100644 --- a/src/spriteloader/grf.cpp +++ b/src/spriteloader/grf.cpp @@ -9,7 +9,6 @@ #include "../stdafx.h" #include "../gfx_func.h" -#include "../fileio_func.h" #include "../debug.h" #include "../settings_type.h" #include "../strings_func.h" @@ -32,14 +31,14 @@ extern const byte _palmap_w2d[]; * @param line the line where the error occurs. * @return always false (to tell loading the sprite failed) */ -static bool WarnCorruptSprite(uint8 file_slot, size_t file_pos, int line) +static bool WarnCorruptSprite(const SpriteFile &file, size_t file_pos, int line) { static byte warning_level = 0; if (warning_level == 0) { - SetDParamStr(0, FioGetFilename(file_slot)); + SetDParamStr(0, file.GetSimplifiedFilename().c_str()); ShowErrorMessage(STR_NEWGRF_ERROR_CORRUPT_SPRITE, INVALID_STRING_ID, WL_ERROR); } - DEBUG(sprite, warning_level, "[%i] Loading corrupted sprite from %s at position %i", line, FioGetFilename(file_slot), (int)file_pos); + DEBUG(sprite, warning_level, "[%i] Loading corrupted sprite from %s at position %i", line, file.GetSimplifiedFilename().c_str(), (int)file_pos); warning_level = 6; return false; } @@ -47,7 +46,7 @@ static bool WarnCorruptSprite(uint8 file_slot, size_t file_pos, int line) /** * Decode the image data of a single sprite. * @param[in,out] sprite Filled with the sprite image data. - * @param file_slot File slot. + * @param file The file with the sprite data. * @param file_pos File position. * @param sprite_type Type of the sprite we're decoding. * @param num Size of the decompressed sprite. @@ -57,7 +56,7 @@ static bool WarnCorruptSprite(uint8 file_slot, size_t file_pos, int line) * @param container_format Container format of the GRF this sprite is in. * @return True if the sprite was successfully loaded. */ -bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, int64 num, byte type, ZoomLevel zoom_lvl, byte colour_fmt, byte container_format) +bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, int64 num, byte type, ZoomLevel zoom_lvl, byte colour_fmt, byte container_format) { std::unique_ptr dest_orig(new byte[num]); byte *dest = dest_orig.get(); @@ -65,24 +64,24 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi /* Read the file, which has some kind of compression */ while (num > 0) { - int8 code = FioReadByte(); + int8 code = file.ReadByte(); if (code >= 0) { /* Plain bytes to read */ int size = (code == 0) ? 0x80 : code; num -= size; - if (num < 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__); + if (num < 0) return WarnCorruptSprite(file, file_pos, __LINE__); for (; size > 0; size--) { - *dest = FioReadByte(); + *dest = file.ReadByte(); dest++; } } else { /* Copy bytes from earlier in the sprite */ - const uint data_offset = ((code & 7) << 8) | FioReadByte(); - if (dest - data_offset < dest_orig.get()) return WarnCorruptSprite(file_slot, file_pos, __LINE__); + const uint data_offset = ((code & 7) << 8) | file.ReadByte(); + if (dest - data_offset < dest_orig.get()) return WarnCorruptSprite(file, file_pos, __LINE__); int size = -(code >> 3); num -= size; - if (num < 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__); + if (num < 0) return WarnCorruptSprite(file, file_pos, __LINE__); for (; size > 0; size--) { *dest = *(dest - data_offset); dest++; @@ -90,7 +89,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi } } - if (num != 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__); + if (num != 0) return WarnCorruptSprite(file, file_pos, __LINE__); sprite->AllocateData(zoom_lvl, sprite->width * sprite->height); @@ -117,7 +116,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi do { if (dest + (container_format >= 2 && sprite->width > 256 ? 4 : 2) > dest_orig.get() + dest_size) { - return WarnCorruptSprite(file_slot, file_pos, __LINE__); + return WarnCorruptSprite(file, file_pos, __LINE__); } SpriteLoader::CommonPixel *data; @@ -143,7 +142,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi data = &sprite->data[y * sprite->width + skip]; if (skip + length > sprite->width || dest + length * bpp > dest_orig.get() + dest_size) { - return WarnCorruptSprite(file_slot, file_pos, __LINE__); + return WarnCorruptSprite(file, file_pos, __LINE__); } for (int x = 0; x < length; x++) { @@ -155,7 +154,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi data->a = (colour_fmt & SCC_ALPHA) ? *dest++ : 0xFF; if (colour_fmt & SCC_PAL) { switch (sprite_type) { - case ST_NORMAL: data->m = _palette_remap_grf[file_slot] ? _palmap_w2d[*dest] : *dest; break; + case ST_NORMAL: data->m = file.NeedsPaletteRemap() ? _palmap_w2d[*dest] : *dest; break; case ST_FONT: data->m = std::min(*dest, 2u); break; default: data->m = *dest; break; } @@ -169,12 +168,12 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi } } else { if (dest_size < sprite->width * sprite->height * bpp) { - return WarnCorruptSprite(file_slot, file_pos, __LINE__); + return WarnCorruptSprite(file, file_pos, __LINE__); } if (dest_size > sprite->width * sprite->height * bpp) { static byte warning_level = 0; - DEBUG(sprite, warning_level, "Ignoring " OTTD_PRINTF64 " unused extra bytes from the sprite from %s at position %i", dest_size - sprite->width * sprite->height * bpp, FioGetFilename(file_slot), (int)file_pos); + DEBUG(sprite, warning_level, "Ignoring " OTTD_PRINTF64 " unused extra bytes from the sprite from %s at position %i", dest_size - sprite->width * sprite->height * bpp, file.GetSimplifiedFilename().c_str(), (int)file_pos); warning_level = 6; } @@ -191,7 +190,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi sprite->data[i].a = (colour_fmt & SCC_ALPHA) ? *pixel++ : 0xFF; if (colour_fmt & SCC_PAL) { switch (sprite_type) { - case ST_NORMAL: sprite->data[i].m = _palette_remap_grf[file_slot] ? _palmap_w2d[*pixel] : *pixel; break; + case ST_NORMAL: sprite->data[i].m = file.NeedsPaletteRemap() ? _palmap_w2d[*pixel] : *pixel; break; case ST_FONT: sprite->data[i].m = std::min(*pixel, 2u); break; default: sprite->data[i].m = *pixel; break; } @@ -205,31 +204,31 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t fi return true; } -uint8 LoadSpriteV1(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, bool load_32bpp) +uint8 LoadSpriteV1(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp) { /* Check the requested colour depth. */ if (load_32bpp) return 0; /* Open the right file and go to the correct position */ - FioSeekToFile(file_slot, file_pos); + file.SeekTo(file_pos, SEEK_SET); /* Read the size and type */ - int num = FioReadWord(); - byte type = FioReadByte(); + int num = file.ReadWord(); + byte type = file.ReadByte(); /* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here */ if (type == 0xFF) return 0; ZoomLevel zoom_lvl = (sprite_type != ST_MAPGEN) ? ZOOM_LVL_OUT_4X : ZOOM_LVL_NORMAL; - sprite[zoom_lvl].height = FioReadByte(); - sprite[zoom_lvl].width = FioReadWord(); - sprite[zoom_lvl].x_offs = FioReadWord(); - sprite[zoom_lvl].y_offs = FioReadWord(); + sprite[zoom_lvl].height = file.ReadByte(); + sprite[zoom_lvl].width = file.ReadWord(); + sprite[zoom_lvl].x_offs = file.ReadWord(); + sprite[zoom_lvl].y_offs = file.ReadWord(); sprite[zoom_lvl].colours = SCC_PAL; if (sprite[zoom_lvl].width > INT16_MAX) { - WarnCorruptSprite(file_slot, file_pos, __LINE__); + WarnCorruptSprite(file, file_pos, __LINE__); return 0; } @@ -237,12 +236,12 @@ uint8 LoadSpriteV1(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_po * In case it is uncompressed, the size is 'num' - 8 (header-size). */ num = (type & 0x02) ? sprite[zoom_lvl].width * sprite[zoom_lvl].height : num - 8; - if (DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, num, type, zoom_lvl, SCC_PAL, 1)) return 1 << zoom_lvl; + if (DecodeSingleSprite(&sprite[zoom_lvl], file, file_pos, sprite_type, num, type, zoom_lvl, SCC_PAL, 1)) return 1 << zoom_lvl; return 0; } -uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, bool load_32bpp) +uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp) { static const ZoomLevel zoom_lvl_map[6] = {ZOOM_LVL_OUT_4X, ZOOM_LVL_NORMAL, ZOOM_LVL_OUT_2X, ZOOM_LVL_OUT_8X, ZOOM_LVL_OUT_16X, ZOOM_LVL_OUT_32X}; @@ -250,21 +249,21 @@ uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_po if (file_pos == SIZE_MAX) return 0; /* Open the right file and go to the correct position */ - FioSeekToFile(file_slot, file_pos); + file.SeekTo(file_pos, SEEK_SET); - uint32 id = FioReadDword(); + uint32 id = file.ReadDword(); uint8 loaded_sprites = 0; do { - int64 num = FioReadDword(); - size_t start_pos = FioGetPos(); - byte type = FioReadByte(); + int64 num = file.ReadDword(); + size_t start_pos = file.GetPos(); + byte type = file.ReadByte(); /* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here. */ if (type == 0xFF) return 0; byte colour = type & SCC_MASK; - byte zoom = FioReadByte(); + byte zoom = file.ReadByte(); bool is_wanted_colour_depth = (colour != 0 && (load_32bpp ? colour != SCC_PAL : colour == SCC_PAL)); bool is_wanted_zoom_lvl; @@ -280,18 +279,18 @@ uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_po if (HasBit(loaded_sprites, zoom_lvl)) { /* We already have this zoom level, skip sprite. */ - DEBUG(sprite, 1, "Ignoring duplicate zoom level sprite %u from %s", id, FioGetFilename(file_slot)); - FioSkipBytes(num - 2); + DEBUG(sprite, 1, "Ignoring duplicate zoom level sprite %u from %s", id, file.GetSimplifiedFilename().c_str()); + file.SkipBytes(num - 2); continue; } - sprite[zoom_lvl].height = FioReadWord(); - sprite[zoom_lvl].width = FioReadWord(); - sprite[zoom_lvl].x_offs = FioReadWord(); - sprite[zoom_lvl].y_offs = FioReadWord(); + sprite[zoom_lvl].height = file.ReadWord(); + sprite[zoom_lvl].width = file.ReadWord(); + sprite[zoom_lvl].x_offs = file.ReadWord(); + sprite[zoom_lvl].y_offs = file.ReadWord(); if (sprite[zoom_lvl].width > INT16_MAX || sprite[zoom_lvl].height > INT16_MAX) { - WarnCorruptSprite(file_slot, file_pos, __LINE__); + WarnCorruptSprite(file, file_pos, __LINE__); return 0; } @@ -308,30 +307,30 @@ uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_po /* For chunked encoding we store the decompressed size in the file, * otherwise we can calculate it from the image dimensions. */ - uint decomp_size = (type & 0x08) ? FioReadDword() : sprite[zoom_lvl].width * sprite[zoom_lvl].height * bpp; + uint decomp_size = (type & 0x08) ? file.ReadDword() : sprite[zoom_lvl].width * sprite[zoom_lvl].height * bpp; - bool valid = DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, decomp_size, type, zoom_lvl, colour, 2); - if (FioGetPos() != start_pos + num) { - WarnCorruptSprite(file_slot, file_pos, __LINE__); + bool valid = DecodeSingleSprite(&sprite[zoom_lvl], file, file_pos, sprite_type, decomp_size, type, zoom_lvl, colour, 2); + if (file.GetPos() != start_pos + num) { + WarnCorruptSprite(file, file_pos, __LINE__); return 0; } if (valid) SetBit(loaded_sprites, zoom_lvl); } else { /* Not the wanted zoom level or colour depth, continue searching. */ - FioSkipBytes(num - 2); + file.SkipBytes(num - 2); } - } while (FioReadDword() == id); + } while (file.ReadDword() == id); return loaded_sprites; } -uint8 SpriteLoaderGrf::LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, bool load_32bpp) +uint8 SpriteLoaderGrf::LoadSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp) { if (this->container_ver >= 2) { - return LoadSpriteV2(sprite, file_slot, file_pos, sprite_type, load_32bpp); + return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp); } else { - return LoadSpriteV1(sprite, file_slot, file_pos, sprite_type, load_32bpp); + return LoadSpriteV1(sprite, file, file_pos, sprite_type, load_32bpp); } } diff --git a/src/spriteloader/grf.hpp b/src/spriteloader/grf.hpp index 20d60edf51..c100590afb 100644 --- a/src/spriteloader/grf.hpp +++ b/src/spriteloader/grf.hpp @@ -17,7 +17,7 @@ class SpriteLoaderGrf : public SpriteLoader { byte container_ver; public: SpriteLoaderGrf(byte container_ver) : container_ver(container_ver) {} - uint8 LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, bool load_32bpp); + uint8 LoadSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp); }; #endif /* SPRITELOADER_GRF_HPP */ diff --git a/src/spriteloader/sprite_file.cpp b/src/spriteloader/sprite_file.cpp new file mode 100644 index 0000000000..be7160628b --- /dev/null +++ b/src/spriteloader/sprite_file.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file sprite_file.cpp Implementation of logic specific to the SpriteFile class. */ + +#include "../stdafx.h" +#include "sprite_file_type.hpp" + +/** Signature of a container version 2 GRF. */ +extern const byte _grf_cont_v2_sig[8] = {'G', 'R', 'F', 0x82, 0x0D, 0x0A, 0x1A, 0x0A}; + +/** + * Get the container version of the currently opened GRF file. + * @return Container version of the GRF file or 0 if the file is corrupt/no GRF file. + */ +static byte GetGRFContainerVersion(SpriteFile &file) +{ + size_t pos = file.GetPos(); + + if (file.ReadWord() == 0) { + /* Check for GRF container version 2, which is identified by the bytes + * '47 52 46 82 0D 0A 1A 0A' at the start of the file. */ + for (uint i = 0; i < lengthof(_grf_cont_v2_sig); i++) { + if (file.ReadByte() != _grf_cont_v2_sig[i]) return 0; // Invalid format + } + + return 2; + } + + /* Container version 1 has no header, rewind to start. */ + file.SeekTo(pos, SEEK_SET); + return 1; +} + +/** + * Create the SpriteFile. + * @param filename Name of the file at the disk. + * @param subdir The sub directory to search this file in. + * @param palette_remap Whether a palette remap needs to be performed for this file. + */ +SpriteFile::SpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap) + : RandomAccessFile(filename, subdir), palette_remap(palette_remap) +{ + this->container_version = GetGRFContainerVersion(*this); + this->content_begin = this->GetPos(); +} diff --git a/src/spriteloader/sprite_file_type.hpp b/src/spriteloader/sprite_file_type.hpp new file mode 100644 index 0000000000..b7492afade --- /dev/null +++ b/src/spriteloader/sprite_file_type.hpp @@ -0,0 +1,46 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file sprite_file_type.hpp Random Access File specialised for accessing sprites. */ + +#ifndef SPRITE_FILE_TYPE_HPP +#define SPRITE_FILE_TYPE_HPP + +#include "../random_access_file_type.h" + +/** + * RandomAccessFile with some extra information specific for sprite files. + * It automatically detects and stores the container version upload opening the file. + */ +class SpriteFile : public RandomAccessFile { + bool palette_remap; ///< Whether or not a remap of the palette is required for this file. + byte container_version; ///< Container format of the sprite file. + size_t content_begin; ///< The begin of the content of the sprite file, i.e. after the container metadata. +public: + SpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap); + SpriteFile(const SpriteFile&) = delete; + void operator=(const SpriteFile&) = delete; + + /** + * Whether a palette remap is needed when loading sprites from this file. + * @return True when needed, otherwise false. + */ + bool NeedsPaletteRemap() const { return this->palette_remap; } + + /** + * Get the version number of container type used by the file. + * @return The version. + */ + byte GetContainerVersion() const { return this->container_version; } + + /** + * Seek to the begin of the content, i.e. the position just after the container version has been determined. + */ + void SeekToBegin() { this->SeekTo(this->content_begin, SEEK_SET); } +}; + +#endif /* SPRITE_FILE_TYPE_HPP */ diff --git a/src/spriteloader/spriteloader.hpp b/src/spriteloader/spriteloader.hpp index 7b24746332..beadbb6591 100644 --- a/src/spriteloader/spriteloader.hpp +++ b/src/spriteloader/spriteloader.hpp @@ -13,6 +13,7 @@ #include "../core/alloc_type.hpp" #include "../core/enum_type.hpp" #include "../gfx_type.h" +#include "sprite_file_type.hpp" struct Sprite; typedef void *AllocatorProc(size_t size); @@ -73,7 +74,7 @@ public: * @param load_32bpp True if 32bpp sprites should be loaded, false for a 8bpp sprite. * @return Bit mask of the zoom levels successfully loaded or 0 if no sprite could be loaded. */ - virtual uint8 LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, bool load_32bpp) = 0; + virtual uint8 LoadSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp) = 0; virtual ~SpriteLoader() { } }; From 10e35ca8e4249a7f443b5c89dd9a59df83052d0d Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 14 Apr 2021 17:41:45 +0200 Subject: [PATCH 126/800] Codechange: let NewGRF make use of SpriteFile instead of most of the FIO slot functions --- src/gfxinit.cpp | 20 ++-- src/newgrf.cpp | 249 +++++++++++++++++++++++------------------- src/newgrf.h | 4 +- src/newgrf_config.cpp | 4 +- 4 files changed, 147 insertions(+), 130 deletions(-) diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 3bacc5af65..063d777edf 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -39,16 +39,15 @@ static const SpriteID * const _landscape_spriteindexes[] = { * Load an old fashioned GRF file. * @param filename The name of the file to open. * @param load_index The offset of the first sprite. - * @param file_index The Fio offset to load the file in. * @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @return The number of loaded sprites. */ -static uint LoadGrfFile(const char *filename, uint load_index, int file_index, bool needs_palette_remap) +static uint LoadGrfFile(const char *filename, uint load_index, bool needs_palette_remap) { uint load_index_org = load_index; uint sprite_id = 0; - SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); + SpriteFile &file = OpenCachedSpriteFile(filename, BASESET_DIR, needs_palette_remap); DEBUG(sprite, 2, "Reading grf-file '%s'", filename); @@ -77,16 +76,15 @@ static uint LoadGrfFile(const char *filename, uint load_index, int file_index, b * Load an old fashioned GRF file to replace already loaded sprites. * @param filename The name of the file to open. * @param index_tbl The offsets of each of the sprites. - * @param file_index The Fio offset to load the file in. * @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @return The number of loaded sprites. */ -static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, int file_index, bool needs_palette_remap) +static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, bool needs_palette_remap) { uint start; uint sprite_id = 0; - SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); + SpriteFile &file = OpenCachedSpriteFile(filename, BASESET_DIR, needs_palette_remap); DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename); @@ -161,10 +159,9 @@ void CheckExternalFiles() /** Actually load the sprite tables. */ static void LoadSpriteTables() { - uint i = FIRST_GRF_SLOT; const GraphicsSet *used_set = BaseGraphics::GetUsedSet(); - LoadGrfFile(used_set->files[GFT_BASE].filename, 0, i++, (PAL_DOS != used_set->palette)); + LoadGrfFile(used_set->files[GFT_BASE].filename, 0, PAL_DOS != used_set->palette); /* * The second basic file always starts at the given location and does @@ -172,7 +169,7 @@ static void LoadSpriteTables() * has a few sprites less. However, we do not care about those missing * sprites as they are not shown anyway (logos in intro game). */ - LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, i++, (PAL_DOS != used_set->palette)); + LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, PAL_DOS != used_set->palette); /* * Load additional sprites for climates other than temperate. @@ -183,8 +180,7 @@ static void LoadSpriteTables() LoadGrfFileIndexed( used_set->files[GFT_ARCTIC + _settings_game.game_creation.landscape - 1].filename, _landscape_spriteindexes[_settings_game.game_creation.landscape - 1], - i++, - (PAL_DOS != used_set->palette) + PAL_DOS != used_set->palette ); } @@ -223,7 +219,7 @@ static void LoadSpriteTables() master->next = extra; _grfconfig = master; - LoadNewGRF(SPR_NEWGRFS_BASE, i, 2); + LoadNewGRF(SPR_NEWGRFS_BASE, 2); uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE; _missing_extra_graphics = GetSpriteCountForFile(used_set->files[GFT_EXTRA].filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index aadd1a3a92..7b8ab9de1d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -80,6 +80,7 @@ static uint32 _ttdpatch_flags[8]; GRFLoadedFeatures _loaded_newgrf_features; static const uint MAX_SPRITEGROUP = UINT8_MAX; ///< Maximum GRF-local ID for a spritegroup. +static const uint MAX_GRF_COUNT = 128; ///< Maximum number of NewGRF files that could be loaded. /** Temporary data during loading of GRFs */ struct GrfProcessingState { @@ -6395,19 +6396,20 @@ static void CfgApply(ByteReader *buf) * to place where parameter is to be stored. */ /* Preload the next sprite */ - size_t pos = FioGetPos(); - uint32 num = _cur.file->GetContainerVersion() >= 2 ? FioReadDword() : FioReadWord(); - uint8 type = FioReadByte(); + SpriteFile &file = *_cur.file; + size_t pos = file.GetPos(); + uint32 num = file.GetContainerVersion() >= 2 ? file.ReadDword() : file.ReadWord(); + uint8 type = file.ReadByte(); byte *preload_sprite = nullptr; /* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */ if (type == 0xFF) { preload_sprite = MallocT(num); - FioReadBlock(preload_sprite, num); + file.ReadBlock(preload_sprite, num); } /* Reset the file position to the start of the next sprite */ - FioSeekTo(pos, SEEK_SET); + file.SeekTo(pos, SEEK_SET); if (type != 0xFF) { grfmsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)"); @@ -6653,7 +6655,7 @@ static void SkipIf(ByteReader *buf) if (choice != nullptr) { grfmsg(2, "SkipIf: Jumping to label 0x%0X at line %d, test was true", choice->label, choice->nfo_line); - FioSeekTo(choice->pos, SEEK_SET); + _cur.file->SeekTo(choice->pos, SEEK_SET); _cur.nfo_line = choice->nfo_line; return; } @@ -7493,7 +7495,7 @@ static void DefineGotoLabel(ByteReader *buf) GRFLabel *label = MallocT(1); label->label = nfo_label; label->nfo_line = _cur.nfo_line; - label->pos = FioGetPos(); + label->pos = _cur.file->GetPos(); label->next = nullptr; /* Set up a linked list of goto targets which we will search in an Action 0x7/0x9 */ @@ -7516,8 +7518,8 @@ static void DefineGotoLabel(ByteReader *buf) static void ImportGRFSound(SoundEntry *sound) { const GRFFile *file; - uint32 grfid = FioReadDword(); - SoundID sound_id = FioReadWord(); + uint32 grfid = _cur.file->ReadDword(); + SoundID sound_id = _cur.file->ReadWord(); file = GetFileByGRFID(grfid); if (file == nullptr || file->sound_offset == 0) { @@ -7577,6 +7579,8 @@ static void GRFSound(ByteReader *buf) sound = GetSound(_cur.grffile->sound_offset); } + SpriteFile &file = *_cur.file; + byte grf_container_version = file.GetContainerVersion(); for (int i = 0; i < num; i++) { _cur.nfo_line++; @@ -7584,22 +7588,21 @@ static void GRFSound(ByteReader *buf) * While this is invalid, we do not check for this. But we should prevent it from causing bigger trouble */ bool invalid = i >= _cur.grffile->num_sounds; - size_t offs = FioGetPos(); + size_t offs = file.GetPos(); - byte grf_container_version = _cur.file->GetContainerVersion(); - uint32 len = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); - byte type = FioReadByte(); + uint32 len = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord(); + byte type = file.ReadByte(); if (grf_container_version >= 2 && type == 0xFD) { /* Reference to sprite section. */ if (invalid) { grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)"); - FioSkipBytes(len); + file.SkipBytes(len); } else if (len != 4) { grfmsg(1, "GRFSound: Invalid sprite section import"); - FioSkipBytes(len); + file.SkipBytes(len); } else { - uint32 id = FioReadDword(); + uint32 id = file.ReadDword(); if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i); } continue; @@ -7607,17 +7610,17 @@ static void GRFSound(ByteReader *buf) if (type != 0xFF) { grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping"); - FioSkipBytes(7); + file.SkipBytes(7); SkipSpriteData(*_cur.file, type, len - 8); continue; } if (invalid) { grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)"); - FioSkipBytes(len); + file.SkipBytes(len); } - byte action = FioReadByte(); + byte action = file.ReadByte(); switch (action) { case 0xFF: /* Allocate sound only in init stage. */ @@ -7628,23 +7631,23 @@ static void GRFSound(ByteReader *buf) LoadGRFSound(offs, sound + i); } } - FioSkipBytes(len - 1); // already read + file.SkipBytes(len - 1); // already read break; case 0xFE: if (_cur.stage == GLS_ACTIVATION) { /* XXX 'Action 0xFE' isn't really specified. It is only mentioned for * importing sounds, so this is probably all wrong... */ - if (FioReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch"); + if (file.ReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch"); ImportGRFSound(sound + i); } else { - FioSkipBytes(len - 1); // already read + file.SkipBytes(len - 1); // already read } break; default: grfmsg(1, "GRFSound: Unexpected Action %x found, skipping", action); - FioSkipBytes(len - 1); // already read + file.SkipBytes(len - 1); // already read break; } } @@ -9234,14 +9237,14 @@ static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage) if (it == _grf_line_to_action6_sprite_override.end()) { /* No preloaded sprite to work with; read the * pseudo sprite content. */ - FioReadBlock(buf, num); + _cur.file->ReadBlock(buf, num); } else { /* Use the preloaded sprite data. */ buf = _grf_line_to_action6_sprite_override[location]; grfmsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data"); /* Skip the real (original) content of this action. */ - FioSeekTo(num, SEEK_CUR); + _cur.file->SeekTo(num, SEEK_CUR); } ByteReader br(buf, buf + num); @@ -9268,15 +9271,102 @@ static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage) } } +/** + * Load a particular NewGRF from a SpriteFile. + * @param config The configuration of the to be loaded NewGRF. + * @param stage The loading stage of the NewGRF. + * @param file The file to load the GRF data from. + */ +static void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file) +{ + _cur.file = &file; + _cur.grfconfig = config; + + DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", config->filename); + + byte grf_container_version = file.GetContainerVersion(); + if (grf_container_version == 0) { + DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); + return; + } + + if (stage == GLS_INIT || stage == GLS_ACTIVATION) { + /* We need the sprite offsets in the init stage for NewGRF sounds + * and in the activation stage for real sprites. */ + ReadGRFSpriteOffsets(file); + } else { + /* Skip sprite section offset if present. */ + if (grf_container_version >= 2) file.ReadDword(); + } + + if (grf_container_version >= 2) { + /* Read compression value. */ + byte compression = file.ReadByte(); + if (compression != 0) { + DEBUG(grf, 7, "LoadNewGRFFile: Unsupported compression format"); + return; + } + } + + /* Skip the first sprite; we don't care about how many sprites this + * does contain; newest TTDPatches and George's longvehicles don't + * neither, apparently. */ + uint32 num = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord(); + if (num == 4 && file.ReadByte() == 0xFF) { + file.ReadDword(); + } else { + DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); + return; + } + + _cur.ClearDataForNextFile(); + + ReusableBuffer buf; + + while ((num = (grf_container_version >= 2 ? file.ReadDword() : file.ReadWord())) != 0) { + byte type = file.ReadByte(); + _cur.nfo_line++; + + if (type == 0xFF) { + if (_cur.skip_sprites == 0) { + DecodeSpecialSprite(buf.Allocate(num), num, stage); + + /* Stop all processing if we are to skip the remaining sprites */ + if (_cur.skip_sprites == -1) break; + + continue; + } else { + file.SkipBytes(num); + } + } else { + if (_cur.skip_sprites == 0) { + grfmsg(0, "LoadNewGRFFile: Unexpected sprite, disabling"); + DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE); + break; + } + + if (grf_container_version >= 2 && type == 0xFD) { + /* Reference to data section. Container version >= 2 only. */ + file.SkipBytes(num); + } else { + file.SkipBytes(7); + SkipSpriteData(file, type, num - 8); + } + } + + if (_cur.skip_sprites > 0) _cur.skip_sprites--; + } +} /** * Load a particular NewGRF. * @param config The configuration of the to be loaded NewGRF. - * @param file_index The Fio index of the first NewGRF to load. * @param stage The loading stage of the NewGRF. * @param subdir The sub directory to find the NewGRF in. + * @param temporary The NewGRF/sprite file is to be loaded temporarily and should be closed immediately, + * contrary to loading the SpriteFile and having it cached by the SpriteCache. */ -void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir) +void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary) { const char *filename = config->filename; @@ -9296,89 +9386,12 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return; } - if (file_index >= MAX_FILE_SLOTS) { - DEBUG(grf, 0, "'%s' is not loaded as the maximum number of file slots has been reached", filename); - config->status = GCS_DISABLED; - config->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED); - return; - } - - _cur.file = &FioOpenFile(file_index, filename, subdir, config->palette & GRFP_USE_MASK); - _cur.grfconfig = config; - - DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", filename); - - byte grf_container_version = _cur.file->GetContainerVersion(); - if (grf_container_version == 0) { - DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); - return; - } - - if (stage == GLS_INIT || stage == GLS_ACTIVATION) { - /* We need the sprite offsets in the init stage for NewGRF sounds - * and in the activation stage for real sprites. */ - ReadGRFSpriteOffsets(*_cur.file); + bool needs_palette_remap = config->palette & GRFP_USE_MASK; + if (temporary) { + SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap); + LoadNewGRFFileFromFile(config, stage, temporarySpriteFile); } else { - /* Skip sprite section offset if present. */ - if (grf_container_version >= 2) FioReadDword(); - } - - if (grf_container_version >= 2) { - /* Read compression value. */ - byte compression = FioReadByte(); - if (compression != 0) { - DEBUG(grf, 7, "LoadNewGRFFile: Unsupported compression format"); - return; - } - } - - /* Skip the first sprite; we don't care about how many sprites this - * does contain; newest TTDPatches and George's longvehicles don't - * neither, apparently. */ - uint32 num = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); - if (num == 4 && FioReadByte() == 0xFF) { - FioReadDword(); - } else { - DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); - return; - } - - _cur.ClearDataForNextFile(); - - ReusableBuffer buf; - - while ((num = (grf_container_version >= 2 ? FioReadDword() : FioReadWord())) != 0) { - byte type = FioReadByte(); - _cur.nfo_line++; - - if (type == 0xFF) { - if (_cur.skip_sprites == 0) { - DecodeSpecialSprite(buf.Allocate(num), num, stage); - - /* Stop all processing if we are to skip the remaining sprites */ - if (_cur.skip_sprites == -1) break; - - continue; - } else { - FioSkipBytes(num); - } - } else { - if (_cur.skip_sprites == 0) { - grfmsg(0, "LoadNewGRFFile: Unexpected sprite, disabling"); - DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE); - break; - } - - if (grf_container_version >= 2 && type == 0xFD) { - /* Reference to data section. Container version >= 2 only. */ - FioSkipBytes(num); - } else { - FioSkipBytes(7); - SkipSpriteData(*_cur.file, type, num - 8); - } - } - - if (_cur.skip_sprites > 0) _cur.skip_sprites--; + LoadNewGRFFileFromFile(config, stage, OpenCachedSpriteFile(filename, subdir, needs_palette_remap)); } } @@ -9677,10 +9690,9 @@ static void AfterLoadGRFs() /** * Load all the NewGRFs. * @param load_index The offset for the first sprite to add. - * @param file_index The Fio index of the first NewGRF to load. * @param num_baseset Number of NewGRFs at the front of the list to look up in the baseset dir instead of the newgrf dir. */ -void LoadNewGRF(uint load_index, uint file_index, uint num_baseset) +void LoadNewGRF(uint load_index, uint num_baseset) { /* In case of networking we need to "sync" the start values * so all NewGRFs are loaded equally. For this we use the @@ -9738,7 +9750,7 @@ void LoadNewGRF(uint load_index, uint file_index, uint num_baseset) } } - uint slot = file_index; + uint num_grfs = 0; uint num_non_static = 0; _cur.stage = stage; @@ -9746,7 +9758,7 @@ void LoadNewGRF(uint load_index, uint file_index, uint num_baseset) if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue; if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue; - Subdirectory subdir = slot < file_index + num_baseset ? BASESET_DIR : NEWGRF_DIR; + Subdirectory subdir = num_grfs < num_baseset ? BASESET_DIR : NEWGRF_DIR; if (!FioCheckFileExists(c->filename, subdir)) { DEBUG(grf, 0, "NewGRF file is missing '%s'; disabling", c->filename); c->status = GCS_NOT_FOUND; @@ -9764,7 +9776,16 @@ void LoadNewGRF(uint load_index, uint file_index, uint num_baseset) } num_non_static++; } - LoadNewGRFFile(c, slot++, stage, subdir); + + if (num_grfs >= MAX_GRF_COUNT) { + DEBUG(grf, 0, "'%s' is not loaded as the maximum number of file slots has been reached", c->filename); + c->status = GCS_DISABLED; + c->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED); + continue; + } + num_grfs++; + + LoadNewGRFFile(c, stage, subdir, false); if (stage == GLS_RESERVE) { SetBit(c->flags, GCF_RESERVED); } else if (stage == GLS_ACTIVATION) { diff --git a/src/newgrf.h b/src/newgrf.h index 477bfa892c..eb6c22d477 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -192,8 +192,8 @@ static inline bool HasGrfMiscBit(GrfMiscBit bit) /* Indicates which are the newgrf features currently loaded ingame */ extern GRFLoadedFeatures _loaded_newgrf_features; -void LoadNewGRFFile(struct GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir); -void LoadNewGRF(uint load_index, uint file_index, uint num_baseset); +void LoadNewGRFFile(struct GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary); +void LoadNewGRF(uint load_index, uint num_baseset); void ReloadNewGRFData(); // in saveload/afterload.cpp void ResetNewGRFData(); void ResetPersistentNewGRFData(); diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index a4ec52f0f8..b92b297da0 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -375,7 +375,7 @@ bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir) } /* Find and load the Action 8 information */ - LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN, subdir); + LoadNewGRFFile(config, GLS_FILESCAN, subdir, true); config->SetSuitablePalette(); config->FinalizeParameterInfo(); @@ -384,7 +384,7 @@ bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir) if (is_static) { /* Perform a 'safety scan' for static GRFs */ - LoadNewGRFFile(config, CONFIG_SLOT, GLS_SAFETYSCAN, subdir); + LoadNewGRFFile(config, GLS_SAFETYSCAN, subdir, true); /* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */ if (HasBit(config->flags, GCF_UNSAFE)) return false; From fa6abe16463de8f252bac2322c9f84b6d02c9abc Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 21 Apr 2021 18:40:37 +0200 Subject: [PATCH 127/800] Cleanup: remove the old FIO slot functions --- src/fileio.cpp | 124 ---------------------------------------------- src/fileio_func.h | 13 ----- src/fios.h | 14 ------ src/openttd.cpp | 3 -- 4 files changed, 154 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 6d5e2da287..bd05a4e7d5 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -30,136 +30,12 @@ #include "safeguards.h" -static SpriteFile *_fio_current_file; ///< current file handle for the Fio functions -static std::array _fio_files; ///< array of random access files we can have open - /** Whether the working directory should be scanned. */ static bool _do_scan_working_directory = true; extern std::string _config_file; extern std::string _highscore_file; -/** - * Transition helper to get the SpriteFile associated with a given slot. - */ -SpriteFile *FioGetSpriteFile(int slot) -{ - return _fio_files[slot]; -} - -/** - * Get position in the current file. - * @return Position in the file. - */ -size_t FioGetPos() -{ - return _fio_current_file->GetPos(); -} - -/** - * Get the filename associated with a slot. - * @param slot Index of queried file. - * @return Name of the file. - */ -const char *FioGetFilename(uint8 slot) -{ - return _fio_current_file->GetSimplifiedFilename().c_str(); -} - -/** - * Seek in the current file. - * @param pos New position. - * @param mode Type of seek (\c SEEK_CUR means \a pos is relative to current position, \c SEEK_SET means \a pos is absolute). - */ -void FioSeekTo(size_t pos, int mode) -{ - _fio_current_file->SeekTo(pos, mode); -} - -/** - * Switch to a different file and seek to a position. - * @param slot Slot number of the new file. - * @param pos New absolute position in the new file. - */ -void FioSeekToFile(uint8 slot, size_t pos) -{ - SpriteFile *file = _fio_files[slot]; - assert(file != nullptr); - _fio_current_file = file; - _fio_current_file->SeekTo(pos, SEEK_SET); -} - -/** - * Read a byte from the file. - * @return Read byte. - */ -byte FioReadByte() -{ - return _fio_current_file->ReadByte(); -} - -/** - * Skip \a n bytes ahead in the file. - * @param n Number of bytes to skip reading. - */ -void FioSkipBytes(int n) -{ - return _fio_current_file->SkipBytes(n); -} - -/** - * Read a word (16 bits) from the file (in low endian format). - * @return Read word. - */ -uint16 FioReadWord() -{ - return _fio_current_file->ReadWord(); -} - -/** - * Read a double word (32 bits) from the file (in low endian format). - * @return Read word. - */ -uint32 FioReadDword() -{ - return _fio_current_file->ReadDword(); -} - -/** - * Read a block. - * @param ptr Destination buffer. - * @param size Number of bytes to read. - */ -void FioReadBlock(void *ptr, size_t size) -{ - _fio_current_file->ReadBlock(ptr, size); -} - -/** Close all slotted open files. */ -void FioCloseAll() -{ - for (int i = 0; i != lengthof(_fio_files); i++) { - delete _fio_files[i]; - _fio_files[i] = nullptr; - } -} - -/** - * Open a slotted file. - * @param slot Index to assign. - * @param filename Name of the file at the disk. - * @param subdir The sub directory to search this file in. - * @param palette_remap Whether palette remapping needs to take place. - */ -SpriteFile &FioOpenFile(int slot, const std::string &filename, Subdirectory subdir, bool palette_remap) -{ - SpriteFile *file = new SpriteFile(filename, subdir, palette_remap); - delete _fio_files[slot]; - _fio_files[slot] = file; - _fio_current_file = file; - return *file; -} - static const char * const _subdirs[] = { "", "save" PATHSEP, diff --git a/src/fileio_func.h b/src/fileio_func.h index b3ed9e138d..baa8cb1bb1 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -15,19 +15,6 @@ #include #include -void FioSeekTo(size_t pos, int mode); -void FioSeekToFile(uint8 slot, size_t pos); -size_t FioGetPos(); -const char *FioGetFilename(uint8 slot); -byte FioReadByte(); -uint16 FioReadWord(); -uint32 FioReadDword(); -void FioCloseAll(); -class SpriteFile &FioOpenFile(int slot, const std::string &filename, Subdirectory subdir, bool palette_remap = false); -void FioReadBlock(void *ptr, size_t size); -void FioSkipBytes(int n); -class SpriteFile *FioGetSpriteFile(int slot); - void FioFCloseFile(FILE *f); FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); bool FioCheckFileExists(const std::string &filename, Subdirectory subdir); diff --git a/src/fios.h b/src/fios.h index 5029d4862f..34504d5e00 100644 --- a/src/fios.h +++ b/src/fios.h @@ -83,20 +83,6 @@ struct LoadCheckData { extern LoadCheckData _load_check_data; - -enum FileSlots { - /** - * Slot used for the GRF scanning and such. - * This slot is used for all temporary accesses to files when scanning/testing files, - * and thus cannot be used for files, which are continuously accessed during a game. - */ - CONFIG_SLOT = 0, - /** First slot usable for (New)GRFs used during the game. */ - FIRST_GRF_SLOT = 2, - /** Maximum number of slots. */ - MAX_FILE_SLOTS = 128, -}; - /** Deals with finding savegames */ struct FiosItem { FiosType type; diff --git a/src/openttd.cpp b/src/openttd.cpp index d8b197466a..ea802b3db9 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -324,9 +324,6 @@ static void ShutdownGame() /* No NewGRFs were loaded when it was still bootstrapping. */ if (_game_mode != GM_BOOTSTRAP) ResetNewGRFData(); - /* Close all and any open filehandles */ - FioCloseAll(); - UninitFreeType(); } From de940b1dbc7a1d6f245f3965bc43e8885b690441 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 8 May 2021 14:02:42 +0200 Subject: [PATCH 128/800] Fix fdc11a9: Missing sprite count determined on the wrong file --- src/gfxinit.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 063d777edf..713f6e5439 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -195,7 +195,8 @@ static void LoadSpriteTables() GRFConfig *top = _grfconfig; /* Default extra graphics */ - GRFConfig *master = new GRFConfig("OPENTTD.GRF"); + static const char *master_filename = "OPENTTD.GRF"; + GRFConfig *master = new GRFConfig(master_filename); master->palette |= GRFP_GRF_DOS; FillGRFDetails(master, false, BASESET_DIR); ClrBit(master->flags, GCF_INIT_ONLY); @@ -222,7 +223,7 @@ static void LoadSpriteTables() LoadNewGRF(SPR_NEWGRFS_BASE, 2); uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE; - _missing_extra_graphics = GetSpriteCountForFile(used_set->files[GFT_EXTRA].filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); + _missing_extra_graphics = GetSpriteCountForFile(master_filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); DEBUG(sprite, 1, "%u extra sprites, %u from baseset, %u from fallback", total_extra_graphics, total_extra_graphics - _missing_extra_graphics, _missing_extra_graphics); /* The original baseset extra graphics intentionally make use of the fallback graphics. From 664a8c3e85cef684610e0fa65fb2ea587e46232f Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 8 May 2021 10:53:21 +0200 Subject: [PATCH 129/800] Codechange: move connection_string to private for TCPConnecter The most common case never needs access to it anymore. Make the one exception to this explicit. This means the fact that we store it is now an implementation detail. --- src/network/core/tcp.h | 3 +-- src/network/network.cpp | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index 624555649d..1eddec6a44 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -74,6 +74,7 @@ private: std::chrono::steady_clock::time_point last_attempt; ///< Time we last tried to connect. std::atomic is_resolved = false; ///< Whether resolving is done. + std::string connection_string; ///< Current address we are connecting to (before resolving). void Resolve(); void OnResolved(addrinfo *ai); @@ -84,8 +85,6 @@ private: static void ResolveThunk(TCPConnecter *connecter); public: - std::string connection_string; ///< Current address we are connecting to (before resolving). - TCPConnecter(const std::string &connection_string, uint16 default_port); virtual ~TCPConnecter(); diff --git a/src/network/network.cpp b/src/network/network.cpp index 3965c200fd..5d12aa732b 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1145,8 +1145,11 @@ static void NetworkGenerateServerId() } class TCPNetworkDebugConnecter : TCPConnecter { +private: + std::string connection_string; + public: - TCPNetworkDebugConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT) {} + TCPNetworkDebugConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT), connection_string(connection_string) {} void OnFailure() override { From 1b75a29d123db7aace2e8c2bf9c976e9ff8e89e3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 8 May 2021 14:45:23 +0200 Subject: [PATCH 130/800] Fix: destroying a TCPConnecter that was still resolving made illegal writes Basically, we should join the resolve thread before we destruct the object. --- src/network/core/tcp.h | 5 ++++- src/network/core/tcp_connect.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index 1eddec6a44..46e3af8c66 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -18,6 +18,7 @@ #include #include #include +#include /** The states of sending the packets. */ enum SendPacketsState { @@ -65,6 +66,9 @@ public: */ class TCPConnecter { private: + std::thread resolve_thread; ///< Thread used during resolving. + std::atomic is_resolved = false; ///< Whether resolving is done. + addrinfo *ai = nullptr; ///< getaddrinfo() allocated linked-list of resolved addresses. std::vector addresses; ///< Addresses we can connect to. std::map sock_to_address; ///< Mapping of a socket to the real address it is connecting to. USed for DEBUG statements. @@ -73,7 +77,6 @@ private: std::vector sockets; ///< Pending connect() attempts. std::chrono::steady_clock::time_point last_attempt; ///< Time we last tried to connect. - std::atomic is_resolved = false; ///< Whether resolving is done. std::string connection_string; ///< Current address we are connecting to (before resolving). void Resolve(); diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index a1e369295a..96c82b5af8 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -32,13 +32,17 @@ TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_ _tcp_connecters.push_back(this); - if (!StartNewThread(nullptr, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) { + if (!StartNewThread(&this->resolve_thread, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) { this->Resolve(); } } TCPConnecter::~TCPConnecter() { + if (this->resolve_thread.joinable()) { + this->resolve_thread.join(); + } + for (const auto &socket : this->sockets) { closesocket(socket); } @@ -187,6 +191,7 @@ void TCPConnecter::Resolve() this->ai = ai; this->OnResolved(ai); + this->is_resolved = true; } From fc91f1d1b221435dee870d84690e834e753e39da Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 8 May 2021 14:50:56 +0200 Subject: [PATCH 131/800] Fix: don't do a network disconnect between two queries This meant that on opening the Multiplayer window, if you had more than one server configured, it would one by one cancel all pending queries and send a new. Result: only the last server was updated. --- src/network/network.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 5d12aa732b..ba20b0895d 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -628,11 +628,6 @@ private: public: TCPQueryConnecter(const std::string &connection_string, bool request_company_info) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), request_company_info(request_company_info), connection_string(connection_string) {} - void OnFailure() override - { - NetworkDisconnect(); - } - void OnConnect(SOCKET s) override { _networking = true; @@ -650,7 +645,6 @@ void NetworkTCPQueryServer(const std::string &connection_string, bool request_co { if (!_network_available) return; - NetworkDisconnect(); NetworkInitialize(); new TCPQueryConnecter(connection_string, request_company_info); From b9ab3bd6b3f28b682bf5e155bf35d7cbb8b8224a Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 4 May 2021 20:43:35 +0200 Subject: [PATCH 132/800] Fix: only query a manually added server if it isn't there yet But always mark it as manually, no matter if it was there or not. --- src/network/network.cpp | 9 +++++---- src/network/network_internal.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index ba20b0895d..daf2e1d3fd 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -657,7 +657,7 @@ void NetworkTCPQueryServer(const std::string &connection_string, bool request_co * @param connection_string The IP:port of the server to add. * @return The entry on the game list. */ -NetworkGameList *NetworkAddServer(const std::string &connection_string) +NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually) { if (connection_string.empty()) return nullptr; @@ -666,13 +666,14 @@ NetworkGameList *NetworkAddServer(const std::string &connection_string) if (item->info.server_name.empty()) { ClearGRFConfigList(&item->info.grfconfig); item->info.server_name = connection_string; - item->manually = true; NetworkRebuildHostList(); UpdateNetworkGameWindow(); + + NetworkTCPQueryServer(connection_string); } - NetworkTCPQueryServer(connection_string); + if (manually) item->manually = true; return item; } @@ -1202,7 +1203,7 @@ extern "C" { void CDECL em_openttd_add_server(const char *connection_string) { - NetworkAddServer(connection_string); + NetworkAddServer(connection_string, false); } } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 88af965cfc..ac5472fe18 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -90,7 +90,7 @@ extern CompanyMask _network_company_passworded; void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info = false); void GetBindAddresses(NetworkAddressList *addresses, uint16 port); -struct NetworkGameList *NetworkAddServer(const std::string &connection_string); +struct NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually = true); void NetworkRebuildHostList(); void UpdateNetworkGameWindow(); From 330a305c99766b2e62541a8956a00b2cbe7bbbe1 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sat, 8 May 2021 21:01:16 +0100 Subject: [PATCH 133/800] Fix: Apply unscaled padding to Viewport inside WWT_INSET. (#9219) Since pixel dimensions in SetPadding() are scaled by GUI size, padding for inset viewports was excessive. Instead, automatically apply padding for WWT_INSET at widget level. This applies to all widgets inside a WWT_INSET, which in all instances is a NWID_VIEWPORT. --- src/industry_gui.cpp | 2 +- src/news_gui.cpp | 2 +- src/town_gui.cpp | 4 ++-- src/vehicle_gui.cpp | 2 +- src/waypoint_gui.cpp | 2 +- src/widget.cpp | 16 ++++++++++++++-- 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 147d4dc777..4e6c61ee21 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -1186,7 +1186,7 @@ static const NWidgetPart _nested_industry_view_widgets[] = { EndContainer(), NWidget(WWT_PANEL, COLOUR_CREAM), NWidget(WWT_INSET, COLOUR_CREAM), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_IV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetPadding(1, 1, 1, 1), SetResize(1, 1), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_IV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1), EndContainer(), EndContainer(), NWidget(WWT_PANEL, COLOUR_CREAM, WID_IV_INFO), SetMinimalSize(260, 2), SetResize(1, 0), diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 8d0531682d..d3ddd463fa 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -192,7 +192,7 @@ static const NWidgetPart _nested_small_news_widgets[] = { /* Main part */ NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_N_HEADLINE), NWidget(WWT_INSET, COLOUR_LIGHT_BLUE, WID_N_INSET), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetPadding(1, 1, 1, 1), SetMinimalSize(274, 47), SetFill(1, 0), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetMinimalSize(274, 47), SetFill(1, 0), EndContainer(), NWidget(WWT_EMPTY, COLOUR_WHITE, WID_N_MESSAGE), SetMinimalSize(275, 20), SetFill(1, 0), SetPadding(0, 5, 0, 5), EndContainer(), diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 22f8b757f8..bd5893561b 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -576,7 +576,7 @@ static const NWidgetPart _nested_town_game_view_widgets[] = { EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN), NWidget(WWT_INSET, COLOUR_BROWN), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1), SetPadding(1, 1, 1, 1), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1), EndContainer(), EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(), @@ -606,7 +606,7 @@ static const NWidgetPart _nested_town_editor_view_widgets[] = { EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN), NWidget(WWT_INSET, COLOUR_BROWN), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 1), SetResize(1, 1), SetPadding(1, 1, 1, 1), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 1), SetResize(1, 1), EndContainer(), EndContainer(), NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(), diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index c6f2ee52a7..0066644919 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2485,7 +2485,7 @@ static const NWidgetPart _nested_vehicle_view_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(WWT_INSET, COLOUR_GREY), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1), SetPadding(1, 1, 1, 1), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1), EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index 701fb736ae..40c3401b0c 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -155,7 +155,7 @@ static const NWidgetPart _nested_waypoint_view_widgets[] = { EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(WWT_INSET, COLOUR_GREY), SetPadding(2, 2, 2, 2), - NWidget(NWID_VIEWPORT, COLOUR_GREY, WID_W_VIEWPORT), SetMinimalSize(256, 88), SetPadding(1, 1, 1, 1), SetResize(1, 1), + NWidget(NWID_VIEWPORT, COLOUR_GREY, WID_W_VIEWPORT), SetMinimalSize(256, 88), SetResize(1, 1), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), diff --git a/src/widget.cpp b/src/widget.cpp index aaa00d4d79..638aa05fe7 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1904,8 +1904,11 @@ void NWidgetBackground::SetupSmallestSize(Window *w, bool init_array) this->resize_x = this->child->resize_x; this->resize_y = this->child->resize_y; - /* Account for the size of the frame's text if that exists */ - if (w != nullptr && this->type == WWT_FRAME) { + /* Don't apply automatic padding if there is no child widget. */ + if (w == nullptr) return; + + if (this->type == WWT_FRAME) { + /* Account for the size of the frame's text if that exists */ this->child->padding_left = WD_FRAMETEXT_LEFT; this->child->padding_right = WD_FRAMETEXT_RIGHT; this->child->padding_top = std::max((int)WD_FRAMETEXT_TOP, this->widget_data != STR_NULL ? FONT_HEIGHT_NORMAL + WD_FRAMETEXT_TOP / 2 : 0); @@ -1916,6 +1919,15 @@ void NWidgetBackground::SetupSmallestSize(Window *w, bool init_array) if (this->index >= 0) w->SetStringParameters(this->index); this->smallest_x = std::max(this->smallest_x, GetStringBoundingBox(this->widget_data).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); + } else if (this->type == WWT_INSET) { + /* Apply automatic padding for bevel thickness. */ + this->child->padding_left = WD_BEVEL_LEFT; + this->child->padding_right = WD_BEVEL_RIGHT; + this->child->padding_top = WD_BEVEL_TOP; + this->child->padding_bottom = WD_BEVEL_BOTTOM; + + this->smallest_x += this->child->padding_left + this->child->padding_right; + this->smallest_y += this->child->padding_top + this->child->padding_bottom; } } else { Dimension d = {this->min_x, this->min_y}; From e162d0a55ccc4cf38fd09ce0fa349e4887a55448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 9 May 2021 18:28:47 +0200 Subject: [PATCH 134/800] Fix: [MinGW] Reapply 48fd7b27 to fix launch on Windows 7 x64 (#9225) --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ecfbe408c6..6957c85c28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,7 @@ if(WIN32) ws2_32 winmm imm32 + usp10 ) endif() From 583011bca0a1aa5b508ccdebe591df4eae01efb5 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 9 May 2021 18:48:21 +0200 Subject: [PATCH 135/800] Fix: lobby window doesn't close if no connection could be established (#9223) --- src/network/network.cpp | 52 ++++++++++++++++++++++++++++------ src/network/network_gui.cpp | 6 ++-- src/network/network_internal.h | 3 +- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index daf2e1d3fd..4fdbdab73c 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -619,35 +619,69 @@ static void NetworkInitialize(bool close_admins = true) _network_reconnect = 0; } -/** Non blocking connection create to query servers */ +/** Non blocking connection to query servers for their game info. */ class TCPQueryConnecter : TCPConnecter { private: - bool request_company_info; std::string connection_string; public: - TCPQueryConnecter(const std::string &connection_string, bool request_company_info) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), request_company_info(request_company_info), connection_string(connection_string) {} + TCPQueryConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {} void OnConnect(SOCKET s) override { _networking = true; new ClientNetworkGameSocketHandler(s, this->connection_string); - MyClient::SendInformationQuery(request_company_info); + MyClient::SendInformationQuery(false); } }; /** - * Query a server to fetch his game-info. + * Query a server to fetch the game-info. * @param connection_string the address to query. - * @param request_company_info Whether to request company info too. */ -void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info) +void NetworkQueryServer(const std::string &connection_string) { if (!_network_available) return; NetworkInitialize(); - new TCPQueryConnecter(connection_string, request_company_info); + new TCPQueryConnecter(connection_string); +} + +/** Non blocking connection to query servers for their game and company info. */ +class TCPLobbyQueryConnecter : TCPConnecter { +private: + std::string connection_string; + +public: + TCPLobbyQueryConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {} + + void OnFailure() override + { + DeleteWindowById(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 his 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); } /** @@ -670,7 +704,7 @@ NetworkGameList *NetworkAddServer(const std::string &connection_string, bool man NetworkRebuildHostList(); UpdateNetworkGameWindow(); - NetworkTCPQueryServer(connection_string); + NetworkQueryServer(connection_string); } if (manually) item->manually = true; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index cf16d06b13..613b562fb3 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -752,7 +752,7 @@ public: break; case WID_NG_REFRESH: // Refresh - if (this->server != nullptr) NetworkTCPQueryServer(this->server->connection_string); + if (this->server != nullptr) NetworkQueryServer(this->server->connection_string); break; case WID_NG_NEWGRF: // NewGRF Settings @@ -1487,7 +1487,7 @@ struct NetworkLobbyWindow : public Window { /* Clear the information so removed companies don't remain */ for (auto &company : this->company_info) company = {}; - NetworkTCPQueryServer(this->server->connection_string, true); + NetworkQueryLobbyServer(this->server->connection_string); break; } } @@ -1557,7 +1557,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) strecpy(_settings_client.network.last_joined, ngl->connection_string.c_str(), lastof(_settings_client.network.last_joined)); - NetworkTCPQueryServer(ngl->connection_string, true); + NetworkQueryLobbyServer(ngl->connection_string); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index ac5472fe18..3456ab251a 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -87,7 +87,8 @@ extern uint8 _network_reconnect; extern CompanyMask _network_company_passworded; -void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info = false); +void NetworkQueryServer(const std::string &connection_string); +void NetworkQueryLobbyServer(const std::string &connection_string); void GetBindAddresses(NetworkAddressList *addresses, uint16 port); struct NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually = true); From b7dd602dcd30bba54218e9c382d003f623110bb2 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 9 May 2021 18:57:07 +0000 Subject: [PATCH 136/800] Update: Translations from eints finnish: 1 change by hpiirai --- src/lang/finnish.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index b8a219fb5e..99c5da4087 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -2292,7 +2292,7 @@ STR_CONTENT_SEARCH_EXTERNAL :{BLACK}Etsi ulk STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP :{BLACK}Etsi OpenTTD:n ulkopuolisilta verkkosivuilta sisältöä, jota ei ole saatavilla OpenTTD:n sisältöpalvelussa STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION :{WHITE}Olet poistumassa OpenTTD:stä! STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER :{WHITE}Ulkopuolisilta verkkosivuilta ladattaessa käyttöehdot voivat vaihdella.{}Sinun on noudatettava ulkopuolisen sivuston ohjeita sisällön asentamiseksi OpenTTD:hen.{}Haluatko jatkaa? -STR_CONTENT_FILTER_TITLE :{BLACK}Avainsana/nimi suodatus: +STR_CONTENT_FILTER_TITLE :{BLACK}Suodata avainsanalla tai nimellä: STR_CONTENT_OPEN_URL :{BLACK}Vieraile verkkosivulla STR_CONTENT_OPEN_URL_TOOLTIP :{BLACK}Vieraile sisällön verkkosivulla STR_CONTENT_DOWNLOAD_CAPTION :{BLACK}Lataa From 8f4a612a7c8ceb966d1cd538e9e53fd70336259d Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 10 May 2021 13:40:28 +0200 Subject: [PATCH 137/800] Change: reworded many of the network errors during connect/listen (#9230) Also changed some levels to 0, as a failing listen() is something we should tell the user about. Hiding this information is a bit evil. --- src/network/core/address.cpp | 23 +++++++++++++---------- src/network/core/tcp_connect.cpp | 8 ++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 205b5df224..aa27b41032 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -311,49 +311,52 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList * */ static SOCKET ListenLoopProc(addrinfo *runp) { - const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype); - const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family); std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(); SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (sock == INVALID_SOCKET) { - DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); + const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype); + const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family); + DEBUG(net, 0, "Could not create %s %s socket: %s", type, family, NetworkError::GetLast().AsString()); return INVALID_SOCKET; } if (runp->ai_socktype == SOCK_STREAM && !SetNoDelay(sock)) { - DEBUG(net, 3, "[%s] setting TCP_NODELAY failed for port %s", type, address.c_str()); + DEBUG(net, 1, "Setting no-delay mode failed: %s", NetworkError::GetLast().AsString()); } int on = 1; /* The (const char*) cast is needed for windows!! */ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); + DEBUG(net, 0, "Setting reuse-address mode failed: %s", NetworkError::GetLast().AsString()); } #ifndef __OS2__ if (runp->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) { - DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address.c_str(), NetworkError::GetLast().AsString()); + DEBUG(net, 3, "Could not disable IPv4 over IPv6: %s", NetworkError::GetLast().AsString()); } #endif if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) { - DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); + DEBUG(net, 0, "Could not bind socket on %s: %s", address.c_str(), NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) { - DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString()); + DEBUG(net, 0, "Could not listen on socket: %s", NetworkError::GetLast().AsString()); closesocket(sock); return INVALID_SOCKET; } /* Connection succeeded */ - if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed for %s port %s", type, family, address.c_str()); - DEBUG(net, 1, "[%s] listening on %s port %s", type, family, address.c_str()); + if (!SetNonBlocking(sock)) { + DEBUG(net, 0, "Setting non-blocking mode failed: %s", NetworkError::GetLast().AsString()); + } + + DEBUG(net, 1, "Listening on %s", address.c_str()); return sock; } diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index 96c82b5af8..b343ae463a 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -64,8 +64,12 @@ void TCPConnecter::Connect(addrinfo *address) return; } - if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); - if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed"); + if (!SetNoDelay(sock)) { + DEBUG(net, 1, "Setting TCP_NODELAY failed: %s", NetworkError::GetLast().AsString()); + } + if (!SetNonBlocking(sock)) { + DEBUG(net, 0, "Setting non-blocking mode failed: %s", NetworkError::GetLast().AsString()); + } NetworkAddress network_address = NetworkAddress(address->ai_addr, (int)address->ai_addrlen); DEBUG(net, 4, "Attempting to connect to %s", network_address.GetAddressAsString().c_str()); From c53d9991eed38177ad9b0e251b1e6f4cfb27191a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Mon, 10 May 2021 14:48:04 +0200 Subject: [PATCH 138/800] Add: [Actions] Check CI annotations to detect compile warnings (#9217) --- .github/workflows/ci-build.yml | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 74677ee6d5..e0707291c3 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -315,3 +315,45 @@ jobs: run: | cd ${GITHUB_WORKSPACE}/build ctest --timeout 120 + + check_annotations: + name: Check Annotations + needs: + - emscripten + - linux + - macos + - windows + + if: always() && github.event_name == 'pull_request' + + runs-on: ubuntu-20.04 + + steps: + - name: Get check suite ID + id: check_suite_id + uses: octokit/request-action@v2.x + with: + route: GET /repos/{repository}/actions/runs/{run_id} + repository: ${{ github.repository }} + run_id: ${{ github.run_id }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get check runs + id: check_runs + uses: octokit/request-action@v2.x + with: + route: GET /repos/{repository}/check-suites/{check_suite_id}/check-runs + repository: ${{ github.repository }} + check_suite_id: ${{ fromJson(steps.check_suite_id.outputs.data).check_suite_id }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check annotations + shell: bash + run: | + echo '[ + ${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.title) }}, ${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.summary) }} + ]' | jq '.[0] as $t | .[1] as $s | reduce range(.[0] | length) as $i ([]; . + [if $t[$i] then $t[$i] + ": " + $s[$i] else empty end]) | .[]' + + exit $(echo '${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.annotations_count) }}' | jq 'add') From 79fc094c54801bba83dc8aca2028fd6baf35965f Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 8 May 2021 13:33:26 +0200 Subject: [PATCH 139/800] Cleanup: [Fluidsynth] Remove fluid_player_join The function fluid_player_join in the library is broken beyond compare for the usecases it was used for (see their #872). It does not wait until it is safe to delete the player, so it is up to the end user to ensure that. For OpenTTD we acquire a lock before fluid_synth_write_s16 and we acquire the same lock in the stop function. So, only one of the functions can be doing its thing, meaning we do not need to wait for the player to be stopped as it cannot be doing anything as we prevent that by the lock. --- src/music/fluidsynth.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index 061ade3456..1c4b67e12b 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -163,21 +163,12 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song) void MusicDriver_FluidSynth::StopSong() { - { - std::lock_guard lock{ _midi.synth_mutex }; - - if (_midi.player == nullptr) return; - - fluid_player_stop(_midi.player); - } - - /* The join must be run without lock as the Music rendering needs to be - * running so FluidSynth's internals can actually stop the playing. */ - if (fluid_player_join(_midi.player) != FLUID_OK) { - DEBUG(driver, 0, "Could not join player"); - } - std::lock_guard lock{ _midi.synth_mutex }; + + if (_midi.player == nullptr) return; + + fluid_player_stop(_midi.player); + /* No fluid_player_join needed */ delete_fluid_player(_midi.player); fluid_synth_system_reset(_midi.synth); fluid_synth_all_sounds_off(_midi.synth, -1); From 296194ad36c601cf12d215a65d84222bbdf4de61 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 9 May 2021 22:51:26 +0200 Subject: [PATCH 140/800] Fix: memory leak due to assigning result of strdup to a std::string --- src/newgrf.cpp | 2 +- src/signs_cmd.cpp | 2 +- src/town_cmd.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 7b8ab9de1d..c372f033a8 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7394,7 +7394,7 @@ static void GRFInhibit(ByteReader *buf) if (file != nullptr && file != _cur.grfconfig) { grfmsg(2, "GRFInhibit: Deactivating file '%s'", file->filename); GRFError *error = DisableGrf(STR_NEWGRF_ERROR_FORCEFULLY_DISABLED, file); - error->data = stredup(_cur.grfconfig->GetName()); + error->data = _cur.grfconfig->GetName(); } } } diff --git a/src/signs_cmd.cpp b/src/signs_cmd.cpp index a0843917d8..6ffb6cda1f 100644 --- a/src/signs_cmd.cpp +++ b/src/signs_cmd.cpp @@ -54,7 +54,7 @@ CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 si->y = y; si->z = GetSlopePixelZ(x, y); if (!StrEmpty(text)) { - si->name = stredup(text); + si->name = text; } si->UpdateVirtCoord(); InvalidateWindowData(WC_SIGN_LIST, 0, 0); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 01331a269e..033d042486 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2004,7 +2004,7 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 old_generating_world.Restore(); if (t != nullptr && !StrEmpty(text)) { - t->name = stredup(text); + t->name = text; t->UpdateVirtCoord(); } From 495d73a67fe924eed5504003a3a5ba30758dcbc5 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 9 May 2021 23:00:36 +0200 Subject: [PATCH 141/800] Fix: leaking file descriptors --- src/console_cmds.cpp | 1 + src/network/network_content.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 01c35ecf88..3929b44c11 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -939,6 +939,7 @@ DEF_CONSOLE_CMD(ConExec) } if (_script_current_depth == 11) { + FioFCloseFile(script_file); IConsoleError("Maximum 'exec' depth reached; script A is calling script B is calling script C ... more than 10 times."); return true; } diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 528b7bd777..e4f368618b 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -410,7 +410,8 @@ static bool GunzipFile(const ContentInfo *ci) FILE *ftmp = fopen(GetFullFilename(ci, true).c_str(), "rb"); if (ftmp == nullptr) return false; /* Duplicate the handle, and close the FILE*, to avoid double-closing the handle later. */ - gzFile fin = gzdopen(dup(fileno(ftmp)), "rb"); + int fdup = dup(fileno(ftmp)); + gzFile fin = gzdopen(fdup, "rb"); fclose(ftmp); FILE *fout = fopen(GetFullFilename(ci, false).c_str(), "wb"); @@ -449,7 +450,12 @@ static bool GunzipFile(const ContentInfo *ci) } } - if (fin != nullptr) gzclose(fin); + if (fin != nullptr) { + gzclose(fin); + } else if (fdup != -1) { + /* Failing gzdopen does not close the passed file descriptor. */ + close(fdup); + } if (fout != nullptr) fclose(fout); return ret; From 2e429ee4853fb4baf78c864be6ba462bd5758096 Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 10 May 2021 19:04:28 +0000 Subject: [PATCH 142/800] Update: Translations from eints german: 2 changes by Wuzzy2 --- src/lang/german.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/german.txt b/src/lang/german.txt index 79df8af49c..ae1255d25c 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Dieser C STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Das Herunterladen der Karte dauerte zu lange STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Der Beitritt zum Server dauerte zu lange STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Ihr Spielername ist ungültig +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Der angefragte Server ist für diesen Client zu alt ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :Allgemeiner Fehler @@ -2269,7 +2270,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} is STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} ist den Zuschauern beigetreten STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} hat eine neue Firma gegründet (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} hat das Spiel verlassen ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} hat seinen/ihren Namen in {STRING} geändert +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} hat den eigenen Namen zu {STRING} geändert STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} gab {2:CURRENCY_LONG} an {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Der Server hat das Spiel beendet STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Der Server startet neu...{}Bitte warten... From 36e22f3a7bc0f86c650a293e2f624ac5ddfffa84 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 11 May 2021 12:26:16 +0200 Subject: [PATCH 143/800] Fix: [Network] clients leaving because of broken connections was not broadcasted (#9238) The code mixed up "client has quit but we already told everyone" with "client lost connection, handle this". Split up those two signals: - CLIENT_QUIT means we told everyone and the connection is now dead - CONNECTION_LIST means we should tell everyone we lost a client --- src/network/core/core.h | 21 +++++++++++---------- src/network/core/tcp_admin.cpp | 2 +- src/network/core/tcp_game.cpp | 4 ++-- src/network/network.cpp | 4 ++-- src/network/network_client.cpp | 2 +- src/network/network_server.cpp | 16 ++++++++-------- 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/network/core/core.h b/src/network/core/core.h index aac36080ff..37948ad527 100644 --- a/src/network/core/core.h +++ b/src/network/core/core.h @@ -20,16 +20,17 @@ void NetworkCoreShutdown(); /** Status of a network client; reasons why a client has quit */ enum NetworkRecvStatus { - NETWORK_RECV_STATUS_OKAY, ///< Everything is okay - NETWORK_RECV_STATUS_DESYNC, ///< A desync did occur - NETWORK_RECV_STATUS_NEWGRF_MISMATCH, ///< We did not have the required NewGRFs - NETWORK_RECV_STATUS_SAVEGAME, ///< Something went wrong (down)loading the savegame - NETWORK_RECV_STATUS_CONN_LOST, ///< The connection is 'just' lost - NETWORK_RECV_STATUS_MALFORMED_PACKET, ///< We apparently send a malformed packet - NETWORK_RECV_STATUS_SERVER_ERROR, ///< The server told us we made an error - NETWORK_RECV_STATUS_SERVER_FULL, ///< The server is full - NETWORK_RECV_STATUS_SERVER_BANNED, ///< The server has banned us - NETWORK_RECV_STATUS_CLOSE_QUERY, ///< Done querying the server + NETWORK_RECV_STATUS_OKAY, ///< Everything is okay. + NETWORK_RECV_STATUS_DESYNC, ///< A desync did occur. + NETWORK_RECV_STATUS_NEWGRF_MISMATCH, ///< We did not have the required NewGRFs. + NETWORK_RECV_STATUS_SAVEGAME, ///< Something went wrong (down)loading the savegame. + NETWORK_RECV_STATUS_CLIENT_QUIT, ///< The connection is lost gracefully. Other clients are already informed of this leaving client. + NETWORK_RECV_STATUS_MALFORMED_PACKET, ///< We apparently send a malformed packet. + NETWORK_RECV_STATUS_SERVER_ERROR, ///< The server told us we made an error. + NETWORK_RECV_STATUS_SERVER_FULL, ///< The server is full. + NETWORK_RECV_STATUS_SERVER_BANNED, ///< The server has banned us. + NETWORK_RECV_STATUS_CLOSE_QUERY, ///< Done querying the server. + NETWORK_RECV_STATUS_CONNECTION_LOST, ///< The connection is lost unexpectedly. }; /** Forward declaration due to circular dependencies */ diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index c72583f553..36daae4a14 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -41,7 +41,7 @@ NetworkAdminSocketHandler::~NetworkAdminSocketHandler() NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error) { delete this; - return NETWORK_RECV_STATUS_CONN_LOST; + return NETWORK_RECV_STATUS_CLIENT_QUIT; } /** diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index eb53db5acd..771ea37b15 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -48,10 +48,10 @@ NetworkRecvStatus NetworkGameSocketHandler::CloseConnection(bool error) _networking = false; ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); - return NETWORK_RECV_STATUS_CONN_LOST; + return NETWORK_RECV_STATUS_CLIENT_QUIT; } - return this->CloseConnection(error ? NETWORK_RECV_STATUS_SERVER_ERROR : NETWORK_RECV_STATUS_CONN_LOST); + return this->CloseConnection(NETWORK_RECV_STATUS_CONNECTION_LOST); } diff --git a/src/network/network.cpp b/src/network/network.cpp index 4fdbdab73c..2186cb8a1d 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -585,13 +585,13 @@ void NetworkClose(bool close_admins) } for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { - cs->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } ServerNetworkGameSocketHandler::CloseListeners(); ServerNetworkAdminSocketHandler::CloseListeners(); } else if (MyClient::my_client != nullptr) { MyClient::SendQuit(); - MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } TCPConnecter::KillAll(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index f827c57351..501449705e 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -656,7 +656,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac p->Recv_string(name, sizeof(name)); if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; /* The server validates the name when receiving it from clients, so when it is wrong * here something went really wrong. In the best case the packet got malformed on its * way too us, in the worst case the server is broken or compromised. */ diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index e8266a84fc..eccf80f781 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -256,7 +256,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta */ if (this->sock == INVALID_SOCKET) return status; - if (status != NETWORK_RECV_STATUS_CONN_LOST && status != NETWORK_RECV_STATUS_SERVER_ERROR && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) { + if (status != NETWORK_RECV_STATUS_CLIENT_QUIT && status != NETWORK_RECV_STATUS_SERVER_ERROR && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) { /* We did not receive a leave message from this client... */ char client_name[NETWORK_CLIENT_NAME_LENGTH]; @@ -893,7 +893,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) p->Recv_string(name, sizeof(name)); playas = (Owner)p->Recv_uint8(); - if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; /* join another company does not affect these values */ switch (playas) { @@ -1077,7 +1077,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet CommandPacket cp; const char *err = this->ReceiveCommand(p, &cp); - if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; NetworkClientInfo *ci = this->GetInfo(); @@ -1136,7 +1136,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p /* The client was never joined.. thank the client for the packet, but ignore it */ if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { - return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } this->GetClientName(client_name, lastof(client_name)); @@ -1156,7 +1156,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p NetworkAdminClientError(this->client_id, errorno); - return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p) @@ -1167,7 +1167,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p) /* The client was never joined.. thank the client for the packet, but ignore it */ if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { - return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } this->GetClientName(client_name, lastof(client_name)); @@ -1182,7 +1182,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p) NetworkAdminClientQuit(this->client_id); - return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST); + return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p) @@ -1412,7 +1412,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet p->Recv_string(client_name, sizeof(client_name)); ci = this->GetInfo(); - if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; if (ci != nullptr) { if (!NetworkIsValidClientName(client_name)) { From 9841ebb0bd6531b4ac1474c4c35103d12b8eeb43 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 11 May 2021 12:26:30 +0200 Subject: [PATCH 144/800] Fix: [Network] don't mark the last-joined server as manual (#9239) --- src/network/network_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 613b562fb3..2df40eeec1 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -476,7 +476,7 @@ public: EM_ASM(if (window["openttd_server_list"]) openttd_server_list()); #endif - this->last_joined = NetworkAddServer(_settings_client.network.last_joined); + this->last_joined = NetworkAddServer(_settings_client.network.last_joined, false); this->server = this->last_joined; this->requery_timer.SetInterval(MILLISECONDS_PER_TICK); From 9e7e87ce3e7a7a4f5373883550c6f05a5d023ab6 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 11 May 2021 12:32:27 +0200 Subject: [PATCH 145/800] Fix: [Network] don't rebuild the host-list during iterating the list (#9240) Additionally, only rebuild it when we added a new manual server, as otherwise it is a noop anyway. --- src/network/network.cpp | 1 - src/network/network_gui.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 2186cb8a1d..29e66d932c 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -701,7 +701,6 @@ NetworkGameList *NetworkAddServer(const std::string &connection_string, bool man ClearGRFConfigList(&item->info.grfconfig); item->info.server_name = connection_string; - NetworkRebuildHostList(); UpdateNetworkGameWindow(); NetworkQueryServer(connection_string); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 2df40eeec1..35597fa047 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -830,6 +830,7 @@ public: if (!StrEmpty(str)) { strecpy(_settings_client.network.connect_to_ip, str, lastof(_settings_client.network.connect_to_ip)); NetworkAddServer(str); + NetworkRebuildHostList(); } } From 0968d009c8b4ec5b3f5d84000f2f9f5636f9198a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 11 May 2021 18:53:23 +0200 Subject: [PATCH 146/800] Fix #9243: [Network] For a dedicated server use a fallback client and server name Also warn when the client or server name has not been set and provide pointers on how to set them --- src/network/network.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/network/network.cpp b/src/network/network.cpp index 29e66d932c..d8f0025472 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -841,6 +841,27 @@ static void NetworkInitGameInfo() strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name)); } +/** + * 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. + * If the saved name is the default value, then the user is told to override this value too. + * This is only meant dedicated servers, as for the other servers the GUI ensures a name has been entered. + */ +static void CheckClientAndServerName() +{ + static const char *fallback_client_name = "Unnamed Client"; + if (StrEmpty(_settings_client.network.client_name) || strcmp(_settings_client.network.client_name, fallback_client_name) == 0) { + DEBUG(net, 0, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command.", fallback_client_name); + strecpy(_settings_client.network.client_name, fallback_client_name, lastof(_settings_client.network.client_name)); + } + + static const char *fallback_server_name = "Unnamed Server"; + if (StrEmpty(_settings_client.network.server_name) || strcmp(_settings_client.network.server_name, fallback_server_name) == 0) { + DEBUG(net, 0, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command.", fallback_server_name); + strecpy(_settings_client.network.server_name, fallback_server_name, lastof(_settings_client.network.server_name)); + } +} + bool NetworkServerStart() { if (!_network_available) return false; @@ -849,6 +870,9 @@ bool NetworkServerStart() IConsoleCmdExec("exec scripts/pre_server.scr 0"); if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0"); + /* Check for the client and server names to be set, but only after the scripts had a chance to set them.*/ + if (_network_dedicated) CheckClientAndServerName(); + NetworkDisconnect(false, false); NetworkInitialize(false); DEBUG(net, 1, "starting listeners for clients"); From d0eb3e4bc4904c64667efd791b24846d9ac3c741 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 11 May 2021 19:19:37 +0200 Subject: [PATCH 147/800] Fix: [Network] mark server as offline when no longer reachable (#9244) --- src/network/network.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/network/network.cpp b/src/network/network.cpp index d8f0025472..3b43ddbcd8 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -627,6 +627,14 @@ private: public: TCPQueryConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {} + void OnFailure() override + { + NetworkGameList *item = NetworkGameListAddItem(connection_string); + item->online = false; + + UpdateNetworkGameWindow(); + } + void OnConnect(SOCKET s) override { _networking = true; From 1dfc148613a18b1b71bcc07857149d8941f1b707 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 11 May 2021 19:03:10 +0000 Subject: [PATCH 148/800] Update: Translations from eints korean: 1 change by telk5093 slovak: 149 changes by ApplePie420 --- src/lang/korean.txt | 2 +- src/lang/slovak.txt | 250 ++++++++++++++++++++++++++------------------ 2 files changed, 150 insertions(+), 102 deletions(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 6bf90700c5..a132a0da5c 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -403,7 +403,7 @@ STR_SETTINGS_MENU_TRANSPARENT_SIGNS :역명판 감 ############ range for file menu starts STR_FILE_MENU_SAVE_GAME :게임 저장하기 -STR_FILE_MENU_LOAD_GAME :불러오기 +STR_FILE_MENU_LOAD_GAME :게임 불러오기 STR_FILE_MENU_QUIT_GAME :게임 그만두기 STR_FILE_MENU_SEPARATOR : STR_FILE_MENU_EXIT :종료 diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 563fcaa41d..2ed535c7a9 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -475,7 +475,7 @@ STR_FILE_MENU_EXIT :Ukončiť # map menu STR_MAP_MENU_MAP_OF_WORLD :Mapa sveta STR_MAP_MENU_EXTRA_VIEWPORT :Ďalší pohľad -STR_MAP_MENU_LINGRAPH_LEGEND :Legenka k smerovaniu nákladu +STR_MAP_MENU_LINGRAPH_LEGEND :Legenda k smerovaniu nákladu STR_MAP_MENU_SIGN_LIST :Zoznam popisov ############ range for town menu starts @@ -626,7 +626,7 @@ STR_MONTH_ABBREV_DEC :Dec STR_MONTH_JAN :Január STR_MONTH_FEB :Február STR_MONTH_MAR :Marec -STR_MONTH_APR :April +STR_MONTH_APR :Apríl STR_MONTH_MAY :Máj STR_MONTH_JUN :Jún STR_MONTH_JUL :Júl @@ -877,8 +877,8 @@ STR_NEWS_DISASTER_ZEPPELIN :{BIG_FONT}{BLAC STR_NEWS_DISASTER_SMALL_UFO :{BIG_FONT}{BLACK}Cestné vozidlo bolo zničené pri kolízii s 'UFO' STR_NEWS_DISASTER_AIRPLANE_OIL_REFINERY :{BIG_FONT}{BLACK}Ropná rafinéria explodovala neďaleko mesta {TOWN}! STR_NEWS_DISASTER_HELICOPTER_FACTORY :{BIG_FONT}{BLACK}Za nejasných okolností bola zničená továreň neďaleko mesta {TOWN}! -STR_NEWS_DISASTER_BIG_UFO :{BIG_FONT}{BLACK}'UFO' pristalo nedaleko mesta {TOWN}! -STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE :{BIG_FONT}{BLACK}Zaval v uholnej bani nedaleko mesta {TOWN}! +STR_NEWS_DISASTER_BIG_UFO :{BIG_FONT}{BLACK}'UFO' pristálo neďaleko mesta {TOWN}! +STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE :{BIG_FONT}{BLACK}Zával v uhoľnej bani neďaleko mesta {TOWN}! STR_NEWS_DISASTER_FLOOD_VEHICLE :{BIG_FONT}{BLACK}Povodeň!{}Najmenej {COMMA} ľudí je nezvestných alebo mŕtvych po obrovských záplavách! STR_NEWS_COMPANY_IN_TROUBLE_TITLE :{BIG_FONT}{BLACK}Dopravná spoločnosť má problémy! @@ -909,7 +909,7 @@ STR_NEWS_END_OF_RECESSION :{BIG_FONT}{BLAC STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL :{BIG_FONT}{BLACK}{INDUSTRY} zvyšuje produkciu! STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_COAL :{BIG_FONT}{BLACK}Nové nálezisko uhlia sa objavilo v {INDUSTRY}!{}Očakáva sa zdvojnásobenie produkcie! STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_OIL :{BIG_FONT}{BLACK}Nové nálezisko ropy sa objavilo na {INDUSTRY}!{}Očakáva sa zdvojnásobenie produkcie! -STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM :{BIG_FONT}{BLACK}Na {INDUSTRY} zlepsili pouzivane metody!Ocakava sa zdvojnasobenie produkcie! +STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM :{BIG_FONT}{BLACK}Na {INDUSTRY} zlepšili používané metódy! Očakáva sa zdvojnásobenie produkcie! STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH :{BIG_FONT}{BLACK}{1:INDUSTRY} zvyšuje produkciu {0:STRING.g} o {2:COMMA}%! STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL :{BIG_FONT}{BLACK}{INDUSTRY} znižuje produkciu o 50% STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM :{BIG_FONT}{BLACK}Premnoženie škodcov spôsobilo zničenie úrody na {INDUSTRY}!{}Produkcia sa zíižila o 50% @@ -957,7 +957,7 @@ STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLAC STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} do {STRING} bude budúci rok 3x výnosnejšia! STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} do {STRING} bude budúci rok 4x výnosnejšia! -STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}V meste {TOWN} zavladol dopravny chaos!{}{}Rekonstrukcia ciest financovana {STRING} prinesie 6 mesiacov utrpenia pre motoristov! +STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}V meste {TOWN} zavládol dopravný chaos!{}{}Rekonštrukcia ciest financovaná {STRING} prinesie 6 mesiacov utrpenia pre motoristov! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Prepravné monopoly! STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLACK}Miestna samospráva mesta {TOWN} podpísala exkluzívnu zmluvu na prepravu so spoločnosťou {STRING} na 1 rok !!! @@ -1021,7 +1021,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malajzijský ri STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Jazdia naľavo STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Jazdia napravo -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Názvy miest +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Názvy miest: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Výber štýlu názvov miest ############ start of townname region @@ -1061,6 +1061,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Každých 12 me STR_GAME_OPTIONS_LANGUAGE :{BLACK}Jazyk STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Výber jazyka rozhrania +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% hotovo) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Celá obrazovka STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Zaškrtnite, ak chcete hrať OpenTTD na celej obrazovke @@ -1074,6 +1075,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Hardvér STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Zaškrtnutím políčka dovolíte, aby sa OpenTTD pokúsilo použiť hardvérové zrýchlenie. Zmena nastavenia sa uplatní až po reštartovaní hry STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Nastavenie sa uplatní až po reštartovaní hry +STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync +STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Zaškrtnite toto políčko, aby ste povolili vertikálnu synchronizáciu. Zmeny budú uplatnené až po reštarte hry. Funguje iba ak je zapnutá hardvérová akcelerácia. STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Veľkosť rozhrania STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Výber veľkosti prvkov rozhrania @@ -1162,9 +1165,9 @@ STR_VARIETY_HIGH :Vysoká STR_VARIETY_VERY_HIGH :Veľmi vysoká STR_AI_SPEED_VERY_SLOW :Veľmi pomalé -STR_AI_SPEED_SLOW :Pomale +STR_AI_SPEED_SLOW :Pomalé STR_AI_SPEED_MEDIUM :Stredne -STR_AI_SPEED_FAST :Rychle +STR_AI_SPEED_FAST :Rýchle STR_AI_SPEED_VERY_FAST :Veľmi rýchle STR_SEA_LEVEL_VERY_LOW :Veľmi nízka @@ -1196,9 +1199,9 @@ STR_TERRAIN_TYPE_ALPINIST :Alpinista STR_TERRAIN_TYPE_CUSTOM :Vlastná výška STR_TERRAIN_TYPE_CUSTOM_VALUE :Vlastná výška ({NUM}) -STR_CITY_APPROVAL_PERMISSIVE :Pozitivny -STR_CITY_APPROVAL_TOLERANT :Tolerantny -STR_CITY_APPROVAL_HOSTILE :Odmietavy +STR_CITY_APPROVAL_PERMISSIVE :Pozitívny +STR_CITY_APPROVAL_TOLERANT :Tolerantný +STR_CITY_APPROVAL_HOSTILE :Odmietavý STR_WARNING_NO_SUITABLE_AI :{WHITE}Nieje dostupné žiadne použiteľné AI...{}Niekoľko AI je možné stiahnuť cez 'Online obsah' @@ -1207,6 +1210,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Nastaven STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrovací reťazec: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Rozbaliť všetko STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Zabaliť všetko +STR_CONFIG_SETTING_RESET_ALL :Resetovať všetky hodnoty STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(nie je dostupné vysvetlenie) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Predvolená hodnota: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Nastavenie typu: {ORANGE}{STRING} @@ -1215,6 +1219,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Nastavenie hry STR_CONFIG_SETTING_TYPE_GAME_INGAME :Nastavenie hry (ukladané v uložených hrách; ovplyvní iba aktuálnu hru) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Nastavenie spoločnosti (ukladané v uložených hrách; ovplyvní iba nové hry) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Nastavenie spoločnosti (ukladané v uložených hrách; ovplyvní iba aktuálnu spoločnosť) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Pozor! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Táto akcia vráti všetky nastavenia hry do pôvodného stavu.{}Chcete naozaj pokračovať? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategória: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Typ: @@ -1249,7 +1255,7 @@ STR_CONFIG_SETTING_NONE :Žiadne STR_CONFIG_SETTING_ORIGINAL :Pôvodné STR_CONFIG_SETTING_REALISTIC :Realistické -STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT :vlavo +STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT :vľavo STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER :v strede STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT :vpravo @@ -1349,7 +1355,7 @@ STR_CONFIG_SETTING_BRIBE_HELPTEXT :Povolí podplá STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :Povoliť zakúpenie exkluzívnych dopravných práv: {STRING} STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :Ak si spoločnosť zakúpi exkluzívne prepravné práva od mesta, stanice protihráčov (pasažieri a náklad) nebudú prijímať žiaden náklad po celý rok ! STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :Povoliť financovanie stavieb: {STRING} -STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Povolí spoločnostiam finančne prispievať na rozvoj mesta a budovanie nových domov. +STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Povoliť spoločnostiam finančne prispievať na rozvoj mesta a budovanie nových domov. STR_CONFIG_SETTING_ALLOW_FUND_ROAD :Povoliť financovanie rekonštrukcie miestných ciest: {STRING} STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Povolí spoločnostiam finančne prispievať mestu na rekonštrukciu ciest. To môže zapríčiniť sabotovanie prepráv založených na cestných komunikáciách STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Umožniť posielanie peňazí ostatným spoločnostiam: {STRING} @@ -1482,7 +1488,7 @@ STR_CONFIG_SETTING_LIVERIES_NONE :Žiadne STR_CONFIG_SETTING_LIVERIES_OWN :Vlastná spoločnosť STR_CONFIG_SETTING_LIVERIES_ALL :Všetky spoločnosti STR_CONFIG_SETTING_PREFER_TEAMCHAT :Preferovať tímový chat s klávesou : {STRING} -STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :Prepni systém odosielania správ medzi interným a verejným chatom. respektíve +STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :Prepnúť systém odosielania správ medzi interným a verejným chatom. respektíve STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING :Funkcia rolovacieho kolieska myši: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING_HELPTEXT :Povolí posúvanie pomocou dvoj-dimenzionálnych kolečiek myši STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :Priblížovať mapu @@ -1532,7 +1538,7 @@ STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Zobrazí časy STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Zobraziť príchody a odchody v cestovných poriadkoch: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Zobrazí predpokladané časy príchodov a odchodov v časových rozpisoch. STR_CONFIG_SETTING_QUICKGOTO :Rýchla tvorba cestovného poriadku vozidla: {STRING} -STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Prednastav "Choď do" kurzor pri otvorení okna s príkazmi +STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Prednastaviť "Choď do" kurzor pri otvorení okna s príkazmi STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :Predvolený typ koľají (v novej/nahranej hre): {STRING} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Typ železnice zvolený po štarte alebo nahraní hry. 'prvé dostupné' zvolí najstarší typ koľají, 'posledný dostupný' zvolí najnovší typ koľají, a 'najpoužívanejší' vyberie typ ktorý je v danej dobe najviac používaný. STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :prvé dostupné @@ -1594,10 +1600,10 @@ STR_CONFIG_SETTING_AI_PROFILE_EASY :Ľahký STR_CONFIG_SETTING_AI_PROFILE_MEDIUM :Stredný STR_CONFIG_SETTING_AI_PROFILE_HARD :{G=m}Ťažký -STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :Povoliť AI-ov v hre viacerých hráčov: {STRING} +STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :Povoliť AI v hre viacerých hráčov: {STRING} STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Povoliť AI počítačovým hráčom hrať "Hru viacerých hráčov". STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :#op kódov pred uspaním skriptu: {STRING} -STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maximálne počet krokov skriptu počas 1 ťahu. +STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maximálny počet krokov skriptu počas 1 ťahu. STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :Maximálne využitie pamäte na skript: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_HELPTEXT :Koľko pamäte môže jeden skript spotrebovať pred násilným ukončením. Pri veľkých mapách bude možno potrebné túto hodnotu zvýšiť. STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB @@ -1871,11 +1877,11 @@ STR_CONFIG_ERROR_INVALID_VALUE :{WHITE}... zlá STR_CONFIG_ERROR_TRAILING_CHARACTERS :{WHITE}... staviam postavičky na koniec nastavení '{STRING}' STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... ignorujem NewGRF '{STRING}': duplikuj GRF ID s hodnotou '{STRING}' STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... ignorujem nevhodné NewGRF '{STRING}': {STRING} -STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :nenašiel som +STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :nenájdené STR_CONFIG_ERROR_INVALID_GRF_UNSAFE :nevhodné pre statické použitie STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :systém NewGRF STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE :nekompatibilné s touto verziou OpenTTD -STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN :také nepoznám +STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN :neznáme STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL :{WHITE}... hodnota kompresie '{STRING}' je zle zadaná STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM :{WHITE}... formát uloženej hry '{STRING}' je nedostupný. Zmeniť späť na '{STRING}' STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND :{WHITE}... ignorujem základnú grafickú sadu '{STRING}': nenájdené @@ -1949,8 +1955,8 @@ STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Hrať z STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magický buldozér (odstráni priemysel a nehnuteľnosti): {ORANGE}{STRING} STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunely sa môžu navzájom krížiť: {ORANGE}{STRING} STR_CHEAT_NO_JETCRASH :{LTBLUE}Prúdové lietadlá nehavarujú (tak často) na malých letiskách: {ORANGE} {STRING} -STR_CHEAT_EDIT_MAX_HL :{LTBLUE}Zmeň maximálnu výšku mapy: {ORANGE}{NUM} -STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}Zmeň maximálnu výšku hôr na mape +STR_CHEAT_EDIT_MAX_HL :{LTBLUE}Zmeniť maximálnu výšku mapy: {ORANGE}{NUM} +STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}Zmeniť maximálnu výšku hôr na mape STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE :Krajina mierneho pásma STR_CHEAT_SWITCH_CLIMATE_SUB_ARCTIC_LANDSCAPE :Subpolárna krajina STR_CHEAT_SWITCH_CLIMATE_SUB_TROPICAL_LANDSCAPE :Subtropická krajina @@ -2053,11 +2059,13 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Náušnica: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Zmeniť kravatu alebo náušnicu +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privátny +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Verejný # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Hra pre viac hráčov STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Meno hráča: -STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP :{BLACK}Toto je meno podla ktoreho vas ostatny identifikuju +STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP :{BLACK}Toto je meno podľa ktorého vás ostatný identifikujú STR_NETWORK_SERVER_LIST_GAME_NAME :{BLACK}Názov STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP :{BLACK}Názov hry @@ -2089,12 +2097,12 @@ STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Aktuál STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Heslo: STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}SERVER JE OFFLINE STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}SERVER JE PLNÝ -STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ROZNE VERZIE +STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}RÔZNE VERZIE STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}NEWGRF Chyba -STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Pripojit sa +STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Pripojiť sa STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Obnoviť server -STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Obnovit info o serveri +STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Obnoviť info o serveri STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Prehľadať internet STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Prehľadať verejné servery na internete @@ -2116,6 +2124,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Názov h STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Nastaviť heslo STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Zabezpeč hru heslom, ak nechceš povoliť verejný prístup +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Viditeľnosť +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Aby ostatní hráči videli tento server v zozname verejných servrov STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i ov} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximálny počet klientov: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Zvoľ maximálny počet klientov. Môže sa ich pripojiť aj menej. @@ -2136,17 +2146,17 @@ STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Sieťov STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Pripravuje sa k vstupu: {ORANGE}{STRING} STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Aktuálny zoznam spoločností v tejto hre. Buď môžeš do jednej vstúpiť, alebo založiť novú spoločnosť. -STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}INFO O SPOLOCNOSTI +STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}INFO O SPOLOČNOSTI STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Názov spoločnosti: {WHITE}{STRING} -STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}Zalozene: {WHITE}{NUM} +STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}Založené: {WHITE}{NUM} STR_NETWORK_GAME_LOBBY_VALUE :{SILVER}Hodnota spoločnosti: {WHITE}{CURRENCY_LONG} -STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE :{SILVER}Stav uctu: {WHITE}{CURRENCY_LONG} +STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE :{SILVER}Stav účtu: {WHITE}{CURRENCY_LONG} STR_NETWORK_GAME_LOBBY_LAST_YEARS_INCOME :{SILVER}Zisk v minulom roku: {WHITE}{CURRENCY_LONG} -STR_NETWORK_GAME_LOBBY_PERFORMANCE :{SILVER}Vykon: {WHITE}{NUM} +STR_NETWORK_GAME_LOBBY_PERFORMANCE :{SILVER}Výkon: {WHITE}{NUM} -STR_NETWORK_GAME_LOBBY_VEHICLES :{SILVER}Vozidla: {WHITE}{NUM} {TRAIN}, {NUM} {LORRY}, {NUM} {BUS}, {NUM} {SHIP}, {NUM} {PLANE} +STR_NETWORK_GAME_LOBBY_VEHICLES :{SILVER}Vozidlá: {WHITE}{NUM} {TRAIN}, {NUM} {LORRY}, {NUM} {BUS}, {NUM} {SHIP}, {NUM} {PLANE} STR_NETWORK_GAME_LOBBY_STATIONS :{SILVER}Stanice: {WHITE}{NUM} {TRAIN}, {NUM} {LORRY}, {NUM} {BUS}, {NUM} {SHIP}, {NUM} {PLANE} -STR_NETWORK_GAME_LOBBY_PLAYERS :{SILVER}Hraci: {WHITE}{STRING} +STR_NETWORK_GAME_LOBBY_PLAYERS :{SILVER}Hráči: {WHITE}{STRING} STR_NETWORK_GAME_LOBBY_NEW_COMPANY :{BLACK}Nová spoločnosť STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP :{BLACK}Založiť novú spoločnosť @@ -2179,11 +2189,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server j STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Spoločnosť je chránená. Zadaj heslo # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Zoznam klientov +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Zoznam pripojených klientov # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Hra pre viacerých hráčov +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Meno +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Názov servra, na ktorom práve hráte +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Upraviť názov servra +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Názov servra +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Viditelnosť +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Aby ostatní hráči videli váš server v zozname verejných servrov +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Hráč +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Meno +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Meno vašeho hráča +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Upraviť meno vašeho hráča +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Meno vašeho hráča +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrátorské činnosti, ktoré môžete vykonačť pre tohoto klienta +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrátorské činnosti, ktoré pre túto spoločnosť môžete vykonať +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Pripojiť sa k tejto spoločnosti +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Poslať správu tomuto hráčovi +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Poslať správu všetkým hráčom tejto spoločnosti +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Poslať správu všetkým pozorovateľom +STR_NETWORK_CLIENT_LIST_SPECTATORS :Pozorovatelia +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nová spoločnosť) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Založiť novú spoločnosť a pripojiť sa k nej +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Toto ste vy +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Toto je hosť hry +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Vyhodiť +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Vymazať +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Odomknúť heslom +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Akcia administrátora +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Ste si istý, že chcete vyhodiť hráča '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Ste si istý, že chcete zabanovť hráča '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Ste si istý, že chcete vymazať spoločnosť '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Ste si istý, že chcete zresetovať heslo pre spoločnosť '{COMPANY}'? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient @@ -2218,50 +2261,54 @@ STR_NETWORK_CHAT_OSKTITLE :{BLACK}Zadajte # Network messages STR_NETWORK_ERROR_NOTAVAILABLE :{WHITE}Nebolo nájdené žiadne sieťové zariadenie, alebo je hra kompilovaná bez ENABLE_NETWORK -STR_NETWORK_ERROR_NOSERVER :{WHITE}Nebola najdena ziadna sietova hra -STR_NETWORK_ERROR_NOCONNECTION :{WHITE}Server neodpoveda na ziadost -STR_NETWORK_ERROR_NEWGRF_MISMATCH :{WHITE}Pripojenie zlyhalo kvoli nespravnemu NewGRF +STR_NETWORK_ERROR_NOSERVER :{WHITE}Nebola nájdená žiadna sieťová hra +STR_NETWORK_ERROR_NOCONNECTION :{WHITE}Server neodpovedá na žiadosť +STR_NETWORK_ERROR_NEWGRF_MISMATCH :{WHITE}Pripojenie zlyhalo kvôli nesprávnemu NewGRF STR_NETWORK_ERROR_DESYNC :{WHITE}Sieť - Chyba synchronizácie hry STR_NETWORK_ERROR_LOSTCONNECTION :{WHITE}Sieť - Stratené spojenie STR_NETWORK_ERROR_SAVEGAMEERROR :{WHITE}Nedokážem nahrať hru zo servera STR_NETWORK_ERROR_SERVER_START :{WHITE}Server nemôžem spustiť -STR_NETWORK_ERROR_CLIENT_START :{WHITE}Nemozem sa pripojit. +STR_NETWORK_ERROR_CLIENT_START :{WHITE}Nemožem sa pripojiť STR_NETWORK_ERROR_TIMEOUT :{WHITE}Vypršal časový limit pre spojenie č. {NUM} -STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Chyba vznikla v protokole a spojenie je zatvorene. +STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Chyba vznikla v protokole a spojenie je zatvorené +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Meno vašeho hráča nebolo nastavené. Meno si môžete zmeniť v hlavičke okna Hry pre viacerých hráčov STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Revizia hry u tohto klienta nezodpoveda revizii hry na serveri. -STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Nespravne heslo. -STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Server je plny -STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Si zablokovany na tomto serveri -STR_NETWORK_ERROR_KICKED :{WHITE}Bol si vyhodeny z hry +STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Nesprávne heslo +STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Server je plný +STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Si zabanovaný na tomto serveri +STR_NETWORK_ERROR_KICKED :{WHITE}Bol si vyhodený z hry STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Dôvod: {STRING} -STR_NETWORK_ERROR_CHEATER :{WHITE}Cheatovanie nie je povolene na tomto serveri +STR_NETWORK_ERROR_CHEATER :{WHITE}Cheatovanie nie je povolené na tomto serveri STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Posielali ste priveľa príkazov serveru STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Príliš dlho si zadával heslo STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tvoj počítač sa príliš pomaly pripájal na server STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Tvoj počítač sťahoval mapu príliš dlho STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Tvoj počítač sa príliš dlho pripájal na server +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Meno vašeho hráča nieje platné +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Nájdený server je príliš starý pre vašeho klienta ############ Leave those lines in this order!! -STR_NETWORK_ERROR_CLIENT_GENERAL :generalna chyba -STR_NETWORK_ERROR_CLIENT_DESYNC :chyba synchronizacie +STR_NETWORK_ERROR_CLIENT_GENERAL :všeobecná chyba +STR_NETWORK_ERROR_CLIENT_DESYNC :chyba synchronizácie STR_NETWORK_ERROR_CLIENT_SAVEGAME :nemôžem načítať mapu STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST :spojenie prerušené STR_NETWORK_ERROR_CLIENT_PROTOCOL_ERROR :chyba protokolu -STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH :Nespravne NewGRF -STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED :overenie odmietnute +STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH :Nesprávne NewGRF +STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED :overenie odmietnuté STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED :prijatý neplatný, alebo neočakávaný paket -STR_NETWORK_ERROR_CLIENT_WRONG_REVISION :chybna revizia hry -STR_NETWORK_ERROR_CLIENT_NAME_IN_USE :meno sa uz pouziva -STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD :nespravne heslo +STR_NETWORK_ERROR_CLIENT_WRONG_REVISION :chybná verzia hry +STR_NETWORK_ERROR_CLIENT_NAME_IN_USE :meno sa už používa +STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD :nesprávne heslo STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH :zlá spoločnosť-id in DoCommand STR_NETWORK_ERROR_CLIENT_KICKED :vyhodený zo servera -STR_NETWORK_ERROR_CLIENT_CHEATER :sa pokusal cheatovat -STR_NETWORK_ERROR_CLIENT_SERVER_FULL :server je plny +STR_NETWORK_ERROR_CLIENT_CHEATER :sa pokúšal cheatovať +STR_NETWORK_ERROR_CLIENT_SERVER_FULL :server je plný STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS :posielal priveľa príkazov STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :nebolo včas obdržané heslo STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :všeobecný timeout STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :sťahovanie mapy trvalo príliš dlho STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :spracovanie mapy trvalo príliš dlho +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :Neplatný názov klienta ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Možná ztráta pripojenia @@ -2292,7 +2339,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} za STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} opustil hru ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} zmenil/-a svoje meno na {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} dal {2:CURRENCY_LONG} spoločnosti {1:STRING} -STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server ukoncil relaciu +STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server ukončil reláciu STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server sa reštartuje...{}Čakajte prosím... STR_NETWORK_MESSAGE_KICKED :*** Hráč {STRING} bol vyhodený. Dôvod: ({STRING}) @@ -2462,7 +2509,7 @@ STR_STATION_BUILD_STATION_CLASS_TOOLTIP :{BLACK}Vyberte STR_STATION_BUILD_STATION_TYPE_TOOLTIP :{BLACK}Vyberte typ stanice pre vystavbu STR_STATION_CLASS_DFLT :Pôvodná stanica -STR_STATION_CLASS_WAYP :Smerove body +STR_STATION_CLASS_WAYP :Smerové body # Signal window STR_BUILD_SIGNAL_CAPTION :{WHITE}Výber návestidla @@ -2480,7 +2527,7 @@ STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP :{BLACK}Trasové STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP :{BLACK}Jednosmerné trasové návestidlo (elektrické){}Trasové návestidlo povolí viac vlakov v jednom úseku súčasne, ak má vlak voľnú trasu, ktorú si rezervuje. Jednosmerné trasové návestidla môžu vlaky prechádzať iba z prednej strany STR_BUILD_SIGNAL_CONVERT_TOOLTIP :{BLACK}Zameniť návestidlo{}Po vybratí, kliknutím na existujúce návestidlo dochádza k zámene na vybraný typ a variantu návestidla. Ctrl+klik prepne existujúcu variantu. Shift+klik zobrazí odhadovanú cenu zámeny STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}Hustota návestidiel pri stavbe ťahaním -STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP :{BLACK}Znižit hustotu návestidiel +STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP :{BLACK}Znížiť hustotu návestidiel STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Zvýšit hustotu návestidiel # Bridge selection window @@ -2551,7 +2598,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Postavi STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Umiestniť bóju na vyznačenie trasy. Shift zobrazí odhadovanú cenu STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Postaviť akvadukt. Shift zobrazí odhadovanú cenu STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Definovať oblasť vody.{}Vytvorí vodný kanál, pri stlacení CTRL na úrovni mora zaplaví okolie -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Umiestniť rieku. +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Umiestniť rieku. Ctrl označí oblasť diagonálne # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Orientácia lodenice @@ -2620,16 +2667,16 @@ STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Sadiť v # Land generation window (SE) STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Generovanie územia -STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Umiestnit nahodne skaly +STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Umiestniť náhodne skaly STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA :{BLACK}Vytvoriť oblasť púšte.{}Držaním Ctrl ju odstránite STR_TERRAFORM_TOOLTIP_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Pre zvýšenie/zníženie oblasti je potrebné zväčšiť územie STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Pre zvýšenie/zníženie oblasti je potrebné zmenšiť územie STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND :{BLACK}Vygenerovať náhodné územie STR_TERRAFORM_SE_NEW_WORLD :{BLACK}Vytvoriť nový scenár -STR_TERRAFORM_RESET_LANDSCAPE :{BLACK}Zresetovat územie +STR_TERRAFORM_RESET_LANDSCAPE :{BLACK}Zresetovať územie STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP :{BLACK}Odstrániť všetok majetok spoločnosti z mapy -STR_QUERY_RESET_LANDSCAPE_CAPTION :{WHITE}Zresetovat Územie +STR_QUERY_RESET_LANDSCAPE_CAPTION :{WHITE}Zresetovať Územie STR_RESET_LANDSCAPE_CONFIRMATION_TEXT :{WHITE}Ste si istý, že chcete odstrániť všetok majetok spoločnosti? # Town generation window (SE) @@ -2648,9 +2695,9 @@ STR_FOUND_TOWN_NAME_RANDOM_BUTTON :{BLACK}Náhodn STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP :{BLACK}Vygenerovať nové náhodné meno STR_FOUND_TOWN_INITIAL_SIZE_TITLE :{YELLOW}Veľkosť mesta: -STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON :{BLACK}Male +STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON :{BLACK}Malé STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON :{BLACK}Stredne -STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}Velke +STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}Veľké STR_FOUND_TOWN_SIZE_RANDOM :{BLACK}Náhodný STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Vyber veľkosť mesta STR_FOUND_TOWN_CITY :{BLACK}Veľkomesto @@ -2672,7 +2719,7 @@ STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Pokryť STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Vytvoriť náhodný priemysel STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Ste si istý, že chcete vytvoriť veľké množstvo náhodného priemyslu? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Cena: {YELLOW}{CURRENCY_LONG} -STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Vyhladat +STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Vyhľadať STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Postaviť STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Založiť STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Odstrániť všetok priemysel @@ -2777,7 +2824,7 @@ STR_LAI_TREE_NAME_CACTUS_PLANTS :Kaktusy STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION :Železničná stanica STR_LAI_STATION_DESCRIPTION_AIRCRAFT_HANGAR :Letecký hangár STR_LAI_STATION_DESCRIPTION_AIRPORT :Letisko -STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA :Vykladka +STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA :Vykládka STR_LAI_STATION_DESCRIPTION_BUS_STATION :Stanica STR_LAI_STATION_DESCRIPTION_SHIP_DOCK :Prístav STR_LAI_STATION_DESCRIPTION_BUOY :Bója @@ -2965,13 +3012,13 @@ STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Pokrytie STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Zmeniť rok začiatku hry # SE Map generation -STR_SE_MAPGEN_CAPTION :{WHITE}Typ scenara -STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Rovna krajina +STR_SE_MAPGEN_CAPTION :{WHITE}Typ scenára +STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Rovná krajina STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}Generovať rovnú krajinu -STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Nahodna krajina +STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Náhodná krajina STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}Výška rovnej krajiny: STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Znizit vysku rovnej krajiny o jedno -STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Zvysit vysku rovnej krajiny o jedno +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Zvýšiť výšku rovnej krajiny o jedno STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Zmeniť výšku rovnej krajiny @@ -3001,16 +3048,16 @@ STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}Vybrať STR_NEWGRF_FILTER_TITLE :{ORANGE}Filtrovací reťazec: STR_NEWGRF_SETTINGS_PRESET_LIST_TOOLTIP :{BLACK}Nahrať vybraný zoznam STR_NEWGRF_SETTINGS_PRESET_SAVE :{BLACK}Uložit zoznam -STR_NEWGRF_SETTINGS_PRESET_SAVE_TOOLTIP :{BLACK}Uložit aktuálne nastavenie ako zoznam +STR_NEWGRF_SETTINGS_PRESET_SAVE_TOOLTIP :{BLACK}Uložiť aktuálne nastavenie ako zoznam STR_NEWGRF_SETTINGS_PRESET_SAVE_QUERY :{BLACK}Zadajte názov zoznamu -STR_NEWGRF_SETTINGS_PRESET_DELETE :{BLACK}Vymazat zoznam -STR_NEWGRF_SETTINGS_PRESET_DELETE_TOOLTIP :{BLACK}Vymazat vybraný zoznam -STR_NEWGRF_SETTINGS_ADD :{BLACK}Pridat -STR_NEWGRF_SETTINGS_ADD_FILE_TOOLTIP :{BLACK}Pridat vybraný NewGRF súbor do konfigurácie -STR_NEWGRF_SETTINGS_RESCAN_FILES :{BLACK}Obnovit zoznam súborov -STR_NEWGRF_SETTINGS_RESCAN_FILES_TOOLTIP :{BLACK}Obnovit zoznam dostupných NewGRF súborov -STR_NEWGRF_SETTINGS_REMOVE :{BLACK}Odstránit -STR_NEWGRF_SETTINGS_REMOVE_TOOLTIP :{BLACK}Odstránit vybraný NewGRF súbor zo zoznamu +STR_NEWGRF_SETTINGS_PRESET_DELETE :{BLACK}Vymazať zoznam +STR_NEWGRF_SETTINGS_PRESET_DELETE_TOOLTIP :{BLACK}Vymazať vybraný zoznam +STR_NEWGRF_SETTINGS_ADD :{BLACK}Pridať +STR_NEWGRF_SETTINGS_ADD_FILE_TOOLTIP :{BLACK}Pridať vybraný NewGRF súbor do konfigurácie +STR_NEWGRF_SETTINGS_RESCAN_FILES :{BLACK}Obnoviť zoznam súborov +STR_NEWGRF_SETTINGS_RESCAN_FILES_TOOLTIP :{BLACK}Obnoviť zoznam dostupných NewGRF súborov +STR_NEWGRF_SETTINGS_REMOVE :{BLACK}Odstrániť +STR_NEWGRF_SETTINGS_REMOVE_TOOLTIP :{BLACK}Odstrániť vybraný NewGRF súbor zo zoznamu STR_NEWGRF_SETTINGS_MOVEUP :{BLACK}Vyššie STR_NEWGRF_SETTINGS_MOVEUP_TOOLTIP :{BLACK}Posunút vybraný NewGRF súbor v zozname vyššie STR_NEWGRF_SETTINGS_MOVEDOWN :{BLACK}Nižšie @@ -3019,11 +3066,11 @@ STR_NEWGRF_SETTINGS_UPGRADE :{BLACK}Aktualiz STR_NEWGRF_SETTINGS_UPGRADE_TOOLTIP :{BLACK}Aktualizujte NewGRF súbory ktoré máte inštalované, na novšie verzie STR_NEWGRF_SETTINGS_FILE_TOOLTIP :{BLACK}Zoznam inštalovaných NewGRF súborov. -STR_NEWGRF_SETTINGS_SET_PARAMETERS :{BLACK}Nastavit parametre +STR_NEWGRF_SETTINGS_SET_PARAMETERS :{BLACK}Nastaviť parametre STR_NEWGRF_SETTINGS_SHOW_PARAMETERS :{BLACK}Ukázať parametre STR_NEWGRF_SETTINGS_TOGGLE_PALETTE :{BLACK}Prepnúť paletu STR_NEWGRF_SETTINGS_TOGGLE_PALETTE_TOOLTIP :{BLACK}Prepnúť paletu na zvolené NewGRF.{}Vykonajte to ak grafika z tohoto NewGRF je v hre ružová -STR_NEWGRF_SETTINGS_APPLY_CHANGES :{BLACK}Potvrdit zmeny +STR_NEWGRF_SETTINGS_APPLY_CHANGES :{BLACK}Potvrdiť zmeny STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON :{BLACK}Nájsť chýbajúci obsah online STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP :{BLACK}Skontrolovať či je chýbajúci obsah dostupný online @@ -3101,6 +3148,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Upozorneni STR_NEWGRF_ERROR_MSG_ERROR :{RED}Chyba: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Kritická chyba: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Nastala závažná chyba NewGRF:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Vyskytla sa chyba NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} nebude fungovať s TTDPatch verziou nahlásenou OpenTTD. STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} je pre verziu {STRING} TTD. STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} je navrhnutý pre použitie s {STRING} @@ -3212,7 +3260,7 @@ STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Miestna STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Zobraziť informácie o miestnej správe STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Zmeniť názov mesta -STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Rozsirit +STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Rozšíriť STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Zväčšiť veľkosť mesta STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Vymazať STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Kompletne vymazať toto mesto @@ -3318,7 +3366,7 @@ STR_STATION_LIST_CAPTION :{WHITE}{COMPANY STR_STATION_LIST_STATION :{YELLOW}{STATION} {STATION_FEATURES} STR_STATION_LIST_WAYPOINT :{YELLOW}{WAYPOINT} STR_STATION_LIST_NONE :{YELLOW}- Žiadne - -STR_STATION_LIST_SELECT_ALL_FACILITIES :{BLACK}Oznacit vsetky moznosti +STR_STATION_LIST_SELECT_ALL_FACILITIES :{BLACK}Označiť všetky možnosti STR_STATION_LIST_SELECT_ALL_TYPES :{BLACK}Označiť všetky druhy nákladu (vrátane nečakajúceho na prepravu) STR_STATION_LIST_NO_WAITING_CARGO :{BLACK}Nečaká žiadny typ nákladu @@ -3603,7 +3651,7 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :Nové automobil STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :Nové električky ############ range for vehicle availability starts -STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :Železnicne vozidlá +STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :Železničné vozidlá STR_BUY_VEHICLE_ROAD_VEHICLE_ALL_CAPTION :Nové cestné vozidlá STR_BUY_VEHICLE_SHIP_CAPTION :Nové lode STR_BUY_VEHICLE_AIRCRAFT_CAPTION :Nové lietadlá @@ -3719,10 +3767,10 @@ STR_DEPOT_SELL_ALL_BUTTON_ROAD_VEHICLE_TOOLTIP :{BLACK}Predať STR_DEPOT_SELL_ALL_BUTTON_SHIP_TOOLTIP :{BLACK}Predať všetky lode v lodenici STR_DEPOT_SELL_ALL_BUTTON_AIRCRAFT_TOOLTIP :{BLACK}Predať všetky lietadlá v hangári -STR_DEPOT_AUTOREPLACE_TRAIN_TOOLTIP :{BLACK}Automaticky nahradit všetky vlaky v depe -STR_DEPOT_AUTOREPLACE_ROAD_VEHICLE_TOOLTIP :{BLACK}Automaticky nahradit všetky vozidlá v garáži -STR_DEPOT_AUTOREPLACE_SHIP_TOOLTIP :{BLACK}Automaticky nahradit všetky lode v lodenici -STR_DEPOT_AUTOREPLACE_AIRCRAFT_TOOLTIP :{BLACK}Automaticky nahradit všetky lietadlá v hangári +STR_DEPOT_AUTOREPLACE_TRAIN_TOOLTIP :{BLACK}Automaticky nahradiť všetky vlaky v depe +STR_DEPOT_AUTOREPLACE_ROAD_VEHICLE_TOOLTIP :{BLACK}Automaticky nahradiť všetky vozidlá v garáži +STR_DEPOT_AUTOREPLACE_SHIP_TOOLTIP :{BLACK}Automaticky nahradiť všetky lode v lodenici +STR_DEPOT_AUTOREPLACE_AIRCRAFT_TOOLTIP :{BLACK}Automaticky nahradiť všetky lietadlá v hangári STR_DEPOT_TRAIN_NEW_VEHICLES_BUTTON :{BLACK}Nové vlaky STR_DEPOT_ROAD_VEHICLE_NEW_VEHICLES_BUTTON :{BLACK}Nové vozidlá @@ -3886,7 +3934,7 @@ STR_VEHICLE_STATUS_CRASHED :{RED}Zničené! STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Pokazený STR_VEHICLE_STATUS_STOPPED :{RED}Zastavené STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL :{RED}Zastavuje, {VELOCITY} -STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}Nie je prud +STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}Nie je prúd STR_VEHICLE_STATUS_TRAIN_STUCK :{ORANGE}Čakám na uvoľnenie trate STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR :{ORANGE}K ďalšej destinácii je to príliš ďaleko @@ -3980,7 +4028,7 @@ STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT :{BLACK}Nová ka STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT :{BLACK}Nová kapacita: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}Príjem z prestavby: {GREEN}{CURRENCY_LONG} STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}Vyber vozidlo k prestavbe. Ťah myšou umožní vybrať viacej vozidiel. Kliknutie do voľného mista vybere celé vozidlo. Ctrl+Klik vyberie vozidlo a následujúci reťaz -STR_REFIT_TRAIN_LIST_TOOLTIP :{BLACK}Vybrat typ prepravovaneho nakladu +STR_REFIT_TRAIN_LIST_TOOLTIP :{BLACK}Vybrať typ prepravovaného nákladu STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Vyberte požadovaný typ nákladu pre cestné vozidlo STR_REFIT_SHIP_LIST_TOOLTIP :{BLACK}Vybrať typ nákladu pre loď STR_REFIT_AIRCRAFT_LIST_TOOLTIP :{BLACK}Vybrať nový typ nákladu @@ -4273,7 +4321,7 @@ STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}Nastavi STR_AI_LIST_CAPTION :{WHITE}Dostupné {STRING} STR_AI_LIST_CAPTION_AI :AI STR_AI_LIST_CAPTION_GAMESCRIPT :Herné skripty -STR_AI_LIST_TOOLTIP :{BLACK}Klikni pre výber skriptu +STR_AI_LIST_TOOLTIP :{BLACK}Kliknite pre výber skriptu STR_AI_LIST_AUTHOR :{LTBLUE}Autor: {ORANGE}{STRING} STR_AI_LIST_VERSION :{LTBLUE}Verzia: {ORANGE}{NUM} @@ -4294,7 +4342,7 @@ STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Snímka # AI Parameters STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parametre -STR_AI_SETTINGS_CAPTION_AI :Imelá inteligencia +STR_AI_SETTINGS_CAPTION_AI :Umelá inteligencia STR_AI_SETTINGS_CAPTION_GAMESCRIPT :Skript STR_AI_SETTINGS_CLOSE :{BLACK}Zavrieť STR_AI_SETTINGS_RESET :{BLACK}Resetovať @@ -4339,7 +4387,7 @@ STR_MESSAGE_ESTIMATED_INCOME :{WHITE}Odhadova # Saveload messages STR_ERROR_SAVE_STILL_IN_PROGRESS :{WHITE}Ukladanie hry este bezi,{}pockajte prosim na dokoncenie! -STR_ERROR_AUTOSAVE_FAILED :{WHITE}Autoulozenie zlyhalo +STR_ERROR_AUTOSAVE_FAILED :{WHITE}Automatické ukladanie zlyhalo STR_ERROR_UNABLE_TO_READ_DRIVE :{BLACK}Zariadenie je nečitateľné STR_ERROR_GAME_SAVE_FAILED :{WHITE}Uloženie hry zlyhalo{}{STRING} STR_ERROR_UNABLE_TO_DELETE_FILE :{WHITE}Súbor sa nedá vymazať @@ -4429,7 +4477,7 @@ STR_ERROR_CAN_T_CHANGE_PRESIDENT :{WHITE}Meno pre STR_ERROR_MAXIMUM_PERMITTED_LOAN :{WHITE}... úverovy limit je {CURRENCY_LONG} STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôžete si požičať viac peňazí... STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... úver už bol splatený -STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} potrebuješ +STR_ERROR_CURRENCY_REQUIRED :{WHITE}... Potrebuješ {CURRENCY_LONG} STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Úver sa nedá splatiť... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je možné presunúť peniaze, ktoré sú požičané z banky... STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti... @@ -4447,7 +4495,7 @@ STR_ERROR_CAN_T_EXPAND_TOWN :{WHITE}Nemožno STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... príliš blízko okraja mapy STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... príliš blízko iného mesta STR_ERROR_TOO_MANY_TOWNS :{WHITE}... príliš veľa miest -STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nie je dalsie miesto na mape +STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nie je miesto na mape STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Mesto nebude stavať cesty. Môžete povoliť budovanie ciest cez Pokročilé nasvavenia->Ekonomika->Mestá. STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Prebiehajú cestné práce STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Toto mesto nie je možné odstrániť...{}Stanica alebo depo sa odvoláva na mesto, alebo parcela vo vlastníctve mesta nemôže byť odstránená @@ -4717,7 +4765,7 @@ STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Nemôže STR_ERROR_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Lietadlo je vo vzduchu # Order related errors -STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Nemozno zadat dalsie prikazy +STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Nemožno zadať ďalšie príkazy STR_ERROR_TOO_MANY_ORDERS :{WHITE}Príliš veľa príkazov STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}Nemožno vložiť nový príkaz... STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}Nemožno vymazať tento príkaz... @@ -4736,7 +4784,7 @@ STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... prí STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... lietadlo nemá dostatočný dosah # Timetable related errors -STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Vozidlu nie je možné zadat cestovný poriadok ... +STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Vozidlu nie je možné zadať cestovný poriadok ... STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Vozidlá možu cakat len v staniciach. STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}Toto vozidlo nezastavuje v tejto stanici. @@ -4773,21 +4821,21 @@ STR_TOWN_BUILDING_NAME_HOTEL_1 :{G=m}Hotel STR_TOWN_BUILDING_NAME_STATUE_1 :{G=z}Socha STR_TOWN_BUILDING_NAME_FOUNTAIN_1 :{G=z}Fontána STR_TOWN_BUILDING_NAME_PARK_1 :{G=m}Park -STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_2 :Kancelarie +STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_2 :Kancelárie STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1 :Obchody a kancelárie STR_TOWN_BUILDING_NAME_MODERN_OFFICE_BUILDING_1 :Moderná administratívna budova STR_TOWN_BUILDING_NAME_WAREHOUSE_1 :{G=m}Sklad STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_3 :Kancelárie -STR_TOWN_BUILDING_NAME_STADIUM_1 :{G=m}Stadión -STR_TOWN_BUILDING_NAME_OLD_HOUSES_1 :Stare domy +STR_TOWN_BUILDING_NAME_STADIUM_1 :{G=m}Štadión +STR_TOWN_BUILDING_NAME_OLD_HOUSES_1 :Staré domy STR_TOWN_BUILDING_NAME_COTTAGES_1 :Chaty STR_TOWN_BUILDING_NAME_HOUSES_1 :Domy STR_TOWN_BUILDING_NAME_FLATS_1 :Byty -STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_2 :{G=z}Administrativa -STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_2 :Obchody a kancelarie -STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_3 :Obchody a kancelarie +STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_2 :{G=z}Administratíva +STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_2 :Obchody a kancelárie +STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_3 :Obchody a kancelárie STR_TOWN_BUILDING_NAME_THEATER_1 :{G=s}Divadlo -STR_TOWN_BUILDING_NAME_STADIUM_2 :{G=m}Stadión +STR_TOWN_BUILDING_NAME_STADIUM_2 :{G=m}Štadión STR_TOWN_BUILDING_NAME_OFFICES_1 :Kancelárie STR_TOWN_BUILDING_NAME_HOUSES_2 :Domy STR_TOWN_BUILDING_NAME_CINEMA_1 :{G=s}Kino From c0a0d85d202843ca68dbc3cd817158a6ccfb53d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Tue, 11 May 2021 21:43:43 +0200 Subject: [PATCH 149/800] Fix: [Actions] Annotations not shown for MSVC (#9247) --- cmake/CompileFlags.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index 86d336b595..2f7528fe3c 100644 --- a/cmake/CompileFlags.cmake +++ b/cmake/CompileFlags.cmake @@ -26,8 +26,10 @@ macro(compile_flags) add_compile_options(/Zc:rvalueCast) if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # Enable multi-threaded compilation. - add_compile_options(/MP) + add_compile_options( + /MP # Enable multi-threaded compilation. + /FC # Display the full path of source code files passed to the compiler in diagnostics. + ) endif() endif() From 3d9436bd75d2d6ff2024ac4ccacf8d6e1e730cc3 Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 12 May 2021 08:11:14 +0100 Subject: [PATCH 150/800] Fix #9202: Invalid test for unset NewGRF override mapping. (#9226) --- src/newgrf_commons.h | 1 - src/saveload/newgrf_sl.cpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index b86e3d10af..ed18aaa9e2 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -218,7 +218,6 @@ public: inline uint16 GetMaxMapping() const { return max_new_entities; } inline uint16 GetMaxOffset() const { return max_offset; } - inline bool IsValidID(uint16 entity_id) const { return entity_overrides[entity_id] != invalid_ID; } }; diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index f7f6ab72e0..2e9f1ccaf6 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -30,7 +30,8 @@ static const SaveLoad _newgrf_mapping_desc[] = { void Save_NewGRFMapping(const OverrideManagerBase &mapping) { for (uint i = 0; i < mapping.GetMaxMapping(); i++) { - if (!mapping.IsValidID(i)) continue; + if (mapping.mapping_ID[i].grfid == 0 && + mapping.mapping_ID[i].entity_id == 0) continue; SlSetArrayIndex(i); SlObject(&mapping.mapping_ID[i], _newgrf_mapping_desc); } From 56050fc96f59cef171d3b8a03ae3f3c9b83f9426 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 12 May 2021 16:31:31 +0200 Subject: [PATCH 151/800] Fix 91b8ce07: dedicated servers could no longer create screenshots (#9232) Although most commands are not useful on a dedicated server, screenshot commands should be dequeued. --- src/video/dedicated_v.cpp | 1 + src/video/video_driver.hpp | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index e905a9d2c9..a412782344 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -270,6 +270,7 @@ void VideoDriver_Dedicated::MainLoop() while (!_exit_game) { if (!_dedicated_forks) DedicatedHandleKeyInput(); + this->DrainCommandQueue(); ChangeGameSpeed(_ddc_fastforward); this->Tick(); diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index db522a761d..b87dc70529 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -319,23 +319,6 @@ protected: return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate); } - std::chrono::steady_clock::time_point next_game_tick; - std::chrono::steady_clock::time_point next_draw_tick; - - bool fast_forward_key_pressed; ///< The fast-forward key is being pressed. - bool fast_forward_via_key; ///< The fast-forward was enabled by key press. - - bool is_game_threaded; - std::thread game_thread; - std::mutex game_state_mutex; - std::mutex game_thread_wait_mutex; - - static void GameThreadThunk(VideoDriver *drv); - -private: - std::mutex cmd_queue_mutex; - std::vector> cmd_queue; - /** Execute all queued commands. */ void DrainCommandQueue() { @@ -354,6 +337,23 @@ private: } } + std::chrono::steady_clock::time_point next_game_tick; + std::chrono::steady_clock::time_point next_draw_tick; + + bool fast_forward_key_pressed; ///< The fast-forward key is being pressed. + bool fast_forward_via_key; ///< The fast-forward was enabled by key press. + + bool is_game_threaded; + std::thread game_thread; + std::mutex game_state_mutex; + std::mutex game_thread_wait_mutex; + + static void GameThreadThunk(VideoDriver *drv); + +private: + std::mutex cmd_queue_mutex; + std::vector> cmd_queue; + void GameLoop(); void GameThread(); }; From b136e65cf9375700e77579b344f8dd86a5a61336 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 12 May 2021 16:34:02 +0200 Subject: [PATCH 152/800] Change: reworked the debug levels for network facility (#9251) It now follows very simple rules: 0 - Fatal, user should know about this 1 - Error, but we are recovering 2 - Warning, wrong but okay if you don't know 3 - Info, information you might care about 4 - 5 - Debug #1 - High level debug messages 6 - Debug #2 - Low level debug messages 7 - Trace information --- src/genworld.cpp | 6 ++--- src/genworld_gui.cpp | 2 +- src/network/core/address.cpp | 2 +- src/network/core/core.cpp | 4 +-- src/network/core/game_info.cpp | 4 +-- src/network/core/host.cpp | 6 ++--- src/network/core/tcp.cpp | 6 ++--- src/network/core/tcp_admin.cpp | 6 ++--- src/network/core/tcp_connect.cpp | 14 +++++----- src/network/core/tcp_content.cpp | 6 ++--- src/network/core/tcp_game.cpp | 6 ++--- src/network/core/tcp_http.cpp | 28 +++++++++---------- src/network/core/tcp_listen.h | 12 ++++----- src/network/core/udp.cpp | 14 +++++----- src/network/network.cpp | 34 +++++++++++------------ src/network/network_admin.cpp | 20 +++++++------- src/network/network_client.cpp | 16 +++++------ src/network/network_command.cpp | 2 +- src/network/network_gamelist.cpp | 1 - src/network/network_server.cpp | 18 ++++++------- src/network/network_udp.cpp | 46 ++++++++++++++++---------------- src/openttd.cpp | 6 ++--- src/saveload/afterload.cpp | 4 +-- src/video/dedicated_v.cpp | 2 +- 24 files changed, 132 insertions(+), 133 deletions(-) diff --git a/src/genworld.cpp b/src/genworld.cpp index 28b28ac056..dc722ac000 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -91,7 +91,7 @@ static void _GenerateWorld() try { _generating_world = true; - if (_network_dedicated) DEBUG(net, 1, "Generating map, please wait..."); + if (_network_dedicated) DEBUG(net, 3, "Generating map, please wait..."); /* Set the Random() seed to generation_seed so we produce the same map with the same seed */ if (_settings_game.game_creation.generation_seed == GENERATE_NEW_SEED) _settings_game.game_creation.generation_seed = _settings_newgame.game_creation.generation_seed = InteractiveRandom(); _random.SetSeed(_settings_game.game_creation.generation_seed); @@ -188,7 +188,7 @@ static void _GenerateWorld() ShowNewGRFError(); - if (_network_dedicated) DEBUG(net, 1, "Map generated, starting game"); + if (_network_dedicated) DEBUG(net, 3, "Map generated, starting game"); DEBUG(desync, 1, "new_map: %08x", _settings_game.game_creation.generation_seed); if (_debug_desync_level > 0) { @@ -204,7 +204,7 @@ static void _GenerateWorld() if (_network_dedicated) { /* Exit the game to prevent a return to main menu. */ - DEBUG(net, 0, "Generating map failed, aborting"); + DEBUG(net, 0, "Generating map failed; closing server"); _exit_game = true; } else { SwitchToMode(_switch_mode); diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 46f2eac246..69ae9576ae 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -1458,7 +1458,7 @@ static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uin /* Never show steps smaller than 2%, even if it is a mod 5% */ if (_gws.percent <= last_percent + 2) return; - DEBUG(net, 1, "Map generation percentage complete: %d", _gws.percent); + DEBUG(net, 3, "Map generation percentage complete: %d", _gws.percent); last_percent = _gws.percent; return; diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index aa27b41032..91a481795c 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -356,7 +356,7 @@ static SOCKET ListenLoopProc(addrinfo *runp) DEBUG(net, 0, "Setting non-blocking mode failed: %s", NetworkError::GetLast().AsString()); } - DEBUG(net, 1, "Listening on %s", address.c_str()); + DEBUG(net, 3, "Listening on %s", address.c_str()); return sock; } diff --git a/src/network/core/core.cpp b/src/network/core/core.cpp index 563deae963..af35720dbc 100644 --- a/src/network/core/core.cpp +++ b/src/network/core/core.cpp @@ -27,9 +27,9 @@ bool NetworkCoreInitialize() #ifdef _WIN32 { WSADATA wsa; - DEBUG(net, 3, "[core] loading windows socket library"); + DEBUG(net, 5, "Loading windows socket library"); if (WSAStartup(MAKEWORD(2, 0), &wsa) != 0) { - DEBUG(net, 0, "[core] WSAStartup failed, network unavailable"); + DEBUG(net, 0, "WSAStartup failed, network unavailable"); return false; } } diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index f7044a3fce..46bb42ec1b 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -51,7 +51,7 @@ const char *GetNetworkRevisionString() /* Tag names are not mangled further. */ if (_openttd_revision_tagged) { - DEBUG(net, 1, "Network revision name is '%s'", network_revision); + DEBUG(net, 3, "Network revision name: %s", network_revision); return network_revision; } @@ -71,7 +71,7 @@ const char *GetNetworkRevisionString() /* Replace the git hash in revision string. */ strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH); assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than - DEBUG(net, 1, "Network revision name is '%s'", network_revision); + DEBUG(net, 3, "Network revision name: %s", network_revision); } return network_revision; diff --git a/src/network/core/host.cpp b/src/network/core/host.cpp index bcb048e474..54a97aff01 100644 --- a/src/network/core/host.cpp +++ b/src/network/core/host.cpp @@ -39,14 +39,14 @@ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // BE int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { - DEBUG(net, 0, "[core] error creating socket"); + DEBUG(net, 0, "Could not create socket: %s", NetworkError::GetLast().AsString()); return; } char *output_pointer = nullptr; int output_length = _netstat(sock, &output_pointer, 1); if (output_length < 0) { - DEBUG(net, 0, "[core] error running _netstat"); + DEBUG(net, 0, "Error running _netstat()"); return; } @@ -200,6 +200,6 @@ void NetworkFindBroadcastIPs(NetworkAddressList *broadcast) int i = 0; for (NetworkAddress &addr : *broadcast) { addr.SetPort(NETWORK_DEFAULT_PORT); - DEBUG(net, 3, "%d) %s", i++, addr.GetHostname()); + DEBUG(net, 3, " %d) %s", i++, addr.GetHostname()); } } diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index 842e1a89b9..3bba291c73 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -90,7 +90,7 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down) if (!err.WouldBlock()) { /* Something went wrong.. close client! */ if (!closing_down) { - DEBUG(net, 0, "send failed with error %s", err.AsString()); + DEBUG(net, 0, "Send failed: %s", err.AsString()); this->CloseConnection(); } return SPS_CLOSED; @@ -139,7 +139,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() NetworkError err = NetworkError::GetLast(); if (!err.WouldBlock()) { /* Something went wrong... */ - if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); + if (!err.IsConnectionReset()) DEBUG(net, 0, "Recv failed: %s", err.AsString()); this->CloseConnection(); return nullptr; } @@ -167,7 +167,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() NetworkError err = NetworkError::GetLast(); if (!err.WouldBlock()) { /* Something went wrong... */ - if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); + if (!err.IsConnectionReset()) DEBUG(net, 0, "Recv failed: %s", err.AsString()); this->CloseConnection(); return nullptr; } diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index 36daae4a14..8cc8b1efe6 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -93,9 +93,9 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p) default: if (this->HasClientQuit()) { - DEBUG(net, 0, "[tcp/admin] received invalid packet type %d from '%s' (%s)", type, this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received invalid packet type %d from '%s' (%s)", type, this->admin_name, this->admin_version); } else { - DEBUG(net, 0, "[tcp/admin] received illegal packet from '%s' (%s)", this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received illegal packet from '%s' (%s)", this->admin_name, this->admin_version); } this->CloseConnection(); @@ -129,7 +129,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::ReceivePackets() */ NetworkRecvStatus NetworkAdminSocketHandler::ReceiveInvalidPacket(PacketAdminType type) { - DEBUG(net, 0, "[tcp/admin] received illegal packet type %d from admin %s (%s)", type, this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received illegal packet type %d from admin %s (%s)", type, this->admin_name, this->admin_version); return NETWORK_RECV_STATUS_MALFORMED_PACKET; } diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index b343ae463a..381f7e5892 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -72,7 +72,7 @@ void TCPConnecter::Connect(addrinfo *address) } NetworkAddress network_address = NetworkAddress(address->ai_addr, (int)address->ai_addrlen); - DEBUG(net, 4, "Attempting to connect to %s", network_address.GetAddressAsString().c_str()); + DEBUG(net, 5, "Attempting to connect to %s", network_address.GetAddressAsString().c_str()); int err = connect(sock, address->ai_addr, (int)address->ai_addrlen); if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) { @@ -149,10 +149,10 @@ void TCPConnecter::OnResolved(addrinfo *ai) } } - if (_debug_net_level >= 5) { - DEBUG(net, 5, "%s resolved in:", this->connection_string.c_str()); + if (_debug_net_level >= 6) { + DEBUG(net, 6, "%s resolved in:", this->connection_string.c_str()); for (const auto &address : this->addresses) { - DEBUG(net, 5, "- %s", NetworkAddress(address->ai_addr, (int)address->ai_addrlen).GetAddressAsString().c_str()); + DEBUG(net, 6, "- %s", NetworkAddress(address->ai_addr, (int)address->ai_addrlen).GetAddressAsString().c_str()); } } @@ -188,7 +188,7 @@ void TCPConnecter::Resolve() } if (e != 0) { - DEBUG(misc, 0, "Failed to resolve DNS for %s", this->connection_string.c_str()); + DEBUG(net, 0, "Failed to resolve DNS for %s", this->connection_string.c_str()); this->OnFailure(); return; } @@ -235,7 +235,7 @@ bool TCPConnecter::CheckActivity() /* select() failed; hopefully next try it doesn't. */ if (n < 0) { /* select() normally never fails; so hopefully it works next try! */ - DEBUG(net, 1, "select() failed with %s", NetworkError::GetLast().AsString()); + DEBUG(net, 1, "select() failed: %s", NetworkError::GetLast().AsString()); return false; } @@ -301,7 +301,7 @@ bool TCPConnecter::CheckActivity() } assert(connected_socket != INVALID_SOCKET); - DEBUG(net, 1, "Connected to %s", this->connection_string.c_str()); + DEBUG(net, 3, "Connected to %s", this->connection_string.c_str()); if (_debug_net_level >= 5) { DEBUG(net, 5, "- using %s", NetworkAddress::GetPeerName(connected_socket).c_str()); } diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index 488be50003..0371b76215 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -167,9 +167,9 @@ bool NetworkContentSocketHandler::HandlePacket(Packet *p) default: if (this->HasClientQuit()) { - DEBUG(net, 0, "[tcp/content] received invalid packet type %d", type); + DEBUG(net, 0, "[tcp/content] Received invalid packet type %d", type); } else { - DEBUG(net, 0, "[tcp/content] received illegal packet"); + DEBUG(net, 0, "[tcp/content] Received illegal packet"); } return false; } @@ -220,7 +220,7 @@ bool NetworkContentSocketHandler::ReceivePackets() */ bool NetworkContentSocketHandler::ReceiveInvalidPacket(PacketContentType type) { - DEBUG(net, 0, "[tcp/content] received illegal packet type %d", type); + DEBUG(net, 0, "[tcp/content] Received illegal packet type %d", type); return false; } diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 771ea37b15..0e38133fbf 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -117,9 +117,9 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p) this->CloseConnection(); if (this->HasClientQuit()) { - DEBUG(net, 0, "[tcp/game] received invalid packet type %d from client %d", type, this->client_id); + DEBUG(net, 0, "[tcp/game] Received invalid packet type %d from client %d", type, this->client_id); } else { - DEBUG(net, 0, "[tcp/game] received illegal packet from client %d", this->client_id); + DEBUG(net, 0, "[tcp/game] Received illegal packet from client %d", this->client_id); } return NETWORK_RECV_STATUS_MALFORMED_PACKET; } @@ -151,7 +151,7 @@ NetworkRecvStatus NetworkGameSocketHandler::ReceivePackets() */ NetworkRecvStatus NetworkGameSocketHandler::ReceiveInvalidPacket(PacketGameType type) { - DEBUG(net, 0, "[tcp/game] received illegal packet type %d from client %d", type, this->client_id); + DEBUG(net, 0, "[tcp/game] Received illegal packet type %d from client %d", type, this->client_id); return NETWORK_RECV_STATUS_MALFORMED_PACKET; } diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index ccad120aec..08961e4029 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -45,7 +45,7 @@ NetworkHTTPSocketHandler::NetworkHTTPSocketHandler(SOCKET s, size_t bufferSize = strlen(url) + strlen(host) + strlen(GetNetworkRevisionString()) + (data == nullptr ? 0 : strlen(data)) + 128; char *buffer = AllocaM(char, bufferSize); - DEBUG(net, 7, "[tcp/http] requesting %s%s", host, url); + DEBUG(net, 5, "[tcp/http] Requesting %s%s", host, url); if (data != nullptr) { seprintf(buffer, buffer + bufferSize - 1, "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: OpenTTD/%s\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s\r\n", url, host, GetNetworkRevisionString(), (int)strlen(data), data); } else { @@ -85,7 +85,7 @@ NetworkRecvStatus NetworkHTTPSocketHandler::CloseConnection(bool error) * Helper to simplify the error handling. * @param msg the error message to show. */ -#define return_error(msg) { DEBUG(net, 0, msg); return -1; } +#define return_error(msg) { DEBUG(net, 1, msg); return -1; } static const char * const NEWLINE = "\r\n"; ///< End of line marker static const char * const END_OF_HEADER = "\r\n\r\n"; ///< End of header marker @@ -112,7 +112,7 @@ int NetworkHTTPSocketHandler::HandleHeader() /* We expect a HTTP/1.[01] reply */ if (strncmp(this->recv_buffer, HTTP_1_0, strlen(HTTP_1_0)) != 0 && strncmp(this->recv_buffer, HTTP_1_1, strlen(HTTP_1_1)) != 0) { - return_error("[tcp/http] received invalid HTTP reply"); + return_error("[tcp/http] Received invalid HTTP reply"); } char *status = this->recv_buffer + strlen(HTTP_1_0); @@ -121,7 +121,7 @@ int NetworkHTTPSocketHandler::HandleHeader() /* Get the length of the document to receive */ char *length = strcasestr(this->recv_buffer, CONTENT_LENGTH); - if (length == nullptr) return_error("[tcp/http] missing 'content-length' header"); + if (length == nullptr) return_error("[tcp/http] Missing 'content-length' header"); /* Skip the header */ length += strlen(CONTENT_LENGTH); @@ -139,9 +139,9 @@ int NetworkHTTPSocketHandler::HandleHeader() /* Make sure we're going to download at least something; * zero sized files are, for OpenTTD's purposes, always * wrong. You can't have gzips of 0 bytes! */ - if (len == 0) return_error("[tcp/http] refusing to download 0 bytes"); + if (len == 0) return_error("[tcp/http] Refusing to download 0 bytes"); - DEBUG(net, 7, "[tcp/http] downloading %i bytes", len); + DEBUG(net, 7, "[tcp/http] Downloading %i bytes", len); return len; } @@ -154,15 +154,15 @@ int NetworkHTTPSocketHandler::HandleHeader() /* Search the end of the line. This is safe because the header will * always end with two newlines. */ *strstr(status, NEWLINE) = '\0'; - DEBUG(net, 0, "[tcp/http] unhandled status reply %s", status); + DEBUG(net, 1, "[tcp/http] Unhandled status reply %s", status); return -1; } - if (this->redirect_depth == 5) return_error("[tcp/http] too many redirects, looping redirects?"); + if (this->redirect_depth == 5) return_error("[tcp/http] Too many redirects, looping redirects?"); /* Redirect to other URL */ char *uri = strcasestr(this->recv_buffer, LOCATION); - if (uri == nullptr) return_error("[tcp/http] missing 'location' header for redirect"); + if (uri == nullptr) return_error("[tcp/http] Missing 'location' header for redirect"); uri += strlen(LOCATION); @@ -171,7 +171,7 @@ int NetworkHTTPSocketHandler::HandleHeader() char *end_of_line = strstr(uri, NEWLINE); *end_of_line = '\0'; - DEBUG(net, 6, "[tcp/http] redirecting to %s", uri); + DEBUG(net, 7, "[tcp/http] Redirecting to %s", uri); int ret = NetworkHTTPSocketHandler::Connect(uri, this->callback, this->data, this->redirect_depth + 1); if (ret != 0) return ret; @@ -194,12 +194,12 @@ int NetworkHTTPSocketHandler::HandleHeader() /* static */ int NetworkHTTPSocketHandler::Connect(char *uri, HTTPCallback *callback, const char *data, int depth) { char *hname = strstr(uri, "://"); - if (hname == nullptr) return_error("[tcp/http] invalid location"); + if (hname == nullptr) return_error("[tcp/http] Invalid location"); hname += 3; char *url = strchr(hname, '/'); - if (url == nullptr) return_error("[tcp/http] invalid location"); + if (url == nullptr) return_error("[tcp/http] Invalid location"); *url = '\0'; @@ -228,7 +228,7 @@ int NetworkHTTPSocketHandler::Receive() NetworkError err = NetworkError::GetLast(); if (!err.WouldBlock()) { /* Something went wrong... */ - if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString()); + if (!err.IsConnectionReset()) DEBUG(net, 0, "Recv failed: %s", err.AsString()); return -1; } /* Connection would block, so stop for now */ @@ -256,7 +256,7 @@ int NetworkHTTPSocketHandler::Receive() if (end_of_header == nullptr) { if (read == lengthof(this->recv_buffer)) { - DEBUG(net, 0, "[tcp/http] header too big"); + DEBUG(net, 1, "[tcp/http] Header too big"); return -1; } this->recv_pos = read; diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h index e23ecae707..40fc84efee 100644 --- a/src/network/core/tcp_listen.h +++ b/src/network/core/tcp_listen.h @@ -49,7 +49,7 @@ public: SetNonBlocking(s); // XXX error handling? NetworkAddress address(sin, sin_len); - DEBUG(net, 1, "[%s] Client connected from %s on frame %d", Tsocket::GetName(), address.GetHostname(), _frame_counter); + DEBUG(net, 3, "[%s] Client connected from %s on frame %d", Tsocket::GetName(), address.GetHostname(), _frame_counter); SetNoDelay(s); // XXX error handling? @@ -61,10 +61,10 @@ public: Packet p(Tban_packet); p.PrepareToSend(); - DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str()); + DEBUG(net, 2, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str()); if (p.TransferOut(send, s, 0) < 0) { - DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString()); + DEBUG(net, 0, "[%s] send failed: %s", Tsocket::GetName(), NetworkError::GetLast().AsString()); } closesocket(s); break; @@ -81,7 +81,7 @@ public: p.PrepareToSend(); if (p.TransferOut(send, s, 0) < 0) { - DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString()); + DEBUG(net, 0, "[%s] send failed: %s", Tsocket::GetName(), NetworkError::GetLast().AsString()); } closesocket(s); @@ -150,7 +150,7 @@ public: } if (sockets.size() == 0) { - DEBUG(net, 0, "[server] could not start network: could not create listening socket"); + DEBUG(net, 0, "Could not start network: could not create listening socket"); ShowNetworkError(STR_NETWORK_ERROR_SERVER_START); return false; } @@ -165,7 +165,7 @@ public: closesocket(s.second); } sockets.clear(); - DEBUG(net, 1, "[%s] closed listeners", Tsocket::GetName()); + DEBUG(net, 5, "[%s] Closed listeners", Tsocket::GetName()); } }; diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index c4d448f268..c8d7533640 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -95,16 +95,16 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a /* Enable broadcast */ unsigned long val = 1; if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) { - DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkError::GetLast().AsString()); + DEBUG(net, 1, "Setting broadcast mode failed: %s", NetworkError::GetLast().AsString()); } } /* Send the buffer */ ssize_t res = p->TransferOut(sendto, s.second, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength()); - DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str()); + DEBUG(net, 7, "sendto(%s)", send.GetAddressAsString().c_str()); /* Check for any errors, but ignore it otherwise */ - if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", send.GetAddressAsString().c_str(), NetworkError::GetLast().AsString()); + if (res == -1) DEBUG(net, 1, "sendto(%s) failed: %s", send.GetAddressAsString().c_str(), NetworkError::GetLast().AsString()); if (!all) break; } @@ -140,7 +140,7 @@ void NetworkUDPSocketHandler::ReceivePackets() /* If the size does not match the packet must be corrupted. * Otherwise it will be marked as corrupted later on. */ if (!p.ParsePacketSize() || (size_t)nbytes != p.Size()) { - DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString().c_str()); + DEBUG(net, 1, "Received a packet with mismatching size from %s", address.GetAddressAsString().c_str()); continue; } p.PrepareToRead(); @@ -181,9 +181,9 @@ void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, NetworkAddress *client_ default: if (this->HasClientQuit()) { - DEBUG(net, 0, "[udp] received invalid packet type %d from %s", type, client_addr->GetAddressAsString().c_str()); + DEBUG(net, 0, "[udp] Received invalid packet type %d from %s", type, client_addr->GetAddressAsString().c_str()); } else { - DEBUG(net, 0, "[udp] received illegal packet from %s", client_addr->GetAddressAsString().c_str()); + DEBUG(net, 0, "[udp] Received illegal packet from %s", client_addr->GetAddressAsString().c_str()); } break; } @@ -196,7 +196,7 @@ void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, NetworkAddress *client_ */ void NetworkUDPSocketHandler::ReceiveInvalidPacket(PacketUDPType type, NetworkAddress *client_addr) { - DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", type, client_addr->GetAddressAsString().c_str()); + DEBUG(net, 0, "[udp] Received packet type %d on wrong port from %s", type, client_addr->GetAddressAsString().c_str()); } void NetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_FIND_SERVER, client_addr); } diff --git a/src/network/network.cpp b/src/network/network.cpp index 3b43ddbcd8..a87aab88c7 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -859,13 +859,13 @@ static void CheckClientAndServerName() { static const char *fallback_client_name = "Unnamed Client"; if (StrEmpty(_settings_client.network.client_name) || strcmp(_settings_client.network.client_name, fallback_client_name) == 0) { - DEBUG(net, 0, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command.", fallback_client_name); + DEBUG(net, 1, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command", fallback_client_name); strecpy(_settings_client.network.client_name, fallback_client_name, lastof(_settings_client.network.client_name)); } static const char *fallback_server_name = "Unnamed Server"; if (StrEmpty(_settings_client.network.server_name) || strcmp(_settings_client.network.server_name, fallback_server_name) == 0) { - DEBUG(net, 0, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command.", fallback_server_name); + DEBUG(net, 1, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command", fallback_server_name); strecpy(_settings_client.network.server_name, fallback_server_name, lastof(_settings_client.network.server_name)); } } @@ -883,17 +883,17 @@ bool NetworkServerStart() NetworkDisconnect(false, false); NetworkInitialize(false); - DEBUG(net, 1, "starting listeners for clients"); + DEBUG(net, 5, "Starting listeners for clients"); if (!ServerNetworkGameSocketHandler::Listen(_settings_client.network.server_port)) return false; /* Only listen for admins when the password isn't empty. */ if (!StrEmpty(_settings_client.network.admin_password)) { - DEBUG(net, 1, "starting listeners for admins"); + DEBUG(net, 5, "Starting listeners for admins"); if (!ServerNetworkAdminSocketHandler::Listen(_settings_client.network.server_admin_port)) return false; } /* Try to start UDP-server */ - DEBUG(net, 1, "starting listeners for incoming server queries"); + DEBUG(net, 5, "Starting listeners for incoming server queries"); NetworkUDPServerListen(); _network_company_states = CallocT(MAX_COMPANIES); @@ -1044,7 +1044,7 @@ void NetworkGameLoop() static bool check_sync_state = false; static uint32 sync_state[2]; if (f == nullptr && next_date == 0) { - DEBUG(net, 0, "Cannot open commands.log"); + DEBUG(desync, 0, "Cannot open commands.log"); next_date = 1; } @@ -1052,15 +1052,15 @@ void NetworkGameLoop() if (_date == next_date && _date_fract == next_date_fract) { if (cp != nullptr) { NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text, cp->company); - DEBUG(net, 0, "injecting: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text, GetCommandName(cp->cmd)); + DEBUG(desync, 0, "Injecting: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text, GetCommandName(cp->cmd)); free(cp); cp = nullptr; } if (check_sync_state) { if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) { - DEBUG(net, 0, "sync check: %08x; %02x; match", _date, _date_fract); + DEBUG(desync, 0, "Sync check: %08x; %02x; match", _date, _date_fract); } else { - DEBUG(net, 0, "sync check: %08x; %02x; mismatch expected {%08x, %08x}, got {%08x, %08x}", + DEBUG(desync, 0, "Sync check: %08x; %02x; mismatch expected {%08x, %08x}, got {%08x, %08x}", _date, _date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]); NOT_REACHED(); } @@ -1101,7 +1101,7 @@ void NetworkGameLoop() /* Manually insert a pause when joining; this way the client can join at the exact right time. */ int ret = sscanf(p + 6, "%x; %x", &next_date, &next_date_fract); assert(ret == 2); - DEBUG(net, 0, "injecting pause for join at %08x:%02x; please join when paused", next_date, next_date_fract); + DEBUG(desync, 0, "Injecting pause for join at %08x:%02x; please join when paused", next_date, next_date_fract); cp = CallocT(1); cp->company = COMPANY_SPECTATOR; cp->cmd = CMD_PAUSE; @@ -1117,16 +1117,16 @@ void NetworkGameLoop() /* A message that is not very important to the log playback, but part of the log. */ #ifndef DEBUG_FAILED_DUMP_COMMANDS } else if (strncmp(p, "cmdf: ", 6) == 0) { - DEBUG(net, 0, "Skipping replay of failed command: %s", p + 6); + DEBUG(desync, 0, "Skipping replay of failed command: %s", p + 6); #endif } else { /* Can't parse a line; what's wrong here? */ - DEBUG(net, 0, "trying to parse: %s", p); + DEBUG(desync, 0, "Trying to parse: %s", p); NOT_REACHED(); } } if (f != nullptr && feof(f)) { - DEBUG(net, 0, "End of commands.log"); + DEBUG(desync, 0, "End of commands.log"); fclose(f); f = nullptr; } @@ -1218,7 +1218,7 @@ public: void OnConnect(SOCKET s) override { - DEBUG(net, 0, "Redirecting DEBUG() to %s", this->connection_string.c_str()); + DEBUG(net, 3, "Redirecting DEBUG() to %s", this->connection_string.c_str()); extern SOCKET _debug_socket; _debug_socket = s; @@ -1233,7 +1233,7 @@ void NetworkStartDebugLog(const std::string &connection_string) /** This tries to launch the network for a given OS */ void NetworkStartUp() { - DEBUG(net, 3, "[core] starting network..."); + DEBUG(net, 3, "Starting network"); /* Network is available */ _network_available = NetworkCoreInitialize(); @@ -1246,7 +1246,7 @@ void NetworkStartUp() _network_game_info = {}; NetworkInitialize(); - DEBUG(net, 3, "[core] network online, multiplayer available"); + DEBUG(net, 3, "Network online, multiplayer available"); NetworkFindBroadcastIPs(&_broadcast_list); } @@ -1256,7 +1256,7 @@ void NetworkShutDown() NetworkDisconnect(true); NetworkUDPClose(); - DEBUG(net, 3, "[core] shutting down network"); + DEBUG(net, 3, "Shutting down network"); _network_available = false; diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 7b49754515..4e73aed0f8 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -74,7 +74,7 @@ ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : Net ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler() { _network_admins_connected--; - DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version); + DEBUG(net, 3, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version); if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID; } @@ -97,7 +97,7 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler() { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) { if (as->status == ADMIN_STATUS_INACTIVE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) { - DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", (uint32)std::chrono::duration_cast(ADMIN_AUTHORISATION_TIMEOUT).count()); + DEBUG(net, 2, "[admin] Admin did not send its authorisation within %d seconds", (uint32)std::chrono::duration_cast(ADMIN_AUTHORISATION_TIMEOUT).count()); as->CloseConnection(true); continue; } @@ -137,7 +137,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode er StringID strid = GetNetworkErrorMsg(error); GetString(str, strid, lastof(str)); - DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str); + DEBUG(net, 1, "[admin] The admin '%s' (%s) made an error and has been disconnected: '%s'", this->admin_name, this->admin_version, str); return this->CloseConnection(true); } @@ -518,7 +518,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) p->Recv_string(command, sizeof(command)); - DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command); + DEBUG(net, 3, "[admin] Rcon command from '%s' (%s): %s", this->admin_name, this->admin_version, command); _redirect_console_to_admin = this->index; IConsoleCmdExec(command); @@ -534,7 +534,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Pack p->Recv_string(json, sizeof(json)); - DEBUG(net, 2, "[admin] GameScript JSON from '%s' (%s): '%s'", this->admin_name, this->admin_version, json); + DEBUG(net, 6, "[admin] GameScript JSON from '%s' (%s): %s", this->admin_name, this->admin_version, json); Game::NewEvent(new ScriptEventAdminPort(json)); return NETWORK_RECV_STATUS_OKAY; @@ -546,7 +546,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) uint32 d1 = p->Recv_uint32(); - DEBUG(net, 2, "[admin] Ping from '%s' (%s): '%d'", this->admin_name, this->admin_version, d1); + DEBUG(net, 6, "[admin] Ping from '%s' (%s): %d", this->admin_name, this->admin_version, d1); return this->SendPong(d1); } @@ -683,7 +683,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p) this->status = ADMIN_STATUS_ACTIVE; - DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version); + DEBUG(net, 3, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version); return this->SendProtocol(); } @@ -703,7 +703,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENC if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) { /* The server does not know of this UpdateType. */ - DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Not supported update frequency %d (%d) from '%s' (%s)", type, freq, this->admin_name, this->admin_version); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } @@ -771,7 +771,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p) default: /* An unsupported "poll" update type. */ - DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } @@ -798,7 +798,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) break; default: - DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 501449705e..34746e935c 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -136,7 +136,7 @@ void ClientNetworkEmergencySave() if (!_networking) return; const char *filename = "netsave.sav"; - DEBUG(net, 0, "Client: Performing emergency save (%s)", filename); + DEBUG(net, 3, "Performing emergency save: %s", filename); SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false); } @@ -172,7 +172,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvSta */ if (this->sock == INVALID_SOCKET) return status; - DEBUG(net, 1, "Closed client connection %d", this->client_id); + DEBUG(net, 3, "Closed client connection %d", this->client_id); this->SendPackets(true); @@ -286,7 +286,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) #endif ShowNetworkError(STR_NETWORK_ERROR_DESYNC); DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract); - DEBUG(net, 0, "Sync error detected!"); + DEBUG(net, 0, "Sync error detected"); my_client->ClientError(NETWORK_RECV_STATUS_DESYNC); return false; } @@ -301,7 +301,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) _sync_frame = 0; } else if (_sync_frame < _frame_counter) { - DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter); + DEBUG(net, 1, "Missed frame for sync-test: %d / %d", _sync_frame, _frame_counter); _sync_frame = 0; } } @@ -978,13 +978,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FRAME(Packet *p /* Receive the token. */ if (p->CanReadFromPacket(sizeof(uint8))) this->token = p->Recv_uint8(); - DEBUG(net, 5, "Received FRAME %d", _frame_counter_server); + DEBUG(net, 7, "Received FRAME %d", _frame_counter_server); /* Let the server know that we received this frame correctly * We do this only once per day, to save some bandwidth ;) */ if (!_network_first_time && last_ack_frame < _frame_counter) { last_ack_frame = _frame_counter + DAY_TICKS; - DEBUG(net, 4, "Sent ACK at %d", _frame_counter); + DEBUG(net, 7, "Sent ACK at %d", _frame_counter); SendAck(); } @@ -1100,7 +1100,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_QUIT(Packet *p) NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING); delete ci; } else { - DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id); + DEBUG(net, 1, "Unknown client (%d) is leaving the game", client_id); } InvalidateWindowData(WC_CLIENT_LIST, 0); @@ -1180,7 +1180,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MOVE(Packet *p) if (client_id == 0) { /* definitely an invalid client id, debug message and do nothing. */ - DEBUG(net, 0, "[move] received invalid client index = 0"); + DEBUG(net, 1, "Received invalid client index = 0"); return NETWORK_RECV_STATUS_MALFORMED_PACKET; } diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index e876670587..c9b21204a1 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -333,7 +333,7 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp) } if (callback == lengthof(_callback_table)) { - DEBUG(net, 0, "Unknown callback. (Pointer: %p) No callback sent", cp->callback); + DEBUG(net, 0, "Unknown callback for command; no callback sent (command: %d)", cp->cmd); callback = 0; // _callback_table[0] == nullptr } p->Send_uint8 (callback); diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp index 20fbb19a7c..ae716070c6 100644 --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -112,7 +112,6 @@ void NetworkGameListRemoveItem(NetworkGameList *remove) ClearGRFConfigList(&remove->info.grfconfig); delete remove; - DEBUG(net, 4, "[gamelist] removed server from list"); NetworkRebuildHostList(); UpdateNetworkGameWindow(); return; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index eccf80f781..bbadbeba4d 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -283,7 +283,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta } NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST); - DEBUG(net, 1, "Closed client connection %d", this->client_id); + DEBUG(net, 3, "Closed client connection %d", this->client_id); /* We just lost one client :( */ if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--; @@ -448,7 +448,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err this->GetClientName(client_name, lastof(client_name)); - DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str); + DEBUG(net, 1, "'%s' made an error and has been disconnected: %s", client_name, str); if (error == NETWORK_ERROR_KICKED && reason != nullptr) { NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid); @@ -469,7 +469,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err NetworkAdminClientError(this->client_id, error); } else { - DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str); + DEBUG(net, 1, "Client %d made an error and has been disconnected: %s", this->client_id, str); } /* The client made a mistake, so drop his connection now! */ @@ -1144,7 +1144,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p StringID strid = GetNetworkErrorMsg(errorno); GetString(str, strid, lastof(str)); - DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str); + DEBUG(net, 1, "'%s' reported an error and is closing its connection: %s", client_name, str); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid); @@ -1335,7 +1335,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co break; } default: - DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype); + DEBUG(net, 1, "Received unknown chat destination type %d; doing broadcast instead", desttype); FALLTHROUGH; case DESTTYPE_BROADCAST: @@ -1445,11 +1445,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p) p->Recv_string(command, sizeof(command)); if (strcmp(pass, _settings_client.network.rcon_password) != 0) { - DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id); + DEBUG(net, 1, "[rcon] Wrong password from client-id %d", this->client_id); return NETWORK_RECV_STATUS_OKAY; } - DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command); + DEBUG(net, 3, "[rcon] Client-id %d executed: %s", this->client_id, command); _redirect_console_to_client = this->client_id; IConsoleCmdExec(command); @@ -1474,7 +1474,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p) /* Incorrect password sent, return! */ if (strcmp(password, _network_company_states[company_id].password) != 0) { - DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1); + DEBUG(net, 2, "Wrong password from client-id #%d for company #%d", this->client_id, company_id + 1); return NETWORK_RECV_STATUS_OKAY; } } @@ -1597,7 +1597,7 @@ void NetworkUpdateClientInfo(ClientID client_id) static void NetworkCheckRestartMap() { if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) { - DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year); + DEBUG(net, 3, "Auto-restarting map: year %d reached", _cur_year); _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED; switch(_file_to_saveload.abstract_ftype) { diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 8a95596c17..75bf4563d3 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -67,7 +67,7 @@ struct UDPSocket { std::unique_lock lock(mutex, std::defer_lock); if (!lock.try_lock()) { if (++receive_iterations_locked % 32 == 0) { - DEBUG(net, 0, "[udp] %s background UDP loop processing appears to be blocked. Your OS may be low on UDP send buffers.", name.c_str()); + DEBUG(net, 0, "%s background UDP loop processing appears to be blocked. Your OS may be low on UDP send buffers.", name.c_str()); } return; } @@ -133,7 +133,7 @@ public: void MasterNetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER(Packet *p, NetworkAddress *client_addr) { _network_advertise_retries = 0; - DEBUG(net, 2, "[udp] advertising on master server successful (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family)); + DEBUG(net, 3, "Advertising on master server successful (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family)); /* We are advertised, but we don't want to! */ if (!_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(false); @@ -142,7 +142,7 @@ void MasterNetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER(Packet *p, Netwo void MasterNetworkUDPSocketHandler::Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr) { _session_key = p->Recv_uint64(); - DEBUG(net, 2, "[udp] received new session key from master server (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family)); + DEBUG(net, 6, "Received new session key from master server (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family)); } ///*** Communication with clients (we are server) ***/ @@ -175,7 +175,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ /* Let the client know that we are here */ this->SendPacket(&packet, client_addr); - DEBUG(net, 2, "[udp] queried from %s", client_addr->GetHostname()); + DEBUG(net, 7, "Queried from %s", client_addr->GetHostname()); } void ServerNetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) @@ -252,7 +252,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ uint8 in_reply_count = 0; size_t packet_len = 0; - DEBUG(net, 6, "[udp] newgrf data request from %s", client_addr->GetAddressAsString().c_str()); + DEBUG(net, 7, "NewGRF data request from %s", client_addr->GetAddressAsString().c_str()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; @@ -314,7 +314,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd /* Just a fail-safe.. should never happen */ if (_network_udp_server) return; - DEBUG(net, 4, "[udp] server response from %s", client_addr->GetAddressAsString().c_str()); + DEBUG(net, 3, "Server response from %s", client_addr->GetAddressAsString().c_str()); /* Find next item */ item = NetworkGameListAddItem(client_addr->GetAddressAsString(false)); @@ -409,7 +409,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd uint8 num_grfs; uint i; - DEBUG(net, 6, "[udp] newgrf data reply from %s", client_addr->GetAddressAsString().c_str()); + DEBUG(net, 7, "NewGRF data reply from %s", client_addr->GetAddressAsString().c_str()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; @@ -441,7 +441,7 @@ static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) for (NetworkAddress &addr : _broadcast_list) { Packet p(PACKET_UDP_CLIENT_FIND_SERVER); - DEBUG(net, 4, "[udp] broadcasting to %s", addr.GetHostname()); + DEBUG(net, 5, "Broadcasting to %s", addr.GetHostname()); socket->SendPacket(&p, &addr, true, true); } @@ -461,7 +461,7 @@ void NetworkUDPQueryMasterServer() std::lock_guard lock(_udp_client.mutex); _udp_client.socket->SendPacket(&p, &out_addr, true); - DEBUG(net, 2, "[udp] master server queried at %s", out_addr.GetAddressAsString().c_str()); + DEBUG(net, 6, "Master server queried at %s", out_addr.GetAddressAsString().c_str()); } /** Find all servers */ @@ -470,7 +470,7 @@ void NetworkUDPSearchGame() /* We are still searching.. */ if (_network_udp_broadcast > 0) return; - DEBUG(net, 0, "[udp] searching server"); + DEBUG(net, 3, "Searching server"); NetworkUDPBroadCast(_udp_client.socket); _network_udp_broadcast = 300; // Stay searching for 300 ticks @@ -481,7 +481,7 @@ void NetworkUDPSearchGame() */ static void NetworkUDPRemoveAdvertiseThread() { - DEBUG(net, 1, "[udp] removing advertise from master server"); + DEBUG(net, 3, "Removing advertise from master server"); /* Find somewhere to send */ NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT); @@ -518,22 +518,22 @@ static void NetworkUDPAdvertiseThread() /* Find somewhere to send */ NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT); - DEBUG(net, 1, "[udp] advertising to master server"); + DEBUG(net, 3, "Advertising to master server"); /* Add a bit more messaging when we cannot get a session key */ static byte session_key_retries = 0; if (_session_key == 0 && session_key_retries++ == 2) { - DEBUG(net, 0, "[udp] advertising to the master server is failing"); - DEBUG(net, 0, "[udp] we are not receiving the session key from the server"); - DEBUG(net, 0, "[udp] please allow udp packets from %s to you to be delivered", out_addr.GetAddressAsString(false).c_str()); - DEBUG(net, 0, "[udp] please allow udp packets from you to %s to be delivered", out_addr.GetAddressAsString(false).c_str()); + DEBUG(net, 0, "Advertising to the master server is failing"); + DEBUG(net, 0, " we are not receiving the session key from the server"); + DEBUG(net, 0, " please allow udp packets from %s to you to be delivered", out_addr.GetAddressAsString(false).c_str()); + DEBUG(net, 0, " please allow udp packets from you to %s to be delivered", out_addr.GetAddressAsString(false).c_str()); } if (_session_key != 0 && _network_advertise_retries == 0) { - DEBUG(net, 0, "[udp] advertising to the master server is failing"); - DEBUG(net, 0, "[udp] we are not receiving the acknowledgement from the server"); - DEBUG(net, 0, "[udp] this usually means that the master server cannot reach us"); - DEBUG(net, 0, "[udp] please allow udp and tcp packets to port %u to be delivered", _settings_client.network.server_port); - DEBUG(net, 0, "[udp] please allow udp and tcp packets from port %u to be delivered", _settings_client.network.server_port); + DEBUG(net, 0, "Advertising to the master server is failing"); + DEBUG(net, 0, " we are not receiving the acknowledgement from the server"); + DEBUG(net, 0, " this usually means that the master server cannot reach us"); + DEBUG(net, 0, " please allow udp and tcp packets to port %u to be delivered", _settings_client.network.server_port); + DEBUG(net, 0, " please allow udp and tcp packets from port %u to be delivered", _settings_client.network.server_port); } /* Send the packet */ @@ -589,7 +589,7 @@ void NetworkUDPInitialize() /* If not closed, then do it. */ if (_udp_server.socket != nullptr) NetworkUDPClose(); - DEBUG(net, 1, "[udp] initializing listeners"); + DEBUG(net, 3, "Initializing UDP listeners"); assert(_udp_client.socket == nullptr && _udp_server.socket == nullptr && _udp_master.socket == nullptr); std::scoped_lock lock(_udp_client.mutex, _udp_server.mutex, _udp_master.mutex); @@ -625,7 +625,7 @@ void NetworkUDPClose() _network_udp_server = false; _network_udp_broadcast = 0; - DEBUG(net, 1, "[udp] closed listeners"); + DEBUG(net, 5, "Closed UDP listeners"); } /** Receive the UDP packets. */ diff --git a/src/openttd.cpp b/src/openttd.cpp index ea802b3db9..785ba80dda 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -560,7 +560,7 @@ int openttd_main(int argc, char *argv[]) videodriver = "dedicated"; blitter = "null"; dedicated = true; - SetDebugString("net=6"); + SetDebugString("net=4"); if (mgo.opt != nullptr) { scanner->dedicated_host = ParseFullConnectionString(mgo.opt, scanner->dedicated_port); } @@ -666,7 +666,7 @@ int openttd_main(int argc, char *argv[]) DeterminePaths(argv[0]); TarScanner::DoScan(TarScanner::BASESET); - if (dedicated) DEBUG(net, 0, "Starting dedicated version %s", _openttd_revision); + if (dedicated) DEBUG(net, 3, "Starting dedicated server, version %s", _openttd_revision); if (_dedicated_forks && !dedicated) _dedicated_forks = false; #if defined(UNIX) @@ -945,7 +945,7 @@ bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileTy * special cases which make clients desync immediately. So we fall * back to just generating a new game with the current settings. */ - DEBUG(net, 0, "Loading game failed, so a new (random) game will be started!"); + DEBUG(net, 0, "Loading game failed, so a new (random) game will be started"); MakeNewGame(false, true); return false; } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 7fd2204943..26c749bf73 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -566,8 +566,8 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_119)) { _pause_mode = (_pause_mode == 2) ? PM_PAUSED_NORMAL : PM_UNPAUSED; } else if (_network_dedicated && (_pause_mode & PM_PAUSED_ERROR) != 0) { - DEBUG(net, 0, "The loading savegame was paused due to an error state."); - DEBUG(net, 0, " The savegame cannot be used for multiplayer!"); + DEBUG(net, 0, "The loading savegame was paused due to an error state"); + DEBUG(net, 0, " This savegame cannot be used for multiplayer"); /* Restore the signals */ ResetSignalHandlers(); return false; diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index a412782344..6f631e2278 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -256,7 +256,7 @@ void VideoDriver_Dedicated::MainLoop() * intro game... */ if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, BASE_DIR) == SL_ERROR) { /* Loading failed, pop out.. */ - DEBUG(net, 0, "Loading requested map failed, aborting"); + DEBUG(net, 0, "Loading requested map failed; closing server."); return; } else { /* We can load this game, so go ahead */ From 7b7dbbc935c32263be800c0e22831e52ace813e9 Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 12 May 2021 17:43:35 +0100 Subject: [PATCH 153/800] Fix #9063: Caption of news window incorrectly aligned. (#9252) --- src/news_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/news_gui.cpp b/src/news_gui.cpp index d3ddd463fa..e3fb600336 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -422,7 +422,7 @@ struct NewsWindow : Window { { switch (widget) { case WID_N_CAPTION: - DrawCaption(r, COLOUR_LIGHT_BLUE, this->owner, TC_FROMSTRING, STR_NEWS_MESSAGE_CAPTION, SA_HOR_CENTER); + DrawCaption(r, COLOUR_LIGHT_BLUE, this->owner, TC_FROMSTRING, STR_NEWS_MESSAGE_CAPTION, SA_CENTER); break; case WID_N_PANEL: From b972ed86045e1c287d03b3f7cda1ff21243d00fe Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 12 May 2021 18:17:57 +0100 Subject: [PATCH 154/800] Fix #9242: Tree tick handler did not scale by map size. (#9246) This means that random tree generation density is higher on small maps and lower on large maps. This difference is enough to make the Lumber Mill impractical to use on large maps. This change skips ticks on maps smaller than 256x256 and increases iterations or shortens the interval on maps larger than 256x256. --- src/tree_cmd.cpp | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index c0865ffc68..f1a5be7f90 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -22,6 +22,7 @@ #include "company_base.h" #include "core/random_func.hpp" #include "newgrf_generic.h" +#include "date_func.h" #include "table/strings.h" #include "table/tree_land.h" @@ -803,6 +804,23 @@ static void TileLoop_Trees(TileIndex tile) MarkTileDirtyByTile(tile); } +/** + * Decrement the tree tick counter. + * The interval is scaled by map size to allow for the same density regardless of size. + * Adjustment for map sizes below the standard 256 * 256 are handled earlier. + * @return true if the counter was decremented past zero + */ +bool DecrementTreeCounter() +{ + /* Ensure _trees_tick_ctr can be decremented past zero only once for the largest map size. */ + static_assert(2 * (MAX_MAP_SIZE_BITS - MIN_MAP_SIZE_BITS) - 4 <= std::numeric_limits::digits); + + /* byte underflow */ + byte old_trees_tick_ctr = _trees_tick_ctr; + _trees_tick_ctr -= ScaleByMapSize(1); + return old_trees_tick_ctr <= _trees_tick_ctr; +} + void OnTick_Trees() { /* Don't spread trees if that's not allowed */ @@ -812,16 +830,24 @@ void OnTick_Trees() TileIndex tile; TreeType tree; + /* Skip some tree ticks for map sizes below 256 * 256. 64 * 64 is 16 times smaller, so + * this is the maximum number of ticks that are skipped. Number of ticks to skip is + * inversely proportional to map size, so that is handled to create a mask. */ + int skip = ScaleByMapSize(16); + if (skip < 16 && (_tick_counter & (16 / skip - 1)) != 0) return; + /* place a tree at a random rainforest spot */ - if (_settings_game.game_creation.landscape == LT_TROPIC && - (r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) && - CanPlantTreesOnTile(tile, false) && - (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { - PlantTreesOnTile(tile, tree, 0, 0); + if (_settings_game.game_creation.landscape == LT_TROPIC) { + for (uint c = ScaleByMapSize(1); c > 0; c--) { + if ((r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) && + CanPlantTreesOnTile(tile, false) && + (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { + PlantTreesOnTile(tile, tree, 0, 0); + } + } } - /* byte underflow */ - if (--_trees_tick_ctr != 0 || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST) return; + if (!DecrementTreeCounter() || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST) return; /* place a tree at a random spot */ r = Random(); From 3e7e2d9ca3f798bd1a5f72574510d7205e5f97b2 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 12 May 2021 19:08:38 +0000 Subject: [PATCH 155/800] Update: Translations from eints romanian: 38 changes by kneekoo slovak: 19 changes by FuryPapaya catalan: 1 change by J0anJosep turkish: 191 changes by Anceph --- src/lang/catalan.txt | 2 +- src/lang/romanian.txt | 46 +++++++-- src/lang/slovak.txt | 38 ++++---- src/lang/turkish.txt | 212 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 249 insertions(+), 49 deletions(-) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index bc89f55f40..9c666cd112 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2270,7 +2270,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} s' STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} s'ha unit als espectadors STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} ha començat una nova companyia (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} ha deixat la partida ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} ha canviat el seu nom a {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} ha canviat el seu nom a {STRING}. STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} ha donat {2:CURRENCY_LONG} a {1:STRING}. STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}El servidor ha tancat la sessió STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}El servidor està reiniciant...{}Espera un moment... diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 60cb7a616e..fe070471dc 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -928,7 +928,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaysi STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Pe partea stângă STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Pe partea dreaptă -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Numele oraşelor +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Numele orașelor: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Alege naţionalitatea numelor oraşelor ############ start of townname region @@ -990,6 +990,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Normală STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Mărime dublă STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Mărime împătrită +STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Dimensiune font STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Alege dimensiunea fontului pentru interfață STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(auto-detecție) @@ -998,7 +999,9 @@ STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Mărime dublă STR_GAME_OPTIONS_GRAPHICS :{BLACK}Grafică +STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Afișează rata de reîmprospătare STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}Alegeți rata de reîmprospătare dorită +STR_GAME_OPTIONS_REFRESH_RATE_OTHER :alta STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}Ratele de împrospătare de peste 60Hz ar putea afecta performanța. @@ -1177,6 +1180,7 @@ STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Alege în ce m STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Înălțimea limită a hărții: {STRING} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(auto) STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Nu poți seta înălțimea maximă a hărții la această valoare. Cel puțin un munte de pe hartă este mai înalt de-atât. STR_CONFIG_SETTING_AUTOSLOPE :Permite terra-formarea sub clădiri, şine, etc. (auto-pante): {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Permite terraformarea sub clădiri şi şine fără eliminarea acestora @@ -1430,6 +1434,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Pastrează acti STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Menține barele de construcție pentru tunele, poduri șamd deschise după folosire STR_CONFIG_SETTING_EXPENSES_LAYOUT :Grupează cheltuielile în raportul financiar al companiei: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Definește stilul ferestrei care afișează cheltuielile companiei +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Elimină automat semnalele pe durata construcției șinelor: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Elimină automat semnalele când construiești căi ferate dacă ele îți vin în cale. Nu uita că asta ar putea conduce la accidente feroviare. STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :Limita de viteză pentru trecerea timpului: {STRING} STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% din viteza normală a jocului @@ -1550,6 +1555,8 @@ STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :Lin STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :Înghețată STR_CONFIG_SETTING_ALLOW_SHARES :Permite cumpărarea de acţiuni de la alte companii: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Dacă este activată, se permite cumpărarea și vânzarea de acțiuni ale companiilor. Acțiunile devin disponibile doar când compania depășește o anumită vârstă +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Vârsta minimă a companiilor pentru tranzacțiile cu acțiuni: {STRING} +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Stabilește vechimea minimă a unei companii, ca alții să-i poată tranzacționa acțiunile. STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Procentul din profitul pe secţiune care să fie plătit pentru alimentare: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Procentul din câştig care este oferit legăturilor intermediare pentru alimentare, oferind mai mult control asupra încasărilor STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Când se trage cu mouse-ul, plasează semnale la fiecare: {STRING} @@ -1801,6 +1808,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Sigur v # Cheat window STR_CHEATS :{WHITE}Cheat-uri STR_CHEATS_TOOLTIP :{BLACK}Bifa vă indică dacă aţi folosit anterior acest cheat +STR_CHEATS_NOTE :{BLACK}Notă: utilizarea acestor setări va fi memorată în salvarea jocului STR_CHEAT_MONEY :{LTBLUE}Măreşte fondurile cu {CURRENCY_LONG} STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Joacă drept compania: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Buldozer magic (demolează industrii şi lucruri amovibile): {ORANGE}{STRING} @@ -1910,6 +1918,7 @@ STR_FACE_TIE :Cravată: STR_FACE_EARRING :Cercei: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Schimbă cravata sau cerceii +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privat # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer @@ -1973,6 +1982,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Numele j STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Pune parolă STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protejează-ţi jocul cu o parolă dacă nu vrei să intre jucători neautorizaţi +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Vizibilitate +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Dacă alți oameni îți pot vedea serverul în lista publică STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Număr maxim de clienţi: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Alege un număr maxim de clienţi. Nu trebuie ocupate toate locurile. STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Companii maxim: @@ -2032,11 +2043,21 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server p STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Companie protejată. Introdu parola # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clienţi +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jucători conectați # Network client list +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Modifică numele serverului tău +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Vizibilitate +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Dacă alți oameni îți pot vedea serverul în lista publică +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Modifică-ți numele +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Trimite un mesaj tuturor jucătorilor acestei companii +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Trimite un mesaj tuturor spectatorilor +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Deblocare cu parolă +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Sigur vrei să dai afară jucătorul '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Sigur vrei să blochezi jucătorul '{STRING}'? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client @@ -2092,6 +2113,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}A expira STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Calculatorul dvs. este prea lent pentru a se sincroniza cu serverul STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}A expirat timpul pentru descărcarea hărţii STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}A expirat timpul pentru conectarea la server +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Serverul solicitat este prea vechi pentru acest client ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :eroare generală @@ -2141,7 +2163,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} a STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} a intrat ca spectator STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} a început o companie nouă (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} a ieşit din joc ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} şi-a schimbat numele în {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} și-a schimbat numele în {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} a dat {2:CURRENCY_LONG} către {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Serverul a închis conexiunea STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Serverul este repornit...{}Vă rugăm aşteptaţi... @@ -2695,9 +2717,11 @@ STR_FRAMERATE_AI :{BLACK} IA {N ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GAMELOOP :Buclă de joc STR_FRAMETIME_CAPTION_GL_ECONOMY :Manipularea încărcăturilor +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Decalaj grafic de conexiuni STR_FRAMETIME_CAPTION_DRAWING :Randare grafică STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Randarea vizorului global STR_FRAMETIME_CAPTION_SOUND :Mixaj de sunet +STR_FRAMETIME_CAPTION_ALLSCRIPTS :Totalul de scripturi GS/AI STR_FRAMETIME_CAPTION_AI :IA {NUM} {STRING} ############ End of leave-in-this-order @@ -3309,6 +3333,7 @@ STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRI STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Necesită: STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} +STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} așteaptă{STRING} STR_CONFIG_GAME_PRODUCTION :{WHITE}Schimba productia (multiplu de 8, până la 2040) STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Modifică nivelul producţiei (procent, până la 800%) @@ -3428,11 +3453,12 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Cumpăr STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Cumpără și schimbă marfa transportată de aeronavă STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Cumpără vehiculul feroviar selectat. Shift+Click arată costul estimat fără să cumpere vehiculul -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Cumpără autovehiculul selectat. Shift+Click arată costul estimat fără să cumpere autovehiculul +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Cumpără autovehiculul selectat. Shift+clic arată costul estimat fără achiziția autovehiculului STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Cumpără nava selectată. Shift+Click arată costul estimativ fără a efectua achiziţia STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}Cumpără aeronava selectată. Shift+Click arată costul estimativ fără a efectua achiziţia -STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Cumpără și repară trenul selectat. Shift+Click arată costul estimat fără cumpărare +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Cumpără și repară trenul selectat. Shift+clic arată costul estimat fără achiziție +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Cumpără și repară autovehiculul selectat. Shift+clic arată costul estimat fără achiziție STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Cumpără și repară aeronava selectată. Shift+clic afișează costul estimat fără achiziție STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Nume nou @@ -3544,6 +3570,7 @@ STR_ENGINE_PREVIEW_CAPTION :{WHITE}Mesaj de STR_ENGINE_PREVIEW_MESSAGE :{GOLD}Am creat un nou tip de {STRING}. Aţi fi interesaţi de folosirea exclusivă pentru un an a acestui vehicul, astfel ca noi să-i putem observa performanţele înaintea lansării oficiale? STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :locomotivă +STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE :locomotivă electrificată STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :locomotivă monoşină STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :locomotivă pernă magnetică @@ -3555,8 +3582,9 @@ STR_ENGINE_PREVIEW_SHIP :navă STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY_LONG} Greutate: {WEIGHT_SHORT}{}Vitezã: {VELOCITY} Putere: {POWER}{}Cost de rulare: {CURRENCY_LONG}/an{}Capacitate: {CARGO_LONG} STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {CURRENCY_LONG} Greutate: {WEIGHT_SHORT}{}Viteză: {VELOCITY} Putere: {POWER} Ef. T. Max.: {6:FORCE}{}Cost rulaj: {4:CURRENCY_LONG}/an{}Capacitate: {5:CARGO_LONG} -STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Capacitate: {CARGO_LONG}{}Mentenanţă: {CURRENCY_LONG}/an -STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteza maximă: {VELOCITY}{}Tip avion: {STRING} Rază: {COMMA} pătrățele{}Capacitate: {CARGO_LONG}, {CARGO_LONG}{}Cost întreținere: {CURRENCY_LONG}/an +STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Capacitate: {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Tip avion: {STRING}{}Capacitate: {CARGO_LONG}, {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteza maximă: {VELOCITY}{}Tip avion: {STRING} Rază: {COMMA} pătrățele{}Capacitate: {CARGO_LONG}, {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Înlocuieşte {STRING} - {STRING} @@ -3606,6 +3634,7 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fă opti # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Centrează vizorul principal pe locația vehiculului. Dublu-clic va urmări vehiculul în vizorul principal. Ctrl+clic deschide un nou vizor cu locația vehiculului STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Centrează imaginea pe locația navei. Dublu clic va urmări nava în vizorul principal. Ctrl+Clic deschide un nou vizor pe locația navei STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Trimite trenul într-un depou @@ -3639,6 +3668,7 @@ STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Afişeaz STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Afişează detaliile aeronavei STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Acțiunea trenului curent - clic pentru oprirea/pornirea trenului +STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Acțiunea vehiculului curent - clic pentru oprirea/pornirea vehiculului STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Acțiunea avionului curent - clic pentru oprirea/pornirea avionului @@ -4193,7 +4223,7 @@ STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Nu se po STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nu se poate construi sediul companiei... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nu se pot cumpăra 25% din acţiunile acestei companii... STR_ERROR_CAN_T_SELL_25_SHARE_IN :{WHITE}Nu se pot vinde 25% din acţiunile acestei companii... -STR_ERROR_PROTECTED :{WHITE}Această companie încă nu vinde acţiuni... +STR_ERROR_PROTECTED :{WHITE}Compania nu are vechimea necesară pentru tranzacționarea de acțiuni... # Town related errors STR_ERROR_CAN_T_GENERATE_TOWN :{WHITE}Nu pot construi nici un oras diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 2ed535c7a9..908f055ecf 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -4461,9 +4461,9 @@ STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE :{WHITE}{TOWN} m STR_ERROR_BRIBE_FAILED :{WHITE}Tvoj pokus o podplácanie bol odhalený vyšetrovateľom # Levelling errors -STR_ERROR_CAN_T_RAISE_LAND_HERE :{WHITE}Nemôžeš tu zvýšiť terén... -STR_ERROR_CAN_T_LOWER_LAND_HERE :{WHITE}Nemôžeš tu znížiť terén... -STR_ERROR_CAN_T_LEVEL_LAND_HERE :{WHITE}Nemôžem tu upraviť terén... +STR_ERROR_CAN_T_RAISE_LAND_HERE :{WHITE}Nemôžete tu zvýšiť terén... +STR_ERROR_CAN_T_LOWER_LAND_HERE :{WHITE}Nemôžete tu znížiť terén... +STR_ERROR_CAN_T_LEVEL_LAND_HERE :{WHITE}Nemôžete tu upraviť terén... STR_ERROR_EXCAVATION_WOULD_DAMAGE :{WHITE}Vyhĺbenie by poškodilo tunel STR_ERROR_ALREADY_AT_SEA_LEVEL :{WHITE}... už na úrovni mora STR_ERROR_TOO_HIGH :{WHITE}... príliš vysoko @@ -4483,14 +4483,14 @@ STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je m STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Spoločnosť nie je možné kúpiť ... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžete tu postaviť sídlo spoločnosti... -STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžeš kúpiť 25% podiel v tejto spoločnosti... +STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžete kúpiť 25% podiel v tejto spoločnosti... STR_ERROR_CAN_T_SELL_25_SHARE_IN :{WHITE}25% podiel v tejto spoločnosti sa nedá predať ... STR_ERROR_PROTECTED :{WHITE}S akciami tejto spoločnosti nie je zatiaľ možné obchodovať... # Town related errors STR_ERROR_CAN_T_GENERATE_TOWN :{WHITE}Nie je možné postaviť viac miest STR_ERROR_CAN_T_RENAME_TOWN :{WHITE}Mesto nemôže byť odstránené... -STR_ERROR_CAN_T_FOUND_TOWN_HERE :{WHITE}Nemôžeš tu postaviť mesto... +STR_ERROR_CAN_T_FOUND_TOWN_HERE :{WHITE}Nemôžete tu založiť mesto... STR_ERROR_CAN_T_EXPAND_TOWN :{WHITE}Nemožno rozšíriť mesto... STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... príliš blízko okraja mapy STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... príliš blízko iného mesta @@ -4526,7 +4526,7 @@ STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Pre zís # Station construction related errors STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nemôžete tu postaviť železničnú stanicu... STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Nemôžete tu postaviť autobusovú zastávku... -STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemôžeš tu postaviť vykládku... +STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemôžete tu postaviť vykládku... STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú zastávku... STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú vykládku... STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Nemôžete tu postaviť prístav... @@ -4569,7 +4569,7 @@ STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Susedí STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Príliš blízko iného smerovému bodu STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Tu nie je možné postaviť železničný smerový bod... -STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Nemôžeš tu postaviť bóju... +STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Nemôžete tu umiestniť bóju... STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Názov smerového bodu sa nedá zmeniť... STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}Tu nie je možné odstrániť železničný smerový bod... @@ -4580,8 +4580,8 @@ STR_ERROR_BUOY_IS_IN_USE :{WHITE}... bój # Depot related errors STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nemôžete tu postaviť vlakové depo... STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Nemôžete tu postaviť garáž... -STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Nemôžeš tu postaviť električkové depo... -STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nemôžeš tu postaviť lodenicu... +STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Nemôžete tu postaviť električkovú garáž... +STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nemôžete tu postaviť lodenicu... STR_ERROR_CAN_T_RENAME_DEPOT :{WHITE}Depo sa nedá premenovať... @@ -4618,7 +4618,7 @@ STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Musíš STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Cesta je jednosmerná alebo blokovaná. STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Nie sú povolené priecestia pre tento typ železnice STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Nie sú povolené priecestia pre tento typ cesty -STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nemôžeš tu umiestniť návestidlá... +STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nemôžete tu umiestniť návestidlá... STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nemôžete tu postaviť železničnú trať... STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nemôžeš tu odstrániť železničné koľaje... STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nemôžeš tu odstrániť návestidlá... @@ -4626,19 +4626,19 @@ STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Tu nie j STR_ERROR_THERE_IS_NO_RAILROAD_TRACK :{WHITE}...nenašli sa železničné koľaje STR_ERROR_THERE_ARE_NO_SIGNALS :{WHITE}... nenašli sa návestidlá -STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Nemôžeš tu konvertovať železnicu... +STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Nemôžete tu konvertovať železnicu... # Road construction errors STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprv treba odstrániť cestu STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}... na jednosmerných cestách nie sú dovolené križovatky STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Nemôžete tu postaviť cestu... -STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Nemôžeš tu stavať električkovú trať... +STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Nemôžete tu postaviť električkovú trať... STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nemôžeš tu odstrániť cestu... STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Nemôžeš tu odstrániť električkovú trať... STR_ERROR_THERE_IS_NO_ROAD :{WHITE}... nenašla sa cesta STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}...nenašla sa električková trať -STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Nemôžeš tu konvertovať cestu... -STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Nemôžeš tu konvertovať električkovú trať... +STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Nemôžete tu konvertovať cestu... +STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Nemôžete tu konvertovať električkovú trať... STR_ERROR_NO_SUITABLE_ROAD :{WHITE}Žiadna použiteľná cesta STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}Žiadna použiteľná električková trať STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... nekompatibilné električkové trate @@ -4658,7 +4658,7 @@ STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Nemôže # Tree related errors STR_ERROR_TREE_ALREADY_HERE :{WHITE}... strom tu už je STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE :{WHITE}... zlý terén pre tento typ stromov -STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Nemôžeš tu zasadiť strom... +STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Nemôžete tu zasadiť stromy... # Bridge related errors STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nemôžete tu postaviť most... @@ -4673,7 +4673,7 @@ STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... most STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Most skončí za okrajom mapy # Tunnel related errors -STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nemôžeš tu postaviť tunel... +STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nemôžete tu postaviť tunel... STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Miesto nevhodné pre vjazd do tunela STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Tunel musi byť najskôr zbúraný STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Iný tunel v ceste @@ -4746,7 +4746,7 @@ STR_ERROR_SHIP_NOT_AVAILABLE :{WHITE}Loď nie STR_ERROR_AIRCRAFT_NOT_AVAILABLE :{WHITE}Lietadlo nie je dostupné STR_ERROR_TOO_MANY_VEHICLES_IN_GAME :{WHITE}V hre je príliš veľa dopravných prostriedkov -STR_ERROR_CAN_T_CHANGE_SERVICING :{WHITE}Nie je možné zmenit servisný interval ... +STR_ERROR_CAN_T_CHANGE_SERVICING :{WHITE}Nemožno zmeniť servisný interval... STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... vozidlo je zničené @@ -4760,7 +4760,7 @@ STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemôže STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nemožno otočiť vlak naopak... STR_ERROR_TRAIN_START_NO_POWER :Vlak nemá energiu -STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Nemôžem otočiť cestné vozidlo... +STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Nemožno otočiť cestné vozidlo... STR_ERROR_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Lietadlo je vo vzduchu @@ -4792,7 +4792,7 @@ STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}Toto voz STR_ERROR_TOO_MANY_SIGNS :{WHITE}... príliš veľa popisov STR_ERROR_CAN_T_PLACE_SIGN_HERE :{WHITE}Tu sa nedá umiestniť popis... STR_ERROR_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nemožno zmeniť text popisu... -STR_ERROR_CAN_T_DELETE_SIGN :{WHITE}Nemôžem zmazať popis... +STR_ERROR_CAN_T_DELETE_SIGN :{WHITE}Nemožno vymazať popis... # Translatable comment for OpenTTD's desktop shortcut STR_DESKTOP_SHORTCUT_COMMENT :Simulátor založený na hre Transport Tycoon Deluxe diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index cbedd61fae..76d30a7a6c 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -195,6 +195,7 @@ STR_COLOUR_DEFAULT :Varsayılan STR_UNITS_VELOCITY_IMPERIAL :{COMMA}{NBSP}mil/s STR_UNITS_VELOCITY_METRIC :{COMMA}{NBSP}km/s STR_UNITS_VELOCITY_SI :{COMMA}{NBSP}m/s +STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}karo/gün STR_UNITS_POWER_IMPERIAL :{COMMA}{NBSP}bg STR_UNITS_POWER_METRIC :{COMMA}{NBSP}bg @@ -313,8 +314,15 @@ STR_SORT_BY_CARGO_CAPACITY :Kargo kapasites STR_SORT_BY_RANGE :Menzil STR_SORT_BY_POPULATION :Nüfus STR_SORT_BY_RATING :Değerlendirme +STR_SORT_BY_NUM_VEHICLES :Araç sayısı +STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Geçen yılki toplam kar +STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Bu yılki toplam kar +STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Geçen yılki ortalama kar +STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Bu yılki ortalama kar # Group by options for vehicle list +STR_GROUP_BY_NONE :Hiçbiri +STR_GROUP_BY_SHARED_ORDERS :Paylaşılan talimatlar # Tooltips for the main toolbar STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Oyunu durdur @@ -688,7 +696,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Kullanı STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK} {NUM} STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME :{BIG_FONT}{BLACK} {NUM} senesindeki şirket ligi STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}. -STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :İşadamı +STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :İş insanı STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Girişimci STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Sanayici STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Sermayedar @@ -740,6 +748,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Engebeli Alan STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Çim alan STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Çıplak Arazi +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Yağmur ormanı STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Meralar STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Ağaçlar STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Kayalar @@ -771,6 +780,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Haritada STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Son mesajı ya da haberi göster STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * DURAKLATILDI * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * DURDU (bağlantı grafiğinin güncellenmesi bekleniyor) * * STR_STATUSBAR_AUTOSAVE :{RED}OTOMATİK KAYDET STR_STATUSBAR_SAVING_GAME :{RED}* * KAYDEDiYOR * * @@ -937,13 +947,14 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Yeni Tayvan Dol STR_GAME_OPTIONS_CURRENCY_CNY :Çin Yuanı (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kong Doları (HKD) STR_GAME_OPTIONS_CURRENCY_INR :Hindistan Rupisi (INR) +STR_GAME_OPTIONS_CURRENCY_IDR :Endonezya Rupiahı (IDR) STR_GAME_OPTIONS_CURRENCY_MYR :Malezya Ringgiti (MYR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Soldan trafik STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Sağdan trafik -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Şehir isimleri +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Şehir isimleri: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Şehir isimleri için bir tür seçin ############ start of townname region @@ -983,6 +994,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Her oniki ayda STR_GAME_OPTIONS_LANGUAGE :{BLACK}Dil STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Görünen dili seçin +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} (%{NUM} tamamlandı) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Tam ekran STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Tam ekran oynamak için bunu isaretleyin @@ -992,11 +1004,17 @@ STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}Kullanı STR_GAME_OPTIONS_RESOLUTION_OTHER :diğer STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} +STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Donanım hızlandırma +STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}OpenTTD'nin donanım ivmesini kullanmayı denemesine izin vermek için bu kutuyu işaretleyin. Değiştirilmiş bir ayar sadece oyun yeniden başlatıldığında uygulanır +STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Ayar sadece oyun yeniden başlatıldığında uygulanır +STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync +STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Dikey senkronizasyon'u aktif etmek için bu kutuyu işaretleyin. Değiştirilmiş bir ayar sadece oyun yeniden başlatıldığında uygulanır. Yalnızca donanım ivmesi aktifken çalışır STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Arayüz boyutu STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Kullanmak üzere arayüz bileşen boyutunu seçin +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO :(otomatik-tespit) STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :İki kat büyük STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Dört kat büyük @@ -1004,11 +1022,18 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Dört kat büy STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Yazı boyutu STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :Arayüz boyutunu seç +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(otomatik-tespit) STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Yazı iki kat büyük STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Dört kat büyük +STR_GAME_OPTIONS_GRAPHICS :{BLACK}Grafikler +STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Tazeleme oranını görüntüle +STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}Kullanılacak tazeleme oranını seç +STR_GAME_OPTIONS_REFRESH_RATE_OTHER :diğer +STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz +STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}60Hz'den yüksek tazeleme oranları performansı etkileyebilir. STR_GAME_OPTIONS_BASE_GRF :{BLACK}Temel grafik kümesi STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Kullanılacak temel grafik kümesini seçin @@ -1104,6 +1129,8 @@ STR_TERRAIN_TYPE_FLAT :Düz STR_TERRAIN_TYPE_HILLY :Engebeli STR_TERRAIN_TYPE_MOUNTAINOUS :Dağlık STR_TERRAIN_TYPE_ALPINIST :Alp Meraklısı +STR_TERRAIN_TYPE_CUSTOM :Özel yükseklik +STR_TERRAIN_TYPE_CUSTOM_VALUE :Özel yükseklik ({NUM}) STR_CITY_APPROVAL_PERMISSIVE :İzne tabi STR_CITY_APPROVAL_TOLERANT :Töleranslı @@ -1116,6 +1143,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Ayarlar STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Süzgeç metni: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Tümünü genişlet STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Tümünü kısalt +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Tüm değerleri sıfırla STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(açıklama bulunmamaktadır) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Varsayılan değer: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Ayar türü: {ORANGE}{STRING} @@ -1124,6 +1152,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Kullanıcı aya STR_CONFIG_SETTING_TYPE_GAME_INGAME :Oyun ayarları (kayıtlı dosyada saklanır; sadece mevcut oyunu etkilemektedir) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Şirket ayarları (kayıtlı dosyada saklanır; sadece yeni oyunu etkilemektedir) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Şirket ayarları (kayıtlı dosyada saklanır; sadece mevcut şirketi etkilemektedir) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Dikkat! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Bu eylem tüm oyun ayarlarını varsayılan değerlerine sıfırlayacaktır.{}Devam etmek istediğine emin misin? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategori: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tür: @@ -1185,6 +1215,10 @@ STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Araçları ya d STR_CONFIG_SETTING_CITY_APPROVAL :Arazi şekillendirmeye karşı belediye meclisinin tavrı: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Şirketlerin sebep olduğu gürültü ve çevreye zararın kasaba beğenilerini ve ilerideki inşaatlarını nasıl etkileyeceğini seçin +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Harita azami yükseklik limiti: {STRING} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Harita arazisinin azami yüksekliğini ayarlayın. "(otomatik)" ile arazi oluşturulduktan sonra güzel bir değer seçilecektir +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(otomatik) STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Azami harita yüksekliğini bu değere ayarlayamazsınız. Haritadaki en az bir dağ bu değerden yüksek STR_CONFIG_SETTING_AUTOSLOPE :Binaların, yolların vb. altındaki araziyi değiştirmeye izin ver: {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Binaları ve yolları kaldırmaksızın altlarında yeryüzü şekillendirmesi yapılmasına izin ver @@ -1329,7 +1363,13 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Oyun boyunca ka STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Petrol rafinerilerinin kenarlardan azami uzaklığı: {STRING} STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Petrol rafinerileri sadece haritanın sınırlarında inşa edilir; ada haritalarında sahillere kurulurlar. STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Kar kalınlığı: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Kutupsal arazide, karın ne kadar yükseklikten başlayacağını denetleyin. Kar aynı zamanda fabrika oluşumunu ve şehir gelişme gereksinimini de etkiler +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Kutupsal arazide, karın ne kadar yükseklikten başlayacağını denetleyin. Kar aynı zamanda fabrika oluşumunu ve şehir gelişme gereksinimini de etkiler. Yalnızca Senerya Editörü ile değiştirilebilir veya "kar örtüsü" üzerinden hesaplanır +STR_CONFIG_SETTING_SNOW_COVERAGE :Kar örtüsü: {STRING} +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Arktik altındaki yaklaşık kar miktarını kontrol eder. Kar, aynı zamanda endüstri üretimini ve kasaba büyüme gereksinimlerini de etkiler. Yalnızca harita oluşumu sırasında kullanılır. Deniz seviyesinin hemen üzerindeki arazi her zaman karsızdır +STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :%{NUM} +STR_CONFIG_SETTING_DESERT_COVERAGE :Çöl örtüsü: {STRING} +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Tropikal arazideki yaklaşık çöl miktarını kontrol eder. Çöl ayrıca endüstri üretimini de etkiler. Yalnızca harita oluşturma sırasında kullanılır +STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :%{NUM} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Arazinin engebesi: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Sadece TerraGenesis) Tepelerin sıklığını seçin: Yumuşak yerleşimler daha az, geniş alana yayılmış tepelere sahiptir. Sıkı yerleşimler tekrarlanmış gibi görülen çok sayıda tepeye sahip olacaklar. STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Dümdüz @@ -1443,6 +1483,11 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Yapı araçlar STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Köprü, tünel vb. için kullanılan inşa araçlarını kullanımdan sonra da açık tut STR_CONFIG_SETTING_EXPENSES_LAYOUT :Şirket mali tablosunda grup harcamaları: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Şirket harcamaları penceresinin nasıl düzenleneceğini belirle +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Ray yapımı sırasında sinyalleri otomatik olarak kaldır: {STRING} +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Ray yapımı sırasında sinyaller yolun üzerinde ise otomatik kaldır. Bunun potansiyel olarak tren kazalarına yol açabileceğini unutmayın. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :İleri sarma hız limiti: {STRING} +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :Hızlı ileri sarma etkinleştirildiğinde oyunun ne kadar hızlı sarıldığını sınırlayın. 0 = sınır yok (bilgisayarın el verdiği kadar). %100'ün altındaki değerler oyunu yavaşlatır. Üst sınır bilgisayarının özelliklerine ve oyuna göre değişkenlik gösterebilir. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :%{NUM} normal oyun hızı STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :Limit yok (bilgisayarın izin verdiği maksimum hızda ) STR_CONFIG_SETTING_SOUND_TICKER :Kayan haber bandı: {STRING} @@ -1557,6 +1602,11 @@ STR_CONFIG_SETTING_ENDING_YEAR :Yıl sonu puan STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Oyunun puan sonucuna göre bittiği yıl. Bu yılın sonunda, şirketin puanı kaydedilir ve yüksek puan ekranında gösterilir ama oyuncular oynamaya devam edebilir.{}Eğer bu başlama yılından önce ise, yüksek puan ekranı gösterilmez. STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Asla +STR_CONFIG_SETTING_ECONOMY_TYPE :Ekonomi türü: {STRING} +STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :Sorunsuz ekonomi, üretim değişikliklerini daha sık ve daha küçük adımlarla yapar. Donuk ekonomi, üretim değişikliklerini ve endüstri kapanışlarını durdurur. Sektör türleri bir NewGRF tarafından sağlanırsa bu ayarın hiçbir etkisi olmayabilir. +STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :Orijinal +STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :Pürüzsüz +STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :Donuk STR_CONFIG_SETTING_ALLOW_SHARES :Diğer şirketlerin hisseleri alınabilsin: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Etkinleştirildiğinde, şirketlerin hisse senetlerinin alınıp satılması mümkün olur. Hisse senetleri sadece belli bir yaşa ulaşan şirketler için geçerlidir STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Hisse satmak için gerekli minimum şirket yaşı: {STRING} @@ -1608,6 +1658,10 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Doğrusal STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Oyunda ağaç dikme: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Oyundaki rastgele ağaçların görünümünü kontrol eder. Bu, ağaçların büyümesine bağımlı olan endüstrileri etkileyebilir, örneğin keresteciler gibi +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Büyü ama yayılma {RED}(kereste fabrikasını kırar) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Büyü ama sadece yağmur ormanlarında yayıl +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :Büyü ve her yere yayıl +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Büyüme, yayılma {RED}(kereste fabrikasını kırar) STR_CONFIG_SETTING_TOOLBAR_POS :Ana araç çubuğu konumu: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Ekranın üst kısmındaki ana araç çubuğunun yatay konumu @@ -1625,12 +1679,17 @@ STR_CONFIG_SETTING_ZOOM_MIN :Azami yaklaşma STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Görüş alanları için azami yakınlaşma seviyesi. Daha yüksek uzaklaştırma ayarları oyunda gecikmelere sebep olabilir STR_CONFIG_SETTING_ZOOM_MAX :Azami uzaklaşma seviyesi: {STRING} STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :Görüş alanları için azami uzaklaşma seviyesi. Daha yüksek uzaklaştırma ayarları oyunda gecikmelere sebep olabilir +STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :Kullanılacak en yüksek çözünürlüklü sprite'lar: {STRING} +STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :Sprite'lar için kullanılacak maksimum çözünürlüğü sınırlar. Sprite çözünürlüğünü sınırlamak, mevcut olunca bile yüksek çözünürlüklü grafikleri kullanmaktan kaçınacaktır. Bu, yüksek çözünürlüklü grafikleri içeren ve içermeyen GRF dosyalarının bir karşımı kullanılırken oyun görünümünü bir arada tutmaya yardımcı olabilir. STR_CONFIG_SETTING_ZOOM_LVL_MIN :4x STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2x STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :Normal STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X :2x STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X :4x STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8x +STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_MIN :4x +STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_IN_2X :2x +STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_NORMAL :1x STR_CONFIG_SETTING_TOWN_GROWTH :Şehirlerin genişleme hızı: {STRING} STR_CONFIG_SETTING_TOWN_GROWTH_HELPTEXT :Şehir büyüme hızı STR_CONFIG_SETTING_TOWN_GROWTH_NONE :Hiçbiri @@ -1674,6 +1733,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Kullanıcı ara STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (İngiliz ölçü birimleri) (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metrik (km/s) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (Uluslararası Ölçüm Sistemi) (m/s) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Oyun birimleri (karo/gün) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Araç gücü ölçü birimi: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Kullanıcı arayüzünde bir aracın gücü görüntülendiğinde, bunu seçili ölçü biriminde göster. @@ -1764,6 +1824,8 @@ STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}Bellek y STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}{BYTES} sprite-önbelleği ayırma işlemi başarısız. Sprite-önbelleği {BYTES}'a düşürüldü. Bu OpenTTD'nin performansını azaltacak. Bellek gereksinimini azaltmak için 32bpp grafikleri ve/veya yakınlaştırma seviyelerini kapatmayı deneyebilirsiniz # Video initalization errors +STR_VIDEO_DRIVER_ERROR :{WHITE}Video ayarlarında hata... +STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... uyumlu GPU bulunamadı. Donanım hızlandırma devre dışı bırakıldı # Intro window STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} @@ -1808,6 +1870,7 @@ STR_INTRO_TRANSLATION :{BLACK}Bu çevi # Quit window STR_QUIT_CAPTION :{WHITE}Çıkış +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Oyundan çıkmak istediğinize emin misiniz? STR_QUIT_YES :{BLACK}Evet STR_QUIT_NO :{BLACK}Hayır @@ -1819,6 +1882,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Bu sena # Cheat window STR_CHEATS :{WHITE}Hileler STR_CHEATS_TOOLTIP :{BLACK}Onay kutuları bu hilenin daha önce kullanılıp kullanmadığını bildirir. +STR_CHEATS_NOTE :{BLACK}Not: bu ayarların herhangi bir kullanımı kayıt oyunu tarafından kaydedilecektir STR_CHEAT_MONEY :{LTBLUE}Parayı {CURRENCY_LONG} kadar arttır STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Oynanan şirket: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Sihirli buldozer (fabrikaları, silinemeyen nesneleri siler): {ORANGE}{STRING} @@ -1928,6 +1992,8 @@ STR_FACE_TIE :Kravat: STR_FACE_EARRING :Küpe: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Kravatı veya küpeyi değiştir +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Özel +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Halka açık # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Çok Oyunculu @@ -1971,6 +2037,10 @@ STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Oyuna gi STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Sunucuyu tazele STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Sunucu bilgisini tazele +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}İnterneti Ara +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}İnternette halka açık sunucu ara +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}LAN ara +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Yerel alan ağında sunucu ara STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Sunucu ekle STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Her zaman çalışan oyunlarına bakabilmek için bir sunucu ekle STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Sunucu başlat @@ -1987,6 +2057,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Bu oyun STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Parola koy STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Erişimi kısıtlamak için oyuna parola koy +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Görünürlük +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Halka açık listelemede öbür oyuncuların sizin sunucunuzu görüp göremeyeceği STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} istemci STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Azami istemci sayısı: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}İzin verilen en fazla oyuncu sayısını seç. Her yerin dolması gerekmez @@ -2050,11 +2122,44 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Sunucu k STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Şirket korumalı. Parola girin # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Oyuncu listesi +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Aktif oyuncular # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Çok Oyunculu +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Sunucu +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}İsim +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Oynadığın sunucunun adı +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Sunucunun adını değiştir +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Sunucunun adı +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Görünürlük +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Halka açık listelemede öbür oyuncuların sizin sunucunuzu görüp göremeyeceği +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Oyuncu +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}İsim +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}İsmin +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}İsmini değiştir +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :İsmin +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Client için gerçekleştirilecek yönetici eylemleri +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Şirket için gerçekleştirilecek yönetici eylemleri +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Bu şirkete katıl +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Bu oyuncuya bir mesaj gönder +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Bu şirketteki tüm oyunculara bir mesaj gönder +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Bütün izleyicilere bir mesaj yolla +STR_NETWORK_CLIENT_LIST_SPECTATORS :İzleyiciler +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Yeni şirket) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Yeni bir şirket oluştur ve ona katıl +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Bu sensin +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Bu, oyunun ev sahibi +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :At +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Yasakla +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Sil +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Parola ile kilit açma +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Yönetici eylemi +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}'{STRING}' adlı oyuncuyu atmak istediğine emin misin? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}'{STRING}' adlı oyunucuyu yasaklamak istediğine emin misin? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}'{COMPANY}' şirketini silmek istediğine emin misin? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}'{COMPANY}' adlı şirketin şifresini sıfırlamak istediğine emin misin? STR_NETWORK_SERVER :Sunucu STR_NETWORK_CLIENT :İstemci @@ -2099,6 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Sunucu b STR_NETWORK_ERROR_CLIENT_START :{WHITE}Bağlanamadı STR_NETWORK_ERROR_TIMEOUT :{WHITE}Bağlantı #{NUM} zaman aşımına uğradı STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Protokol hatası yapıldı ve bağlantı koparıldı +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}İsmin ayarlanmamış. Çok Oyunculu penceresinin üstünden ayarlanabilir STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Bu istemcinin revizyonu sunucununki ile aynı değil STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Yanlış parola STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Sunucu dolu @@ -2111,6 +2217,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Şifre g STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Bilgisayarınız sunucuyla haberleşmeyi sürdürmek için çok yavaş. STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Bilgisayarınızın haritayı indirmesi çok uzun sürdü STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Bilgisayarınızın sunucuya katılması çok uzun sürdü +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}İsminiz geçerli değil +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Sorgulanan sunucu bu istemci için çok eski ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :genel hata @@ -2133,6 +2241,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :şifre zamanın STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :genel zamanaşımı STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :haritayı indirmek çok uzun sürdü STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :haritayı işlemek çok uzun sürdü +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :Geçersiz ev sahibi ismi ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Olası bağlantı kaybı @@ -2146,11 +2255,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Oyun hala durak STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Oyun hala duraklıyor ({STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Oyun hala duraklıyor ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Oyun hala duraklatılmış ({STRING}, {STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Oyun hala duraklatıldı ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Oyun devam ediyor ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :oyuncu sayısı STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :istemcilere bağlanıyor STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :el ile STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :oyun betiği +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :bağlantı grafiğinin güncellenmesi bekleniyor ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :ayrılıyor STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} oyuna katıldı @@ -2160,6 +2271,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} g STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} yeni bir şirket kurdu (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} oyunu terketti ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} adını {STRING} olarak değiştirdi +STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} {1:STRING} adlı şirkete {2:CURRENCY_LONG} verdi STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Sunucu kapandı STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Sunucu baştan başlatılıyor...{}Lütfen bekleyin... STR_NETWORK_MESSAGE_KICKED :*** {STRING} atıldı. Sebep: ({STRING}) @@ -2237,6 +2349,9 @@ STR_MISSING_GRAPHICS_SET_MESSAGE :{BLACK}OpenTTD STR_MISSING_GRAPHICS_YES_DOWNLOAD :{BLACK}Evet, grafikleri indir STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}Hayır, OpenTTD'den çık +STR_MISSING_GRAPHICS_ERROR_TITLE :{WHITE}İndirme başarısız +STR_MISSING_GRAPHICS_ERROR :{BLACK}Grafikleri indirme başarısız.{}Lütfen grafikleri manuel olarak indirin. +STR_MISSING_GRAPHICS_ERROR_QUIT :{BLACK}OpenTTD'den Çık # Transparency settings window STR_TRANSPARENCY_CAPTION :{WHITE}Şeffaflık Seçenekleri @@ -2280,6 +2395,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Yerimini STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Ayrı bir yerimi yap # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Şu anda bu altyapı için hiçbir araç bulunmadığından devre dışı bırakıldı # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Demiryolu Yapımı @@ -2415,7 +2531,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}İskele STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Yerimi olarak kullanilabilecek bir şamandıra yerlestir. Shift ile tıklama maliyet tahminini gösterir STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Su kemeri yap. Shift ile tıklama maliyet tahminini gösterir STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Su alanını belirle.{}Deniz seviyesinde CTRL tuşu basılı olmadığı sürece kanal yapar, basılıysa etraftakileri su altında bırakır -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Nehir yerleştir +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Nehir yerleştir. Ctrl tuşu alanı çapraz olarak seçer # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Tersane Yönü @@ -2475,6 +2591,12 @@ STR_TREES_RANDOM_TYPE :{BLACK}Rastgele STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Rastgele türde ağaçlar koy. Shift ile ağaç koyma/maliyet gösterme tercihi yapılır STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Rastgele Ağaç STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Haritaya rastgele ağaç dik +STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Normal +STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}Arazinin üzerine sürükleyerek tekli ağaçlar dikin. +STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Koru +STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}Arazinin üzerine sürükleyerek küçük ormanlar dikin. +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Orman +STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Arazinin üzerine sürükleyerek büyük ormanlar dikin. # Land generation window (SE) STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Arazi Yapımı @@ -2525,12 +2647,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Rastgele # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Yeni fabrika aç STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Bu listeden uygun fabrikayı seçin -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Birçok rastgele fabrika +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Rastgele endüstriler oluştur STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Haritayı rastgele fabrikalarla doldur +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Rastgele endüstriler oluştur +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Birçok sayıda rastgele endüstri oluşturmak istediğinize emin misiniz? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Fiyat: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Tetkik arama STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}İnşa et STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Parayla Yap +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Bütün endüstrileri kaldır +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Şu anda haritada bulunan tüm endüstrileri kaldır +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Bütün endüstrileri kaldır +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Bütün endüstrileri kaldırmak istediğinize emin misiniz? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}{STRING} fabrikası için sanayi zinciri @@ -2551,6 +2679,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Gösterm # Land area window STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Arazi Bilgisi +STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}Ana görünümü karonun konumuna ortalar. Ctrl+Sol Tık karonun konumunu gösteren yeni bir pencere açar STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}Temizleme fiyatı: {LTBLUE}Yok STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Temizleme fiyatı: {RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Kaldırıldığında kazanılacak: {LTBLUE}{CURRENCY_LONG} @@ -2760,6 +2889,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Süzgeç dizgesi: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Dosya Üzerine Yaz STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Mevcut dosyanın üzerine yazmak istediğinizden emin misiniz? +STR_SAVELOAD_DIRECTORY :{STRING} (Dizin) +STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Ana dizin) STR_SAVELOAD_OSKTITLE :{BLACK}Kayıtlı oyun için bir isim girin @@ -2771,6 +2902,17 @@ STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Şehir sayısı: STR_MAPGEN_DATE :{BLACK}Tarih: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Fabrika sayısı: +STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}En yüksek tepe: +STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Haritadaki en yüksek tepenin azami yüksekliğini 1 arttırın +STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Haritadaki en yüksek tepenin azami yüksekliğini 1 düşürün +STR_MAPGEN_SNOW_COVERAGE :{BLACK}Kar örtüsü: +STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}Kar örtüsünü yüzde on arttır +STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}Kar örtüsünü yüzde on azalt +STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}%{NUM} +STR_MAPGEN_DESERT_COVERAGE :{BLACK}Çöl örtüsü: +STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}Çöl örtüsünü yüzde on arttır +STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Çöl örtüsünü yüzde on azalt +STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}%{NUM} STR_MAPGEN_LAND_GENERATOR :{BLACK}Harita üretici: STR_MAPGEN_TERRAIN_TYPE :{BLACK}Arazi türü: STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}Deniz seviyesi: @@ -2796,6 +2938,10 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Yüksekl STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Boyut: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} +STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Hedef zirve yüksekliği +STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}En yüksek tepe +STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Kar örtüsü (% olarak) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Çöl örtüsü (% olarak) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Başlangıç yılını değiştir # SE Map generation @@ -2935,6 +3081,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Uyarı: {S STR_NEWGRF_ERROR_MSG_ERROR :{RED}Hata: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Ölümcül hata: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ölümcül bir NewGRF hatası oluştu:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF hatası oluştu:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} OpenTTD tarafından belirtilen TTDPatch sürümüyle çalışmayacaktır STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING}, TTD'nin {STRING} sürümü içindir STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING}, {STRING} ile kullanılmak için tasarlanmıştır @@ -3012,6 +3159,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Tabela a # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}Tabelayı değiştir +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Ana görünümü işaretin konumuna ortalar. Ctrl+Sol Tık ile işaretin konumunda yeni bir pencere açar STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Sonraki tabelaya git STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Önceki tabelaya git @@ -3072,20 +3220,23 @@ STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :Yeni binalar ya STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :Ayrıcalıklı nakliyat haklarını satın al STR_LOCAL_AUTHORITY_ACTION_BRIBE :Belediyeye rüşvet ver -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW} Müsteri çekmek için duvarlara poster yapıştır.{} Fiyat: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW} Müsteri çekmek için radyoya reklam ver.{} Fiyat: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW} Müsteri çekmek için televizyona reklam ver.{} Fiyat: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW} Yol tamirleri için belediyeye bağış yap. 6 ay boyunca şehrin yolları kullanılamaz.{} Fiyat: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Şirket sahibinin heykelini dik.{}Fiyatı: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Şehirde ticari binaların yapımı için bağış yap.{}Fiyatı: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW} Bir yıllık ayrıcalıklı nakliyat haklarını satın al. Belediye şehirde sadece senin şirketine yolcu ve kargo taşıma izni verir.{} Fiyat: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW} Müsteri çekmek için duvarlara poster yapıştır.{}Şehir merkezinin etrafında küçük bir çapta istasyon derecelendirmesinde geçici bir yükseltme sağlar.{}Fiyat: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW} Müsteri çekmek için radyoya reklam ver.{}Şehir merkezinin etrafında orta bir çapta istasyon derecelendirmesinde geçici bir yükseltme sağlar.{}Fiyat: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW} Müsteri çekmek için televizyona reklam ver.{}Şehir merkezinin etrafında büyük bir çapta istasyon derecelendirmesinde geçici bir yükseltme sağlar.{}Fiyat: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW} Yol tamirleri için belediyeye bağış yap.{}6 ay boyunca şehrin yolları kullanılamaz.{}Fiyat: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Şirket sahibinin heykelini dik.{}Şehirdeki istasyon derecelendirmesinde kalıcı bir yükseltme sağlar.{}Fiyatı: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Şehirde ticari binaların yapımı için bağış yap.{}Bu kasabanın büyümesine geçici bir yükseltme sağlar.{}Fiyatı: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW} Bir yıllık ayrıcalıklı nakliyat haklarını satın al.{} Belediye, rakip istasyonların yolcu ve kargo taşımasına izin vermez.{} Fiyat: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Yakalanma riskini göze alarak belediyeye rüşvet ver.{}Fiyat: {CURRENCY_LONG} # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} Hedefler STR_GOALS_SPECTATOR_CAPTION :{WHITE}Evrensel Amaçlar STR_GOALS_SPECTATOR :Evrensel Amaçlar +STR_GOALS_GLOBAL_BUTTON :{BLACK}Küresel STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}Evrensel amaçları göster +STR_GOALS_COMPANY_BUTTON :{BLACK}Şirket +STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}Şirket hedeflerini göster STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_NONE :{ORANGE}- Hiçbiri - STR_GOALS_PROGRESS :{ORANGE}{STRING} @@ -3093,10 +3244,10 @@ STR_GOALS_PROGRESS_COMPLETE :{GREEN}{STRING} STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Ana görünümü istenen fabrika/kasaba/kareye getirmek için hedefe tıklayın. Ctrl+Tıklama fabrika/kasaba/kare konumunda yeni bir pencerede görünüm açar # Goal question window -STR_GOAL_QUESTION_CAPTION_QUESTION :Soru -STR_GOAL_QUESTION_CAPTION_INFORMATION :Bilgi -STR_GOAL_QUESTION_CAPTION_WARNING :Uyarı -STR_GOAL_QUESTION_CAPTION_ERROR :Hata +STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}Soru +STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}Bilgi +STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}Uyarı +STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}Hata ############ Start of Goal Question button list STR_GOAL_QUESTION_BUTTON_CANCEL :İptal @@ -3286,6 +3437,8 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Binayı STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Şirket değerinin %1'i karşılığında binanın yerini değiştir. Shift+tıklama şirket binasının yerini değiştirmeden tahmini maliyeti gösterir STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Ayrıntılar STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Ayrıntılı altyapı sayılarını göster +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Para ver +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Bu şirkete para ver STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}Yeni Surat STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Müdür için yeni surat seç @@ -3303,6 +3456,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}Şirketi STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :Şirketin ismi STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :Yöneticinin ismi +STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :Vermek istediğin para miktarını gir STR_BUY_COMPANY_MESSAGE :{WHITE}Şirketimizi satın alacak birilerini arıyoruz.{}{} {COMPANY} şirketini şu fiyata almak ister misiniz: {CURRENCY_LONG}? @@ -3457,6 +3611,7 @@ STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Güç Ve STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Dönüştürülebildiği kargolar: {GOLD}{STRING} STR_PURCHASE_INFO_ALL_TYPES :Tüm kargo türleri STR_PURCHASE_INFO_NONE :Hiçbiri +STR_PURCHASE_INFO_ENGINES_ONLY :Yalnızca lokomotifler STR_PURCHASE_INFO_ALL_BUT :Şunlar hariç tümü: {CARGO_LIST} STR_PURCHASE_INFO_MAX_TE :{BLACK}Aza. Çekim Gücü: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Menzil: {GOLD}{COMMA} kare @@ -3663,6 +3818,10 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Otomatik # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Ana görünümü trenin konumuna ortalar. Çift tık ana görünümdeki treni takip eder. Ctrl+Sol Tık trenin konumunu gösteren yeni bir pencere açar +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Ana görünümü aracın konumuna ortalayın. Çift tık ana görünümdeki aracı takip eder. Ctrl+Sol Tık uçağın konumunda yeni bir görünüm penceresi açar +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Ana görünümü geminin konumuna ortalar. Çift tık ana görünümdeki gemiyi takip eder. Ctrl+Sol Tık geminin konumunu gösteren yeni bir pencere açar +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Ana görünümü uçağın konumuna ortalayın. Çift tık ana görünümdeki uçağı takip eder. Ctrl+Sol Tık uçağın konumunda yeni bir görünüm penceresi açar STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Treni garaja gönder STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Aracı garaja gönder @@ -3694,7 +3853,12 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Karayolu STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Gemi ayrıntılarını göster STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Uçak ayrıntılarını göster +STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Şu anki tren eylemi - treni durdurup/başlatmak için tıkla +STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Şu anki araç eylemi - aracı durdurup/başlatmak için tıkla +STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Şu anki gemi eylemi - gemiyi durdurup/başlatmak için tıkla +STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Şu anki uçak eylemi - uçağı durdurup/başlatmak için tıkla +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Ana görünümü talimatın konumuna ortalar. Ctrl+Sol Tık ile talimatın konumunda yeni bir pencere açar # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Yükleme / Boşaltma @@ -3922,6 +4086,7 @@ STR_ORDER_REFIT_STOP_ORDER :(Kargo türün STR_ORDER_STOP_ORDER :(Dur) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} +STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(İstasyon kullanılamıyor){POP_COLOUR} {STRING} {STATION} {STRING} STR_ORDER_IMPLICIT :(Otomatik) @@ -4194,6 +4359,7 @@ STR_WARNING_FALLBACK_SOUNDSET :{WHITE}Yalnız STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}Dev ekran görüntüsü STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}Ekran görüntüsünün çözünürlüğü {COMMA} x {COMMA} piksel. Görüntüyü kaydetmek biraz zaman alabilir. Devam etmek istiyor musunuz? +STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY :{WHITE}Yükseklik haritası başarıyla '{STRING}' olarak kaydedildi. En yüksek tepe: {NUM} STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}Ekran görüntüsü '{STRING}' olarak kaydedildi STR_ERROR_SCREENSHOT_FAILED :{WHITE}Ekran görüntüsü alınamadı! @@ -4247,6 +4413,7 @@ STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... öde STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} gerekli STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Kredi ödenemiyor... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Bankadan borç alınan para verilemez... +STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Bu şirkete para veremezsin... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Şirket satın alınamaz... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Şirket binasi yapılamaz... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Şirketin %25'i alınamıyor... @@ -4373,6 +4540,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Yanlış gar t STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} değiştirmeden sonra çok uzun oldu STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}Hiçbir otomatik değiştirme/yenileme kuralı uygulanmadı STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(para yetmedi) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}Yeni araçlar bunu taşıyamıyor {STRING} +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}{NUM} numaralı talimattaki yeni araç yenilenemez. # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}İmkansiz ray birleşimi @@ -4664,10 +4833,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Şeker Madeni ##id 0x6000 STR_SV_EMPTY : STR_SV_UNNAMED :İsimsiz -STR_SV_TRAIN_NAME :Tren {COMMA} -STR_SV_ROAD_VEHICLE_NAME :Karayolu Aracı {COMMA} -STR_SV_SHIP_NAME :Gemi {COMMA} -STR_SV_AIRCRAFT_NAME :Uçak {COMMA} +STR_SV_TRAIN_NAME :Tren #{COMMA} +STR_SV_ROAD_VEHICLE_NAME :Karayolu Aracı #{COMMA} +STR_SV_SHIP_NAME :Gemi #{COMMA} +STR_SV_AIRCRAFT_NAME :Uçak #{COMMA} STR_SV_STNAME :{STRING} STR_SV_STNAME_NORTH :{STRING} Kuzey @@ -4969,6 +5138,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Şamand STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Şamandırası #{COMMA} STR_FORMAT_COMPANY_NUM :(Company {COMMA}) STR_FORMAT_GROUP_NAME :Grup {COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING.tamlanan} STR_FORMAT_WAYPOINT_NAME :Yerimi {TOWN} STR_FORMAT_WAYPOINT_NAME_SERIAL :Yerimi {TOWN} #{COMMA} From ba193f2e23ce82cdfca37771147848751c6993e1 Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 12 May 2021 21:35:48 +0100 Subject: [PATCH 156/800] Fix #9186: Fix incorrect bounding box height causing station sprite glitch. (#9187) Increased height of small station building bounding box to cover the build rather than just the platform. --- src/table/station_land.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/table/station_land.h b/src/table/station_land.h index 8429914f32..53a69e1e21 100644 --- a/src/table/station_land.h +++ b/src/table/station_land.h @@ -71,13 +71,13 @@ static const DrawTileSeqStruct _station_display_datas_1[] = { }; static const DrawTileSeqStruct _station_display_datas_2[] = { - TILE_SEQ_LINE( 0, 0, 0, 16, 5, 2, SPR_RAIL_PLATFORM_BUILDING_X | (1U << PALETTE_MODIFIER_COLOUR)) + TILE_SEQ_LINE( 0, 0, 0, 16, 5, 15, SPR_RAIL_PLATFORM_BUILDING_X | (1U << PALETTE_MODIFIER_COLOUR)) TILE_SEQ_LINE( 0, 11, 0, 16, 5, 2, SPR_RAIL_PLATFORM_X_FRONT | (1U << PALETTE_MODIFIER_COLOUR)) TILE_SEQ_END() }; static const DrawTileSeqStruct _station_display_datas_3[] = { - TILE_SEQ_LINE( 0, 0, 0, 5, 16, 2, SPR_RAIL_PLATFORM_BUILDING_Y | (1U << PALETTE_MODIFIER_COLOUR)) + TILE_SEQ_LINE( 0, 0, 0, 5, 16, 15, SPR_RAIL_PLATFORM_BUILDING_Y | (1U << PALETTE_MODIFIER_COLOUR)) TILE_SEQ_LINE(11, 0, 0, 5, 16, 2, SPR_RAIL_PLATFORM_Y_FRONT | (1U << PALETTE_MODIFIER_COLOUR)) TILE_SEQ_END() }; From 95abdfdef9c9c79e79cb3f32bc54aec66e224d7e Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 9 May 2021 16:20:38 +0200 Subject: [PATCH 157/800] Cleanup: remove unneeded labels and gotos. The window list supports deletion of arbitrary windows, while iterating over it. --- src/window.cpp | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index 3fcda7d42d..d6901bd97a 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1168,14 +1168,10 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) */ void DeleteWindowByClass(WindowClass cls) { -restart_search: - /* When we find the window to delete, we need to restart the search - * as deleting this window could cascade in deleting (many) others - * anywhere in the z-array */ + /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::IterateFromBack()) { if (w->window_class == cls) { delete w; - goto restart_search; } } } @@ -1188,14 +1184,10 @@ restart_search: */ void DeleteCompanyWindows(CompanyID id) { -restart_search: - /* When we find the window to delete, we need to restart the search - * as deleting this window could cascade in deleting (many) others - * anywhere in the z-array */ + /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::IterateFromBack()) { if (w->owner == id) { delete w; - goto restart_search; } } @@ -3325,10 +3317,7 @@ void CallWindowGameTickEvent() */ void DeleteNonVitalWindows() { -restart_search: - /* When we find the window to delete, we need to restart the search - * as deleting this window could cascade in deleting (many) others - * anywhere in the z-array */ + /* Note: the container remains stable, even when deleting windows. */ for (const Window *w : Window::IterateFromBack()) { if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_SELECT_GAME && @@ -3338,7 +3327,6 @@ restart_search: (w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned' delete w; - goto restart_search; } } } @@ -3355,14 +3343,10 @@ void DeleteAllNonVitalWindows() /* Delete every window except for stickied ones, then sticky ones as well */ DeleteNonVitalWindows(); -restart_search: - /* When we find the window to delete, we need to restart the search - * as deleting this window could cascade in deleting (many) others - * anywhere in the z-array */ + /* Note: the container remains stable, even when deleting windows. */ for (const Window *w : Window::IterateFromBack()) { if (w->flags & WF_STICKY) { delete w; - goto restart_search; } } } @@ -3384,14 +3368,10 @@ void DeleteAllMessages() */ void DeleteConstructionWindows() { -restart_search: - /* When we find the window to delete, we need to restart the search - * as deleting this window could cascade in deleting (many) others - * anywhere in the z-array */ + /* Note: the container remains stable, even when deleting windows. */ for (const Window *w : Window::IterateFromBack()) { if (w->window_desc->flags & WDF_CONSTRUCTION) { delete w; - goto restart_search; } } From aba239479b6e75990cc914331bd2d735b8918628 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 9 May 2021 18:35:49 +0200 Subject: [PATCH 158/800] Codechange: remove excessive templating in favour of a single const_cast. The const_cast will be removed again in a later commit. --- src/window_gui.h | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/window_gui.h b/src/window_gui.h index 66c867a547..cf4ebcf73b 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -813,65 +813,59 @@ public: /** * Iterator to iterate all valid Windows - * @tparam T Type of the class/struct that is going to be iterated * @tparam Tfront Wether we iterate from front */ - template + template struct WindowIterator { - typedef T value_type; - typedef T *pointer; - typedef T &reference; + typedef Window *value_type; + typedef value_type *pointer; + typedef value_type &reference; typedef size_t difference_type; typedef std::forward_iterator_tag iterator_category; - explicit WindowIterator(T *start) : w(start) + explicit WindowIterator(const Window *start) : w(const_cast(start)) { this->Validate(); } bool operator==(const WindowIterator &other) const { return this->w == other.w; } bool operator!=(const WindowIterator &other) const { return !(*this == other); } - T * operator*() const { return this->w; } + Window * operator*() const { return this->w; } WindowIterator & operator++() { this->Next(); this->Validate(); return *this; } private: - T *w; + Window *w; void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); } void Next() { if (this->w != nullptr) this->w = Tfront ? this->w->z_back : this->w->z_front; } }; /** * Iterable ensemble of all valid Windows - * @tparam T Type of the class/struct that is going to be iterated * @tparam Tfront Wether we iterate from front */ - template + template struct Iterate { - Iterate(T *from) : from(from) {} - WindowIterator begin() { return WindowIterator(this->from); } - WindowIterator end() { return WindowIterator(nullptr); } + Iterate(const Window *from) : from(from) {} + WindowIterator begin() { return WindowIterator(this->from); } + WindowIterator end() { return WindowIterator(nullptr); } bool empty() { return this->begin() == this->end(); } private: - T *from; + const Window *from; }; /** * Returns an iterable ensemble of all valid Window from back to front - * @tparam T Type of the class/struct that is going to be iterated * @param from index of the first Window to consider * @return an iterable ensemble of all valid Window */ - template - static Iterate IterateFromBack(T *from = _z_back_window) { return Iterate(from); } + static Iterate IterateFromBack(const Window *from = _z_back_window) { return Iterate(from); } /** * Returns an iterable ensemble of all valid Window from front to back - * @tparam T Type of the class/struct that is going to be iterated * @param from index of the first Window to consider * @return an iterable ensemble of all valid Window */ - template - static Iterate IterateFromFront(T *from = _z_front_window) { return Iterate(from); } + static Iterate IterateFromFront(const Window *from = _z_front_window) { return Iterate(from); } }; /** From 22567a1f43d29a7596b9ef88441d5a65776fa2c8 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 9 May 2021 16:42:36 +0200 Subject: [PATCH 159/800] Codechange: use iterators instead of 'subranges' when iterating from a specific window. Using iterators makes it easier to include or exclude the start window in the iteration. --- src/viewport.cpp | 27 ++++++++++++++++----------- src/window.cpp | 10 ++++++++-- src/window_gui.h | 29 +++++++++-------------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index 303e027600..3e4c2d273f 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -266,35 +266,36 @@ void InitializeWindowViewport(Window *w, int x, int y, static Point _vp_move_offs; -static void DoSetViewportPosition(const Window *w, int left, int top, int width, int height) +static void DoSetViewportPosition(Window::IteratorToFront it, int left, int top, int width, int height) { - for (const Window *w : Window::IterateFromBack(w)) { + for (; !it.IsEnd(); ++it) { + const Window *w = *it; if (left + width > w->left && w->left + w->width > left && top + height > w->top && w->top + w->height > top) { if (left < w->left) { - DoSetViewportPosition(w, left, top, w->left - left, height); - DoSetViewportPosition(w, left + (w->left - left), top, width - (w->left - left), height); + DoSetViewportPosition(it, left, top, w->left - left, height); + DoSetViewportPosition(it, left + (w->left - left), top, width - (w->left - left), height); return; } if (left + width > w->left + w->width) { - DoSetViewportPosition(w, left, top, (w->left + w->width - left), height); - DoSetViewportPosition(w, left + (w->left + w->width - left), top, width - (w->left + w->width - left), height); + DoSetViewportPosition(it, left, top, (w->left + w->width - left), height); + DoSetViewportPosition(it, left + (w->left + w->width - left), top, width - (w->left + w->width - left), height); return; } if (top < w->top) { - DoSetViewportPosition(w, left, top, width, (w->top - top)); - DoSetViewportPosition(w, left, top + (w->top - top), width, height - (w->top - top)); + DoSetViewportPosition(it, left, top, width, (w->top - top)); + DoSetViewportPosition(it, left, top + (w->top - top), width, height - (w->top - top)); return; } if (top + height > w->top + w->height) { - DoSetViewportPosition(w, left, top, width, (w->top + w->height - top)); - DoSetViewportPosition(w, left, top + (w->top + w->height - top), width, height - (w->top + w->height - top)); + DoSetViewportPosition(it, left, top, width, (w->top + w->height - top)); + DoSetViewportPosition(it, left, top + (w->top + w->height - top), width, height - (w->top + w->height - top)); return; } @@ -380,7 +381,11 @@ static void SetViewportPosition(Window *w, int x, int y) i = top + height - _screen.height; if (i >= 0) height -= i; - if (height > 0) DoSetViewportPosition(w->z_front, left, top, width, height); + if (height > 0) { + Window::IteratorToFront it(w); + ++it; + DoSetViewportPosition(it, left, top, width, height); + } } } diff --git a/src/window.cpp b/src/window.cpp index d6901bd97a..9b51eafd8a 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -896,7 +896,10 @@ static bool MayBeShown(const Window *w) */ static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom) { - for (const Window *v : Window::IterateFromBack(w->z_front)) { + Window::IteratorToFront it(w); + ++it; + for (; !it.IsEnd(); ++it) { + const Window *v = *it; if (MayBeShown(v) && right > v->left && bottom > v->top && @@ -2530,7 +2533,10 @@ static bool MaybeBringWindowToFront(Window *w) w_height = w->unshaded_size.height; } - for (Window *u : Window::IterateFromBack(w->z_front)) { + Window::IteratorToFront it(w); + ++it; + for (; !it.IsEnd(); ++it) { + Window *u = *it; /* A modal child will prevent the activation of the parent window */ if (u->parent == w && (u->window_desc->flags & WDF_MODAL)) { u->SetWhiteBorder(); diff --git a/src/window_gui.h b/src/window_gui.h index cf4ebcf73b..7f7ab2667e 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -833,39 +833,28 @@ public: Window * operator*() const { return this->w; } WindowIterator & operator++() { this->Next(); this->Validate(); return *this; } + bool IsEnd() const { return this->w == nullptr; } + private: Window *w; void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); } void Next() { if (this->w != nullptr) this->w = Tfront ? this->w->z_back : this->w->z_front; } }; + using IteratorToFront = WindowIterator; //!< Iterate in Z order towards front. + using IteratorToBack = WindowIterator; //!< Iterate in Z order towards back. /** * Iterable ensemble of all valid Windows * @tparam Tfront Wether we iterate from front */ template - struct Iterate { - Iterate(const Window *from) : from(from) {} - WindowIterator begin() { return WindowIterator(this->from); } + struct AllWindows { + AllWindows() {} + WindowIterator begin() { return WindowIterator(Tfront ? _z_front_window : _z_back_window); } WindowIterator end() { return WindowIterator(nullptr); } - bool empty() { return this->begin() == this->end(); } - private: - const Window *from; }; - - /** - * Returns an iterable ensemble of all valid Window from back to front - * @param from index of the first Window to consider - * @return an iterable ensemble of all valid Window - */ - static Iterate IterateFromBack(const Window *from = _z_back_window) { return Iterate(from); } - - /** - * Returns an iterable ensemble of all valid Window from front to back - * @param from index of the first Window to consider - * @return an iterable ensemble of all valid Window - */ - static Iterate IterateFromFront(const Window *from = _z_front_window) { return Iterate(from); } + using IterateFromBack = AllWindows; //!< Iterate all windows in Z order from back to front. + using IterateFromFront = AllWindows; //!< Iterate all windows in Z order from front to back. }; /** From f96f11395162a8d57f5fdcef18c7a64f7acf76f8 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 9 May 2021 17:10:07 +0200 Subject: [PATCH 160/800] Codechange: use IterateFromBack/Front only if the order is important. Use Iterate if the order does not matter. --- src/misc_gui.cpp | 2 +- src/sound.cpp | 1 + src/viewport.cpp | 6 ++-- src/widgets/dropdown.cpp | 2 +- src/window.cpp | 68 ++++++++++++++++++++-------------------- src/window_gui.h | 1 + 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index a40bf50139..3094d0eade 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -1289,7 +1289,7 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback { if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0); - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue; const QueryWindow *qw = (const QueryWindow *)w; diff --git a/src/sound.cpp b/src/sound.cpp index 413c70af2a..c22e044372 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -245,6 +245,7 @@ static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, in { if (_settings_client.music.effect_vol == 0) return; + /* Iterate from back, so that main viewport is checked first */ for (const Window *w : Window::IterateFromBack()) { const Viewport *vp = w->viewport; diff --git a/src/viewport.cpp b/src/viewport.cpp index 3e4c2d273f..4344eac2a3 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1480,7 +1480,7 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const zoomlevels[zoom].bottom = this->top + ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM + 1, zoom); } - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { Viewport *vp = w->viewport; if (vp != nullptr && vp->zoom <= maxzoom) { assert(vp->width != 0); @@ -1953,7 +1953,7 @@ bool MarkAllViewportsDirty(int left, int top, int right, int bottom) { bool dirty = false; - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { Viewport *vp = w->viewport; if (vp != nullptr) { assert(vp->width != 0); @@ -1966,7 +1966,7 @@ bool MarkAllViewportsDirty(int left, int top, int right, int bottom) void ConstrainAllViewportsZoom() { - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { if (w->viewport == nullptr) continue; ZoomLevel zoom = static_cast(Clamp(w->viewport->zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max)); diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index b6f7de3c18..a4bd002593 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -501,7 +501,7 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt */ int HideDropDownMenu(Window *pw) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class != WC_DROPDOWN_MENU) continue; DropdownWindow *dw = dynamic_cast(w); diff --git a/src/window.cpp b/src/window.cpp index 9b51eafd8a..54671f90bc 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1055,7 +1055,7 @@ void Window::SetShaded(bool make_shaded) */ static Window *FindChildWindow(const Window *w, WindowClass wc) { - for (Window *v : Window::IterateFromBack()) { + for (Window *v : Window::Iterate()) { if ((wc == WC_INVALID || wc == v->window_class) && v->parent == w) return v; } @@ -1129,7 +1129,7 @@ Window::~Window() */ Window *FindWindowById(WindowClass cls, WindowNumber number) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls && w->window_number == number) return w; } @@ -1144,7 +1144,7 @@ Window *FindWindowById(WindowClass cls, WindowNumber number) */ Window *FindWindowByClass(WindowClass cls) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls) return w; } @@ -1172,7 +1172,7 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) void DeleteWindowByClass(WindowClass cls) { /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls) { delete w; } @@ -1188,7 +1188,7 @@ void DeleteWindowByClass(WindowClass cls) void DeleteCompanyWindows(CompanyID id) { /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->owner == id) { delete w; } @@ -1207,7 +1207,7 @@ void DeleteCompanyWindows(CompanyID id) */ void ChangeWindowOwner(Owner old_owner, Owner new_owner) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->owner != old_owner) continue; switch (w->window_class) { @@ -1576,7 +1576,7 @@ static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolb if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false; /* Make sure it is not obscured by any window. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (right > w->left && @@ -1621,7 +1621,7 @@ static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolb if (top < toolbar_y || top > _screen.height - (height >> 2)) return false; /* Make sure it is not obscured by any window. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (left + width > w->left && @@ -1658,7 +1658,7 @@ static Point GetAutoPlacePosition(int width, int height) * The new window must be entirely on-screen, and not overlap with an existing window. * Eight starting points are tried, two at each corner. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (IsGoodAutoPlace1(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; @@ -1675,7 +1675,7 @@ static Point GetAutoPlacePosition(int width, int height) * The new window may be partly off-screen, and must not overlap with an existing window. * Only four starting points are tried. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == WC_MAIN_WINDOW) continue; if (IsGoodAutoPlace2(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; @@ -1692,7 +1692,7 @@ static Point GetAutoPlacePosition(int width, int height) int offset_y = std::max(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM); restart: - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->left == left && w->top == top) { left += offset_x; top += offset_y; @@ -1896,7 +1896,7 @@ void UnInitWindowSystem() { UnshowCriticalError(); - for (Window *w : Window::IterateFromFront()) delete w; + for (Window *w : Window::Iterate()) delete w; for (Window *w = _z_front_window; w != nullptr; /* nothing */) { Window *to_del = w; @@ -1925,7 +1925,7 @@ static void DecreaseWindowCounters() if (_scroller_click_timeout != 0) _scroller_click_timeout--; if (hundredth_tick_timeout != 0) hundredth_tick_timeout--; - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { if (!_network_dedicated && hundredth_tick_timeout == 0) w->OnHundredthTick(); if (_scroller_click_timeout == 0) { @@ -1951,7 +1951,7 @@ static void DecreaseWindowCounters() w->OnMouseLoop(); } - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { if ((w->flags & WF_TIMEOUT) && --w->timeout_timer == 0) { CLRBITS(w->flags, WF_TIMEOUT); @@ -2190,7 +2190,7 @@ static EventState HandleWindowDragging() if (_left_button_down && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; /* Otherwise find the window... */ - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->flags & WF_DRAGGING) { /* Stop the dragging if the left mouse button was released */ if (!_left_button_down) { @@ -2210,7 +2210,7 @@ static EventState HandleWindowDragging() int vsnap = _settings_client.gui.window_snap_radius; int delta; - for (const Window *v : Window::IterateFromBack()) { + for (const Window *v : Window::Iterate()) { if (v == w) continue; // Don't snap at yourself if (y + w->height > v->top && y < v->top + v->height) { @@ -2423,7 +2423,7 @@ static void HandleScrollbarScrolling(Window *w) */ static EventState HandleActiveWidget() { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->mouse_capture_widget >= 0) { /* Abort if no button is clicked any more. */ if (!_left_button_down) { @@ -3095,7 +3095,7 @@ void InputLoop() */ void CallWindowRealtimeTickEvent(uint delta_ms) { - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { w->OnRealtimeTick(delta_ms); } } @@ -3124,7 +3124,7 @@ void UpdateWindows() } /* Process invalidations before anything else. */ - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { w->ProcessScheduledInvalidations(); w->ProcessHighlightedInvalidations(); } @@ -3157,7 +3157,7 @@ void UpdateWindows() if (window_timer.HasElapsed()) { window_timer.SetInterval(MILLISECONDS_PER_TICK); - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { if ((w->flags & WF_WHITE_BORDER) && --w->white_border_timer == 0) { CLRBITS(w->flags, WF_WHITE_BORDER); w->SetDirty(); @@ -3167,7 +3167,7 @@ void UpdateWindows() DrawDirtyBlocks(); - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { /* Update viewport only if window is not shaded. */ if (w->viewport != nullptr && !w->IsShaded()) UpdateViewportPosition(w); } @@ -3183,7 +3183,7 @@ void UpdateWindows() */ void SetWindowDirty(WindowClass cls, WindowNumber number) { - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == cls && w->window_number == number) w->SetDirty(); } } @@ -3196,7 +3196,7 @@ void SetWindowDirty(WindowClass cls, WindowNumber number) */ void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index) { - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == cls && w->window_number == number) { w->SetWidgetDirty(widget_index); } @@ -3209,7 +3209,7 @@ void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_inde */ void SetWindowClassesDirty(WindowClass cls) { - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class == cls) w->SetDirty(); } } @@ -3281,7 +3281,7 @@ void Window::ProcessHighlightedInvalidations() */ void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls && w->window_number == number) { w->InvalidateData(data, gui_scope); } @@ -3298,7 +3298,7 @@ void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool g */ void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope) { - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls) { w->InvalidateData(data, gui_scope); } @@ -3310,7 +3310,7 @@ void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope) */ void CallWindowGameTickEvent() { - for (Window *w : Window::IterateFromFront()) { + for (Window *w : Window::Iterate()) { w->OnGameTick(); } } @@ -3324,7 +3324,7 @@ void CallWindowGameTickEvent() void DeleteNonVitalWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_SELECT_GAME && w->window_class != WC_MAIN_TOOLBAR && @@ -3350,7 +3350,7 @@ void DeleteAllNonVitalWindows() DeleteNonVitalWindows(); /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->flags & WF_STICKY) { delete w; } @@ -3375,13 +3375,13 @@ void DeleteAllMessages() void DeleteConstructionWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->window_desc->flags & WDF_CONSTRUCTION) { delete w; } } - for (const Window *w : Window::IterateFromBack()) w->SetDirty(); + for (const Window *w : Window::Iterate()) w->SetDirty(); } /** Delete all always on-top windows to get an empty screen */ @@ -3400,7 +3400,7 @@ void ReInitAllWindows(bool zoom_changed) extern void InitDepotWindowBlockSizes(); InitDepotWindowBlockSizes(); - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { if (zoom_changed) w->nested_root->AdjustPaddingForZoom(); w->ReInit(); } @@ -3490,7 +3490,7 @@ int PositionNetworkChatWindow(Window *w) */ void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index) { - for (const Window *w : Window::IterateFromBack()) { + for (const Window *w : Window::Iterate()) { if (w->viewport != nullptr && w->viewport->follow_vehicle == from_index) { w->viewport->follow_vehicle = to_index; w->SetDirty(); @@ -3508,7 +3508,7 @@ void RelocateAllWindows(int neww, int newh) { DeleteWindowById(WC_DROPDOWN_MENU, 0); - for (Window *w : Window::IterateFromBack()) { + for (Window *w : Window::Iterate()) { int left, top; /* XXX - this probably needs something more sane. For example specifying * in a 'backup'-desc that the window should always be centered. */ diff --git a/src/window_gui.h b/src/window_gui.h index 7f7ab2667e..2b7c693674 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -853,6 +853,7 @@ public: WindowIterator begin() { return WindowIterator(Tfront ? _z_front_window : _z_back_window); } WindowIterator end() { return WindowIterator(nullptr); } }; + using Iterate = AllWindows; //!< Iterate all windows in whatever order is easiest. using IterateFromBack = AllWindows; //!< Iterate all windows in Z order from back to front. using IterateFromFront = AllWindows; //!< Iterate all windows in Z order from front to back. }; From f6d5c0136e5ac130fd887daf1b07c13a160c7fc3 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 9 May 2021 17:12:34 +0200 Subject: [PATCH 161/800] Codechange: make Window destruction not rely on undefined behavior. --- src/window.cpp | 136 +++++++++-------------------------------------- src/window_gui.h | 67 +++++++++++++---------- 2 files changed, 63 insertions(+), 140 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index 54671f90bc..af47214454 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -53,10 +53,8 @@ static Point _drag_delta; ///< delta between mouse cursor and upper left corner static Window *_mouseover_last_w = nullptr; ///< Window of the last OnMouseOver event. static Window *_last_scroll_window = nullptr; ///< Window of the last scroll event. -/** List of windows opened at the screen sorted from the front. */ -Window *_z_front_window = nullptr; -/** List of windows opened at the screen sorted from the back. */ -Window *_z_back_window = nullptr; +/** List of windows opened at the screen sorted from the front to back. */ +WindowList _z_windows; /** If false, highlight is white, otherwise the by the widget defined colour. */ bool _window_highlight_colour = false; @@ -1109,16 +1107,7 @@ Window::~Window() free(this->nested_array); // Contents is released through deletion of #nested_root. delete this->nested_root; - /* - * Make fairly sure that this is written, and not "optimized" away. - * The delete operator is overwritten to not delete it; the deletion - * happens at a later moment in time after the window has been - * removed from the list of windows to prevent issues with items - * being removed during the iteration as not one but more windows - * may be removed by a single call to ~Window by means of the - * DeleteChildWindows function. - */ - const_cast(this->window_class) = WC_INVALID; + *this->z_position = nullptr; } /** @@ -1231,7 +1220,7 @@ void ChangeWindowOwner(Owner old_owner, Owner new_owner) } } -static void BringWindowToFront(Window *w); +static void BringWindowToFront(Window *w, bool dirty = true); /** * Find a window and make it the relative top-window on the screen. @@ -1351,90 +1340,23 @@ static uint GetWindowZPriority(WindowClass wc) } } -/** - * Adds a window to the z-ordering, according to its z-priority. - * @param w Window to add - */ -static void AddWindowToZOrdering(Window *w) -{ - assert(w->z_front == nullptr && w->z_back == nullptr); - - if (_z_front_window == nullptr) { - /* It's the only window. */ - _z_front_window = _z_back_window = w; - w->z_front = w->z_back = nullptr; - } else { - /* Search down the z-ordering for its location. */ - Window *v = _z_front_window; - uint last_z_priority = UINT_MAX; - (void)last_z_priority; // Unused without asserts - while (v != nullptr && (v->window_class == WC_INVALID || GetWindowZPriority(v->window_class) > GetWindowZPriority(w->window_class))) { - if (v->window_class != WC_INVALID) { - /* Sanity check z-ordering, while we're at it. */ - assert(last_z_priority >= GetWindowZPriority(v->window_class)); - last_z_priority = GetWindowZPriority(v->window_class); - } - - v = v->z_back; - } - - if (v == nullptr) { - /* It's the new back window. */ - w->z_front = _z_back_window; - w->z_back = nullptr; - _z_back_window->z_back = w; - _z_back_window = w; - } else if (v == _z_front_window) { - /* It's the new front window. */ - w->z_front = nullptr; - w->z_back = _z_front_window; - _z_front_window->z_front = w; - _z_front_window = w; - } else { - /* It's somewhere else in the z-ordering. */ - w->z_front = v->z_front; - w->z_back = v; - v->z_front->z_back = w; - v->z_front = w; - } - } -} - - -/** - * Removes a window from the z-ordering. - * @param w Window to remove - */ -static void RemoveWindowFromZOrdering(Window *w) -{ - if (w->z_front == nullptr) { - assert(_z_front_window == w); - _z_front_window = w->z_back; - } else { - w->z_front->z_back = w->z_back; - } - - if (w->z_back == nullptr) { - assert(_z_back_window == w); - _z_back_window = w->z_front; - } else { - w->z_back->z_front = w->z_front; - } - - w->z_front = w->z_back = nullptr; -} - /** * On clicking on a window, make it the frontmost window of all windows with an equal * or lower z-priority. The window is marked dirty for a repaint * @param w window that is put into the relative foreground + * @param dirty whether to mark the window dirty */ -static void BringWindowToFront(Window *w) +static void BringWindowToFront(Window *w, bool dirty) { - RemoveWindowFromZOrdering(w); - AddWindowToZOrdering(w); + auto priority = GetWindowZPriority(w->window_class); + WindowList::iterator dest = _z_windows.begin(); + while (dest != _z_windows.end() && (*dest == nullptr || GetWindowZPriority((*dest)->window_class) <= priority)) ++dest; - w->SetDirty(); + if (dest != w->z_position) { + _z_windows.splice(dest, _z_windows, w->z_position); + } + + if (dirty) w->SetDirty(); } /** @@ -1476,7 +1398,7 @@ void Window::InitializeData(WindowNumber window_number) if (!EditBoxInGlobalFocus() || this->nested_root->GetWidgetOfType(WWT_EDITBOX) != nullptr) SetFocusedWindow(this); /* Insert the window into the correct location in the z-ordering. */ - AddWindowToZOrdering(this); + BringWindowToFront(this, false); } /** @@ -1848,6 +1770,7 @@ void Window::InitNested(WindowNumber window_number) */ Window::Window(WindowDesc *desc) : window_desc(desc), mouse_capture_widget(-1) { + this->z_position = _z_windows.insert(_z_windows.end(), this); } /** @@ -1875,8 +1798,6 @@ void InitWindowSystem() { IConsoleClose(); - _z_back_window = nullptr; - _z_front_window = nullptr; _focused_window = nullptr; _mouseover_last_w = nullptr; _last_scroll_window = nullptr; @@ -1898,14 +1819,7 @@ void UnInitWindowSystem() for (Window *w : Window::Iterate()) delete w; - for (Window *w = _z_front_window; w != nullptr; /* nothing */) { - Window *to_del = w; - w = w->z_back; - free(to_del); - } - - _z_front_window = nullptr; - _z_back_window = nullptr; + _z_windows.clear(); } /** @@ -3068,15 +2982,13 @@ void InputLoop() CheckSoftLimit(); - /* Do the actual free of the deleted windows. */ - for (Window *v = _z_front_window; v != nullptr; /* nothing */) { - Window *w = v; - v = v->z_back; - - if (w->window_class != WC_INVALID) continue; - - RemoveWindowFromZOrdering(w); - free(w); + /* Remove dead entries from the window list */ + for (auto it = _z_windows.begin(); it != _z_windows.end(); ) { + if (*it == nullptr) { + it = _z_windows.erase(it); + } else { + ++it; + } } if (_input_events_this_tick != 0) { diff --git a/src/window_gui.h b/src/window_gui.h index 2b7c693674..1195c6c491 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -10,6 +10,8 @@ #ifndef WINDOW_GUI_H #define WINDOW_GUI_H +#include + #include "vehicle_type.h" #include "viewport_type.h" #include "company_type.h" @@ -143,8 +145,8 @@ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, Fra void DrawCaption(const Rect &r, Colours colour, Owner owner, TextColour text_colour, StringID str, StringAlignment align); /* window.cpp */ -extern Window *_z_front_window; -extern Window *_z_back_window; +using WindowList = std::list; +extern WindowList _z_windows; extern Window *_focused_window; @@ -293,19 +295,7 @@ public: * to destruct them all at the same time too, which is kinda hard. * @param size the amount of space not to allocate */ - inline void *operator new[](size_t size) - { - NOT_REACHED(); - } - - /** - * Helper allocation function to disallow something. - * Don't free the window directly; it corrupts the linked list when iterating - * @param ptr the pointer not to free - */ - inline void operator delete(void *ptr) - { - } + inline void *operator new[](size_t size) = delete; WindowDesc *window_desc; ///< Window description WindowFlags flags; ///< Window flags @@ -336,8 +326,7 @@ public: int mouse_capture_widget; ///< Widgetindex of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture. Window *parent; ///< Parent window. - Window *z_front; ///< The window in front of us in z-order. - Window *z_back; ///< The window behind us in z-order. + WindowList::iterator z_position; template inline const NWID *GetWidget(uint widnum) const; @@ -813,9 +802,9 @@ public: /** * Iterator to iterate all valid Windows - * @tparam Tfront Wether we iterate from front + * @tparam TtoBack whether we iterate towards the back. */ - template + template struct WindowIterator { typedef Window *value_type; typedef value_type *pointer; @@ -823,22 +812,35 @@ public: typedef size_t difference_type; typedef std::forward_iterator_tag iterator_category; - explicit WindowIterator(const Window *start) : w(const_cast(start)) + explicit WindowIterator(WindowList::iterator start) : it(start) { this->Validate(); } + explicit WindowIterator(const Window *w) : it(w->z_position) {} - bool operator==(const WindowIterator &other) const { return this->w == other.w; } + bool operator==(const WindowIterator &other) const { return this->it == other.it; } bool operator!=(const WindowIterator &other) const { return !(*this == other); } - Window * operator*() const { return this->w; } + Window * operator*() const { return *this->it; } WindowIterator & operator++() { this->Next(); this->Validate(); return *this; } - bool IsEnd() const { return this->w == nullptr; } + bool IsEnd() const { return this->it == _z_windows.end(); } private: - Window *w; - void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); } - void Next() { if (this->w != nullptr) this->w = Tfront ? this->w->z_back : this->w->z_front; } + WindowList::iterator it; + void Validate() + { + while (!this->IsEnd() && *this->it == nullptr) this->Next(); + } + void Next() + { + if constexpr (!TtoBack) { + ++this->it; + } else if (this->it == _z_windows.begin()) { + this->it = _z_windows.end(); + } else { + --this->it; + } + } }; using IteratorToFront = WindowIterator; //!< Iterate in Z order towards front. using IteratorToBack = WindowIterator; //!< Iterate in Z order towards back. @@ -850,8 +852,17 @@ public: template struct AllWindows { AllWindows() {} - WindowIterator begin() { return WindowIterator(Tfront ? _z_front_window : _z_back_window); } - WindowIterator end() { return WindowIterator(nullptr); } + WindowIterator begin() + { + if constexpr (Tfront) { + auto back = _z_windows.end(); + if (back != _z_windows.begin()) --back; + return WindowIterator(back); + } else { + return WindowIterator(_z_windows.begin()); + } + } + WindowIterator end() { return WindowIterator(_z_windows.end()); } }; using Iterate = AllWindows; //!< Iterate all windows in whatever order is easiest. using IterateFromBack = AllWindows; //!< Iterate all windows in Z order from back to front. From 5bd81448539b63519d70ba85d4833e446f0597fe Mon Sep 17 00:00:00 2001 From: frosch Date: Wed, 12 May 2021 23:40:03 +0200 Subject: [PATCH 162/800] Fix #9256, 12e43c697d2: invalid read after free. (#9258) This also changes ScriptEventVehicleAutoReplaced when replacing wagons: The event is now only spawned, if the head engine changes, so only if the VehicleID of the consist changes. Previously replacing wagons spawned an event with OldVehicleID==NewVehicleID. --- src/autoreplace_cmd.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index d9996bb117..d5f031aa65 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -614,6 +614,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon /* Success ! */ if ((flags & DC_EXEC) != 0 && new_head != old_head) { *chain = new_head; + AI::NewEvent(old_head->owner, new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index)); } /* Transfer cargo of old vehicles and sell them */ @@ -631,10 +632,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon cost.AddCost(DoCommand(0, w->index, 0, flags | DC_AUTOREPLACE, GetCmdSellVeh(w))); if ((flags & DC_EXEC) != 0) { old_vehs[i] = nullptr; - if (i == 0) { - AI::NewEvent(old_head->owner, new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index)); - old_head = nullptr; - } + if (i == 0) old_head = nullptr; } } From 38c97e14926f4bc538c20b24f8a3decdef1668f9 Mon Sep 17 00:00:00 2001 From: glx22 Date: Wed, 12 May 2021 16:45:28 +0200 Subject: [PATCH 163/800] Codechange: Replace TILE_AREA_LOOP with range-based for loops --- src/industry_cmd.cpp | 20 ++++++++++---------- src/newgrf_airporttiles.cpp | 2 +- src/newgrf_industrytiles.cpp | 4 ++-- src/newgrf_object.cpp | 2 +- src/newgrf_station.cpp | 6 +++--- src/object_cmd.cpp | 14 +++++++------- src/openttd.cpp | 4 ++-- src/road_gui.cpp | 2 +- src/saveload/station_sl.cpp | 2 +- src/script/api/script_industry.cpp | 4 ++-- src/script/api/script_order.cpp | 8 ++++---- src/script/api/script_tilelist.cpp | 8 ++++---- src/smallmap_gui.cpp | 2 +- src/station.cpp | 8 ++++---- src/station_base.h | 4 ++-- src/station_cmd.cpp | 24 ++++++++++++------------ src/station_gui.cpp | 4 ++-- src/subsidy.cpp | 4 ++-- src/terraform_gui.cpp | 10 +++++----- src/tilearea.cpp | 18 ++++++++++++++++++ src/tilearea_type.h | 23 +++++++++++++++-------- src/tree_cmd.cpp | 2 +- src/water_cmd.cpp | 2 +- 23 files changed, 101 insertions(+), 76 deletions(-) diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index f9e75ed880..5bd2a3dc27 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -149,7 +149,7 @@ Industry::~Industry() const bool has_neutral_station = this->neutral_station != nullptr; - TILE_AREA_LOOP(tile_cur, this->location) { + for (TileIndex tile_cur : this->location) { if (IsTileType(tile_cur, MP_INDUSTRY)) { if (GetIndustryIndex(tile_cur) == this->index) { DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur); @@ -164,7 +164,7 @@ Industry::~Industry() if (has_neutral_station) { /* Remove possible docking tiles */ - TILE_AREA_LOOP(tile_cur, this->location) { + for (TileIndex tile_cur : this->location) { ClearDockingTilesCheckingNeighbours(tile_cur); } } @@ -173,7 +173,7 @@ Industry::~Industry() TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21); /* Remove the farmland and convert it to regular tiles over time. */ - TILE_AREA_LOOP(tile_cur, ta) { + for (TileIndex tile_cur : ta) { if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) && GetIndustryIndexOfField(tile_cur) == this->index) { SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY); @@ -1041,7 +1041,7 @@ static void PlantFarmField(TileIndex tile, IndustryID industry) /* check the amount of bad tiles */ int count = 0; - TILE_AREA_LOOP(cur_tile, ta) { + for (TileIndex cur_tile : ta) { assert(cur_tile < MapSize()); count += IsSuitableForFarmField(cur_tile, false); } @@ -1053,7 +1053,7 @@ static void PlantFarmField(TileIndex tile, IndustryID industry) uint field_type = GB(r, 8, 8) * 9 >> 8; /* make field */ - TILE_AREA_LOOP(cur_tile, ta) { + for (TileIndex cur_tile : ta) { assert(cur_tile < MapSize()); if (IsSuitableForFarmField(cur_tile, true)) { MakeField(cur_tile, field_type, industry); @@ -1115,7 +1115,7 @@ static bool SearchLumberMillTrees(TileIndex tile, void *user_data) static void ChopLumberMillTrees(Industry *i) { /* We only want to cut trees if all tiles are completed. */ - TILE_AREA_LOOP(tile_cur, i->location) { + for (TileIndex tile_cur : i->location) { if (i->TileBelongsToIndustry(tile_cur)) { if (!IsIndustryCompleted(tile_cur)) return; } @@ -1532,7 +1532,7 @@ static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int i if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false; TileArea ta(tile - TileDiffXY(1, 1), 2, 2); - TILE_AREA_LOOP(tile_walk, ta) { + for (TileIndex tile_walk : ta) { uint curh = TileHeight(tile_walk); /* Is the tile clear? */ if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false; @@ -1587,7 +1587,7 @@ static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */ Backup cur_company(_current_company, OWNER_TOWN, FILE_LINE); - TILE_AREA_LOOP(tile_walk, ta) { + for (TileIndex tile_walk : ta) { uint curh = TileHeight(tile_walk); if (curh != h) { /* This tile needs terraforming. Check if we can do that without @@ -1607,7 +1607,7 @@ static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, if (flags & DC_EXEC) { /* Terraform the land under the industry */ - TILE_AREA_LOOP(tile_walk, ta) { + for (TileIndex tile_walk : ta) { uint curh = TileHeight(tile_walk); while (curh != h) { /* We give the terraforming for free here, because we can't calculate @@ -1639,7 +1639,7 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int t if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) { const Industry* i = nullptr; TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax); - TILE_AREA_LOOP(atile, tile_area) { + for (TileIndex atile : tile_area) { if (GetTileType(atile) == MP_INDUSTRY) { const Industry *i2 = Industry::GetByTile(atile); if (i == i2) continue; diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index a437fb596a..a049064515 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -307,7 +307,7 @@ void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID { if (st->airport.tile == INVALID_TILE) return; - TILE_AREA_LOOP(tile, st->airport) { + for (TileIndex tile : st->airport) { if (st->TileBelongsToAirport(tile)) AirportTileAnimationTrigger(st, tile, trigger, cargo_type); } } diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index e9c99f6cd5..0e48d0be97 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -287,7 +287,7 @@ bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigge { bool ret = true; uint32 random = Random(); - TILE_AREA_LOOP(tile, ind->location) { + for (TileIndex tile : ind->location) { if (ind->TileBelongsToIndustry(tile)) { if (StartStopIndustryTileAnimation(tile, iat, random)) { SB(random, 0, 16, Random()); @@ -372,7 +372,7 @@ void TriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger) void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger) { uint32 reseed_industry = 0; - TILE_AREA_LOOP(tile, ind->location) { + for (TileIndex tile : ind->location) { if (ind->TileBelongsToIndustry(tile)) { DoTriggerIndustryTile(tile, trigger, ind, reseed_industry); } diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 3c069f4c95..640ac46705 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -554,7 +554,7 @@ void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const Obj { if (!HasBit(spec->animation.triggers, trigger)) return; - TILE_AREA_LOOP(tile, o->location) { + for (TileIndex tile : o->location) { TriggerObjectTileAnimation(o, tile, trigger, spec); } } diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index eff5ef2b2c..fbc6f5c600 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -737,7 +737,7 @@ void DeallocateSpecFromStation(BaseStation *st, byte specindex) ETileArea area = ETileArea(st, INVALID_TILE, TA_WHOLE); /* Check all tiles over the station to check if the specindex is still in use */ - TILE_AREA_LOOP(tile, area) { + for (TileIndex tile : area) { if (st->TileBelongsToRailStation(tile) && GetCustomStationSpecIndex(tile) == specindex) { return; } @@ -939,7 +939,7 @@ void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTr ETileArea area = ETileArea(st, tile, tas[trigger]); /* Check all tiles over the station to check if the specindex is still in use */ - TILE_AREA_LOOP(tile, area) { + for (TileIndex tile : area) { if (st->TileBelongsToRailStation(tile)) { const StationSpec *ss = GetStationSpec(tile); if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) { @@ -995,7 +995,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg uint32 used_triggers = 0; /* Check all tiles over the station to check if the specindex is still in use */ - TILE_AREA_LOOP(tile, area) { + for (TileIndex tile : area) { if (st->TileBelongsToRailStation(tile)) { const StationSpec *ss = GetStationSpec(tile); if (ss == nullptr) continue; diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 7a2ff26524..c11409d4ba 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -114,7 +114,7 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u assert(o->town != nullptr); - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { WaterClass wc = (IsWaterTile(t) ? GetWaterClass(t) : WATER_CLASS_INVALID); /* Update company infrastructure counts for objects build on canals owned by nobody. */ if (wc == WATER_CLASS_CANAL && owner != OWNER_NONE && (IsTileOwner(tile, OWNER_NONE) || IsTileOwner(tile, OWNER_WATER))) { @@ -136,7 +136,7 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u static void IncreaseAnimationStage(TileIndex tile) { TileArea ta = Object::GetByTile(tile)->location; - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { SetAnimationFrame(t, GetAnimationFrame(t) + 1); MarkTileDirtyByTile(t); } @@ -230,7 +230,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * some information about the tiles. */ bool allow_water = (spec->flags & (OBJECT_FLAG_BUILT_ON_WATER | OBJECT_FLAG_NOT_ON_LAND)) != 0; bool allow_ground = (spec->flags & OBJECT_FLAG_NOT_ON_LAND) == 0; - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { if (HasTileWaterGround(t)) { if (!allow_water) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER); if (!IsWaterTile(t)) { @@ -263,7 +263,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 int allowed_z; if (GetTileSlope(tile, &allowed_z) != SLOPE_FLAT) allowed_z++; - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { uint16 callback = CALLBACK_FAILED; if (HasBit(spec->callback_mask, CBM_OBJ_SLOPE_CHECK)) { TileIndex diff = t - tile; @@ -283,7 +283,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (flags & DC_EXEC) { /* This is basically a copy of the loop above with the exception that we now * execute the commands and don't check for errors, since that's already done. */ - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { if (HasTileWaterGround(t)) { if (!IsWaterTile(t)) { DoCommand(t, 0, 0, (flags & ~DC_NO_WATER) | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR); @@ -297,7 +297,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (cost.Failed()) return cost; /* Finally do a check for bridges. */ - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { if (IsBridgeAbove(t) && ( !(spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) || (GetTileMaxZ(t) + spec->height >= GetBridgeHeight(GetSouthernBridgeEnd(t))))) { @@ -438,7 +438,7 @@ static Foundation GetFoundation_Object(TileIndex tile, Slope tileh) static void ReallyClearObjectTile(Object *o) { Object::DecTypeCount(o->type); - TILE_AREA_LOOP(tile_cur, o->location) { + for (TileIndex tile_cur : o->location) { DeleteNewGRFInspectWindow(GSF_OBJECTS, tile_cur); MakeWaterKeepingClass(tile_cur, GetTileOwner(tile_cur)); diff --git a/src/openttd.cpp b/src/openttd.cpp index 785ba80dda..a416f531a2 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1265,7 +1265,7 @@ static void CheckCaches() /* Check docking tiles */ TileArea ta; std::map docking_tiles; - TILE_AREA_LOOP(tile, st->docking_station) { + for (TileIndex tile : st->docking_station) { ta.Add(tile); docking_tiles[tile] = IsDockingTile(tile); } @@ -1273,7 +1273,7 @@ static void CheckCaches() if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) { DEBUG(desync, 2, "station docking mismatch: station %i, company %i", st->index, (int)st->owner); } - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (docking_tiles[tile] != IsDockingTile(tile)) { DEBUG(desync, 2, "docking tile mismatch: tile %i", (int)tile); } diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 9cc68028d5..ae84404a2a 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -163,7 +163,7 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile); if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); TileArea roadstop_area(tile, GB(p1, 0, 8), GB(p1, 8, 8)); - TILE_AREA_LOOP(cur_tile, roadstop_area) { + for (TileIndex cur_tile : roadstop_area) { ConnectRoadToStructure(cur_tile, dir); /* For a drive-through road stop build connecting road for other entrance. */ if (HasBit(p2, 1)) ConnectRoadToStructure(cur_tile, ReverseDiagDir(dir)); diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index c4d157c0f4..74f3a5fb9b 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -86,7 +86,7 @@ void MoveBuoysToWaypoints() if (train) { /* When we make a rail waypoint of the station, convert the map as well. */ - TILE_AREA_LOOP(t, train_st) { + for (TileIndex t : train_st) { if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != index) continue; SB(_me[t].m6, 3, 3, STATION_WAYPOINT); diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp index 0a5ca98d35..6f54fda14c 100644 --- a/src/script/api/script_industry.cpp +++ b/src/script/api/script_industry.cpp @@ -186,7 +186,7 @@ if (!HasHeliport(industry_id)) return INVALID_TILE; const Industry *ind = ::Industry::Get(industry_id); - TILE_AREA_LOOP(tile_cur, ind->location) { + for (TileIndex tile_cur : ind->location) { if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) { return tile_cur; } @@ -208,7 +208,7 @@ if (!HasDock(industry_id)) return INVALID_TILE; const Industry *ind = ::Industry::Get(industry_id); - TILE_AREA_LOOP(tile_cur, ind->location) { + for (TileIndex tile_cur : ind->location) { if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) { return tile_cur; } diff --git a/src/script/api/script_order.cpp b/src/script/api/script_order.cpp index 5166c06144..b7bcde7307 100644 --- a/src/script/api/script_order.cpp +++ b/src/script/api/script_order.cpp @@ -256,11 +256,11 @@ static int ScriptOrderPositionToRealOrderPosition(VehicleID vehicle_id, ScriptOr case OT_GOTO_STATION: { const Station *st = ::Station::Get(order->GetDestination()); if (st->train_station.tile != INVALID_TILE) { - TILE_AREA_LOOP(t, st->train_station) { + for (TileIndex t : st->train_station) { if (st->TileBelongsToRailStation(t)) return t; } } else if (st->ship_station.tile != INVALID_TILE) { - TILE_AREA_LOOP(t, st->ship_station) { + for (TileIndex t : st->ship_station) { if (IsTileType(t, MP_STATION) && (IsDock(t) || IsOilRig(t)) && GetStationIndex(t) == st->index) return t; } } else if (st->bus_stops != nullptr) { @@ -268,7 +268,7 @@ static int ScriptOrderPositionToRealOrderPosition(VehicleID vehicle_id, ScriptOr } else if (st->truck_stops != nullptr) { return st->truck_stops->xy; } else if (st->airport.tile != INVALID_TILE) { - TILE_AREA_LOOP(tile, st->airport) { + for (TileIndex tile : st->airport) { if (st->TileBelongsToAirport(tile) && !::IsHangar(tile)) return tile; } } @@ -278,7 +278,7 @@ static int ScriptOrderPositionToRealOrderPosition(VehicleID vehicle_id, ScriptOr case OT_GOTO_WAYPOINT: { const Waypoint *wp = ::Waypoint::Get(order->GetDestination()); if (wp->train_station.tile != INVALID_TILE) { - TILE_AREA_LOOP(t, wp->train_station) { + for (TileIndex t : wp->train_station) { if (wp->TileBelongsToRailStation(t)) return t; } } diff --git a/src/script/api/script_tilelist.cpp b/src/script/api/script_tilelist.cpp index 7f4e3ca5cf..8266f46ff9 100644 --- a/src/script/api/script_tilelist.cpp +++ b/src/script/api/script_tilelist.cpp @@ -21,7 +21,7 @@ void ScriptTileList::AddRectangle(TileIndex t1, TileIndex t2) if (!::IsValidTile(t2)) return; TileArea ta(t1, t2); - TILE_AREA_LOOP(t, ta) this->AddItem(t); + for (TileIndex t : ta) this->AddItem(t); } void ScriptTileList::AddTile(TileIndex tile) @@ -37,7 +37,7 @@ void ScriptTileList::RemoveRectangle(TileIndex t1, TileIndex t2) if (!::IsValidTile(t2)) return; TileArea ta(t1, t2); - TILE_AREA_LOOP(t, ta) this->RemoveItem(t); + for (TileIndex t : ta) this->RemoveItem(t); } void ScriptTileList::RemoveTile(TileIndex tile) @@ -55,7 +55,7 @@ void ScriptTileList::RemoveTile(TileIndex tile) */ static void FillIndustryCatchment(const Industry *i, int radius, BitmapTileArea &bta) { - TILE_AREA_LOOP(cur_tile, i->location) { + for (TileIndex cur_tile : i->location) { if (!::IsTileType(cur_tile, MP_INDUSTRY) || ::GetIndustryIndex(cur_tile) != i->index) continue; int tx = TileX(cur_tile); @@ -156,7 +156,7 @@ ScriptTileList_StationType::ScriptTileList_StationType(StationID station_id, Scr if ((station_type & ScriptStation::STATION_DOCK) != 0) station_type_value |= (1 << ::STATION_DOCK) | (1 << ::STATION_OILRIG); TileArea ta(::TileXY(rect->left, rect->top), rect->right - rect->left + 1, rect->bottom - rect->top + 1); - TILE_AREA_LOOP(cur_tile, ta) { + for (TileIndex cur_tile : ta) { if (!::IsTileType(cur_tile, MP_STATION)) continue; if (::GetStationIndex(cur_tile) != station_id) continue; if (!HasBit(station_type_value, ::GetStationType(cur_tile))) continue; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index b00cf0e7a9..17d1d25cb0 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -750,7 +750,7 @@ inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const TileIndex tile = INVALID_TILE; // Position of the most important tile. TileType et = MP_VOID; // Effective tile type at that position. - TILE_AREA_LOOP(ti, ta) { + for (TileIndex ti : ta) { TileType ttype = GetTileType(ti); switch (ttype) { diff --git a/src/station.cpp b/src/station.cpp index f859495d19..8926773122 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -416,7 +416,7 @@ void Station::RecomputeCatchment() if (!_settings_game.station.serve_neutral_industries && this->industry != nullptr) { /* Station is associated with an industry, so we only need to deliver to that industry. */ this->catchment_tiles.Initialize(this->industry->location); - TILE_AREA_LOOP(tile, this->industry->location) { + for (TileIndex tile : this->industry->location) { if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == this->industry->index) { this->catchment_tiles.SetTile(tile); } @@ -435,7 +435,7 @@ void Station::RecomputeCatchment() /* Loop finding all station tiles */ TileArea ta(TileXY(this->rect.left, this->rect.top), TileXY(this->rect.right, this->rect.bottom)); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (!IsTileType(tile, MP_STATION) || GetStationIndex(tile) != this->index) continue; uint r = GetTileCatchmentRadius(tile, this); @@ -443,7 +443,7 @@ void Station::RecomputeCatchment() /* This tile sub-loop doesn't need to test any tiles, they are simply added to the catchment set. */ TileArea ta2 = TileArea(tile, 1, 1).Expand(r); - TILE_AREA_LOOP(tile2, ta2) this->catchment_tiles.SetTile(tile2); + for (TileIndex tile2 : ta2) this->catchment_tiles.SetTile(tile2); } /* Search catchment tiles for towns and industries */ @@ -567,7 +567,7 @@ CommandCost StationRect::BeforeAddRect(TileIndex tile, int w, int h, StationRect /* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a) { TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a)); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true; } diff --git a/src/station_base.h b/src/station_base.h index 4f16469766..4f79dd98c6 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -575,7 +575,7 @@ void ForAllStationsAroundTiles(const TileArea &ta, Func func) * to find the possible nearby stations. */ uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED; TileArea ta_ext = TileArea(ta).Expand(max_c); - TILE_AREA_LOOP(tile, ta_ext) { + for (TileIndex tile : ta_ext) { if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile)); } @@ -587,7 +587,7 @@ void ForAllStationsAroundTiles(const TileArea &ta, Func func) if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue; /* Test if the tile is within the station's catchment */ - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (st->TileIsInCatchment(tile)) { if (func(st, tile)) break; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 39efb710e6..eecb08d7cd 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -105,7 +105,7 @@ CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID c ta.Expand(1); /* check around to see if there are any stations there owned by the company */ - TILE_AREA_LOOP(tile_cur, ta) { + for (TileIndex tile_cur : ta) { if (IsTileType(tile_cur, MP_STATION)) { StationID t = GetStationIndex(tile_cur); if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue; @@ -511,7 +511,7 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) /* Loop over all tiles to get the produced cargo of * everything except industries */ - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsTileType(tile, MP_INDUSTRY)) industries.insert(GetIndustryIndex(tile)); AddProducedCargo(tile, produced); } @@ -549,7 +549,7 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, Cargo TileArea ta = TileArea(tile, w, h).Expand(rad); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { /* Ignore industry if it has a neutral station. */ if (!_settings_game.station.serve_neutral_industries && IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != nullptr) continue; @@ -872,7 +872,7 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index); bool slope_cb = statspec != nullptr && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK); - TILE_AREA_LOOP(tile_cur, tile_area) { + for (TileIndex tile_cur : tile_area) { CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -954,7 +954,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags CommandCost cost(EXPENSES_CONSTRUCTION); int allowed_z = -1; - TILE_AREA_LOOP(cur_tile, tile_area) { + for (TileIndex cur_tile : tile_area) { CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -1435,7 +1435,7 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 update_reservation_area = TileArea(tile_org, numtracks_orig, 1); } - TILE_AREA_LOOP(tile, update_reservation_area) { + for (TileIndex tile : update_reservation_area) { /* Don't even try to make eye candy parts reserved. */ if (IsStationTileBlocked(tile)) continue; @@ -1563,7 +1563,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st CommandCost error; /* Do the action for every tile into the area */ - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { /* Make sure the specified tile is a rail station */ if (!HasStationTileRail(tile)) continue; @@ -1729,7 +1729,7 @@ CommandCost RemoveRailStation(T *st, DoCommandFlag flags, Money removal_cost) CommandCost cost(EXPENSES_CONSTRUCTION); /* clear all areas of the station */ - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { /* only remove tiles that are actually train station tiles */ if (st->TileBelongsToRailStation(tile)) { std::vector affected_stations; // dummy @@ -1894,7 +1894,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (flags & DC_EXEC) { /* Check every tile in the area. */ - TILE_AREA_LOOP(cur_tile, roadstop_area) { + for (TileIndex cur_tile : roadstop_area) { /* Get existing road types and owners before any tile clearing */ RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE; RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE; @@ -2101,7 +2101,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION); bool had_success = false; - TILE_AREA_LOOP(cur_tile, roadstop_area) { + for (TileIndex cur_tile : roadstop_area) { /* Make sure the specified tile is a road stop of the correct type */ if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue; @@ -2409,7 +2409,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist); } - TILE_AREA_LOOP(tile_cur, st->airport) { + for (TileIndex tile_cur : st->airport) { if (!st->TileBelongsToAirport(tile_cur)) continue; CommandCost ret = EnsureNoVehicleOnGround(tile_cur); @@ -4120,7 +4120,7 @@ void UpdateStationDockingTiles(Station *st) int y1 = std::max(y - 1, 0); TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1)); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsValidTile(tile) && IsPossibleDockingTile(tile)) CheckForDockingTile(tile); } } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index cf3f455bc9..ab0eb5d1a5 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -103,7 +103,7 @@ static void FindStationsAroundSelection() Station *adjacent = nullptr; /* Direct loop instead of ForAllStationsAroundTiles as we are not interested in catchment area */ - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) { Station *st = Station::GetByTile(tile); if (st == nullptr) continue; @@ -2214,7 +2214,7 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join) _deleted_stations_nearby.clear(); /* Check the inside, to return, if we sit on another station */ - TILE_AREA_LOOP(t, ta) { + for (TileIndex t : ta) { if (t < MapSize() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return T::GetByTile(t); } diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 2668a62bd7..4cf42eb5c9 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -329,7 +329,7 @@ bool FindSubsidyTownCargoRoute() /* Calculate the produced cargo of houses around town center. */ CargoArray town_cargo_produced; TileArea ta = TileArea(src_town->xy, 1, 1).Expand(SUBSIDY_TOWN_CARGO_RADIUS); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsTileType(tile, MP_HOUSE)) { AddProducedCargo(tile, town_cargo_produced); } @@ -440,7 +440,7 @@ bool FindSubsidyCargoDestination(CargoID cid, SourceType src_type, SourceID src) /* Calculate cargo acceptance of houses around town center. */ CargoArray town_cargo_accepted; TileArea ta = TileArea(dst_town->xy, 1, 1).Expand(SUBSIDY_TOWN_CARGO_RADIUS); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { if (IsTileType(tile, MP_HOUSE)) { AddAcceptedCargo(tile, town_cargo_accepted, nullptr); } diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 84cd2eca8e..0e1896a440 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -57,7 +57,7 @@ static void GenerateDesertArea(TileIndex end, TileIndex start) _generating_world = true; TileArea ta(start, end); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { SetTropicZone(tile, (_ctrl_pressed) ? TROPICZONE_NORMAL : TROPICZONE_DESERT); DoCommandP(tile, 0, 0, CMD_LANDSCAPE_CLEAR); MarkTileDirtyByTile(tile); @@ -74,7 +74,7 @@ static void GenerateRockyArea(TileIndex end, TileIndex start) bool success = false; TileArea ta(start, end); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { switch (GetTileType(tile)) { case MP_TREES: if (GetTreeGround(tile) == TREE_GROUND_SHORE) continue; @@ -408,18 +408,18 @@ static void CommonRaiseLowerBigLand(TileIndex tile, int mode) if (mode != 0) { /* Raise land */ h = MAX_TILE_HEIGHT; - TILE_AREA_LOOP(tile2, ta) { + for (TileIndex tile2 : ta) { h = std::min(h, TileHeight(tile2)); } } else { /* Lower land */ h = 0; - TILE_AREA_LOOP(tile2, ta) { + for (TileIndex tile2 : ta) { h = std::max(h, TileHeight(tile2)); } } - TILE_AREA_LOOP(tile2, ta) { + for (TileIndex tile2 : ta) { if (TileHeight(tile2) == h) { DoCommandP(tile2, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND); } diff --git a/src/tilearea.cpp b/src/tilearea.cpp index 84ac7a90ff..21271f94f1 100644 --- a/src/tilearea.cpp +++ b/src/tilearea.cpp @@ -146,6 +146,24 @@ void OrthogonalTileArea::ClampToMap() this->h = std::min(this->h, MapSizeY() - TileY(this->tile)); } +/** + * Returns an iterator to the beginning of the tile area. + * @return The OrthogonalTileIterator. + */ +OrthogonalTileIterator OrthogonalTileArea::begin() const +{ + return OrthogonalTileIterator(*this); +} + +/** + * Returns an iterator to the end of the tile area. + * @return The OrthogonalTileIterator. + */ +OrthogonalTileIterator OrthogonalTileArea::end() const +{ + return OrthogonalTileIterator(OrthogonalTileArea()); +} + /** * Create a diagonal tile area from two corners. * @param start First corner of the area. diff --git a/src/tilearea_type.h b/src/tilearea_type.h index 2648219853..e6d9bad602 100644 --- a/src/tilearea_type.h +++ b/src/tilearea_type.h @@ -12,6 +12,8 @@ #include "map_func.h" +class OrthogonalTileIterator; + /** Represents the covered area of e.g. a rail station */ struct OrthogonalTileArea { TileIndex tile; ///< The base tile of the area @@ -58,6 +60,10 @@ struct OrthogonalTileArea { { return TILE_ADDXY(this->tile, this->w / 2, this->h / 2); } + + OrthogonalTileIterator begin() const; + + OrthogonalTileIterator end() const; }; /** Represents a diagonal tile area. */ @@ -123,6 +129,15 @@ public: return this->tile; } + /** + * Get the tile we are currently at. + * @return The tile we are at, or INVALID_TILE when we're done. + */ + inline TileIndex operator *() const + { + return this->tile; + } + /** * Move ourselves to the next tile in the rectangle on the map. */ @@ -223,12 +238,4 @@ public: } }; -/** - * A loop which iterates over the tiles of a TileArea. - * @param var The name of the variable which contains the current tile. - * This variable will be allocated in this \c for of this loop. - * @param ta The tile area to search over. - */ -#define TILE_AREA_LOOP(var, ta) for (OrthogonalTileIterator var(ta); var != INVALID_TILE; ++var) - #endif /* TILEAREA_TYPE_H */ diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index f1a5be7f90..9798c2bb56 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -392,7 +392,7 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16)); TileArea ta(tile, p2); - TILE_AREA_LOOP(tile, ta) { + for (TileIndex tile : ta) { switch (GetTileType(tile)) { case MP_TREES: /* no more space for trees? */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 731954c2eb..8c8a438a58 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -1044,7 +1044,7 @@ static void FloodVehicles(TileIndex tile) if (IsAirportTile(tile)) { const Station *st = Station::GetByTile(tile); - TILE_AREA_LOOP(tile, st->airport) { + for (TileIndex tile : st->airport) { if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc); } From d7ce61f10674567c97a1edd78ea1baf4e08153f2 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 13 May 2021 08:13:48 +0200 Subject: [PATCH 164/800] Fix #9255: [Network] TCPConnecter crashes when hostname not found (#9259) --- src/network/core/tcp.h | 16 +++++++++- src/network/core/tcp_connect.cpp | 55 ++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index 46e3af8c66..44316bfca0 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -66,8 +66,22 @@ public: */ class TCPConnecter { private: + /** + * The current status of the connecter. + * + * We track the status like this to ensure everything is executed from the + * game-thread, and not at another random time where we might not have the + * lock on the game-state. + */ + enum class Status { + INIT, ///< TCPConnecter is created but resolving hasn't started. + RESOLVING, ///< The hostname is being resolved (threaded). + FAILURE, ///< Resolving failed. + CONNECTING, ///< We are currently connecting. + }; + std::thread resolve_thread; ///< Thread used during resolving. - std::atomic is_resolved = false; ///< Whether resolving is done. + std::atomic status = Status::INIT; ///< The current status of the connecter. addrinfo *ai = nullptr; ///< getaddrinfo() allocated linked-list of resolved addresses. std::vector addresses; ///< Addresses we can connect to. diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index 381f7e5892..921a1e6c12 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -31,10 +31,6 @@ TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_ this->connection_string = NormalizeConnectionString(connection_string, default_port); _tcp_connecters.push_back(this); - - if (!StartNewThread(&this->resolve_thread, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) { - this->Resolve(); - } } TCPConnecter::~TCPConnecter() @@ -100,6 +96,10 @@ bool TCPConnecter::TryNextAddress() return true; } +/** + * Callback when resolving is done. + * @param ai A linked-list of address information. + */ void TCPConnecter::OnResolved(addrinfo *ai) { std::deque addresses_ipv4, addresses_ipv6; @@ -159,6 +159,12 @@ void TCPConnecter::OnResolved(addrinfo *ai) this->current_address = 0; } +/** + * Start resolving the hostname. + * + * This function must change "status" to either Status::FAILURE + * or Status::CONNECTING before returning. + */ void TCPConnecter::Resolve() { /* Port is already guaranteed part of the connection_string. */ @@ -177,7 +183,7 @@ void TCPConnecter::Resolve() auto start = std::chrono::steady_clock::now(); addrinfo *ai; - int e = getaddrinfo(address.GetHostname(), port_name, &hints, &ai); + int error = getaddrinfo(address.GetHostname(), port_name, &hints, &ai); auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); @@ -187,18 +193,21 @@ void TCPConnecter::Resolve() getaddrinfo_timeout_error_shown = true; } - if (e != 0) { + if (error != 0) { DEBUG(net, 0, "Failed to resolve DNS for %s", this->connection_string.c_str()); - this->OnFailure(); + this->status = Status::FAILURE; return; } this->ai = ai; this->OnResolved(ai); - this->is_resolved = true; + this->status = Status::CONNECTING; } +/** + * Thunk to start Resolve() on the right instance. + */ /* static */ void TCPConnecter::ResolveThunk(TCPConnecter *connecter) { connecter->Resolve(); @@ -210,7 +219,35 @@ void TCPConnecter::Resolve() */ bool TCPConnecter::CheckActivity() { - if (!this->is_resolved.load()) return false; + switch (this->status.load()) { + case Status::INIT: + /* Start the thread delayed, so the vtable is loaded. This allows classes + * to overload functions used by Resolve() (in case threading is disabled). */ + if (StartNewThread(&this->resolve_thread, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) { + this->status = Status::RESOLVING; + return false; + } + + /* No threads, do a blocking resolve. */ + this->Resolve(); + + /* Continue as we are either failed or can start the first + * connection. The rest of this function handles exactly that. */ + break; + + case Status::RESOLVING: + /* Wait till Resolve() comes back with an answer (in case it runs threaded). */ + return false; + + case Status::FAILURE: + /* Ensure the OnFailure() is called from the game-thread instead of the + * resolve-thread, as otherwise we can get into some threading issues. */ + this->OnFailure(); + return true; + + case Status::CONNECTING: + break; + } /* If there are no attempts pending, connect to the next. */ if (this->sockets.empty()) { From 7755f81bb8ba1c6a47e3a528acbbc462e56adaff Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 12 May 2021 19:44:00 +0200 Subject: [PATCH 165/800] Codechange: make explicit that virtual functions in a con/destructor are resolved statically This as during construction the sub class has not been initialized yet, and during destruction the sub class has already been destroyed, so the overriding virtual function would be accessing uninitialized data. --- src/fontcache.cpp | 3 ++- src/script/script_config.cpp | 5 ++++- src/window.cpp | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index ce15233b7e..530dc7cf80 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -216,7 +216,8 @@ TrueTypeFontCache::TrueTypeFontCache(FontSize fs, int pixels) : FontCache(fs), r */ TrueTypeFontCache::~TrueTypeFontCache() { - this->ClearFontCache(); + /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ + this->TrueTypeFontCache::ClearFontCache(); for (auto &iter : this->font_tables) { free(iter.second.second); diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index 9bb953c4c1..eeab51bede 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -37,6 +37,7 @@ void ScriptConfig::Change(const char *name, int version, bool force_exact_match, this->SetSetting(item.name, InteractiveRandomRange(item.max_value + 1 - item.min_value) + item.min_value); } } + this->AddRandomDeviation(); } } @@ -52,7 +53,9 @@ ScriptConfig::ScriptConfig(const ScriptConfig *config) for (const auto &item : config->settings) { this->settings[stredup(item.first)] = item.second; } - this->AddRandomDeviation(); + + /* Virtual functions get called statically in constructors, so make it explicit to remove any confusion. */ + this->ScriptConfig::AddRandomDeviation(); } ScriptConfig::~ScriptConfig() diff --git a/src/window.cpp b/src/window.cpp index af47214454..bb7787581a 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1094,7 +1094,8 @@ Window::~Window() /* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */ if (_focused_window == this) { - this->OnFocusLost(); + /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ + this->Window::OnFocusLost(); _focused_window = nullptr; } From 187a3f20bfd7578362f666b869580bafe25ffd0b Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 12 May 2021 23:06:35 +0200 Subject: [PATCH 166/800] Codechange: remove pointless close call due to resolving virtual functions statically in destructors In the destructors of many of the network related classes Close() is called, just like the top class in that hierarchy. However, due to virtual functions getting resolved statically in the destructor it would always call the empty Close() of the top class. Document the other cases where a virtual call is resolved statically. --- src/network/core/core.h | 5 +---- src/network/core/tcp.cpp | 3 ++- src/network/core/tcp_content.cpp | 6 ++++-- src/network/core/tcp_content.h | 8 ++++++-- src/network/core/udp.h | 2 +- src/network/network_content.cpp | 4 +++- src/network/network_content.h | 2 +- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/network/core/core.h b/src/network/core/core.h index 37948ad527..a16ed9f23b 100644 --- a/src/network/core/core.h +++ b/src/network/core/core.h @@ -46,10 +46,7 @@ public: NetworkSocketHandler() { this->has_quit = false; } /** Close the socket when destructing the socket handler */ - virtual ~NetworkSocketHandler() { this->Close(); } - - /** Really close the socket */ - virtual void Close() {} + virtual ~NetworkSocketHandler() {} /** * Close the current connection; for TCP this will be mostly equivalent diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index 3bba291c73..5c436edf05 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -29,7 +29,8 @@ NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) : NetworkTCPSocketHandler::~NetworkTCPSocketHandler() { - this->CloseConnection(); + /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ + this->NetworkTCPSocketHandler::CloseConnection(); if (this->sock != INVALID_SOCKET) closesocket(this->sock); this->sock = INVALID_SOCKET; diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index 0371b76215..3abf1c29c9 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -137,9 +137,11 @@ const char *ContentInfo::GetTextfile(TextfileType type) const return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp); } -void NetworkContentSocketHandler::Close() +/** + * Close the actual socket. + */ +void NetworkContentSocketHandler::CloseSocket() { - CloseConnection(); if (this->sock == INVALID_SOCKET) return; closesocket(this->sock); diff --git a/src/network/core/tcp_content.h b/src/network/core/tcp_content.h index 52cae1e0ed..b1bde48172 100644 --- a/src/network/core/tcp_content.h +++ b/src/network/core/tcp_content.h @@ -21,7 +21,7 @@ /** Base socket handler for all Content TCP sockets */ class NetworkContentSocketHandler : public NetworkTCPSocketHandler { protected: - void Close() override; + void CloseSocket(); bool ReceiveInvalidPacket(PacketContentType type); @@ -124,7 +124,11 @@ public: } /** On destructing of this class, the socket needs to be closed */ - virtual ~NetworkContentSocketHandler() { this->Close(); } + virtual ~NetworkContentSocketHandler() + { + /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ + this->CloseSocket(); + } bool ReceivePackets(); }; diff --git a/src/network/core/udp.h b/src/network/core/udp.h index 881fb0a612..ab898eeee3 100644 --- a/src/network/core/udp.h +++ b/src/network/core/udp.h @@ -190,7 +190,7 @@ public: virtual ~NetworkUDPSocketHandler() { this->Close(); } bool Listen(); - void Close() override; + void Close(); void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false); void ReceivePackets(); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index e4f368618b..26d220b6ae 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -784,7 +784,9 @@ void ClientNetworkContentSocketHandler::Connect() void ClientNetworkContentSocketHandler::Close() { if (this->sock == INVALID_SOCKET) return; - NetworkContentSocketHandler::Close(); + + this->CloseConnection(); + this->CloseSocket(); this->OnDisconnect(); } diff --git a/src/network/network_content.h b/src/network/network_content.h index f28821a0bf..13b93417c3 100644 --- a/src/network/network_content.h +++ b/src/network/network_content.h @@ -107,7 +107,7 @@ public: void Connect(); void SendReceive(); - void Close() override; + void Close(); void RequestContentList(ContentType type); void RequestContentList(uint count, const ContentID *content_ids); From 6ee8690b47beab9429c754dd438b7936165af4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20=C5=9Awi=C4=85tkowski?= Date: Sun, 9 May 2021 01:12:33 +0200 Subject: [PATCH 167/800] Fix: Replace Susz with Leszno Susz is masculine, not neuter, so it should result in "Susz Mazowiecki", "Susz Morski", and not "Susz Mazowieckie" or "Susz Morskie". However, because order of the names whould not be changed, it was replaced with Leszno, which is neuter. --- src/table/townname.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/table/townname.h b/src/table/townname.h index 086fc4f116..8a6e9964ff 100644 --- a/src/table/townname.h +++ b/src/table/townname.h @@ -1480,7 +1480,7 @@ static const char * const _name_polish_2_n[] = { "Pilzno", "Przodkowo", "Strzelno", - "Susz", + "Leszno", "Jaworzno", "Choszczno", "Mogilno", From 56a46f5cae73e2362d6ab9b1741e51361d753b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20=C5=9Awi=C4=85tkowski?= Date: Sun, 9 May 2021 15:11:44 +0200 Subject: [PATCH 168/800] Fix: Correct name of Golub-Dobrzyn --- src/table/townname.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/table/townname.h b/src/table/townname.h index 8a6e9964ff..85ac330609 100644 --- a/src/table/townname.h +++ b/src/table/townname.h @@ -1386,7 +1386,7 @@ static const char * const _name_polish_2_o[] = { "Zakopane", u8"Szklarska Por\u0119ba", "Bochnia", - "Golub-Dobrzyn", + u8"Golub-Dobrzy\u0144", "Chojnice", "Ostrowiec", "Otwock", From 86741ad489c3ee2d519eeb071be846721b90412c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 13 May 2021 04:13:34 -0400 Subject: [PATCH 169/800] Fix: [Emscripten] Force secure WebSockets over HTTPS (#9248) --- os/emscripten/pre.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/os/emscripten/pre.js b/os/emscripten/pre.js index 82664004ea..2fb641017c 100644 --- a/os/emscripten/pre.js +++ b/os/emscripten/pre.js @@ -9,7 +9,15 @@ Module['websocket'] = { url: function(host, port, proto) { * If you run your own server you can setup your own WebSocket proxy in * front of it and let people connect to your server via the proxy. You * are best to add another "if" statement as above for this. */ - return null; + + if (location.protocol === 'https:') { + /* Insecure WebSockets do not work over HTTPS, so we force + * secure ones. */ + return 'wss://'; + } else { + /* Use the default provided by Emscripten. */ + return null; + } } }; Module.preRun.push(function() { From a403653805c6fd6022868c5f381e10107e1d2b20 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 13 May 2021 11:46:51 +0200 Subject: [PATCH 170/800] Codechange: [Network] split CloseSocket and CloseConnection more clearly (#9261) * Codechange: [Network] split CloseSocket and CloseConnection more clearly - CloseSocket now closes the actual OS socket. - CloseConnection frees up the resources to just before CloseSocket. - dtors call CloseSocket / CloseConnection where needed. --- src/network/core/core.h | 13 +++++---- src/network/core/packet.cpp | 2 +- src/network/core/tcp.cpp | 41 ++++++++++++++++++++++------- src/network/core/tcp.h | 6 ++++- src/network/core/tcp_admin.cpp | 4 --- src/network/core/tcp_admin.h | 1 - src/network/core/tcp_content.cpp | 11 -------- src/network/core/tcp_content.h | 2 -- src/network/core/tcp_http.cpp | 15 ++++++----- src/network/core/tcp_http.h | 2 +- src/network/core/udp.cpp | 12 +++------ src/network/core/udp.h | 6 ++--- src/network/network_client.cpp | 4 +-- src/network/network_content.cpp | 18 +++++++------ src/network/network_content.h | 2 +- src/network/network_content_gui.cpp | 2 +- src/network/network_udp.cpp | 10 +++---- 17 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/network/core/core.h b/src/network/core/core.h index a16ed9f23b..3e470ef5f1 100644 --- a/src/network/core/core.h +++ b/src/network/core/core.h @@ -40,7 +40,9 @@ struct Packet; * SocketHandler for all network sockets in OpenTTD. */ class NetworkSocketHandler { +private: bool has_quit; ///< Whether the current client has quit/send a bad packet + public: /** Create a new unbound socket */ NetworkSocketHandler() { this->has_quit = false; } @@ -49,12 +51,13 @@ public: virtual ~NetworkSocketHandler() {} /** - * Close the current connection; for TCP this will be mostly equivalent - * to Close(), but for UDP it just means the packet has to be dropped. - * @param error Whether we quit under an error condition or not. - * @return new status of the connection. + * Mark the connection as closed. + * + * This doesn't mean the actual connection is closed, but just that we + * act like it is. This is useful for UDP, which doesn't normally close + * a socket, but its handler might need to pretend it does. */ - virtual NetworkRecvStatus CloseConnection(bool error = true) { this->has_quit = true; return NETWORK_RECV_STATUS_OKAY; } + void MarkClosed() { this->has_quit = true; } /** * Whether the current client connected to the socket has quit. diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 7369707910..883097dea1 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -222,7 +222,7 @@ bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection) /* Check if variable is within packet-size */ if (this->pos + bytes_to_read > this->Size()) { - if (close_connection) this->cs->NetworkSocketHandler::CloseConnection(); + if (close_connection) this->cs->NetworkSocketHandler::MarkClosed(); return false; } diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index 5c436edf05..d5754f69a1 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -29,24 +29,45 @@ NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) : NetworkTCPSocketHandler::~NetworkTCPSocketHandler() { - /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ - this->NetworkTCPSocketHandler::CloseConnection(); - - if (this->sock != INVALID_SOCKET) closesocket(this->sock); - this->sock = INVALID_SOCKET; + this->EmptyPacketQueue(); + this->CloseSocket(); } -NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection(bool error) +/** + * Free all pending and partially received packets. + */ +void NetworkTCPSocketHandler::EmptyPacketQueue() { - this->writable = false; - NetworkSocketHandler::CloseConnection(error); - - /* Free all pending and partially received packets */ while (this->packet_queue != nullptr) { delete Packet::PopFromQueue(&this->packet_queue); } delete this->packet_recv; this->packet_recv = nullptr; +} + +/** + * Close the actual socket of the connection. + * Please make sure CloseConnection is called before CloseSocket, as + * otherwise not all resources might be released. + */ +void NetworkTCPSocketHandler::CloseSocket() +{ + if (this->sock != INVALID_SOCKET) closesocket(this->sock); + this->sock = INVALID_SOCKET; +} + +/** + * This will put this socket handler in a close state. It will not + * actually close the OS socket; use CloseSocket for this. + * @param error Whether we quit under an error condition or not. + * @return new status of the connection. + */ +NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection(bool error) +{ + this->MarkClosed(); + this->writable = false; + + this->EmptyPacketQueue(); return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index 44316bfca0..3b217cb2e1 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -33,6 +33,8 @@ class NetworkTCPSocketHandler : public NetworkSocketHandler { private: Packet *packet_queue; ///< Packets that are awaiting delivery Packet *packet_recv; ///< Partially received packet + + void EmptyPacketQueue(); public: SOCKET sock; ///< The socket currently connected to bool writable; ///< Can we write to this socket? @@ -43,7 +45,9 @@ public: */ bool IsConnected() const { return this->sock != INVALID_SOCKET; } - NetworkRecvStatus CloseConnection(bool error = true) override; + virtual NetworkRecvStatus CloseConnection(bool error = true); + void CloseSocket(); + virtual void SendPacket(Packet *packet); SendPacketsState SendPackets(bool closing_down = false); diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index 8cc8b1efe6..0b48b419b6 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -34,10 +34,6 @@ NetworkAdminSocketHandler::NetworkAdminSocketHandler(SOCKET s) : status(ADMIN_ST this->admin_version[0] = '\0'; } -NetworkAdminSocketHandler::~NetworkAdminSocketHandler() -{ -} - NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error) { delete this; diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h index e5bcefa86f..8b4a738bfa 100644 --- a/src/network/core/tcp_admin.h +++ b/src/network/core/tcp_admin.h @@ -482,7 +482,6 @@ public: NetworkRecvStatus CloseConnection(bool error = true) override; NetworkAdminSocketHandler(SOCKET s); - ~NetworkAdminSocketHandler(); NetworkRecvStatus ReceivePackets(); diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index 3abf1c29c9..a53a352c28 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -137,17 +137,6 @@ const char *ContentInfo::GetTextfile(TextfileType type) const return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp); } -/** - * Close the actual socket. - */ -void NetworkContentSocketHandler::CloseSocket() -{ - if (this->sock == INVALID_SOCKET) return; - - closesocket(this->sock); - this->sock = INVALID_SOCKET; -} - /** * Handle the given packet, i.e. pass it to the right * parser receive command. diff --git a/src/network/core/tcp_content.h b/src/network/core/tcp_content.h index b1bde48172..d99986ef26 100644 --- a/src/network/core/tcp_content.h +++ b/src/network/core/tcp_content.h @@ -21,8 +21,6 @@ /** Base socket handler for all Content TCP sockets */ class NetworkContentSocketHandler : public NetworkTCPSocketHandler { protected: - void CloseSocket(); - bool ReceiveInvalidPacket(PacketContentType type); /** diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp index 08961e4029..f11722ae38 100644 --- a/src/network/core/tcp_http.cpp +++ b/src/network/core/tcp_http.cpp @@ -68,17 +68,18 @@ NetworkHTTPSocketHandler::NetworkHTTPSocketHandler(SOCKET s, /** Free whatever needs to be freed. */ NetworkHTTPSocketHandler::~NetworkHTTPSocketHandler() { - this->CloseConnection(); + this->CloseSocket(); - if (this->sock != INVALID_SOCKET) closesocket(this->sock); - this->sock = INVALID_SOCKET; free(this->data); } -NetworkRecvStatus NetworkHTTPSocketHandler::CloseConnection(bool error) +/** + * Close the actual socket of the connection. + */ +void NetworkHTTPSocketHandler::CloseSocket() { - NetworkSocketHandler::CloseConnection(error); - return NETWORK_RECV_STATUS_OKAY; + if (this->sock != INVALID_SOCKET) closesocket(this->sock); + this->sock = INVALID_SOCKET; } /** @@ -313,7 +314,7 @@ int NetworkHTTPSocketHandler::Receive() if (ret < 0) cur->callback->OnFailure(); if (ret <= 0) { /* Then... the connection can be closed */ - cur->CloseConnection(); + cur->CloseSocket(); iter = _http_connections.erase(iter); delete cur; continue; diff --git a/src/network/core/tcp_http.h b/src/network/core/tcp_http.h index d7be0c327b..da7a04ac48 100644 --- a/src/network/core/tcp_http.h +++ b/src/network/core/tcp_http.h @@ -58,7 +58,7 @@ public: return this->sock != INVALID_SOCKET; } - NetworkRecvStatus CloseConnection(bool error = true) override; + void CloseSocket(); NetworkHTTPSocketHandler(SOCKET sock, HTTPCallback *callback, const char *host, const char *url, const char *data, int depth); diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index c8d7533640..312ac0f0a2 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -44,7 +44,7 @@ NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind) bool NetworkUDPSocketHandler::Listen() { /* Make sure socket is closed */ - this->Close(); + this->CloseSocket(); for (NetworkAddress &addr : this->bind) { addr.Listen(SOCK_DGRAM, &this->sockets); @@ -54,9 +54,9 @@ bool NetworkUDPSocketHandler::Listen() } /** - * Close the given UDP socket + * Close the actual UDP socket. */ -void NetworkUDPSocketHandler::Close() +void NetworkUDPSocketHandler::CloseSocket() { for (auto &s : this->sockets) { closesocket(s.second); @@ -64,12 +64,6 @@ void NetworkUDPSocketHandler::Close() this->sockets.clear(); } -NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection(bool error) -{ - NetworkSocketHandler::CloseConnection(error); - return NETWORK_RECV_STATUS_OKAY; -} - /** * Send a packet over UDP * @param p the packet to send diff --git a/src/network/core/udp.h b/src/network/core/udp.h index ab898eeee3..489e219856 100644 --- a/src/network/core/udp.h +++ b/src/network/core/udp.h @@ -49,8 +49,6 @@ protected: /** The opened sockets. */ SocketList sockets; - NetworkRecvStatus CloseConnection(bool error = true) override; - void ReceiveInvalidPacket(PacketUDPType, NetworkAddress *client_addr); /** @@ -187,10 +185,10 @@ public: NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr); /** On destructing of this class, the socket needs to be closed */ - virtual ~NetworkUDPSocketHandler() { this->Close(); } + virtual ~NetworkUDPSocketHandler() { this->CloseSocket(); } bool Listen(); - void Close(); + void CloseSocket(); void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false); void ReceivePackets(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 34746e935c..7852a6da9e 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -158,6 +158,7 @@ ClientNetworkGameSocketHandler::~ClientNetworkGameSocketHandler() ClientNetworkGameSocketHandler::my_client = nullptr; delete this->savegame; + delete this->GetInfo(); } NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status) @@ -182,7 +183,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvSta * which would trigger the server to close the connection as well. */ CSleep(3 * MILLISECONDS_PER_TICK); - delete this->GetInfo(); delete this; return status; @@ -200,7 +200,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) /* We just want to close the connection.. */ if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) { - this->NetworkSocketHandler::CloseConnection(); + this->NetworkSocketHandler::MarkClosed(); this->CloseConnection(res); _networking = false; diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 26d220b6ae..2b90cf4153 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -76,7 +76,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) if (!ci->IsValid()) { delete ci; - this->Close(); + this->CloseConnection(); return false; } @@ -488,7 +488,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) p->Recv_string(this->curInfo->filename, lengthof(this->curInfo->filename)); if (!this->BeforeDownload()) { - this->Close(); + this->CloseConnection(); return false; } } else { @@ -497,7 +497,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) if (toRead != 0 && (size_t)p->TransferOut(TransferOutFWrite, this->curFile) != toRead) { DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); - this->Close(); + this->CloseConnection(); fclose(this->curFile); this->curFile = nullptr; @@ -781,14 +781,16 @@ void ClientNetworkContentSocketHandler::Connect() /** * Disconnect from the content server. */ -void ClientNetworkContentSocketHandler::Close() +NetworkRecvStatus ClientNetworkContentSocketHandler::CloseConnection(bool error) { - if (this->sock == INVALID_SOCKET) return; + NetworkContentSocketHandler::CloseConnection(); + + if (this->sock == INVALID_SOCKET) return NETWORK_RECV_STATUS_OKAY; - this->CloseConnection(); this->CloseSocket(); - this->OnDisconnect(); + + return NETWORK_RECV_STATUS_OKAY; } /** @@ -800,7 +802,7 @@ void ClientNetworkContentSocketHandler::SendReceive() if (this->sock == INVALID_SOCKET || this->isConnecting) return; if (std::chrono::steady_clock::now() > this->lastActivity + IDLE_TIMEOUT) { - this->Close(); + this->CloseConnection(); return; } diff --git a/src/network/network_content.h b/src/network/network_content.h index 13b93417c3..b74308a100 100644 --- a/src/network/network_content.h +++ b/src/network/network_content.h @@ -107,7 +107,7 @@ public: void Connect(); void SendReceive(); - void Close(); + NetworkRecvStatus CloseConnection(bool error = true) override; void RequestContentList(ContentType type); void RequestContentList(uint count, const ContentID *content_ids); diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 0cd711877d..dd9590e99c 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -260,7 +260,7 @@ public: { if (widget == WID_NCDS_CANCELOK) { if (this->downloaded_bytes != this->total_bytes) { - _network_content_client.Close(); + _network_content_client.CloseConnection(); delete this; } else { /* If downloading succeeded, close the online content window. This will close diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 75bf4563d3..0da5a8b260 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -54,10 +54,10 @@ struct UDPSocket { UDPSocket(const std::string &name_) : name(name_), socket(nullptr) {} - void Close() + void CloseSocket() { std::lock_guard lock(mutex); - socket->Close(); + socket->CloseSocket(); delete socket; socket = nullptr; } @@ -619,9 +619,9 @@ void NetworkUDPServerListen() /** Close all UDP related stuff. */ void NetworkUDPClose() { - _udp_client.Close(); - _udp_server.Close(); - _udp_master.Close(); + _udp_client.CloseSocket(); + _udp_server.CloseSocket(); + _udp_master.CloseSocket(); _network_udp_server = false; _network_udp_broadcast = 0; From 423a5034ee9210a3019a0ad983b64ae7df4d4f8d Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 13 May 2021 19:09:30 +0000 Subject: [PATCH 171/800] Update: Translations from eints french: 2 changes by glx22 --- src/lang/french.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/french.txt b/src/lang/french.txt index b0491a80cb..20f49c90f0 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -2218,6 +2218,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Votre or STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Votre ordinateur a mis trop de temps pour télécharger la carte STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Votre ordinateur a mis trop de temps pour rejoindre le serveur STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Votre nom n'est pas valide +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Le serveur interrogé est trop ancien pour ce client ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :erreur générale @@ -2831,7 +2832,7 @@ STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COM STR_FRAMERATE_GAMELOOP :{BLACK}Total de la boucle de jeu{NBSP}: STR_FRAMERATE_GL_ECONOMY :{BLACK} Traitement des marchandises{NBSP}: STR_FRAMERATE_GL_TRAINS :{BLACK} Ticks des trains{NBSP}: -STR_FRAMERATE_GL_ROADVEHS :{WHITE} Ticks des véhicules routiers{NBSP}: +STR_FRAMERATE_GL_ROADVEHS :{BLACK} Ticks des véhicules routiers{NBSP}: STR_FRAMERATE_GL_SHIPS :{BLACK} Ticks des navires{NBSP}: STR_FRAMERATE_GL_AIRCRAFT :{BLACK} Ticks des aéroplanes{NBSP}: STR_FRAMERATE_GL_LANDSCAPE :{BLACK} Ticks du monde{NBSP}: From f219354f891c45dcefad2dd0a2f1fd92b07e4ba5 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 20:32:35 +0200 Subject: [PATCH 172/800] Change: further support for std::string in settings --- src/network/network_gui.cpp | 2 +- src/settings.cpp | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 35597fa047..56fdc7309e 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -648,7 +648,7 @@ public: DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version y += FONT_HEIGHT_NORMAL; - SetDParamStr(0, sel->connection_string.c_str()); + SetDParamStr(0, sel->connection_string); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address y += FONT_HEIGHT_NORMAL; diff --git a/src/settings.cpp b/src/settings.cpp index 855bedd18d..e347d7c0af 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -527,18 +527,26 @@ static void Write_ValidateString(void *ptr, const SaveLoad *sld, const char *p) /** * Set the string value of a setting. * @param ptr Pointer to the std::string. - * @param sld Pointer to the information for the conversions and limitations to apply. + * @param sd Pointer to the information for the conversions and limitations to apply. * @param p The string to save. */ -static void Write_ValidateStdString(void *ptr, const SaveLoad *sld, const char *p) +static void Write_ValidateStdString(void *ptr, const SettingDesc *sd, const char *p) { std::string *dst = reinterpret_cast(ptr); - switch (GetVarMemType(sld->conv)) { + switch (GetVarMemType(sd->save.conv)) { case SLE_VAR_STR: case SLE_VAR_STRQ: if (p != nullptr) { - dst->assign(p); + if (sd->desc.max != 0 && strlen(p) >= sd->desc.max) { + /* In case a maximum length is imposed by the setting, the length + * includes the '\0' termination for network transfer purposes. + * Also ensure the string is valid after chopping of some bytes. */ + std::string str(p, sd->desc.max - 1); + dst->assign(str_validate(str, SVS_NONE)); + } else { + dst->assign(p); + } } else { dst->clear(); } @@ -608,7 +616,7 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp break; case SDT_STDSTRING: - Write_ValidateStdString(ptr, sld, (const char *)p); + Write_ValidateStdString(ptr, sd, (const char *)p); break; case SDT_INTLIST: { @@ -2119,6 +2127,8 @@ bool SetSettingValue(uint index, const char *value, bool force_newgame) void *ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); if (sd->desc.cmd == SDT_STRING) { Write_ValidateString(ptr, &sd->save, value); + } else { + Write_ValidateStdString(ptr, sd, value); } if (sd->desc.proc != nullptr) sd->desc.proc(0); @@ -2176,7 +2186,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) } bool success; - if (sd->desc.cmd == SDT_STRING) { + if (sd->desc.cmd == SDT_STRING || sd->desc.cmd == SDT_STDSTRING) { success = SetSettingValue(index, value, force_newgame); } else { uint32 val; @@ -2229,6 +2239,8 @@ void IConsoleGetSetting(const char *name, bool force_newgame) if (sd->desc.cmd == SDT_STRING) { IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ) ? *(const char * const *)ptr : (const char *)ptr); + } else if (sd->desc.cmd == SDT_STDSTRING) { + IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); } else { if (sd->desc.cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool*)ptr != 0) ? "on" : "off"); @@ -2260,6 +2272,8 @@ void IConsoleListSettings(const char *prefilter) seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); } else if (sd->desc.cmd == SDT_STRING) { seprintf(value, lastof(value), "%s", (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ) ? *(const char * const *)ptr : (const char *)ptr); + } else if (sd->desc.cmd == SDT_STDSTRING) { + seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); } else { seprintf(value, lastof(value), sd->desc.min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); } From c73d64adf984036a99d6974b130eda65dfc18c6c Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 20:26:56 +0200 Subject: [PATCH 173/800] Codechange: move passwords in settings to std::string --- src/company_cmd.cpp | 4 ++-- src/fios_gui.cpp | 2 +- src/network/core/game_info.cpp | 2 +- src/network/network.cpp | 2 +- src/network/network_admin.cpp | 6 +++--- src/network/network_gui.cpp | 6 +++--- src/network/network_server.cpp | 10 +++++----- src/openttd.cpp | 4 ++-- src/settings.cpp | 8 ++++---- src/settings_type.h | 8 ++++---- src/table/settings.h.preamble | 3 +++ src/table/settings.ini | 21 +++++++++++++-------- 12 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 063d32d3f3..45a679c108 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -843,8 +843,8 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (client_id == _network_own_client_id) { assert(_local_company == COMPANY_SPECTATOR); SetLocalCompany(c->index); - if (!StrEmpty(_settings_client.network.default_company_pass)) { - NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); + if (!_settings_client.network.default_company_pass.empty()) { + NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass.c_str()); } /* Now that we have a new company, broadcast our company settings to diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index e4de1acaaa..40a082d64f 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -53,7 +53,7 @@ void LoadCheckData::Clear() this->map_size_x = this->map_size_y = 256; // Default for old savegames which do not store mapsize. this->current_date = 0; - memset(&this->settings, 0, sizeof(this->settings)); + this->settings = {}; for (auto &pair : this->companies) { delete pair.second; diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index 46bb42ec1b..dd58ae500c 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -127,7 +127,7 @@ void CheckGameCompatibility(NetworkGameInfo &ngi) */ void FillStaticNetworkServerGameInfo() { - _network_game_info.use_password = !StrEmpty(_settings_client.network.server_password); + _network_game_info.use_password = !_settings_client.network.server_password.empty(); _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; diff --git a/src/network/network.cpp b/src/network/network.cpp index a87aab88c7..b9160e2081 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -887,7 +887,7 @@ bool NetworkServerStart() if (!ServerNetworkGameSocketHandler::Listen(_settings_client.network.server_port)) return false; /* Only listen for admins when the password isn't empty. */ - if (!StrEmpty(_settings_client.network.admin_password)) { + if (!_settings_client.network.admin_password.empty()) { DEBUG(net, 5, "Starting listeners for admins"); if (!ServerNetworkAdminSocketHandler::Listen(_settings_client.network.server_admin_port)) return false; } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 4e73aed0f8..057ce32c06 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -84,7 +84,7 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler() */ /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection() { - bool accept = !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS; + bool accept = !_settings_client.network.admin_password.empty() && _network_admins_connected < MAX_ADMINS; /* We can't go over the MAX_ADMINS limit here. However, if we accept * the connection, there has to be space in the pool. */ static_assert(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS); @@ -667,8 +667,8 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p) char password[NETWORK_PASSWORD_LENGTH]; p->Recv_string(password, sizeof(password)); - if (StrEmpty(_settings_client.network.admin_password) || - strcmp(password, _settings_client.network.admin_password) != 0) { + if (_settings_client.network.admin_password.empty() || + _settings_client.network.admin_password.compare(password) != 0) { /* Password is invalid */ return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 56fdc7309e..67992cac7e 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1032,7 +1032,7 @@ struct NetworkStartServerWindow : public Window { switch (widget) { case WID_NSS_SETPWD: /* If password is set, draw red '*' next to 'Set password' button. */ - if (!StrEmpty(_settings_client.network.server_password)) DrawString(r.right + WD_FRAMERECT_LEFT, this->width - WD_FRAMERECT_RIGHT, r.top, "*", TC_RED); + if (!_settings_client.network.server_password.empty()) DrawString(r.right + WD_FRAMERECT_LEFT, this->width - WD_FRAMERECT_RIGHT, r.top, "*", TC_RED); } } @@ -1156,7 +1156,7 @@ struct NetworkStartServerWindow : public Window { if (str == nullptr) return; if (this->widget_id == WID_NSS_SETPWD) { - strecpy(_settings_client.network.server_password, str, lastof(_settings_client.network.server_password)); + _settings_client.network.server_password = str; } else { int32 value = atoi(str); this->SetWidgetDirty(this->widget_id); @@ -2583,7 +2583,7 @@ struct NetworkCompanyPasswordWindow : public Window { void OnOk() { if (this->IsWidgetLowered(WID_NCP_SAVE_AS_DEFAULT_PASSWORD)) { - strecpy(_settings_client.network.default_company_pass, this->password_editbox.text.buf, lastof(_settings_client.network.default_company_pass)); + _settings_client.network.default_company_pass = this->password_editbox.text.buf; } NetworkChangeCompanyPassword(_local_company, this->password_editbox.text.buf); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index bbadbeba4d..c7a70300b0 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -859,7 +859,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED NetworkClientInfo *ci = this->GetInfo(); /* We now want a password from the client else we do not allow him in! */ - if (!StrEmpty(_settings_client.network.server_password)) { + if (!_settings_client.network.server_password.empty()) { return this->SendNeedGamePassword(); } @@ -957,8 +957,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(P p->Recv_string(password, sizeof(password)); /* Check game password. Allow joining if we cleared the password meanwhile */ - if (!StrEmpty(_settings_client.network.server_password) && - strcmp(password, _settings_client.network.server_password) != 0) { + if (!_settings_client.network.server_password.empty() && + _settings_client.network.server_password.compare(password) != 0) { /* Password is invalid */ return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); } @@ -1439,12 +1439,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p) char pass[NETWORK_PASSWORD_LENGTH]; char command[NETWORK_RCONCOMMAND_LENGTH]; - if (StrEmpty(_settings_client.network.rcon_password)) return NETWORK_RECV_STATUS_OKAY; + if (_settings_client.network.rcon_password.empty()) return NETWORK_RECV_STATUS_OKAY; p->Recv_string(pass, sizeof(pass)); p->Recv_string(command, sizeof(command)); - if (strcmp(pass, _settings_client.network.rcon_password) != 0) { + if (_settings_client.network.rcon_password.compare(pass) != 0) { DEBUG(net, 1, "[rcon] Wrong password from client-id %d", this->client_id); return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/openttd.cpp b/src/openttd.cpp index a416f531a2..5674a46713 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -874,8 +874,8 @@ static void MakeNewGameDone() /* 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 (_network_server && !_settings_client.network.default_company_pass.empty()) { + NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass.c_str()); } if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE); diff --git a/src/settings.cpp b/src/settings.cpp index e347d7c0af..0c6c08f9a4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1420,8 +1420,8 @@ static bool UpdateClientName(int32 p1) static bool UpdateServerPassword(int32 p1) { - if (strcmp(_settings_client.network.server_password, "*") == 0) { - _settings_client.network.server_password[0] = '\0'; + if (_settings_client.network.server_password.compare("*") == 0) { + _settings_client.network.server_password.clear(); } NetworkServerUpdateGameInfo(); @@ -1430,8 +1430,8 @@ static bool UpdateServerPassword(int32 p1) static bool UpdateRconPassword(int32 p1) { - if (strcmp(_settings_client.network.rcon_password, "*") == 0) { - _settings_client.network.rcon_password[0] = '\0'; + if (_settings_client.network.rcon_password.compare("*") == 0) { + _settings_client.network.rcon_password.clear(); } return true; diff --git a/src/settings_type.h b/src/settings_type.h index 5361fc3f1f..248761fe64 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -263,12 +263,12 @@ struct NetworkSettings { uint16 server_admin_port; ///< port the server listens on for the admin network bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network char server_name[NETWORK_NAME_LENGTH]; ///< name of the server - char server_password[NETWORK_PASSWORD_LENGTH]; ///< password for joining this server - char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< password for rconsole (server side) - char admin_password[NETWORK_PASSWORD_LENGTH]; ///< password for the admin network + std::string server_password; ///< password for joining this server + std::string rcon_password; ///< password for rconsole (server side) + std::string admin_password; ///< password for the admin network bool server_advertise; ///< advertise the server to the masterserver char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) - char default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form + std::string default_company_pass; ///< default password for new companies in encrypted form char connect_to_ip[NETWORK_HOSTNAME_PORT_LENGTH]; ///< default for the "Add server" query char network_id[NETWORK_SERVER_ID_LENGTH]; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index c3e0678b7b..09a89821a2 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -129,6 +129,9 @@ static size_t ConvertLandscape(const char *value); #define SDTC_STR(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, str, strhelp, strval, proc, from, to, cat, extra, startup)\ + SDTG_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, max_length, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) + #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index d12f58236d..e8fa4560be 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -70,6 +70,7 @@ SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_STR = SDTC_STR( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), @@ -3924,35 +3925,39 @@ def = nullptr proc = UpdateClientName cat = SC_BASIC -[SDTC_STR] +[SDTC_SSTR] var = network.server_password -type = SLE_STRB +type = SLE_STR +length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr proc = UpdateServerPassword cat = SC_BASIC -[SDTC_STR] +[SDTC_SSTR] var = network.rcon_password -type = SLE_STRB +type = SLE_STR +length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr proc = UpdateRconPassword cat = SC_BASIC -[SDTC_STR] +[SDTC_SSTR] var = network.admin_password -type = SLE_STRB +type = SLE_STR +length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr cat = SC_BASIC -[SDTC_STR] +[SDTC_SSTR] var = network.default_company_pass -type = SLE_STRB +type = SLE_STR +length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr From cc6c078dec3792173b5d2057667bec9597c71d90 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 21:10:11 +0200 Subject: [PATCH 174/800] Codechange: move hostnames in settings to std::string --- src/console_cmds.cpp | 4 ++-- src/network/network.cpp | 2 +- src/network/network_gui.cpp | 4 ++-- src/settings_type.h | 4 ++-- src/table/settings.ini | 10 ++++++---- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 3929b44c11..90f635d60a 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -893,13 +893,13 @@ DEF_CONSOLE_CMD(ConNetworkReconnect) break; } - if (StrEmpty(_settings_client.network.last_joined)) { + if (_settings_client.network.last_joined.empty()) { IConsolePrint(CC_DEFAULT, "No server for reconnecting."); return true; } /* Don't resolve the address first, just print it directly as it comes from the config file. */ - IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined); + IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined.c_str()); return NetworkClientConnectGame(_settings_client.network.last_joined, playas); } diff --git a/src/network/network.cpp b/src/network/network.cpp index b9160e2081..94566d2326 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -824,7 +824,7 @@ void NetworkClientJoinGame() NetworkDisconnect(); NetworkInitialize(); - strecpy(_settings_client.network.last_joined, _network_join.connection_string.c_str(), lastof(_settings_client.network.last_joined)); + _settings_client.network.last_joined = _network_join.connection_string; _network_join_status = NETWORK_JOIN_STATUS_CONNECTING; ShowJoinStatusWindow(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 67992cac7e..ca0e67d0a2 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -828,7 +828,7 @@ public: void OnQueryTextFinished(char *str) override { if (!StrEmpty(str)) { - strecpy(_settings_client.network.connect_to_ip, str, lastof(_settings_client.network.connect_to_ip)); + _settings_client.network.connect_to_ip = str; NetworkAddServer(str); NetworkRebuildHostList(); } @@ -1556,7 +1556,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); - strecpy(_settings_client.network.last_joined, ngl->connection_string.c_str(), lastof(_settings_client.network.last_joined)); + _settings_client.network.last_joined = ngl->connection_string; NetworkQueryLobbyServer(ngl->connection_string); diff --git a/src/settings_type.h b/src/settings_type.h index 248761fe64..0828baa58c 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -269,7 +269,7 @@ struct NetworkSettings { bool server_advertise; ///< advertise the server to the masterserver char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) std::string default_company_pass; ///< default password for new companies in encrypted form - char connect_to_ip[NETWORK_HOSTNAME_PORT_LENGTH]; ///< default for the "Add server" query + std::string connect_to_ip; ///< default for the "Add server" query char network_id[NETWORK_SERVER_ID_LENGTH]; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use uint8 autoclean_unprotected; ///< remove passwordless companies after this many months @@ -281,7 +281,7 @@ struct NetworkSettings { Year restart_game_year; ///< year the server restarts uint8 min_active_clients; ///< minimum amount of active clients to unpause the game bool reload_cfg; ///< reload the config file before restarting - char last_joined[NETWORK_HOSTNAME_PORT_LENGTH]; ///< Last joined server + std::string last_joined; ///< Last joined server bool no_http_content_downloads; ///< do not do content downloads over HTTP }; diff --git a/src/table/settings.ini b/src/table/settings.ini index e8fa4560be..6dbff01db4 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3970,9 +3970,10 @@ def = nullptr proc = UpdateClientConfigValues cat = SC_BASIC -[SDTC_STR] +[SDTC_SSTR] var = network.connect_to_ip -type = SLE_STRB +type = SLE_STR +length = 0 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr @@ -4075,9 +4076,10 @@ guiflags = SGF_NETWORK_ONLY def = false cat = SC_EXPERT -[SDTC_STR] +[SDTC_SSTR] var = network.last_joined -type = SLE_STRB +type = SLE_STR +length = 0 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = """" cat = SC_EXPERT From 02fdb5b210ede022cb921e869cdb34758ee5299e Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 21:25:52 +0200 Subject: [PATCH 175/800] Codechange: move server name/id in settings to std::string --- src/network/network.cpp | 16 ++++++++-------- src/network/network_gui.cpp | 4 ++-- src/network/network_server.cpp | 2 +- src/settings_type.h | 4 ++-- src/table/settings.ini | 10 ++++++---- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 94566d2326..5a25c7acb0 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -833,8 +833,8 @@ void NetworkClientJoinGame() static void NetworkInitGameInfo() { - if (StrEmpty(_settings_client.network.server_name)) { - strecpy(_settings_client.network.server_name, "Unnamed Server", lastof(_settings_client.network.server_name)); + if (_settings_client.network.server_name.empty()) { + _settings_client.network.server_name = "Unnamed Server"; } FillStaticNetworkServerGameInfo(); @@ -863,10 +863,10 @@ static void CheckClientAndServerName() strecpy(_settings_client.network.client_name, fallback_client_name, lastof(_settings_client.network.client_name)); } - static const char *fallback_server_name = "Unnamed Server"; - if (StrEmpty(_settings_client.network.server_name) || strcmp(_settings_client.network.server_name, fallback_server_name) == 0) { - DEBUG(net, 1, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command", fallback_server_name); - strecpy(_settings_client.network.server_name, fallback_server_name, lastof(_settings_client.network.server_name)); + static const std::string fallback_server_name = "Unnamed Server"; + if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) { + DEBUG(net, 1, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command", fallback_server_name.c_str()); + _settings_client.network.server_name = fallback_server_name; } } @@ -1201,7 +1201,7 @@ static void NetworkGenerateServerId() } /* _settings_client.network.network_id is our id */ - seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output); + _settings_client.network.network_id = hex_output; } class TCPNetworkDebugConnecter : TCPConnecter { @@ -1241,7 +1241,7 @@ void NetworkStartUp() _network_need_advertise = true; /* Generate an server id when there is none yet */ - if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateServerId(); + if (_settings_client.network.network_id.empty()) NetworkGenerateServerId(); _network_game_info = {}; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index ca0e67d0a2..6fdf73bc4b 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -990,7 +990,7 @@ struct NetworkStartServerWindow : public Window { this->InitNested(WN_NETWORK_WINDOW_START); this->querystrings[WID_NSS_GAMENAME] = &this->name_editbox; - this->name_editbox.text.Assign(_settings_client.network.server_name); + this->name_editbox.text.Assign(_settings_client.network.server_name.c_str()); this->SetFocusedWidget(WID_NSS_GAMENAME); } @@ -1136,7 +1136,7 @@ struct NetworkStartServerWindow : public Window { void OnEditboxChanged(int wid) override { if (wid == WID_NSS_GAMENAME) { - strecpy(_settings_client.network.server_name, this->name_editbox.text.buf, lastof(_settings_client.network.server_name)); + _settings_client.network.server_name = this->name_editbox.text.buf; } } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index c7a70300b0..f2a8a52307 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1762,7 +1762,7 @@ void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, if (!Company::IsValidHumanID(company_id)) return; if (!already_hashed) { - password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed); + password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id.c_str(), _settings_game.game_creation.generation_seed); } strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password)); diff --git a/src/settings_type.h b/src/settings_type.h index 0828baa58c..8cff371428 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -262,7 +262,7 @@ struct NetworkSettings { uint16 server_port; ///< port the server listens on uint16 server_admin_port; ///< port the server listens on for the admin network bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network - char server_name[NETWORK_NAME_LENGTH]; ///< name of the server + std::string server_name; ///< name of the server std::string server_password; ///< password for joining this server std::string rcon_password; ///< password for rconsole (server side) std::string admin_password; ///< password for the admin network @@ -270,7 +270,7 @@ struct NetworkSettings { char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) std::string default_company_pass; ///< default password for new companies in encrypted form std::string connect_to_ip; ///< default for the "Add server" query - char network_id[NETWORK_SERVER_ID_LENGTH]; ///< network ID for servers + std::string network_id; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use uint8 autoclean_unprotected; ///< remove passwordless companies after this many months uint8 autoclean_protected; ///< remove the password from passworded companies after this many months diff --git a/src/table/settings.ini b/src/table/settings.ini index 6dbff01db4..0a439edaa4 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3961,9 +3961,10 @@ length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr -[SDTC_STR] +[SDTC_SSTR] var = network.server_name -type = SLE_STRB +type = SLE_STR +length = NETWORK_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr @@ -3977,9 +3978,10 @@ length = 0 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr -[SDTC_STR] +[SDTC_SSTR] var = network.network_id -type = SLE_STRB +type = SLE_STR +length = NETWORK_SERVER_ID_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr From 16437b7c0dc2cf8c0ab32e375df7b2712feff73d Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 27 Apr 2021 22:02:40 +0200 Subject: [PATCH 176/800] Codechange: move client name in settings to std::string --- src/console_cmds.cpp | 4 ++-- src/network/network.cpp | 10 ++++----- src/network/network_client.cpp | 21 ++++++++++--------- src/network/network_func.h | 4 ++-- src/network/network_gui.cpp | 9 +++++---- src/newgrf_storage.h | 2 +- src/settings_type.h | 2 +- src/string.cpp | 37 +++++++--------------------------- src/string_func.h | 2 +- src/table/settings.h.preamble | 3 --- src/table/settings.ini | 6 +++--- 11 files changed, 39 insertions(+), 61 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 90f635d60a..0756f72667 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -717,14 +717,14 @@ DEF_CONSOLE_CMD(ConClientNickChange) return true; } - char *client_name = argv[2]; + std::string client_name(argv[2]); StrTrimInPlace(client_name); if (!NetworkIsValidClientName(client_name)) { IConsoleError("Cannot give a client an empty name"); return true; } - if (!NetworkServerChangeClientName(client_id, client_name)) { + if (!NetworkServerChangeClientName(client_id, client_name.c_str())) { IConsoleError("Cannot give a client a duplicate name"); } diff --git a/src/network/network.cpp b/src/network/network.cpp index 5a25c7acb0..a66da42bc5 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -846,7 +846,7 @@ static void NetworkInitGameInfo() 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)); + strecpy(ci->client_name, _settings_client.network.client_name.c_str(), lastof(ci->client_name)); } /** @@ -857,10 +857,10 @@ static void NetworkInitGameInfo() */ static void CheckClientAndServerName() { - static const char *fallback_client_name = "Unnamed Client"; - if (StrEmpty(_settings_client.network.client_name) || strcmp(_settings_client.network.client_name, fallback_client_name) == 0) { - DEBUG(net, 1, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command", fallback_client_name); - strecpy(_settings_client.network.client_name, fallback_client_name, lastof(_settings_client.network.client_name)); + static const std::string fallback_client_name = "Unnamed Client"; + if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) { + DEBUG(net, 1, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command", fallback_client_name.c_str()); + _settings_client.network.client_name = fallback_client_name; } static const std::string fallback_server_name = "Unnamed Server"; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 7852a6da9e..b9bcfe1f22 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1305,10 +1305,10 @@ void NetworkClientsToSpectators(CompanyID cid) * @param client_name The client name to check for validity. * @return True iff the name is valid. */ -bool NetworkIsValidClientName(const char *client_name) +bool NetworkIsValidClientName(const std::string_view client_name) { - if (StrEmpty(client_name)) return false; - if (*client_name == ' ') return false; + if (client_name.empty()) return false; + if (client_name[0] == ' ') return false; return true; } @@ -1327,7 +1327,7 @@ bool NetworkIsValidClientName(const char *client_name) * and trailing spaces. * @return True iff the client name is valid. */ -bool NetworkValidateClientName(char *client_name) +bool NetworkValidateClientName(std::string &client_name) { StrTrimInPlace(client_name); if (NetworkIsValidClientName(client_name)) return true; @@ -1363,13 +1363,16 @@ void NetworkUpdateClientName() if (!NetworkValidateClientName()) return; /* Don't change the name if it is the same as the old name */ - if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) { + if (_settings_client.network.client_name.compare(ci->client_name) != 0) { if (!_network_server) { - MyClient::SendSetName(_settings_client.network.client_name); + MyClient::SendSetName(_settings_client.network.client_name.c_str()); } else { - if (NetworkFindName(_settings_client.network.client_name, lastof(_settings_client.network.client_name))) { - NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, _settings_client.network.client_name); - strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name)); + /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ + char temporary_name[NETWORK_CLIENT_NAME_LENGTH]; + strecpy(temporary_name, _settings_client.network.client_name.c_str(), lastof(temporary_name)); + if (NetworkFindName(temporary_name, lastof(temporary_name))) { + NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); + strecpy(ci->client_name, temporary_name, lastof(ci->client_name)); NetworkUpdateClientInfo(CLIENT_ID_SERVER); } } diff --git a/src/network/network_func.h b/src/network/network_func.h index e7709d3075..cb0ca3355c 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -35,9 +35,9 @@ extern StringList _network_host_list; extern StringList _network_ban_list; byte NetworkSpectatorCount(); -bool NetworkIsValidClientName(const char *client_name); +bool NetworkIsValidClientName(const std::string_view client_name); bool NetworkValidateClientName(); -bool NetworkValidateClientName(char *client_name); +bool NetworkValidateClientName(std::string &client_name); void NetworkUpdateClientName(); bool NetworkCompanyHasClients(CompanyID company); const char *NetworkChangeCompanyPassword(CompanyID company_id, const char *password); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 6fdf73bc4b..8dec56a6de 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -462,7 +462,7 @@ public: this->FinishInitNested(WN_NETWORK_WINDOW_GAME); this->querystrings[WID_NG_CLIENT] = &this->name_editbox; - this->name_editbox.text.Assign(_settings_client.network.client_name); + this->name_editbox.text.Assign(_settings_client.network.client_name.c_str()); this->querystrings[WID_NG_FILTER] = &this->filter_editbox; this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR; @@ -820,7 +820,7 @@ public: case WID_NG_CLIENT: /* Validation of the name will happen once the user tries to join or start a game, as getting * error messages while typing (e.g. when you clear the name) defeats the purpose of the check. */ - strecpy(_settings_client.network.client_name, this->name_editbox.text.buf, lastof(_settings_client.network.client_name)); + _settings_client.network.client_name = this->name_editbox.text.buf; break; } } @@ -2207,11 +2207,12 @@ public: } case WID_CL_CLIENT_NAME_EDIT: { - if (!NetworkValidateClientName(str)) break; + std::string client_name(str); + if (!NetworkValidateClientName(client_name)) break; uint index; GetSettingFromName("network.client_name", &index); - SetSettingValue(index, str); + SetSettingValue(index, client_name.c_str()); this->InvalidateData(); break; } diff --git a/src/newgrf_storage.h b/src/newgrf_storage.h index ff322c9445..819e8d9394 100644 --- a/src/newgrf_storage.h +++ b/src/newgrf_storage.h @@ -21,7 +21,7 @@ enum PersistentStorageMode { PSM_LEAVE_GAMELOOP, ///< Leave the gameloop, changes will be temporary. PSM_ENTER_COMMAND, ///< Enter command scope, changes will be permanent. PSM_LEAVE_COMMAND, ///< Leave command scope, revert to previous mode. - PSM_ENTER_TESTMODE, ///< Enter command test mode, changes will be tempoary. + PSM_ENTER_TESTMODE, ///< Enter command test mode, changes will be temporary. PSM_LEAVE_TESTMODE, ///< Leave command test mode, revert to previous mode. }; diff --git a/src/settings_type.h b/src/settings_type.h index 8cff371428..66e3e38eb7 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -267,7 +267,7 @@ struct NetworkSettings { std::string rcon_password; ///< password for rconsole (server side) std::string admin_password; ///< password for the admin network bool server_advertise; ///< advertise the server to the masterserver - char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) + std::string client_name; ///< name of the player (as client) std::string default_company_pass; ///< default password for new companies in encrypted form std::string connect_to_ip; ///< default for the "Add server" query std::string network_id; ///< network ID for servers diff --git a/src/string.cpp b/src/string.cpp index 38f7d1bd10..a76006fe81 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -326,19 +326,10 @@ bool StrValid(const char *str, const char *last) * When there are spaces at the begin, the whole string is moved forward. * @param str The string to perform the in place left trimming on. */ -static void StrLeftTrimInPlace(char *str) +static void StrLeftTrimInPlace(std::string &str) { - if (StrEmpty(str)) return; - - char *first_non_space = str; - while (*first_non_space == ' ') first_non_space++; - - if (first_non_space == str) return; - - /* The source will reach '\0' first, but set the '\0' on the destination afterwards. */ - char *dst = str; - for (char *src = first_non_space; *src != '\0'; dst++, src++) *dst = *src; - *dst = '\0'; + size_t pos = str.find_first_not_of(' '); + str.erase(0, pos); } /** @@ -347,24 +338,10 @@ static void StrLeftTrimInPlace(char *str) * When there are spaces at the end, the '\0' will be moved forward. * @param str The string to perform the in place left trimming on. */ -static void StrRightTrimInPlace(char *str) +static void StrRightTrimInPlace(std::string &str) { - if (StrEmpty(str)) return; - - char *end = str; - while (*end != '\0') end++; - - char *last_non_space = end - 1; - while (last_non_space >= str && *last_non_space == ' ') last_non_space--; - - /* The last non space points to the last character of the string that is not - * a space. For a string with only spaces or an empty string this would be - * the position before the begin of the string. The previous search ensures - * that this location before the string is not read. - * In any case, the character after the last non space character will be - * either a space or the existing termination, so it can be set to '\0'. - */ - last_non_space[1] = '\0'; + size_t pos = str.find_last_not_of(' '); + if (pos != std::string::npos) str.erase(pos + 1); } /** @@ -374,7 +351,7 @@ static void StrRightTrimInPlace(char *str) * and when there are spaces at the back the '\0' termination is moved. * @param str The string to perform the in place trimming on. */ -void StrTrimInPlace(char *str) +void StrTrimInPlace(std::string &str) { StrLeftTrimInPlace(str); StrRightTrimInPlace(str); diff --git a/src/string_func.h b/src/string_func.h index 787fd6413e..7ff84d43ee 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -49,7 +49,7 @@ bool strtolower(char *str); bool strtolower(std::string &str, std::string::size_type offs = 0); bool StrValid(const char *str, const char *last) NOACCESS(2); -void StrTrimInPlace(char *str); +void StrTrimInPlace(std::string &str); /** * Check if a string buffer is empty. diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 09a89821a2..d0a3dc1778 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -126,9 +126,6 @@ static size_t ConvertLandscape(const char *value); #define SDTC_LIST(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) -#define SDTC_STR(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) - #define SDTC_SSTR(var, type, flags, guiflags, def, max_length, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, max_length, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index 0a439edaa4..5b639e0de4 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -69,7 +69,6 @@ SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_STR = SDTC_STR( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), @@ -3917,9 +3916,10 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = false -[SDTC_STR] +[SDTC_SSTR] var = network.client_name -type = SLE_STRB +type = SLE_STR +length = NETWORK_CLIENT_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr proc = UpdateClientName From 2022e3482417eceeb1045d01c2aa64db42f03f08 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 28 Apr 2021 16:30:49 +0200 Subject: [PATCH 177/800] Codechange: move locale settings to std::string --- src/settings_type.h | 74 +++++++++++++++++------------------ src/strings.cpp | 18 ++++----- src/table/settings.h.preamble | 3 ++ src/table/settings.ini | 8 ++-- 4 files changed, 53 insertions(+), 50 deletions(-) diff --git a/src/settings_type.h b/src/settings_type.h index 66e3e38eb7..bba95ad967 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -214,16 +214,16 @@ struct MusicSettings { /** Settings related to currency/unit systems. */ struct LocaleSettings { - byte currency; ///< currency we currently use - byte units_velocity; ///< unit system for velocity - byte units_power; ///< unit system for power - byte units_weight; ///< unit system for weight - byte units_volume; ///< unit system for volume - byte units_force; ///< unit system for force - byte units_height; ///< unit system for height - char *digit_group_separator; ///< thousand separator for non-currencies - char *digit_group_separator_currency; ///< thousand separator for currencies - char *digit_decimal_separator; ///< decimal separator + byte currency; ///< currency we currently use + byte units_velocity; ///< unit system for velocity + byte units_power; ///< unit system for power + byte units_weight; ///< unit system for weight + byte units_volume; ///< unit system for volume + byte units_force; ///< unit system for force + byte units_height; ///< unit system for height + std::string digit_group_separator; ///< thousand separator for non-currencies + std::string digit_group_separator_currency; ///< thousand separator for currencies + std::string digit_decimal_separator; ///< decimal separator }; /** Settings related to news */ @@ -247,42 +247,42 @@ struct NewsSettings { /** All settings related to the network. */ struct NetworkSettings { - uint16 sync_freq; ///< how often do we check whether we are still in-sync - uint8 frame_freq; ///< how often do we send commands to the clients - uint16 commands_per_frame; ///< how many commands may be sent each frame_freq frames? - uint16 max_commands_in_queue; ///< how many commands may there be in the incoming queue before dropping the connection? - uint16 bytes_per_frame; ///< how many bytes may, over a long period, be received per frame? - uint16 bytes_per_frame_burst; ///< how many bytes may, over a short period, be received? - uint16 max_init_time; ///< maximum amount of time, in game ticks, a client may take to initiate joining - uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to sync up during joining - uint16 max_download_time; ///< maximum amount of time, in game ticks, a client may take to download the map - uint16 max_password_time; ///< maximum amount of time, in game ticks, a client may take to enter the password - uint16 max_lag_time; ///< maximum amount of time, in game ticks, a client may be lagging behind the server - bool pause_on_join; ///< pause the game when people join - uint16 server_port; ///< port the server listens on - uint16 server_admin_port; ///< port the server listens on for the admin network - bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network + uint16 sync_freq; ///< how often do we check whether we are still in-sync + uint8 frame_freq; ///< how often do we send commands to the clients + uint16 commands_per_frame; ///< how many commands may be sent each frame_freq frames? + uint16 max_commands_in_queue; ///< how many commands may there be in the incoming queue before dropping the connection? + uint16 bytes_per_frame; ///< how many bytes may, over a long period, be received per frame? + uint16 bytes_per_frame_burst; ///< how many bytes may, over a short period, be received? + uint16 max_init_time; ///< maximum amount of time, in game ticks, a client may take to initiate joining + uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to sync up during joining + uint16 max_download_time; ///< maximum amount of time, in game ticks, a client may take to download the map + uint16 max_password_time; ///< maximum amount of time, in game ticks, a client may take to enter the password + uint16 max_lag_time; ///< maximum amount of time, in game ticks, a client may be lagging behind the server + bool pause_on_join; ///< pause the game when people join + uint16 server_port; ///< port the server listens on + uint16 server_admin_port; ///< port the server listens on for the admin network + bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network std::string server_name; ///< name of the server std::string server_password; ///< password for joining this server std::string rcon_password; ///< password for rconsole (server side) std::string admin_password; ///< password for the admin network - bool server_advertise; ///< advertise the server to the masterserver + bool server_advertise; ///< advertise the server to the masterserver std::string client_name; ///< name of the player (as client) std::string default_company_pass; ///< default password for new companies in encrypted form std::string connect_to_ip; ///< default for the "Add server" query std::string network_id; ///< network ID for servers - bool autoclean_companies; ///< automatically remove companies that are not in use - uint8 autoclean_unprotected; ///< remove passwordless companies after this many months - uint8 autoclean_protected; ///< remove the password from passworded companies after this many months - uint8 autoclean_novehicles; ///< remove companies with no vehicles after this many months - uint8 max_companies; ///< maximum amount of companies - uint8 max_clients; ///< maximum amount of clients - uint8 max_spectators; ///< maximum amount of spectators - Year restart_game_year; ///< year the server restarts - uint8 min_active_clients; ///< minimum amount of active clients to unpause the game - bool reload_cfg; ///< reload the config file before restarting + bool autoclean_companies; ///< automatically remove companies that are not in use + uint8 autoclean_unprotected; ///< remove passwordless companies after this many months + uint8 autoclean_protected; ///< remove the password from passworded companies after this many months + uint8 autoclean_novehicles; ///< remove companies with no vehicles after this many months + uint8 max_companies; ///< maximum amount of companies + uint8 max_clients; ///< maximum amount of clients + uint8 max_spectators; ///< maximum amount of spectators + Year restart_game_year; ///< year the server restarts + uint8 min_active_clients; ///< minimum amount of active clients to unpause the game + bool reload_cfg; ///< reload the config file before restarting std::string last_joined; ///< Last joined server - bool no_http_content_downloads; ///< do not do content downloads over HTTP + bool no_http_content_downloads; ///< do not do content downloads over HTTP }; /** Settings related to the creation of games. */ diff --git a/src/strings.cpp b/src/strings.cpp index 2b6dbc3ef9..3c2c07bdef 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -343,8 +343,8 @@ static char *FormatNumber(char *buff, int64 number, const char *last, const char uint64 tot = 0; for (int i = 0; i < max_digits; i++) { if (i == max_digits - fractional_digits) { - const char *decimal_separator = _settings_game.locale.digit_decimal_separator; - if (decimal_separator == nullptr) decimal_separator = _langpack.langpack->digit_decimal_separator; + const char *decimal_separator = _settings_game.locale.digit_decimal_separator.c_str(); + if (StrEmpty(decimal_separator)) decimal_separator = _langpack.langpack->digit_decimal_separator; buff += seprintf(buff, last, "%s", decimal_separator); } @@ -368,8 +368,8 @@ static char *FormatNumber(char *buff, int64 number, const char *last, const char static char *FormatCommaNumber(char *buff, int64 number, const char *last, int fractional_digits = 0) { - const char *separator = _settings_game.locale.digit_group_separator; - if (separator == nullptr) separator = _langpack.langpack->digit_group_separator; + const char *separator = _settings_game.locale.digit_group_separator.c_str(); + if (StrEmpty(separator)) separator = _langpack.langpack->digit_group_separator; return FormatNumber(buff, number, last, separator, 1, fractional_digits); } @@ -407,8 +407,8 @@ static char *FormatBytes(char *buff, int64 number, const char *last) id++; } - const char *decimal_separator = _settings_game.locale.digit_decimal_separator; - if (decimal_separator == nullptr) decimal_separator = _langpack.langpack->digit_decimal_separator; + const char *decimal_separator = _settings_game.locale.digit_decimal_separator.c_str(); + if (StrEmpty(decimal_separator)) decimal_separator = _langpack.langpack->digit_decimal_separator; if (number < 1024) { id = 0; @@ -501,9 +501,9 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money n } } - const char *separator = _settings_game.locale.digit_group_separator_currency; - if (separator == nullptr && !StrEmpty(_currency->separator)) separator = _currency->separator; - if (separator == nullptr) separator = _langpack.langpack->digit_group_separator_currency; + const char *separator = _settings_game.locale.digit_group_separator_currency.c_str(); + if (StrEmpty(separator)) separator = _currency->separator; + if (StrEmpty(separator)) separator = _langpack.langpack->digit_group_separator_currency; buff = FormatNumber(buff, number, last, separator); buff = strecpy(buff, multiplier, last); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index d0a3dc1778..14eeb9fdc0 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -107,6 +107,9 @@ static size_t ConvertLandscape(const char *value); #define SDT_STR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) +#define SDT_SSTR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ + SDT_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) + #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, load, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index 5b639e0de4..66dc55e9bb 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -73,7 +73,7 @@ SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), -SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL($length, $from, $to), SDT_END = SDT_END() @@ -2640,7 +2640,7 @@ str = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL -[SDT_STR] +[SDT_SSTR] base = GameSettings var = locale.digit_group_separator type = SLE_STRQ @@ -2650,7 +2650,7 @@ def = nullptr proc = RedrawScreen cat = SC_BASIC -[SDT_STR] +[SDT_SSTR] base = GameSettings var = locale.digit_group_separator_currency type = SLE_STRQ @@ -2660,7 +2660,7 @@ def = nullptr proc = RedrawScreen cat = SC_BASIC -[SDT_STR] +[SDT_SSTR] base = GameSettings var = locale.digit_decimal_separator type = SLE_STRQ From 65cbde4b30f8fdf6d4cf1196f6a596a5550c9aee Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 28 Apr 2021 16:46:24 +0200 Subject: [PATCH 178/800] Codechange: move currency settings to std::string --- src/currency.h | 16 +++++++--------- src/newgrf.cpp | 26 ++++++++++++++++++++------ src/settings_gui.cpp | 12 ++++++------ src/strings.cpp | 6 +++--- src/table/currency_settings.ini | 18 +++++++++--------- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/currency.h b/src/currency.h index e97fc6cb84..10caa59d3a 100644 --- a/src/currency.h +++ b/src/currency.h @@ -70,11 +70,11 @@ enum Currencies { /** Specification of a currency. */ struct CurrencySpec { - uint16 rate; - char separator[8]; - Year to_euro; ///< %Year of switching to the Euro. May also be #CF_NOEURO or #CF_ISEURO. - char prefix[16]; - char suffix[16]; + uint16 rate; ///< The conversion rate compared to the base currency. + std::string separator; ///< The thousands separator for this currency. + Year to_euro; ///< %Year of switching to the Euro. May also be #CF_NOEURO or #CF_ISEURO. + std::string prefix; ///< Prefix to apply when formatting money in this currency. + std::string suffix; ///< Suffix to apply when formatting money in this currency. /** * The currency symbol is represented by two possible values, prefix and suffix * Usage of one or the other is determined by #symbol_pos. @@ -89,11 +89,9 @@ struct CurrencySpec { CurrencySpec() = default; - CurrencySpec(uint16 rate, const char *separator, Year to_euro, const char *prefix, const char *suffix, byte symbol_pos, StringID name) : rate(rate), to_euro(to_euro), symbol_pos(symbol_pos), name(name) + CurrencySpec(uint16 rate, const char *separator, Year to_euro, const char *prefix, const char *suffix, byte symbol_pos, StringID name) : + rate(rate), separator(separator), to_euro(to_euro), prefix(prefix), suffix(suffix), symbol_pos(symbol_pos), name(name) { - strecpy(this->separator, separator, lastof(this->separator)); - strecpy(this->prefix, prefix, lastof(this->prefix)); - strecpy(this->suffix, suffix, lastof(this->suffix)); } }; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index c372f033a8..3473cbdc23 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2587,6 +2587,22 @@ static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader return CIR_SUCCESS; } +/** + * Helper to read a DWord worth of bytes from the reader + * and to return it as a valid string. + * @param reader The source of the DWord. + * @return The read DWord as string. + */ +static std::string ReadDWordAsString(ByteReader *reader) +{ + char output[5]; + for (int i = 0; i < 4; i++) output[i] = reader->ReadByte(); + output[4] = '\0'; + str_validate(output, lastof(output)); + + return std::string(output); +} + /** * Define properties for global variables * @param gvid ID of the global variable. @@ -2674,11 +2690,10 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By case 0x0D: { // Currency prefix symbol uint curidx = GetNewgrfCurrencyIdConverted(gvid + i); - uint32 tempfix = buf->ReadDWord(); + std::string prefix = ReadDWordAsString(buf); if (curidx < CURRENCY_END) { - memcpy(_currency_specs[curidx].prefix, &tempfix, 4); - _currency_specs[curidx].prefix[4] = 0; + _currency_specs[curidx].prefix = prefix; } else { grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx); } @@ -2687,11 +2702,10 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By case 0x0E: { // Currency suffix symbol uint curidx = GetNewgrfCurrencyIdConverted(gvid + i); - uint32 tempfix = buf->ReadDWord(); + std::string suffix = ReadDWordAsString(buf); if (curidx < CURRENCY_END) { - memcpy(&_currency_specs[curidx].suffix, &tempfix, 4); - _currency_specs[curidx].suffix[4] = 0; + _currency_specs[curidx].suffix = suffix; } else { grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 15c6a887e9..664cfbd218 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2668,7 +2668,7 @@ struct CustomCurrencyWindow : Window { case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); str = STR_JUST_RAW_STRING; - len = sizeof(_custom_currency.separator) - 1; // Number of characters excluding '\0' termination + len = 7; line = WID_CC_SEPARATOR; break; @@ -2676,7 +2676,7 @@ struct CustomCurrencyWindow : Window { case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); str = STR_JUST_RAW_STRING; - len = sizeof(_custom_currency.prefix) - 1; // Number of characters excluding '\0' termination + len = 15; line = WID_CC_PREFIX; break; @@ -2684,7 +2684,7 @@ struct CustomCurrencyWindow : Window { case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); str = STR_JUST_RAW_STRING; - len = sizeof(_custom_currency.suffix) - 1; // Number of characters excluding '\0' termination + len = 15; line = WID_CC_SUFFIX; break; @@ -2728,15 +2728,15 @@ struct CustomCurrencyWindow : Window { break; case WID_CC_SEPARATOR: // Thousands separator - strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator)); + _custom_currency.separator = str; break; case WID_CC_PREFIX: - strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix)); + _custom_currency.prefix = str; break; case WID_CC_SUFFIX: - strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix)); + _custom_currency.suffix = str; break; case WID_CC_YEAR: { // Year to switch to euro diff --git a/src/strings.cpp b/src/strings.cpp index 3c2c07bdef..b5cb59d206 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -486,7 +486,7 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money n /* Add prefix part, following symbol_pos specification. * Here, it can can be either 0 (prefix) or 2 (both prefix and suffix). * The only remaining value is 1 (suffix), so everything that is not 1 */ - if (spec->symbol_pos != 1) buff = strecpy(buff, spec->prefix, last); + if (spec->symbol_pos != 1) buff = strecpy(buff, spec->prefix.c_str(), last); /* for huge numbers, compact the number into k or M */ if (compact) { @@ -502,7 +502,7 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money n } const char *separator = _settings_game.locale.digit_group_separator_currency.c_str(); - if (StrEmpty(separator)) separator = _currency->separator; + if (StrEmpty(separator)) separator = _currency->separator.c_str(); if (StrEmpty(separator)) separator = _langpack.langpack->digit_group_separator_currency; buff = FormatNumber(buff, number, last, separator); buff = strecpy(buff, multiplier, last); @@ -510,7 +510,7 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money n /* Add suffix part, following symbol_pos specification. * Here, it can can be either 1 (suffix) or 2 (both prefix and suffix). * The only remaining value is 1 (prefix), so everything that is not 0 */ - if (spec->symbol_pos != 0) buff = strecpy(buff, spec->suffix, last); + if (spec->symbol_pos != 0) buff = strecpy(buff, spec->suffix.c_str(), last); if (negative) { if (buff + Utf8CharLen(SCC_POP_COLOUR) > last) return buff; diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 3e51d0240a..d2f12473e7 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -9,9 +9,9 @@ static const SettingDesc _currency_settings[] = { [post-amble] }; [templates] -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_END = SDT_END() +SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_END = SDT_END() [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -41,10 +41,10 @@ def = 1 min = 0 max = UINT16_MAX -[SDT_STR] +[SDT_SSTR] base = CurrencySpec var = separator -type = SLE_STRBQ +type = SLE_STRQ def = ""."" cat = SC_BASIC @@ -56,16 +56,16 @@ def = 0 min = MIN_YEAR max = MAX_YEAR -[SDT_STR] +[SDT_SSTR] base = CurrencySpec var = prefix -type = SLE_STRBQ +type = SLE_STRQ def = nullptr -[SDT_STR] +[SDT_SSTR] base = CurrencySpec var = suffix -type = SLE_STRBQ +type = SLE_STRQ def = "" credits"" [SDT_END] From 77330d09fd8307261e94fe0eb0260f5ca5cc3898 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 28 Apr 2021 17:10:15 +0200 Subject: [PATCH 179/800] Codechange: move font settings to std::string --- src/fontcache.cpp | 15 ++++++++------- src/fontcache.h | 6 +++--- src/os/macosx/font_osx.cpp | 12 ++++++------ src/os/windows/font_win32.cpp | 21 +++++++++++---------- src/strings.cpp | 11 +++++------ src/table/misc_settings.ini | 16 ++++++++-------- src/textfile_gui.cpp | 2 +- 7 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 530dc7cf80..2535ac69fb 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -490,7 +490,7 @@ static void LoadFreeTypeFont(FontSize fs) case FS_MONO: settings = &_freetype.mono; break; } - if (StrEmpty(settings->font)) return; + if (settings->font.empty()) return; if (_library == nullptr) { if (FT_Init_FreeType(&_library) != FT_Err_Ok) { @@ -501,19 +501,20 @@ static void LoadFreeTypeFont(FontSize fs) DEBUG(freetype, 2, "Initialized"); } + const char *font_name = settings->font.c_str(); FT_Face face = nullptr; /* If font is an absolute path to a ttf, try loading that first. */ - FT_Error error = FT_New_Face(_library, settings->font, 0, &face); + FT_Error error = FT_New_Face(_library, font_name, 0, &face); #if defined(WITH_COCOA) extern void MacOSRegisterExternalFont(const char *file_path); - if (error == FT_Err_Ok) MacOSRegisterExternalFont(settings->font); + if (error == FT_Err_Ok) MacOSRegisterExternalFont(font_name); #endif if (error != FT_Err_Ok) { /* Check if font is a relative filename in one of our search-paths. */ - std::string full_font = FioFindFullPath(BASE_DIR, settings->font); + std::string full_font = FioFindFullPath(BASE_DIR, font_name); if (!full_font.empty()) { error = FT_New_Face(_library, full_font.c_str(), 0, &face); #if defined(WITH_COCOA) @@ -523,10 +524,10 @@ static void LoadFreeTypeFont(FontSize fs) } /* Try loading based on font face name (OS-wide fonts). */ - if (error != FT_Err_Ok) error = GetFontByFaceName(settings->font, &face); + if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, &face); if (error == FT_Err_Ok) { - DEBUG(freetype, 2, "Requested '%s', using '%s %s'", settings->font, face->family_name, face->style_name); + DEBUG(freetype, 2, "Requested '%s', using '%s %s'", font_name, face->family_name, face->style_name); /* Attempt to select the unicode character map */ error = FT_Select_Charmap(face, ft_encoding_unicode); @@ -556,7 +557,7 @@ static void LoadFreeTypeFont(FontSize fs) FT_Done_Face(face); static const char *SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; - ShowInfoF("Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", settings->font, SIZE_TO_NAME[fs], error); + ShowInfoF("Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", font_name, SIZE_TO_NAME[fs], error); return; found_face: diff --git a/src/fontcache.h b/src/fontcache.h index c3b20cb4f7..2eb5634cfb 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -214,9 +214,9 @@ static inline bool GetDrawGlyphShadow(FontSize size) /** Settings for a single freetype font. */ struct FreeTypeSubSetting { - char font[MAX_PATH]; ///< The name of the font, or path to the font. - uint size; ///< The (requested) size of the font. - bool aa; ///< Whether to do anti aliasing or not. + std::string font; ///< The name of the font, or path to the font. + uint size; ///< The (requested) size of the font. + bool aa; ///< Whether to do anti aliasing or not. const void *os_handle = nullptr; ///< Optional native OS font info. Only valid during font search. }; diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index f5ceed8507..295fcf257a 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -359,7 +359,7 @@ void LoadCoreTextFont(FontSize fs) case FS_MONO: settings = &_freetype.mono; break; } - if (StrEmpty(settings->font)) return; + if (settings->font.empty()) return; CFAutoRelease font_ref; @@ -375,10 +375,10 @@ void LoadCoreTextFont(FontSize fs) /* See if this is an absolute path. */ if (FileExists(settings->font)) { - path.reset(CFStringCreateWithCString(kCFAllocatorDefault, settings->font, kCFStringEncodingUTF8)); + path.reset(CFStringCreateWithCString(kCFAllocatorDefault, settings->font.c_str(), kCFStringEncodingUTF8)); } else { /* Scan the search-paths to see if it can be found. */ - std::string full_font = FioFindFullPath(BASE_DIR, settings->font); + std::string full_font = FioFindFullPath(BASE_DIR, settings->font.c_str()); if (!full_font.empty()) { path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8)); } @@ -393,13 +393,13 @@ void LoadCoreTextFont(FontSize fs) font_ref.reset((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0)); CFRetain(font_ref.get()); } else { - ShowInfoF("Unable to load file '%s' for %s font, using default OS font selection instead", settings->font, SIZE_TO_NAME[fs]); + ShowInfoF("Unable to load file '%s' for %s font, using default OS font selection instead", settings->font.c_str(), SIZE_TO_NAME[fs]); } } } if (!font_ref) { - CFAutoRelease name(CFStringCreateWithCString(kCFAllocatorDefault, settings->font, kCFStringEncodingUTF8)); + CFAutoRelease name(CFStringCreateWithCString(kCFAllocatorDefault, settings->font.c_str(), kCFStringEncodingUTF8)); /* Simply creating the font using CTFontCreateWithNameAndSize will *always* return * something, no matter the name. As such, we can't use it to check for existence. @@ -417,7 +417,7 @@ void LoadCoreTextFont(FontSize fs) } if (!font_ref) { - ShowInfoF("Unable to use '%s' for %s font, using sprite font instead", settings->font, SIZE_TO_NAME[fs]); + ShowInfoF("Unable to use '%s' for %s font, using sprite font instead", settings->font.c_str(), SIZE_TO_NAME[fs]); return; } diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 55d4193e89..6c4e67deb0 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -588,8 +588,9 @@ void LoadWin32Font(FontSize fs) default: NOT_REACHED(); } - if (StrEmpty(settings->font)) return; + if (settings->font.empty()) return; + const char *font_name = settings->font.c_str(); LOGFONT logfont; MemSetT(&logfont, 0); logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH; @@ -599,19 +600,19 @@ void LoadWin32Font(FontSize fs) if (settings->os_handle != nullptr) { logfont = *(const LOGFONT *)settings->os_handle; - } else if (strchr(settings->font, '.') != nullptr) { + } else if (strchr(font_name, '.') != nullptr) { /* Might be a font file name, try load it. */ wchar_t fontPath[MAX_PATH] = {}; /* See if this is an absolute path. */ if (FileExists(settings->font)) { - convert_to_fs(settings->font, fontPath, lengthof(fontPath)); + convert_to_fs(font_name, fontPath, lengthof(fontPath)); } else { /* Scan the search-paths to see if it can be found. */ - std::string full_font = FioFindFullPath(BASE_DIR, settings->font); + std::string full_font = FioFindFullPath(BASE_DIR, font_name); if (!full_font.empty()) { - convert_to_fs(full_font.c_str(), fontPath, lengthof(fontPath)); + convert_to_fs(font_name, fontPath, lengthof(fontPath)); } } @@ -639,22 +640,22 @@ void LoadWin32Font(FontSize fs) _wsplitpath(fontPath, nullptr, nullptr, fname, nullptr); wcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE); - logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr || strcasestr(settings->font, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. + logfont.lfWeight = strcasestr(font_name, " bold") != nullptr || strcasestr(font_name, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. } } else { - ShowInfoF("Unable to load file '%s' for %s font, using default windows font selection instead", settings->font, SIZE_TO_NAME[fs]); + ShowInfoF("Unable to load file '%s' for %s font, using default windows font selection instead", font_name, SIZE_TO_NAME[fs]); } } } if (logfont.lfFaceName[0] == 0) { - logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. - convert_to_fs(settings->font, logfont.lfFaceName, lengthof(logfont.lfFaceName)); + logfont.lfWeight = strcasestr(font_name, " bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. + convert_to_fs(font_name, logfont.lfFaceName, lengthof(logfont.lfFaceName)); } HFONT font = CreateFontIndirect(&logfont); if (font == nullptr) { - ShowInfoF("Unable to use '%s' for %s font, Win32 reported error 0x%lX, using sprite font instead", settings->font, SIZE_TO_NAME[fs], GetLastError()); + ShowInfoF("Unable to use '%s' for %s font, Win32 reported error 0x%lX, using sprite font instead", font_name, SIZE_TO_NAME[fs], GetLastError()); return; } DeleteObject(font); diff --git a/src/strings.cpp b/src/strings.cpp index b5cb59d206..fb19438705 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2090,9 +2090,9 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher { void SetFontNames(FreeTypeSettings *settings, const char *font_name, const void *os_data) override { #if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) - strecpy(settings->small.font, font_name, lastof(settings->small.font)); - strecpy(settings->medium.font, font_name, lastof(settings->medium.font)); - strecpy(settings->large.font, font_name, lastof(settings->large.font)); + settings->small.font = font_name; + settings->medium.font = font_name; + settings->large.font = font_name; settings->small.os_handle = os_data; settings->medium.os_handle = os_data; @@ -2123,15 +2123,14 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) if (bad_font) { /* We found an unprintable character... lets try whether we can find * a fallback font that can print the characters in the current language. */ - FreeTypeSettings backup; - memcpy(&backup, &_freetype, sizeof(backup)); + FreeTypeSettings backup = _freetype; _freetype.mono.os_handle = nullptr; _freetype.medium.os_handle = nullptr; bad_font = !SetFallbackFont(&_freetype, _langpack.langpack->isocode, _langpack.langpack->winlangid, searcher); - memcpy(&_freetype, &backup, sizeof(backup)); + _freetype = backup; if (!bad_font) { /* Show that we loaded fallback font. To do this properly we have diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 49a4caa14c..39df34b78a 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -175,31 +175,31 @@ name = ""rightclick_emulate"" var = _rightclick_emulate def = false -[SDTG_STR] +[SDTG_SSTR] ifdef = HAS_TRUETYPE_FONT name = ""small_font"" -type = SLE_STRB +type = SLE_STR var = _freetype.small.font def = nullptr -[SDTG_STR] +[SDTG_SSTR] ifdef = HAS_TRUETYPE_FONT name = ""medium_font"" -type = SLE_STRB +type = SLE_STR var = _freetype.medium.font def = nullptr -[SDTG_STR] +[SDTG_SSTR] ifdef = HAS_TRUETYPE_FONT name = ""large_font"" -type = SLE_STRB +type = SLE_STR var = _freetype.large.font def = nullptr -[SDTG_STR] +[SDTG_SSTR] ifdef = HAS_TRUETYPE_FONT name = ""mono_font"" -type = SLE_STRB +type = SLE_STR var = _freetype.mono.font def = nullptr diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index ac8da5c2e9..d6c37a4580 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -218,7 +218,7 @@ void TextfileWindow::SetupScrollbars(bool force_reflow) /* virtual */ void TextfileWindow::SetFontNames(FreeTypeSettings *settings, const char *font_name, const void *os_data) { #if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) - strecpy(settings->mono.font, font_name, lastof(settings->mono.font)); + settings->mono.font = font_name; settings->mono.os_handle = os_data; #endif } From 95386dc2b8404519c91b9e0ad728c39fb1d9e118 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 28 Apr 2021 17:32:33 +0200 Subject: [PATCH 180/800] Codechange: move misc settings to std::string --- src/osk_gui.cpp | 10 ++++----- src/saveload/saveload.cpp | 44 ++++++++++++++++--------------------- src/saveload/saveload.h | 2 +- src/screenshot.cpp | 4 ++-- src/screenshot.h | 2 +- src/table/misc_settings.ini | 17 +++++++------- src/textbuf_gui.h | 3 +-- 7 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 155343f041..92b15eaba4 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -24,7 +24,7 @@ #include "safeguards.h" -char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1]; +std::string _keyboard_opt[2]; static WChar _keyboard[2][OSK_KEYBOARD_ENTRIES]; enum KeyStateBits { @@ -356,16 +356,16 @@ void GetKeyboardLayout() char errormark[2][OSK_KEYBOARD_ENTRIES + 1]; // used for marking invalid chars bool has_error = false; // true when an invalid char is detected - if (StrEmpty(_keyboard_opt[0])) { + if (_keyboard_opt[0].empty()) { GetString(keyboard[0], STR_OSK_KEYBOARD_LAYOUT, lastof(keyboard[0])); } else { - strecpy(keyboard[0], _keyboard_opt[0], lastof(keyboard[0])); + strecpy(keyboard[0], _keyboard_opt[0].c_str(), lastof(keyboard[0])); } - if (StrEmpty(_keyboard_opt[1])) { + if (_keyboard_opt[1].empty()) { GetString(keyboard[1], STR_OSK_KEYBOARD_LAYOUT_CAPS, lastof(keyboard[1])); } else { - strecpy(keyboard[1], _keyboard_opt[1], lastof(keyboard[1])); + strecpy(keyboard[1], _keyboard_opt[1].c_str(), lastof(keyboard[1])); } for (uint j = 0; j < 2; j++) { diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index f5e823a0df..504df30ab9 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -61,11 +61,11 @@ extern const SaveLoadVersion SAVEGAME_VERSION = (SaveLoadVersion)(SL_MAX_VERSION SavegameType _savegame_type; ///< type of savegame we are loading FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop. -uint32 _ttdp_version; ///< version of TTDP savegame (if applicable) -SaveLoadVersion _sl_version; ///< the major savegame version identifier -byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! -char _savegame_format[8]; ///< how to compress savegames -bool _do_autosave; ///< are we doing an autosave at the moment? +uint32 _ttdp_version; ///< version of TTDP savegame (if applicable) +SaveLoadVersion _sl_version; ///< the major savegame version identifier +byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! +std::string _savegame_format; ///< how to compress savegames +bool _do_autosave; ///< are we doing an autosave at the moment? /** What are we currently doing? */ enum SaveLoadAction { @@ -2351,36 +2351,33 @@ static const SaveLoadFormat _saveload_formats[] = { /** * Return the savegameformat of the game. Whether it was created with ZLIB compression * uncompressed, or another type - * @param s Name of the savegame format. If nullptr it picks the first available one + * @param full_name Name of the savegame format. If empty it picks the first available one * @param compression_level Output for telling what compression level we want. * @return Pointer to SaveLoadFormat struct giving all characteristics of this type of savegame */ -static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level) +static const SaveLoadFormat *GetSavegameFormat(const std::string &full_name, byte *compression_level) { const SaveLoadFormat *def = lastof(_saveload_formats); /* find default savegame format, the highest one with which files can be written */ while (!def->init_write) def--; - if (!StrEmpty(s)) { + if (!full_name.empty()) { /* Get the ":..." of the compression level out of the way */ - char *complevel = strrchr(s, ':'); - if (complevel != nullptr) *complevel = '\0'; + size_t separator = full_name.find(':'); + bool has_comp_level = separator != std::string::npos; + const std::string name(full_name, 0, has_comp_level ? separator : full_name.size()); for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) { - if (slf->init_write != nullptr && strcmp(s, slf->name) == 0) { + if (slf->init_write != nullptr && name.compare(slf->name) == 0) { *compression_level = slf->default_compression; - if (complevel != nullptr) { - /* There is a compression level in the string. - * First restore the : we removed to do proper name matching, - * then move the the begin of the actual version. */ - *complevel = ':'; - complevel++; + if (has_comp_level) { + const std::string complevel(full_name, separator + 1); - /* Get the version and determine whether all went fine. */ - char *end; - long level = strtol(complevel, &end, 10); - if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) { + /* Get the level and determine whether all went fine. */ + size_t processed; + long level = std::stol(complevel, &processed, 10); + if (processed == 0 || level != Clamp(level, slf->min_compression, slf->max_compression)) { SetDParamStr(0, complevel); ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL); } else { @@ -2391,12 +2388,9 @@ static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level) } } - SetDParamStr(0, s); + SetDParamStr(0, name); SetDParamStr(1, def->name); ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL); - - /* Restore the string by adding the : back */ - if (complevel != nullptr) *complevel = ':'; } *compression_level = def->default_compression; return def; diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 28513c70c1..50185902d1 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -934,7 +934,7 @@ static inline void SlSkipBytes(size_t length) for (; length != 0; length--) SlReadByte(); } -extern char _savegame_format[8]; +extern std::string _savegame_format; extern bool _do_autosave; #endif /* SAVELOAD_H */ diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 0e3bf3d8e2..6f42038daa 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -34,7 +34,7 @@ static const char * const SCREENSHOT_NAME = "screenshot"; ///< Default filename of a saved screenshot. static const char * const HEIGHTMAP_NAME = "heightmap"; ///< Default filename of a saved heightmap. -char _screenshot_format_name[8]; ///< Extension of the current screenshot format (corresponds with #_cur_screenshot_format). +std::string _screenshot_format_name; ///< Extension of the current screenshot format (corresponds with #_cur_screenshot_format). uint _num_screenshot_formats; ///< Number of available screenshot formats. uint _cur_screenshot_format; ///< Index of the currently selected screenshot format in #_screenshot_formats. static char _screenshot_name[128]; ///< Filename of the screenshot file. @@ -584,7 +584,7 @@ void InitializeScreenshotFormats() { uint j = 0; for (uint i = 0; i < lengthof(_screenshot_formats); i++) { - if (!strcmp(_screenshot_format_name, _screenshot_formats[i].extension)) { + if (_screenshot_format_name.compare(_screenshot_formats[i].extension) != 0) { j = i; break; } diff --git a/src/screenshot.h b/src/screenshot.h index e65813573f..6324cab11f 100644 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -31,7 +31,7 @@ void MakeScreenshotWithConfirm(ScreenshotType t); bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width = 0, uint32 height = 0); bool MakeMinimapWorldScreenshot(); -extern char _screenshot_format_name[8]; +extern std::string _screenshot_format_name; extern uint _num_screenshot_formats; extern uint _cur_screenshot_format; extern char _full_screenshot_name[MAX_PATH]; diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 39df34b78a..37994644a6 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -23,7 +23,6 @@ static const SettingDescGlobVarList _misc_settings[] = { SDTG_LIST = SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_STR = SDTG_STR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), @@ -156,16 +155,16 @@ var = _cur_resolution def = ""0,0"" cat = SC_BASIC -[SDTG_STR] +[SDTG_SSTR] name = ""screenshot_format"" -type = SLE_STRB +type = SLE_STR var = _screenshot_format_name def = nullptr cat = SC_EXPERT -[SDTG_STR] +[SDTG_SSTR] name = ""savegame_format"" -type = SLE_STRB +type = SLE_STR var = _savegame_format def = nullptr cat = SC_EXPERT @@ -308,16 +307,16 @@ min = 0 max = 0xFF cat = SC_BASIC -[SDTG_STR] +[SDTG_SSTR] name = ""keyboard"" -type = SLE_STRB +type = SLE_STR var = _keyboard_opt[0] def = nullptr cat = SC_EXPERT -[SDTG_STR] +[SDTG_SSTR] name = ""keyboard_caps"" -type = SLE_STRB +type = SLE_STR var = _keyboard_opt[1] def = nullptr cat = SC_EXPERT diff --git a/src/textbuf_gui.h b/src/textbuf_gui.h index c96f4e2e06..200d62582b 100644 --- a/src/textbuf_gui.h +++ b/src/textbuf_gui.h @@ -37,8 +37,7 @@ static const uint OSK_KEYBOARD_ENTRIES = 50; /** * The number of characters has to be OSK_KEYBOARD_ENTRIES. However, these * have to be UTF-8 encoded, which means up to 4 bytes per character. - * Furthermore the string needs to be '\0'-terminated. */ -extern char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1]; +extern std::string _keyboard_opt[2]; #endif /* TEXTBUF_GUI_H */ From a032714dc4ca2b620af1ba9a444840d46ec9326f Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Thu, 29 Apr 2021 19:04:27 +0200 Subject: [PATCH 181/800] Codechange: move script settings to std::string --- src/ini_load.cpp | 8 ++------ src/ini_type.h | 2 +- src/saveload/ai_sl.cpp | 31 +++++++++++++++---------------- src/saveload/game_sl.cpp | 31 +++++++++++++++---------------- src/script/script_config.cpp | 12 ++++++++---- src/script/script_config.hpp | 4 ++-- src/settings.cpp | 6 ++---- 7 files changed, 45 insertions(+), 49 deletions(-) diff --git a/src/ini_load.cpp b/src/ini_load.cpp index 5c208548f3..33bb46b12a 100644 --- a/src/ini_load.cpp +++ b/src/ini_load.cpp @@ -38,13 +38,9 @@ IniItem::~IniItem() * Replace the current value with another value. * @param value the value to replace with. */ -void IniItem::SetValue(const char *value) +void IniItem::SetValue(const std::string_view value) { - if (value == nullptr) { - this->value.reset(); - } else { - this->value.emplace(value); - } + this->value.emplace(value); } /** diff --git a/src/ini_type.h b/src/ini_type.h index 160ba7619c..882ccc7896 100644 --- a/src/ini_type.h +++ b/src/ini_type.h @@ -31,7 +31,7 @@ struct IniItem { IniItem(struct IniGroup *parent, const std::string &name); ~IniItem(); - void SetValue(const char *value); + void SetValue(const std::string_view value); }; /** A group within an ini file. */ diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index 0ece819813..4c751117f0 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -20,14 +20,14 @@ #include "../safeguards.h" -static char _ai_saveload_name[64]; -static int _ai_saveload_version; -static char _ai_saveload_settings[1024]; -static bool _ai_saveload_is_random; +static std::string _ai_saveload_name; +static int _ai_saveload_version; +static std::string _ai_saveload_settings; +static bool _ai_saveload_is_random; static const SaveLoad _ai_company[] = { - SLEG_STR(_ai_saveload_name, SLE_STRB), - SLEG_STR(_ai_saveload_settings, SLE_STRB), + SLEG_SSTR(_ai_saveload_name, SLE_STR), + SLEG_SSTR(_ai_saveload_settings, SLE_STR), SLEG_CONDVAR(_ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION), SLEG_CONDVAR(_ai_saveload_is_random, SLE_BOOL, SLV_136, SL_MAX_VERSION), SLE_END() @@ -39,17 +39,16 @@ static void SaveReal_AIPL(int *index_ptr) AIConfig *config = AIConfig::GetConfig(index); if (config->HasScript()) { - strecpy(_ai_saveload_name, config->GetName(), lastof(_ai_saveload_name)); + _ai_saveload_name = config->GetName(); _ai_saveload_version = config->GetVersion(); } else { /* No AI is configured for this so store an empty string as name. */ - _ai_saveload_name[0] = '\0'; + _ai_saveload_name.clear(); _ai_saveload_version = -1; } _ai_saveload_is_random = config->IsRandom(); - _ai_saveload_settings[0] = '\0'; - config->SettingsToString(_ai_saveload_settings, lastof(_ai_saveload_settings)); + _ai_saveload_settings = config->SettingsToString(); SlObject(nullptr, _ai_company); /* If the AI was active, store his data too */ @@ -77,25 +76,25 @@ static void Load_AIPL() } AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME); - if (StrEmpty(_ai_saveload_name)) { + if (_ai_saveload_name.empty()) { /* A random AI. */ config->Change(nullptr, -1, false, true); } else { - config->Change(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random); + config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random); if (!config->HasScript()) { /* No version of the AI available that can load the data. Try to load the * latest version of the AI instead. */ - config->Change(_ai_saveload_name, -1, false, _ai_saveload_is_random); + config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random); if (!config->HasScript()) { - if (strcmp(_ai_saveload_name, "%_dummy") != 0) { - DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version); + if (_ai_saveload_name.compare("%_dummy") != 0) { + DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version); DEBUG(script, 0, "A random other AI will be loaded in its place."); } else { DEBUG(script, 0, "The savegame had no AIs available at the time of saving."); DEBUG(script, 0, "A random available AI will be loaded now."); } } else { - DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version); + DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version); DEBUG(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible."); } /* Make sure the AI doesn't get the saveload data, as it was not the diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index b570d1054d..d7bb22a668 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -20,14 +20,14 @@ #include "../safeguards.h" -static char _game_saveload_name[64]; -static int _game_saveload_version; -static char _game_saveload_settings[1024]; -static bool _game_saveload_is_random; +static std::string _game_saveload_name; +static int _game_saveload_version; +static std::string _game_saveload_settings; +static bool _game_saveload_is_random; static const SaveLoad _game_script[] = { - SLEG_STR(_game_saveload_name, SLE_STRB), - SLEG_STR(_game_saveload_settings, SLE_STRB), + SLEG_SSTR(_game_saveload_name, SLE_STR), + SLEG_SSTR(_game_saveload_settings, SLE_STR), SLEG_VAR(_game_saveload_version, SLE_UINT32), SLEG_VAR(_game_saveload_is_random, SLE_BOOL), SLE_END() @@ -38,17 +38,16 @@ static void SaveReal_GSDT(int *index_ptr) GameConfig *config = GameConfig::GetConfig(); if (config->HasScript()) { - strecpy(_game_saveload_name, config->GetName(), lastof(_game_saveload_name)); + _game_saveload_name = config->GetName(); _game_saveload_version = config->GetVersion(); } else { /* No GameScript is configured for this so store an empty string as name. */ - _game_saveload_name[0] = '\0'; + _game_saveload_name.clear(); _game_saveload_version = -1; } _game_saveload_is_random = config->IsRandom(); - _game_saveload_settings[0] = '\0'; - config->SettingsToString(_game_saveload_settings, lastof(_game_saveload_settings)); + _game_saveload_settings = config->SettingsToString(); SlObject(nullptr, _game_script); Game::Save(); @@ -71,23 +70,23 @@ static void Load_GSDT() } GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); - if (StrEmpty(_game_saveload_name)) { + if (_game_saveload_name.empty()) { } else { - config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random); + config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random); if (!config->HasScript()) { /* No version of the GameScript available that can load the data. Try to load the * latest version of the GameScript instead. */ - config->Change(_game_saveload_name, -1, false, _game_saveload_is_random); + config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random); if (!config->HasScript()) { - if (strcmp(_game_saveload_name, "%_dummy") != 0) { - DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); + if (_game_saveload_name.compare("%_dummy") != 0) { + DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version); DEBUG(script, 0, "This game will continue to run without GameScript."); } else { DEBUG(script, 0, "The savegame had no GameScript available at the time of saving."); DEBUG(script, 0, "This game will continue to run without GameScript."); } } else { - DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); + DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version); DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible."); } /* Make sure the GameScript doesn't get the saveload data, as it was not the diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index eeab51bede..340b3b3f13 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -179,9 +179,9 @@ int ScriptConfig::GetVersion() const return this->version; } -void ScriptConfig::StringToSettings(const char *value) +void ScriptConfig::StringToSettings(const std::string &value) { - char *value_copy = stredup(value); + char *value_copy = stredup(value.c_str()); char *s = value_copy; while (s != nullptr) { @@ -205,8 +205,10 @@ void ScriptConfig::StringToSettings(const char *value) free(value_copy); } -void ScriptConfig::SettingsToString(char *string, const char *last) const +std::string ScriptConfig::SettingsToString() const { + char string[1024]; + char *last = lastof(string); char *s = string; *s = '\0'; for (const auto &item : this->settings) { @@ -216,7 +218,7 @@ void ScriptConfig::SettingsToString(char *string, const char *last) const /* Check if the string would fit in the destination */ size_t needed_size = strlen(item.first) + 1 + strlen(no); /* If it doesn't fit, skip the next settings */ - if (string + needed_size > last) break; + if (s + needed_size > last) break; s = strecat(s, item.first, last); s = strecat(s, "=", last); @@ -226,6 +228,8 @@ void ScriptConfig::SettingsToString(char *string, const char *last) const /* Remove the last ',', but only if at least one setting was saved. */ if (s != string) s[-1] = '\0'; + + return string; } const char *ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const diff --git a/src/script/script_config.hpp b/src/script/script_config.hpp index be231fcdc2..7ddc0ab6a2 100644 --- a/src/script/script_config.hpp +++ b/src/script/script_config.hpp @@ -169,13 +169,13 @@ public: * Convert a string which is stored in the config file or savegames to * custom settings of this Script. */ - void StringToSettings(const char *value); + void StringToSettings(const std::string &value); /** * Convert the custom settings to a string that can be stored in the config * file or savegames. */ - void SettingsToString(char *string, const char *last) const; + std::string SettingsToString() const; /** * Search a textfile file next to this script. diff --git a/src/settings.cpp b/src/settings.cpp index 0c6c08f9a4..d47c120f0d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1682,8 +1682,7 @@ static void AISaveConfig(IniFile *ini, const char *grpname) for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME); const char *name; - char value[1024]; - config->SettingsToString(value, lastof(value)); + std::string value = config->SettingsToString(); if (config->HasScript()) { name = config->GetName(); @@ -1705,8 +1704,7 @@ static void GameSaveConfig(IniFile *ini, const char *grpname) GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME); const char *name; - char value[1024]; - config->SettingsToString(value, lastof(value)); + std::string value = config->SettingsToString(); if (config->HasScript()) { name = config->GetName(); From 0f062b38826efbfa3b250da3943a6927346bc18c Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 28 Apr 2021 17:38:02 +0200 Subject: [PATCH 182/800] Codechange: clean up C-string support from settings --- src/saveload/saveload.cpp | 4 -- src/saveload/saveload.h | 3 -- src/script/api/script_gamesettings.cpp | 2 +- src/settings.cpp | 68 ++------------------------ src/settings_internal.h | 1 - src/table/settings.h.preamble | 6 --- 6 files changed, 5 insertions(+), 79 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 504df30ab9..34982ecfeb 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -585,7 +585,6 @@ static inline uint SlCalcConvMemLen(VarType conv) switch (length << 4) { case SLE_VAR_STRB: - case SLE_VAR_STRBQ: case SLE_VAR_STR: case SLE_VAR_STRQ: return SlReadArrayLength(); @@ -881,7 +880,6 @@ static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType con len = SIZE_MAX; break; case SLE_VAR_STRB: - case SLE_VAR_STRBQ: str = (const char *)ptr; len = length; break; @@ -920,7 +918,6 @@ static void SlString(void *ptr, size_t length, VarType conv) switch (GetVarMemType(conv)) { default: NOT_REACHED(); case SLE_VAR_STRB: - case SLE_VAR_STRBQ: len = SlCalcNetStringLen((char *)ptr, length); break; case SLE_VAR_STR: @@ -941,7 +938,6 @@ static void SlString(void *ptr, size_t length, VarType conv) switch (GetVarMemType(conv)) { default: NOT_REACHED(); case SLE_VAR_STRB: - case SLE_VAR_STRBQ: if (len >= length) { DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating"); SlCopyBytes(ptr, length); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 50185902d1..d28b81692f 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -446,7 +446,6 @@ enum VarTypes { SLE_VAR_U64 = 8 << 4, SLE_VAR_NULL = 9 << 4, ///< useful to write zeros in savegame. SLE_VAR_STRB = 10 << 4, ///< string (with pre-allocated buffer) - SLE_VAR_STRBQ = 11 << 4, ///< string enclosed in quotes (with pre-allocated buffer) SLE_VAR_STR = 12 << 4, ///< string pointer SLE_VAR_STRQ = 13 << 4, ///< string pointer enclosed in quotes SLE_VAR_NAME = 14 << 4, ///< old custom name to be converted to a char pointer @@ -470,7 +469,6 @@ enum VarTypes { SLE_CHAR = SLE_FILE_I8 | SLE_VAR_CHAR, SLE_STRINGID = SLE_FILE_STRINGID | SLE_VAR_U32, SLE_STRINGBUF = SLE_FILE_STRING | SLE_VAR_STRB, - SLE_STRINGBQUOTE = SLE_FILE_STRING | SLE_VAR_STRBQ, SLE_STRING = SLE_FILE_STRING | SLE_VAR_STR, SLE_STRINGQUOTE = SLE_FILE_STRING | SLE_VAR_STRQ, SLE_NAME = SLE_FILE_STRINGID | SLE_VAR_NAME, @@ -479,7 +477,6 @@ enum VarTypes { SLE_UINT = SLE_UINT32, SLE_INT = SLE_INT32, SLE_STRB = SLE_STRINGBUF, - SLE_STRBQ = SLE_STRINGBQUOTE, SLE_STR = SLE_STRING, SLE_STRQ = SLE_STRINGQUOTE, diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index bdaeb6c93e..2717d4ddd8 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -19,7 +19,7 @@ { uint i; const SettingDesc *sd = GetSettingFromName(setting, &i); - return sd != nullptr && sd->desc.cmd != SDT_STRING; + return sd != nullptr && sd->desc.cmd != SDT_STDSTRING; } /* static */ int32 ScriptGameSettings::GetValue(const char *setting) diff --git a/src/settings.cpp b/src/settings.cpp index d47c120f0d..6882179eb0 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -415,8 +415,7 @@ static const void *StringToVal(const SettingDescBase *desc, const char *orig_str return desc->def; } - case SDT_STDSTRING: - case SDT_STRING: return orig_str; + case SDT_STDSTRING: return orig_str; case SDT_INTLIST: return str; default: break; } @@ -495,35 +494,6 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) WriteValue(ptr, sd->save.conv, (int64)val); } -/** - * Set the string value of a setting. - * @param ptr Pointer to the storage location (might be a pointer to a pointer). - * @param sld Pointer to the information for the conversions and limitations to apply. - * @param p The string to save. - */ -static void Write_ValidateString(void *ptr, const SaveLoad *sld, const char *p) -{ - switch (GetVarMemType(sld->conv)) { - case SLE_VAR_STRB: - case SLE_VAR_STRBQ: - if (p != nullptr) { - char *begin = (char*)ptr; - char *end = begin + sld->length - 1; - strecpy(begin, p, end); - str_validate(begin, end, SVS_NONE); - } - break; - - case SLE_VAR_STR: - case SLE_VAR_STRQ: - free(*(char**)ptr); - *(char**)ptr = p == nullptr ? nullptr : stredup(p); - break; - - default: NOT_REACHED(); - } -} - /** * Set the string value of a setting. * @param ptr Pointer to the std::string. @@ -611,10 +581,6 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp Write_ValidateSetting(ptr, sd, (int32)(size_t)p); break; - case SDT_STRING: - Write_ValidateString(ptr, sld, (const char *)p); - break; - case SDT_STDSTRING: Write_ValidateStdString(ptr, sd, (const char *)p); break; @@ -736,24 +702,6 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp break; } - case SDT_STRING: - switch (GetVarMemType(sld->conv)) { - case SLE_VAR_STRB: strecpy(buf, (char*)ptr, lastof(buf)); break; - case SLE_VAR_STRBQ:seprintf(buf, lastof(buf), "\"%s\"", (char*)ptr); break; - case SLE_VAR_STR: strecpy(buf, *(char**)ptr, lastof(buf)); break; - - case SLE_VAR_STRQ: - if (*(char**)ptr == nullptr) { - buf[0] = '\0'; - } else { - seprintf(buf, lastof(buf), "\"%s\"", *(char**)ptr); - } - break; - - default: NOT_REACHED(); - } - break; - case SDT_STDSTRING: switch (GetVarMemType(sld->conv)) { case SLE_VAR_STR: strecpy(buf, reinterpret_cast(ptr)->c_str(), lastof(buf)); break; @@ -2123,11 +2071,7 @@ bool SetSettingValue(uint index, const char *value, bool force_newgame) } void *ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); - if (sd->desc.cmd == SDT_STRING) { - Write_ValidateString(ptr, &sd->save, value); - } else { - Write_ValidateStdString(ptr, sd, value); - } + Write_ValidateStdString(ptr, sd, value); if (sd->desc.proc != nullptr) sd->desc.proc(0); if (_save_config) SaveToConfig(); @@ -2184,7 +2128,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) } bool success; - if (sd->desc.cmd == SDT_STRING || sd->desc.cmd == SDT_STDSTRING) { + if (sd->desc.cmd == SDT_STDSTRING) { success = SetSettingValue(index, value, force_newgame); } else { uint32 val; @@ -2235,9 +2179,7 @@ void IConsoleGetSetting(const char *name, bool force_newgame) ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); - if (sd->desc.cmd == SDT_STRING) { - IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ) ? *(const char * const *)ptr : (const char *)ptr); - } else if (sd->desc.cmd == SDT_STDSTRING) { + if (sd->desc.cmd == SDT_STDSTRING) { IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); } else { if (sd->desc.cmd == SDT_BOOLX) { @@ -2268,8 +2210,6 @@ void IConsoleListSettings(const char *prefilter) if (sd->desc.cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); - } else if (sd->desc.cmd == SDT_STRING) { - seprintf(value, lastof(value), "%s", (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ) ? *(const char * const *)ptr : (const char *)ptr); } else if (sd->desc.cmd == SDT_STDSTRING) { seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); } else { diff --git a/src/settings_internal.h b/src/settings_internal.h index 14d3531a37..d5f237f3cc 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -26,7 +26,6 @@ enum SettingDescType : byte { SDT_ONEOFMANY = 2, ///< bitmasked number where only ONE bit may be set SDT_MANYOFMANY = 3, ///< bitmasked number where MULTIPLE bits may be set SDT_INTLIST = 4, ///< list of integers separated by a comma ',' - SDT_STRING = 5, ///< string with a pre-allocated buffer SDT_STDSTRING = 6, ///< \c std::string SDT_END, /* 9 more possible primitives */ diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 14eeb9fdc0..826b272d7a 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -73,9 +73,6 @@ static size_t ConvertLandscape(const char *value); #define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) -#define SDTG_STR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) - #define SDTG_SSTR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(name, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) @@ -104,9 +101,6 @@ static size_t ConvertLandscape(const char *value); #define SDT_LIST(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) -#define SDT_STR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) - #define SDT_SSTR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDT_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) From a9ff296c3d608f04a14cd604a94531f5b42b2061 Mon Sep 17 00:00:00 2001 From: frosch Date: Thu, 13 May 2021 15:45:07 +0200 Subject: [PATCH 183/800] Codechange: add constant for number of original cargoes. --- src/cargo_type.h | 1 + src/table/cargo_const.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cargo_type.h b/src/cargo_type.h index 89e6f13808..83af40a83a 100644 --- a/src/cargo_type.h +++ b/src/cargo_type.h @@ -61,6 +61,7 @@ enum CargoType { CT_PLASTIC = 10, CT_FIZZY_DRINKS = 11, + NUM_ORIGINAL_CARGO = 12, NUM_CARGO = 64, ///< Maximal number of cargo types in a game. CT_AUTO_REFIT = 0xFD, ///< Automatically choose cargo type when doing auto refitting. diff --git a/src/table/cargo_const.h b/src/table/cargo_const.h index 8518a25614..bb6f811a92 100644 --- a/src/table/cargo_const.h +++ b/src/table/cargo_const.h @@ -96,7 +96,7 @@ static const CargoSpec _default_cargo[] = { /** Table of cargo types available in each climate, by default */ -static const CargoLabel _default_climate_cargo[NUM_LANDSCAPE][12] = { +static const CargoLabel _default_climate_cargo[NUM_LANDSCAPE][NUM_ORIGINAL_CARGO] = { { 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'GRAI', 'WOOD', 'IORE', 'STEL', 'VALU', 33, }, { 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'WHEA', 'WOOD', 34, 'PAPR', 'GOLD', 'FOOD', }, { 'PASS', 'RUBR', 'MAIL', 4, 'FRUT', 'GOOD', 'MAIZ', 11, 'CORE', 'WATR', 'DIAM', 'FOOD', }, From 9f8d0b1bee104471aff1a5e318b2a92bc235d934 Mon Sep 17 00:00:00 2001 From: frosch Date: Fri, 30 Apr 2021 17:35:32 +0200 Subject: [PATCH 184/800] Fix: Resolve cargo-types of default vehicles via their cargo label. Default vehicles now behave as if they had a cargo translation table. This fixes default vehicles carrying seemingly random cargos, if NewGRF industry sets are present. This behavior is disabled, when a NewGRF touches any of the cargo-type or refitting properties. In that case it's up to the NewGRF to define its own cargo translation table. --- src/cargotype.cpp | 22 ++++++++++++++++++++++ src/cargotype.h | 1 + src/newgrf.cpp | 8 +++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/cargotype.cpp b/src/cargotype.cpp index bf9561dda8..a6ea680d80 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -77,6 +77,28 @@ void SetupCargoForClimate(LandscapeID l) } } +/** + * Get the cargo ID of a default cargo, if present. + * @param l Landscape + * @param ct Default cargo type. + * @return ID number if the cargo exists, else #CT_INVALID + */ +CargoID GetDefaultCargoID(LandscapeID l, CargoType ct) +{ + assert(l < lengthof(_default_climate_cargo)); + + if (ct == CT_INVALID) return CT_INVALID; + + assert(ct < lengthof(_default_climate_cargo[0])); + CargoLabel cl = _default_climate_cargo[l][ct]; + /* Bzzt: check if cl is just an index into the cargo table */ + if (cl < lengthof(_default_cargo)) { + cl = _default_cargo[cl].label; + } + + return GetCargoIDByLabel(cl); +} + /** * Get the cargo ID by cargo label. * @param cl Cargo type to get. diff --git a/src/cargotype.h b/src/cargotype.h index 4a295f1ae5..e411d53126 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -177,6 +177,7 @@ extern CargoTypes _standard_cargo_mask; void SetupCargoForClimate(LandscapeID l); CargoID GetCargoIDByLabel(CargoLabel cl); CargoID GetCargoIDByBitnum(uint8 bitnum); +CargoID GetDefaultCargoID(LandscapeID l, CargoType ct); void InitializeSortedCargoSpecs(); extern std::vector _sorted_cargo_specs; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 3473cbdc23..dd03e23276 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -8768,6 +8768,12 @@ static void CalculateRefitMasks() EngineInfo *ei = &e->info; bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo + /* If the NewGRF did not set any cargo properties, we apply default cargo translation. */ + if (_gted[engine].defaultcargo_grf == nullptr) { + /* Translate cargo_type using the original climate-specific cargo table. */ + ei->cargo_type = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast(ei->cargo_type)); + } + /* Did the newgrf specify any refitting? If not, use defaults. */ if (_gted[engine].refittability != GRFTempEngineData::UNSET) { CargoTypes mask = 0; @@ -8814,7 +8820,7 @@ static void CalculateRefitMasks() } /* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */ - if (!HasBit(_cargo_mask, ei->cargo_type)) ei->cargo_type = CT_INVALID; + if (ei->cargo_type != CT_INVALID && !HasBit(_cargo_mask, ei->cargo_type)) ei->cargo_type = CT_INVALID; /* Ensure that the vehicle is either not refittable, or that the default cargo is one of the refittable cargoes. * Note: Vehicles refittable to no cargo are handle differently to vehicle refittable to a single cargo. The latter might have subtypes. */ From 1da0ba95b2ca102b49a816b46ba7999ddc6a2858 Mon Sep 17 00:00:00 2001 From: frosch Date: Fri, 30 Apr 2021 21:15:27 +0200 Subject: [PATCH 185/800] Feature: Define refittability of default vehicles using cargo classes. This ensures that default vehicles can transport any NewGRF defined cargos, albeit with weird graphics and vehicle names. This also changes the refittability of default vehicles with default industries. --- src/newgrf.cpp | 147 ++++++++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 58 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index dd03e23276..29b6a49031 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -8724,65 +8724,116 @@ GRFFile::~GRFFile() } -/** - * List of what cargo labels are refittable for the given the vehicle-type. - * Only currently active labels are applied. - */ -static const CargoLabel _default_refitmasks_rail[] = { - 'PASS', 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD', - 'IORE', 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE', - 'WATR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', - 'PLST', 'FZDR', - 0 }; - -static const CargoLabel _default_refitmasks_road[] = { - 0 }; - -static const CargoLabel _default_refitmasks_ships[] = { - 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD', 'IORE', - 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE', 'WATR', - 'RUBR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', - 'PLST', 'FZDR', - 0 }; - -static const CargoLabel _default_refitmasks_aircraft[] = { - 'PASS', 'MAIL', 'GOOD', 'VALU', 'GOLD', 'DIAM', 'FOOD', 'FRUT', 'SUGR', - 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR', - 0 }; - -static const CargoLabel * const _default_refitmasks[] = { - _default_refitmasks_rail, - _default_refitmasks_road, - _default_refitmasks_ships, - _default_refitmasks_aircraft, -}; - - /** * Precalculate refit masks from cargo classes for all vehicles. */ static void CalculateRefitMasks() { + CargoTypes original_known_cargoes = 0; + for (int ct = 0; ct != NUM_ORIGINAL_CARGO; ++ct) { + CargoID cid = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast(ct)); + if (cid != CT_INVALID) SetBit(original_known_cargoes, cid); + } + for (Engine *e : Engine::Iterate()) { EngineID engine = e->index; EngineInfo *ei = &e->info; bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo - /* If the NewGRF did not set any cargo properties, we apply default cargo translation. */ + /* If the NewGRF did not set any cargo properties, we apply default values. */ if (_gted[engine].defaultcargo_grf == nullptr) { + /* If the vehicle has any capacity, apply the default refit masks */ + if (e->type != VEH_TRAIN || e->u.rail.capacity != 0) { + static constexpr byte T = 1 << LT_TEMPERATE; + static constexpr byte A = 1 << LT_ARCTIC; + static constexpr byte S = 1 << LT_TROPIC; + static constexpr byte Y = 1 << LT_TOYLAND; + static const struct DefaultRefitMasks { + byte climate; + CargoType cargo_type; + CargoTypes cargo_allowed; + CargoTypes cargo_disallowed; + } _default_refit_masks[] = { + {T | A | S | Y, CT_PASSENGERS, CC_PASSENGERS, 0}, + {T | A | S , CT_MAIL, CC_MAIL, 0}, + {T | A | S , CT_VALUABLES, CC_ARMOURED, CC_LIQUID}, + { Y, CT_MAIL, CC_MAIL | CC_ARMOURED, CC_LIQUID}, + {T | A , CT_COAL, CC_BULK, 0}, + { S , CT_COPPER_ORE, CC_BULK, 0}, + { Y, CT_SUGAR, CC_BULK, 0}, + {T | A | S , CT_OIL, CC_LIQUID, 0}, + { Y, CT_COLA, CC_LIQUID, 0}, + {T , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS}, + { A | S , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS | CC_REFRIGERATED}, + { A | S , CT_FOOD, CC_REFRIGERATED, 0}, + { Y, CT_CANDY, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS}, + }; + + if (e->type == VEH_AIRCRAFT) { + /* Aircraft default to "light" cargoes */ + _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS; + _gted[engine].cargo_disallowed = CC_LIQUID; + } else if (e->type == VEH_SHIP) { + switch (ei->cargo_type) { + case CT_PASSENGERS: + /* Ferries */ + _gted[engine].cargo_allowed = CC_PASSENGERS; + _gted[engine].cargo_disallowed = 0; + break; + case CT_OIL: + /* Tankers */ + _gted[engine].cargo_allowed = CC_LIQUID; + _gted[engine].cargo_disallowed = 0; + break; + default: + /* Cargo ships */ + if (_settings_game.game_creation.landscape == LT_TOYLAND) { + /* No tanker in toyland :( */ + _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID; + _gted[engine].cargo_disallowed = CC_PASSENGERS; + } else { + _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS; + _gted[engine].cargo_disallowed = CC_LIQUID | CC_PASSENGERS; + } + break; + } + e->u.ship.old_refittable = true; + } else if (e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON) { + /* Train engines default to all cargoes, so you can build single-cargo consists with fast engines. + * Trains loading multiple cargoes may start stations accepting unwanted cargoes. */ + _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID; + _gted[engine].cargo_disallowed = 0; + } else { + /* Train wagons and road vehicles are classified by their default cargo type */ + for (const auto &drm : _default_refit_masks) { + if (!HasBit(drm.climate, _settings_game.game_creation.landscape)) continue; + if (drm.cargo_type != ei->cargo_type) continue; + + _gted[engine].cargo_allowed = drm.cargo_allowed; + _gted[engine].cargo_disallowed = drm.cargo_disallowed; + break; + } + + /* All original cargoes have specialised vehicles, so exclude them */ + _gted[engine].ctt_exclude_mask = original_known_cargoes; + } + } + _gted[engine].UpdateRefittability(_gted[engine].cargo_allowed != 0); + /* Translate cargo_type using the original climate-specific cargo table. */ ei->cargo_type = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast(ei->cargo_type)); + if (ei->cargo_type != CT_INVALID) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type); } - /* Did the newgrf specify any refitting? If not, use defaults. */ - if (_gted[engine].refittability != GRFTempEngineData::UNSET) { + /* Compute refittability */ + { CargoTypes mask = 0; CargoTypes not_mask = 0; CargoTypes xor_mask = ei->refit_mask; /* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo. * Note: After applying the translations, the vehicle may end up carrying no defined cargo. It becomes unavailable in that case. */ - only_defaultcargo = _gted[engine].refittability == GRFTempEngineData::EMPTY; + only_defaultcargo = _gted[engine].refittability != GRFTempEngineData::NONEMPTY; if (_gted[engine].cargo_allowed != 0) { /* Build up the list of cargo types from the set cargo classes. */ @@ -8797,26 +8848,6 @@ static void CalculateRefitMasks() /* Apply explicit refit includes/excludes. */ ei->refit_mask |= _gted[engine].ctt_include_mask; ei->refit_mask &= ~_gted[engine].ctt_exclude_mask; - } else { - CargoTypes xor_mask = 0; - - /* Don't apply default refit mask to wagons nor engines with no capacity */ - if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) { - const CargoLabel *cl = _default_refitmasks[e->type]; - for (uint i = 0;; i++) { - if (cl[i] == 0) break; - - CargoID cargo = GetCargoIDByLabel(cl[i]); - if (cargo == CT_INVALID) continue; - - SetBit(xor_mask, cargo); - } - } - - ei->refit_mask = xor_mask & _cargo_mask; - - /* If the mask is zero, the vehicle shall only carry the default cargo */ - only_defaultcargo = (ei->refit_mask == 0); } /* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */ From 98283116fac58053ebd282772b0311a0b417cef7 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 08:27:06 +0200 Subject: [PATCH 186/800] Codechange: [Network] Make company state password std::string --- src/console_cmds.cpp | 2 +- src/network/network.cpp | 4 ++-- src/network/network_server.cpp | 26 +++++++++++++------------- src/network/network_type.h | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 0756f72667..82638a5cba 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1635,7 +1635,7 @@ DEF_CONSOLE_CMD(ConCompanies) if (c->is_ai) { password_state = "AI"; } else if (_network_server) { - password_state = StrEmpty(_network_company_states[c->index].password) ? "unprotected" : "protected"; + password_state = _network_company_states[c->index].password.empty() ? "unprotected" : "protected"; } char colour[512]; diff --git a/src/network/network.cpp b/src/network/network.cpp index a66da42bc5..b77e0477c5 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -601,7 +601,7 @@ void NetworkClose(bool close_admins) NetworkFreeLocalCommandQueue(); - free(_network_company_states); + delete[] _network_company_states; _network_company_states = nullptr; InitializeNetworkPools(close_admins); @@ -896,7 +896,7 @@ bool NetworkServerStart() DEBUG(net, 5, "Starting listeners for incoming server queries"); NetworkUDPServerListen(); - _network_company_states = CallocT(MAX_COMPANIES); + _network_company_states = new NetworkCompanyState[MAX_COMPANIES]; _network_server = true; _networking = true; _frame_counter = 0; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index f2a8a52307..1a6012fb1c 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -863,7 +863,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED return this->SendNeedGamePassword(); } - if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) { + if (Company::IsValidID(ci->client_playas) && !_network_company_states[ci->client_playas].password.empty()) { return this->SendNeedCompanyPassword(); } @@ -964,7 +964,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(P } const NetworkClientInfo *ci = this->GetInfo(); - if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) { + if (Company::IsValidID(ci->client_playas) && !_network_company_states[ci->client_playas].password.empty()) { return this->SendNeedCompanyPassword(); } @@ -985,8 +985,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWOR * Also, check the company is still valid - client could be moved to spectators * in the middle of the authorization process */ CompanyID playas = this->GetInfo()->client_playas; - if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) && - strcmp(password, _network_company_states[playas].password) != 0) { + if (Company::IsValidID(playas) && !_network_company_states[playas].password.empty() && + _network_company_states[playas].password.compare(password) != 0) { /* Password is invalid */ return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); } @@ -1467,13 +1467,13 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p) if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY; /* Check if we require a password for this company */ - if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) { + if (company_id != COMPANY_SPECTATOR && !_network_company_states[company_id].password.empty()) { /* we need a password from the client - should be in this packet */ char password[NETWORK_PASSWORD_LENGTH]; p->Recv_string(password, sizeof(password)); /* Incorrect password sent, return! */ - if (strcmp(password, _network_company_states[company_id].password) != 0) { + if (_network_company_states[company_id].password.compare(password) != 0) { DEBUG(net, 2, "Wrong password from client-id #%d for company #%d", this->client_id, company_id + 1); return NETWORK_RECV_STATUS_OKAY; } @@ -1523,7 +1523,7 @@ void NetworkSocketHandler::SendCompanyInformation(Packet *p, const Company *c, c p->Send_uint16(c->old_economy[0].performance_history); /* Send 1 if there is a password for the company else send 0 */ - p->Send_bool (!StrEmpty(_network_company_states[c->index].password)); + p->Send_bool (!_network_company_states[c->index].password.empty()); for (uint i = 0; i < NETWORK_VEH_END; i++) { p->Send_uint16(stats->num_vehicle[i]); @@ -1660,15 +1660,15 @@ static void NetworkAutoCleanCompanies() _network_company_states[c->index].months_empty++; /* Is the company empty for autoclean_unprotected-months, and is there no protection? */ - if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && StrEmpty(_network_company_states[c->index].password)) { + if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && _network_company_states[c->index].password.empty()) { /* Shut the company down */ DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL); IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1); } /* Is the company empty for autoclean_protected-months, and there is a protection? */ - if (_settings_client.network.autoclean_protected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_protected && !StrEmpty(_network_company_states[c->index].password)) { + if (_settings_client.network.autoclean_protected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_protected && !_network_company_states[c->index].password.empty()) { /* Unprotect the company */ - _network_company_states[c->index].password[0] = '\0'; + _network_company_states[c->index].password.clear(); IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1); _network_company_states[c->index].months_empty = 0; NetworkServerUpdateCompanyPassworded(c->index, false); @@ -1765,8 +1765,8 @@ void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id.c_str(), _settings_game.game_creation.generation_seed); } - strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password)); - NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password)); + _network_company_states[company_id].password = password; + NetworkServerUpdateCompanyPassworded(company_id, !_network_company_states[company_id].password.empty()); } /** @@ -2188,7 +2188,7 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) if (!_network_server) return; _network_company_states[c->index].months_empty = 0; - _network_company_states[c->index].password[0] = '\0'; + _network_company_states[c->index].password.clear(); NetworkServerUpdateCompanyPassworded(c->index, false); if (ci != nullptr) { diff --git a/src/network/network_type.h b/src/network/network_type.h index 4dcdd8c03d..fb99536953 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -62,8 +62,8 @@ struct NetworkCompanyStats { /** Some state information of a company, especially for servers */ struct NetworkCompanyState { - char password[NETWORK_PASSWORD_LENGTH]; ///< The password for the company - uint16 months_empty; ///< How many months the company is empty + std::string password; ///< The password for the company + uint16 months_empty; ///< How many months the company is empty }; struct NetworkClientInfo; From 1de5cdeab8387b23b566142f205ac9232a6f61a3 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 09:07:09 +0200 Subject: [PATCH 187/800] Codechange: [Network] Use std::string for the internal handling of company passwords --- src/network/network.cpp | 8 ++++---- src/network/network_client.cpp | 21 ++++++++++----------- src/network/network_client.h | 12 ++++++------ src/network/network_func.h | 2 +- src/network/network_internal.h | 2 +- src/network/network_server.cpp | 22 +++++++++------------- src/network/network_server.h | 2 +- 7 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index b77e0477c5..61baa76175 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -172,13 +172,13 @@ const char *NetworkChangeCompanyPassword(CompanyID company_id, const char *passw * @param password_game_seed Game seed. * @return The hashed password. */ -const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed) +std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32 password_game_seed) { - if (StrEmpty(password)) return password; + if (password.empty()) return password; char salted_password[NETWORK_SERVER_ID_LENGTH]; - size_t password_length = strlen(password); - size_t password_server_id_length = strlen(password_server_id); + size_t password_length = password.size(); + size_t password_server_id_length = password_server_id.size(); /* Add the game seed and the server's ID as the salt. */ for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) { diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index b9bcfe1f22..675807decc 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -319,7 +319,7 @@ static uint32 last_ack_frame; /** One bit of 'entropy' used to generate a salt for the company passwords. */ static uint32 _password_game_seed; /** The other bit of 'entropy' used to generate a salt for the company passwords. */ -static char _password_server_id[NETWORK_SERVER_ID_LENGTH]; +static std::string _password_server_id; /** Maximum number of companies of the currently joined server. */ static uint8 _network_server_max_companies; @@ -397,7 +397,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendGamePassword(const char *p * Set the company password as requested. * @param password The company password. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyPassword(const char *password) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyPassword(const std::string &password) { Packet *p = new Packet(PACKET_CLIENT_COMPANY_PASSWORD); p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed)); @@ -478,7 +478,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendError(NetworkErrorCode err * Tell the server that we like to change the password of the company. * @param password The new password. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetPassword(const char *password) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetPassword(const std::string &password) { Packet *p = new Packet(PACKET_CLIENT_SET_PASSWORD); @@ -530,7 +530,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const char *pass, con * @param company The company to move to. * @param password The password of the company to move to. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company, const char *password) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company, const std::string &password) { Packet *p = new Packet(PACKET_CLIENT_MOVE); p->Send_uint8(company); @@ -815,12 +815,11 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PA this->status = STATUS_AUTH_COMPANY; _password_game_seed = p->Recv_uint32(); - p->Recv_string(_password_server_id, sizeof(_password_server_id)); + _password_server_id = p->Recv_string(NETWORK_SERVER_ID_LENGTH); if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - const char *password = _network_join.company_password; - if (!StrEmpty(password)) { - return SendCompanyPassword(password); + if (!_network_join.company_password.empty()) { + return SendCompanyPassword(_network_join.company_password); } ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD); @@ -837,7 +836,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet /* Initialize the password hash salting variables, even if they were previously. */ _password_game_seed = p->Recv_uint32(); - p->Recv_string(_password_server_id, sizeof(_password_server_id)); + _password_server_id = p->Recv_string(NETWORK_SERVER_ID_LENGTH); /* Start receiving the map */ return SendGetMap(); @@ -1274,7 +1273,7 @@ void NetworkClientSendRcon(const char *password, const char *command) * @param pass the password, is only checked on the server end if a password is needed. * @return void */ -void NetworkClientRequestMove(CompanyID company_id, const char *pass) +void NetworkClientRequestMove(CompanyID company_id, const std::string &pass) { MyClient::SendMove(company_id, pass); } @@ -1396,7 +1395,7 @@ void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const * Set/Reset company password on the client side. * @param password Password to be set. */ -void NetworkClientSetCompanyPassword(const char *password) +void NetworkClientSetCompanyPassword(const std::string &password) { MyClient::SendSetPassword(password); } diff --git a/src/network/network_client.h b/src/network/network_client.h index ddc0e362c8..c4dc4b1fd8 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -91,13 +91,13 @@ public: static NetworkRecvStatus SendAck(); static NetworkRecvStatus SendGamePassword(const char *password); - static NetworkRecvStatus SendCompanyPassword(const char *password); + static NetworkRecvStatus SendCompanyPassword(const std::string &password); static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data); - static NetworkRecvStatus SendSetPassword(const char *password); + static NetworkRecvStatus SendSetPassword(const std::string &password); static NetworkRecvStatus SendSetName(const char *name); static NetworkRecvStatus SendRCon(const char *password, const char *command); - static NetworkRecvStatus SendMove(CompanyID company, const char *password); + static NetworkRecvStatus SendMove(CompanyID company, const std::string &password); static bool IsConnected(); @@ -110,15 +110,15 @@ public: typedef ClientNetworkGameSocketHandler MyClient; void NetworkClient_Connected(); -void NetworkClientSetCompanyPassword(const char *password); +void NetworkClientSetCompanyPassword(const std::string &password); /** Information required to join a server. */ struct NetworkJoinInfo { - NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {} + NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr) {} std::string connection_string; ///< The address of the server to join. CompanyID company; ///< The company to join. const char *server_password; ///< The password of the server to join. - const char *company_password; ///< The password of the company to join. + std::string company_password; ///< The password of the company to join. }; extern NetworkJoinInfo _network_join; diff --git a/src/network/network_func.h b/src/network/network_func.h index cb0ca3355c..bedc9bc54c 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -53,7 +53,7 @@ void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); void NetworkClientJoinGame(); -void NetworkClientRequestMove(CompanyID company, const char *pass = ""); +void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 3456ab251a..7412d9232c 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -118,7 +118,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, uint NetworkCalculateLag(const NetworkClientSocket *cs); StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); -const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); +std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32 password_game_seed); NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port); std::string NormalizeConnectionString(const std::string &connection_string, uint16 default_port); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 1a6012fb1c..4d35af1166 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -978,8 +978,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWOR return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char password[NETWORK_PASSWORD_LENGTH]; - p->Recv_string(password, sizeof(password)); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); /* Check company password. Allow joining if we cleared the password meanwhile. * Also, check the company is still valid - client could be moved to spectators @@ -1389,11 +1388,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Pa return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char password[NETWORK_PASSWORD_LENGTH]; - const NetworkClientInfo *ci; - - p->Recv_string(password, sizeof(password)); - ci = this->GetInfo(); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); + const NetworkClientInfo *ci = this->GetInfo(); NetworkServerSetCompanyPassword(ci->client_playas, password); return NETWORK_RECV_STATUS_OKAY; @@ -1469,8 +1465,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p) /* Check if we require a password for this company */ if (company_id != COMPANY_SPECTATOR && !_network_company_states[company_id].password.empty()) { /* we need a password from the client - should be in this packet */ - char password[NETWORK_PASSWORD_LENGTH]; - p->Recv_string(password, sizeof(password)); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); /* Incorrect password sent, return! */ if (_network_company_states[company_id].password.compare(password) != 0) { @@ -1757,15 +1752,16 @@ bool NetworkServerChangeClientName(ClientID client_id, const char *new_name) * @param password The new password. * @param already_hashed Is the given password already hashed? */ -void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed) +void NetworkServerSetCompanyPassword(CompanyID company_id, const std::string &password, bool already_hashed) { if (!Company::IsValidHumanID(company_id)) return; - if (!already_hashed) { - password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id.c_str(), _settings_game.game_creation.generation_seed); + if (already_hashed) { + _network_company_states[company_id].password = password; + } else { + _network_company_states[company_id].password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed); } - _network_company_states[company_id].password = password; NetworkServerUpdateCompanyPassworded(company_id, !_network_company_states[company_id].password.empty()); } diff --git a/src/network/network_server.h b/src/network/network_server.h index fb4c4f63eb..f8f58d1e38 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -121,7 +121,7 @@ public: }; void NetworkServer_Tick(bool send_frame); -void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed = true); +void NetworkServerSetCompanyPassword(CompanyID company_id, const std::string &password, bool already_hashed = true); void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded); #endif /* NETWORK_SERVER_H */ From 6db52d52d00516b71a982e61b3b9592a887091aa Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 09:10:09 +0200 Subject: [PATCH 188/800] Codechange: [Network] Use std::string for the internal handling of server passwords --- src/network/network_client.cpp | 7 +++---- src/network/network_client.h | 6 +++--- src/network/network_server.cpp | 3 +-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 675807decc..4740849a0d 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -385,7 +385,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendNewGRFsOk() * Set the game password as requested. * @param password The game password. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendGamePassword(const char *password) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendGamePassword(const std::string &password) { Packet *p = new Packet(PACKET_CLIENT_GAME_PASSWORD); p->Send_string(password); @@ -799,9 +799,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSW if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET; this->status = STATUS_AUTH_GAME; - const char *password = _network_join.server_password; - if (!StrEmpty(password)) { - return SendGamePassword(password); + if (!_network_join.server_password.empty()) { + return SendGamePassword(_network_join.server_password); } ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD); diff --git a/src/network/network_client.h b/src/network/network_client.h index c4dc4b1fd8..baf4f5996f 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -90,7 +90,7 @@ public: static NetworkRecvStatus SendQuit(); static NetworkRecvStatus SendAck(); - static NetworkRecvStatus SendGamePassword(const char *password); + static NetworkRecvStatus SendGamePassword(const std::string &password); static NetworkRecvStatus SendCompanyPassword(const std::string &password); static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data); @@ -114,10 +114,10 @@ void NetworkClientSetCompanyPassword(const std::string &password); /** Information required to join a server. */ struct NetworkJoinInfo { - NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr) {} + NetworkJoinInfo() : company(COMPANY_SPECTATOR) {} std::string connection_string; ///< The address of the server to join. CompanyID company; ///< The company to join. - const char *server_password; ///< The password of the server to join. + std::string server_password; ///< The password of the server to join. std::string company_password; ///< The password of the company to join. }; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 4d35af1166..3144073489 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -953,8 +953,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(P return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char password[NETWORK_PASSWORD_LENGTH]; - p->Recv_string(password, sizeof(password)); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); /* Check game password. Allow joining if we cleared the password meanwhile */ if (!_settings_client.network.server_password.empty() && From ebe32ad9129bb5846433366509728fb594f3be62 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 09:15:12 +0200 Subject: [PATCH 189/800] Codechange: [Network] Use std::string for the internal handling of admin/rcon passwords --- src/network/network_admin.cpp | 3 +-- src/network/network_client.cpp | 2 +- src/network/network_client.h | 2 +- src/network/network_server.cpp | 5 ++--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 057ce32c06..dfe09344a9 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -664,8 +664,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p) { if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - char password[NETWORK_PASSWORD_LENGTH]; - p->Recv_string(password, sizeof(password)); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); if (_settings_client.network.admin_password.empty() || _settings_client.network.admin_password.compare(password) != 0) { diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 4740849a0d..7e2c7bb232 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -516,7 +516,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendQuit() * @param pass The password for the remote command. * @param command The actual command. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const char *pass, const char *command) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const std::string &pass, const char *command) { Packet *p = new Packet(PACKET_CLIENT_RCON); p->Send_string(pass); diff --git a/src/network/network_client.h b/src/network/network_client.h index baf4f5996f..7d0d228104 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -96,7 +96,7 @@ public: static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data); static NetworkRecvStatus SendSetPassword(const std::string &password); static NetworkRecvStatus SendSetName(const char *name); - static NetworkRecvStatus SendRCon(const char *password, const char *command); + static NetworkRecvStatus SendRCon(const std::string &password, const char *command); static NetworkRecvStatus SendMove(CompanyID company, const std::string &password); static bool IsConnected(); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 3144073489..7b77c76c4a 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1431,15 +1431,14 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p) { if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - char pass[NETWORK_PASSWORD_LENGTH]; char command[NETWORK_RCONCOMMAND_LENGTH]; if (_settings_client.network.rcon_password.empty()) return NETWORK_RECV_STATUS_OKAY; - p->Recv_string(pass, sizeof(pass)); + std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); p->Recv_string(command, sizeof(command)); - if (_settings_client.network.rcon_password.compare(pass) != 0) { + if (_settings_client.network.rcon_password.compare(password) != 0) { DEBUG(net, 1, "[rcon] Wrong password from client-id %d", this->client_id); return NETWORK_RECV_STATUS_OKAY; } From 297d6e20bf0467d2a42e49bee291829ce3bb7c58 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 2 May 2021 09:18:56 +0200 Subject: [PATCH 190/800] Codechange: [Network] Pass passwords as std::string to the network code --- src/company_cmd.cpp | 2 +- src/console_cmds.cpp | 6 +++--- src/network/network.cpp | 6 +++--- src/network/network_client.cpp | 2 +- src/network/network_func.h | 6 +++--- src/openttd.cpp | 30 +++++++++++++----------------- 6 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 45a679c108..17923377af 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -844,7 +844,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 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.c_str()); + NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); } /* Now that we have a new company, broadcast our company settings to diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 82638a5cba..a417831cbf 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1737,7 +1737,7 @@ DEF_CONSOLE_CMD(ConCompanyPassword) } CompanyID company_id; - const char *password; + std::string password; const char *errormsg; if (argc == 2) { @@ -1759,10 +1759,10 @@ DEF_CONSOLE_CMD(ConCompanyPassword) password = NetworkChangeCompanyPassword(company_id, password); - if (StrEmpty(password)) { + if (password.empty()) { IConsolePrintF(CC_WARNING, "Company password cleared"); } else { - IConsolePrintF(CC_WARNING, "Company password changed to: %s", password); + IConsolePrintF(CC_WARNING, "Company password changed to: %s", password.c_str()); } return true; diff --git a/src/network/network.cpp b/src/network/network.cpp index 61baa76175..80ecfc2cde 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -152,9 +152,9 @@ byte NetworkSpectatorCount() * @param password The unhashed password we like to set ('*' or '' resets the password) * @return The password. */ -const char *NetworkChangeCompanyPassword(CompanyID company_id, const char *password) +std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password) { - if (strcmp(password, "*") == 0) password = ""; + if (password.compare("*") == 0) password = ""; if (_network_server) { NetworkServerSetCompanyPassword(company_id, password, false); @@ -787,7 +787,7 @@ public: * @param join_company_password The password for the company. * @return Whether the join has started. */ -bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password) +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password, const std::string &join_company_password) { CompanyID join_as = default_company; std::string resolved_connection_string = ParseGameConnectionString(connection_string, NETWORK_DEFAULT_PORT, &join_as).GetAddressAsString(false); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 7e2c7bb232..b6da3dc183 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1261,7 +1261,7 @@ void NetworkClient_Connected() * @param password The password. * @param command The command to execute. */ -void NetworkClientSendRcon(const char *password, const char *command) +void NetworkClientSendRcon(const std::string &password, const char *command) { MyClient::SendRCon(password, command); } diff --git a/src/network/network_func.h b/src/network/network_func.h index bedc9bc54c..82a5deb45c 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -40,7 +40,7 @@ bool NetworkValidateClientName(); bool NetworkValidateClientName(std::string &client_name); void NetworkUpdateClientName(); bool NetworkCompanyHasClients(CompanyID company); -const char *NetworkChangeCompanyPassword(CompanyID company_id, const char *password); +std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password); void NetworkReboot(); void NetworkDisconnect(bool blocking = false, bool close_admins = true); void NetworkGameLoop(); @@ -51,10 +51,10 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); -bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr); +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password = "", const std::string &join_company_password = ""); void NetworkClientJoinGame(); void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); -void NetworkClientSendRcon(const char *password, const char *command); +void NetworkClientSendRcon(const std::string &password, const char *command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); bool NetworkCompanyIsPassworded(CompanyID company_id); diff --git a/src/openttd.cpp b/src/openttd.cpp index 5674a46713..fec8bf9caf 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -400,23 +400,19 @@ void OpenBrowser(const char *url) /** Callback structure of statements to be executed after the NewGRF scan. */ struct AfterNewGRFScan : NewGRFScanCallback { - Year startyear; ///< The start year. - uint32 generation_seed; ///< Seed for the new game. - std::string dedicated_host; ///< Hostname for the dedicated server. - uint16 dedicated_port; ///< Port for the dedicated server. - char *network_conn; ///< Information about the server to connect to, or nullptr. - const char *join_server_password; ///< The password to join the server with. - const char *join_company_password; ///< The password to join the company with. - bool save_config; ///< The save config setting. + Year startyear = INVALID_YEAR; ///< The start year. + uint32 generation_seed = GENERATE_NEW_SEED; ///< Seed for the new game. + std::string dedicated_host; ///< Hostname for the dedicated server. + uint16 dedicated_port = 0; ///< Port for the dedicated server. + std::string connection_string; ///< Information about the server to connect to + std::string join_server_password; ///< The password to join the server with. + std::string join_company_password; ///< The password to join the company with. + bool save_config = true; ///< The save config setting. /** * Create a new callback. */ - AfterNewGRFScan() : - startyear(INVALID_YEAR), generation_seed(GENERATE_NEW_SEED), - dedicated_port(0), network_conn(nullptr), - join_server_password(nullptr), join_company_password(nullptr), - save_config(true) + AfterNewGRFScan() { /* Visual C++ 2015 fails compiling this line (AfterNewGRFScan::generation_seed undefined symbol) * if it's placed outside a member function, directly in the struct body. */ @@ -469,11 +465,11 @@ struct AfterNewGRFScan : NewGRFScanCallback { /* Make sure _settings is filled with _settings_newgame if we switch to a game directly */ if (_switch_mode != SM_NONE) MakeNewgameSettingsLive(); - if (_network_available && network_conn != nullptr) { + if (_network_available && !connection_string.empty()) { LoadIntroGame(); _switch_mode = SM_NONE; - NetworkClientConnectGame(network_conn, COMPANY_NEW_COMPANY, join_server_password, join_company_password); + NetworkClientConnectGame(connection_string, COMPANY_NEW_COMPANY, join_server_password, join_company_password); } /* After the scan we're not used anymore. */ @@ -567,7 +563,7 @@ int openttd_main(int argc, char *argv[]) break; case 'f': _dedicated_forks = true; break; case 'n': - scanner->network_conn = mgo.opt; // optional IP parameter, nullptr if unset + scanner->connection_string = mgo.opt; // optional IP:port#company parameter break; case 'l': debuglog_conn = mgo.opt; @@ -875,7 +871,7 @@ static void MakeNewGameDone() /* We are the server, we start a new company (not dedicated), * so set the default password *if* needed. */ if (_network_server && !_settings_client.network.default_company_pass.empty()) { - NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass.c_str()); + NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); } if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE); From aa5a8fe28a224fd581b6053e4a5ce38f3e1a9694 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Thu, 13 May 2021 10:00:41 +0200 Subject: [PATCH 191/800] Codechange: use thread safe time functions Functions like localtime, gmtime and asctime are not thread safe as they (might) reuse the same buffer. So use the safer _s/_r variant for localtime and gmtime, and use strftime in favour of asctime. --- src/CMakeLists.txt | 1 + src/console_cmds.cpp | 9 ++--- src/crashlog.cpp | 6 +-- src/debug.cpp | 5 +-- src/newgrf_profiling.cpp | 6 +-- src/stdafx.h | 3 ++ src/walltime_func.h | 80 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 src/walltime_func.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d4fffc8c7..801a92cb37 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -467,6 +467,7 @@ add_files( viewport_type.h void_cmd.cpp void_map.h + walltime_func.h water.h water_cmd.cpp water_map.h diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index a417831cbf..39a52f0b5e 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -41,7 +41,7 @@ #include "rail.h" #include "game/game.hpp" #include "table/strings.h" -#include +#include "walltime_func.h" #include "safeguards.h" @@ -1369,10 +1369,9 @@ DEF_CONSOLE_CMD(ConGetSysDate) return true; } - time_t t; - time(&t); - auto timeinfo = localtime(&t); - IConsolePrintF(CC_DEFAULT, "System Date: %04d-%02d-%02d %02d:%02d:%02d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + char buffer[lengthof("2000-01-02 03:04:05")]; + LocalTime::Format(buffer, lastof(buffer), "%Y-%m-%d %H:%M:%S"); + IConsolePrintF(CC_DEFAULT, "System Date: %s", buffer); return true; } diff --git a/src/crashlog.cpp b/src/crashlog.cpp index c447019fef..c69dddef84 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -32,8 +32,7 @@ #include "game/game_info.hpp" #include "company_base.h" #include "company_func.h" - -#include +#include "walltime_func.h" #ifdef WITH_ALLEGRO # include @@ -333,9 +332,8 @@ char *CrashLog::LogRecentNews(char *buffer, const char *last) const */ char *CrashLog::FillCrashLog(char *buffer, const char *last) const { - time_t cur_time = time(nullptr); buffer += seprintf(buffer, last, "*** OpenTTD Crash Report ***\n\n"); - buffer += seprintf(buffer, last, "Crash at: %s", asctime(gmtime(&cur_time))); + buffer += UTCTime::Format(buffer, last, "Crash at: %Y-%m-%d %H:%M:%S (UTC)\n"); YearMonthDay ymd; ConvertDateToYMD(_date, &ymd); diff --git a/src/debug.cpp b/src/debug.cpp index 25a0f1a82f..39c695e036 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -19,7 +19,7 @@ #include "os/windows/win32.h" #endif -#include +#include "walltime_func.h" #include "network/network_admin.h" SOCKET _debug_socket = INVALID_SOCKET; @@ -248,8 +248,7 @@ const char *GetLogPrefix() { static char _log_prefix[24]; if (_settings_client.gui.show_date_in_logs) { - time_t cur_time = time(nullptr); - strftime(_log_prefix, sizeof(_log_prefix), "[%Y-%m-%d %H:%M:%S] ", localtime(&cur_time)); + LocalTime::Format(_log_prefix, lastof(_log_prefix), "[%Y-%m-%d %H:%M:%S] "); } else { *_log_prefix = '\0'; } diff --git a/src/newgrf_profiling.cpp b/src/newgrf_profiling.cpp index 8ec8cff546..27a1bc80ef 100644 --- a/src/newgrf_profiling.cpp +++ b/src/newgrf_profiling.cpp @@ -13,9 +13,9 @@ #include "string_func.h" #include "console_func.h" #include "spritecache.h" +#include "walltime_func.h" #include -#include std::vector _newgrf_profilers; @@ -130,10 +130,8 @@ void NewGRFProfiler::Abort() */ std::string NewGRFProfiler::GetOutputFilename() const { - time_t write_time = time(nullptr); - char timestamp[16] = {}; - strftime(timestamp, lengthof(timestamp), "%Y%m%d-%H%M", localtime(&write_time)); + LocalTime::Format(timestamp, lastof(timestamp), "%Y%m%d-%H%M"); char filepath[MAX_PATH] = {}; seprintf(filepath, lastof(filepath), "%sgrfprofile-%s-%08X.csv", FiosGetScreenshotDir(), timestamp, BSWAP32(this->grffile->grfid)); diff --git a/src/stdafx.h b/src/stdafx.h index 937c053f2f..319d94edf2 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -129,6 +129,7 @@ /* Warn about functions using 'printf' format syntax. First argument determines which parameter * is the format string, second argument is start of values passed to printf. */ # define WARN_FORMAT(string, args) __attribute__ ((format (printf, string, args))) +# define WARN_TIME_FORMAT(string) __attribute__ ((format (strftime, string, 0))) # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) # define FINAL final # else @@ -157,6 +158,7 @@ # define NORETURN # define CDECL # define WARN_FORMAT(string, args) +# define WARN_TIME_FORMAT(string) # define FINAL # define FALLTHROUGH # include @@ -205,6 +207,7 @@ # define CDECL _cdecl # define WARN_FORMAT(string, args) +# define WARN_TIME_FORMAT(string) # define FINAL final /* fallthrough attribute, VS 2017 */ diff --git a/src/walltime_func.h b/src/walltime_func.h new file mode 100644 index 0000000000..219a8907de --- /dev/null +++ b/src/walltime_func.h @@ -0,0 +1,80 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + + /** @file walltime_func.h Functionality related to the time of the clock on your wall. */ + +#ifndef WALLTIME_FUNC_H +#define WALLTIME_FUNC_H + +#include + +/** Helper for safely converting a std::time_t to a local time std::tm using localtime_s. */ +struct LocalTimeToStruct { + static inline std::tm ToTimeStruct(std::time_t time_since_epoch) + { + std::tm time = {}; +#ifdef WIN32 + /* Windows has swapped the parameters around for localtime_s. */ + localtime_s(&time, &time_since_epoch); +#else + localtime_r(&time_since_epoch, &time); +#endif + return time; + } +}; + +/** Helper for safely converting a std::time_t to a UTC time std::tm using gmtime_s. */ +struct UTCTimeToStruct { + static inline std::tm ToTimeStruct(std::time_t time_since_epoch) + { + std::tm time = {}; +#ifdef WIN32 + /* Windows has swapped the parameters around for gmtime_s. */ + gmtime_s(&time, &time_since_epoch); +#else + gmtime_r(&time_since_epoch, &time); +#endif + return time; + } +}; + +/** + * Container for wall clock time related functionality not directly provided by C++. + * @tparam T The type of the time-to-struct implementation class. + */ +template +struct Time { + /** + * Format the current time with the given strftime format specifiers. + * @param buffer The buffer to write the time string to. + * @param last The last element in the buffer. + * @param format The format according to strftime format specifiers. + * @return The number of characters that were written to the buffer. + */ + static inline size_t Format(char *buffer, const char *last, const char *format) NOACCESS(2) WARN_TIME_FORMAT(3) + { + std::tm time_struct = T::ToTimeStruct(time(nullptr)); +#ifndef _MSC_VER + /* GCC bug #39438; unlike for printf where the appropriate attribute prevent the + * "format non literal" warning, that does not happen for strftime. Even though + * format warnings will be created for invalid strftime formats. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif /* _MSC_VER */ + return strftime(buffer, last - buffer, format, &time_struct); +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif /* _MSC_VER */ + } +}; + +/** Wall clock time functionality using the local time zone. */ +using LocalTime = Time; +/** Wall clock time functionality using the UTC time zone. */ +using UTCTime = Time; + +#endif From e6f0d63e258d9847ed564864ddc04967d780c1de Mon Sep 17 00:00:00 2001 From: Rubidium Date: Mon, 10 May 2021 23:02:44 +0200 Subject: [PATCH 192/800] Codechange: comparison result is always the same due to earlier check Practically the length of the handlers not being equal to the number of features is the problem as it means something was forgotten when adding a new feature, so static assert to that and let the existing check on the feature number take care of invalid data from the NewGRFs. --- src/newgrf.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 29b6a49031..d2b3449c96 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -4746,6 +4746,7 @@ static void FeatureChangeInfo(ByteReader *buf) /* GSF_ROADTYPES */ RoadTypeChangeInfo, /* GSF_TRAMTYPES */ TramTypeChangeInfo, }; + static_assert(GSF_END == lengthof(handler)); uint8 feature = buf->ReadByte(); uint8 numprops = buf->ReadByte(); @@ -4760,7 +4761,7 @@ static void FeatureChangeInfo(ByteReader *buf) grfmsg(6, "FeatureChangeInfo: Feature 0x%02X, %d properties, to apply to %d+%d", feature, numprops, engine, numinfo); - if (feature >= lengthof(handler) || handler[feature] == nullptr) { + if (handler[feature] == nullptr) { if (feature != GSF_CARGOES) grfmsg(1, "FeatureChangeInfo: Unsupported feature 0x%02X, skipping", feature); return; } From 031e91de6e06e6b0d12603d78170f92f5def1d00 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Mon, 10 May 2021 23:06:23 +0200 Subject: [PATCH 193/800] Fix: [Network] Check on CIDR for netmask check considered everything valid --- src/network/core/address.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 91a481795c..044df00503 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -170,7 +170,7 @@ bool NetworkAddress::IsInNetmask(const char *netmask) int tmp_cidr = atoi(chr_cidr + 1); /* Invalid CIDR, treat as single host */ - if (tmp_cidr > 0 || tmp_cidr < cidr) cidr = tmp_cidr; + if (tmp_cidr > 0 && tmp_cidr < cidr) cidr = tmp_cidr; /* Remove the / so that NetworkAddress works on the IP portion */ std::string ip_str(netmask, chr_cidr - netmask); From bb9121dbd4690405b54e7e6ed6e711ead16435ac Mon Sep 17 00:00:00 2001 From: Rubidium Date: Mon, 10 May 2021 23:43:52 +0200 Subject: [PATCH 194/800] Fix: comparison of narrow type to wide type in loop (potential for infinite loops) --- src/depot_gui.cpp | 4 ++-- src/industry_gui.cpp | 8 ++++---- src/linkgraph/linkgraph.h | 2 +- src/linkgraph/linkgraphjob.cpp | 2 +- src/linkgraph/mcf.cpp | 8 ++++---- src/network/core/packet.cpp | 7 ++++--- src/rail_gui.cpp | 2 +- src/saveload/linkgraph_sl.cpp | 2 +- src/story_gui.cpp | 4 ++-- src/texteff.hpp | 2 +- 10 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 8c018b73d8..0756eae2ca 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -395,11 +395,11 @@ struct DepotWindow : Window { uint16 rows_in_display = wid->current_y / wid->resize_y; - uint16 num = this->vscroll->GetPosition() * this->num_columns; + uint num = this->vscroll->GetPosition() * this->num_columns; uint maxval = static_cast(std::min(this->vehicle_list.size(), num + (rows_in_display * this->num_columns))); int y; for (y = r.top + 1; num < maxval; y += this->resize.step_height) { // Draw the rows - for (byte i = 0; i < this->num_columns && num < maxval; i++, num++) { + for (uint i = 0; i < this->num_columns && num < maxval; i++, num++) { /* Draw all vehicles in the current row */ const Vehicle *v = this->vehicle_list[num]; if (this->num_columns == 1) { diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 4e6c61ee21..b1768af1f0 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -357,7 +357,7 @@ class BuildIndustryWindow : public Window { int numcargo = 0; int firstcargo = -1; - for (byte j = 0; j < cargolistlen; j++) { + for (int j = 0; j < cargolistlen; j++) { if (cargolist[j] == CT_INVALID) continue; numcargo++; if (firstcargo < 0) { @@ -419,7 +419,7 @@ public: switch (widget) { case WID_DPI_MATRIX_WIDGET: { Dimension d = GetStringBoundingBox(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES); - for (byte i = 0; i < this->count; i++) { + for (uint16 i = 0; i < this->count; i++) { if (this->index[i] == INVALID_INDUSTRYTYPE) continue; d = maxdim(d, GetStringBoundingBox(GetIndustrySpec(this->index[i])->name)); } @@ -438,7 +438,7 @@ public: uint extra_lines_newgrf = 0; uint max_minwidth = FONT_HEIGHT_NORMAL * MAX_MINWIDTH_LINEHEIGHTS; Dimension d = {0, 0}; - for (byte i = 0; i < this->count; i++) { + for (uint16 i = 0; i < this->count; i++) { if (this->index[i] == INVALID_INDUSTRYTYPE) continue; const IndustrySpec *indsp = GetIndustrySpec(this->index[i]); @@ -528,7 +528,7 @@ public: int icon_bottom = icon_top + this->legend.height; int y = r.top; - for (byte i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->count; i++) { + for (uint16 i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->count; i++) { bool selected = this->selected_index == i + this->vscroll->GetPosition(); if (this->index[i + this->vscroll->GetPosition()] == INVALID_INDUSTRYTYPE) { diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index 99348daa1c..4f44db8276 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -495,7 +495,7 @@ public: * Get the current size of the component. * @return Size. */ - inline uint Size() const { return (uint)this->nodes.size(); } + inline uint16 Size() const { return (uint16)this->nodes.size(); } /** * Get date of last compression. diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 5e69dbeba0..6a70e9fb69 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -101,7 +101,7 @@ LinkGraphJob::~LinkGraphJob() /* Link graph has been merged into another one. */ if (!LinkGraph::IsValidID(this->link_graph.index)) return; - uint size = this->Size(); + uint16 size = this->Size(); for (NodeID node_id = 0; node_id < size; ++node_id) { Node from = (*this)[node_id]; diff --git a/src/linkgraph/mcf.cpp b/src/linkgraph/mcf.cpp index 003412850c..f24a8e0282 100644 --- a/src/linkgraph/mcf.cpp +++ b/src/linkgraph/mcf.cpp @@ -260,7 +260,7 @@ void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths) { typedef std::set AnnoSet; Tedge_iterator iter(this->job); - uint size = this->job.Size(); + uint16 size = this->job.Size(); AnnoSet annos; paths.resize(size, nullptr); for (NodeID node = 0; node < size; ++node) { @@ -473,7 +473,7 @@ bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next bool MCF1stPass::EliminateCycles() { bool cycles_found = false; - uint size = this->job.Size(); + uint16 size = this->job.Size(); PathVector path(size, nullptr); for (NodeID node = 0; node < size; ++node) { /* Starting at each node in the graph find all cycles involving this @@ -491,7 +491,7 @@ bool MCF1stPass::EliminateCycles() MCF1stPass::MCF1stPass(LinkGraphJob &job) : MultiCommodityFlow(job) { PathVector paths; - uint size = job.Size(); + uint16 size = job.Size(); uint accuracy = job.Settings().accuracy; bool more_loops; std::vector finished_sources(size); @@ -540,7 +540,7 @@ MCF2ndPass::MCF2ndPass(LinkGraphJob &job) : MultiCommodityFlow(job) { this->max_saturation = UINT_MAX; // disable artificial cap on saturation PathVector paths; - uint size = job.Size(); + uint16 size = job.Size(); uint accuracy = job.Settings().accuracy; bool demand_left = true; std::vector finished_sources(size); diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 883097dea1..738afec4e6 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -374,14 +374,13 @@ uint64 Packet::Recv_uint64() */ void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings) { - PacketSize pos; char *bufp = buffer; const char *last = buffer + size - 1; /* Don't allow reading from a closed socket */ if (cs->HasClientQuit()) return; - pos = this->pos; + size_t pos = this->pos; while (--size > 0 && pos < this->Size() && (*buffer++ = this->buffer[pos++]) != '\0') {} if (size == 0 || pos == this->Size()) { @@ -391,7 +390,9 @@ void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings set while (pos < this->Size() && this->buffer[pos] != '\0') pos++; pos++; } - this->pos = pos; + + assert(pos <= std::numeric_limits::max()); + this->pos = static_cast(pos); str_validate(bufp, last, settings); } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 49c7d736af..3cb99d785d 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -1219,7 +1219,7 @@ public: StringID str = this->GetWidget(widget)->widget_data; for (auto station_class : this->station_classes) { StationClass *stclass = StationClass::Get(station_class); - for (uint16 j = 0; j < stclass->GetSpecCount(); j++) { + for (uint j = 0; j < stclass->GetSpecCount(); j++) { const StationSpec *statspec = stclass->GetSpec(j); SetDParam(0, (statspec != nullptr && statspec->name != 0) ? statspec->name : STR_STATION_CLASS_DFLT); d = maxdim(d, GetStringBoundingBox(str)); diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index f571e331a5..e46054cf0f 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -139,7 +139,7 @@ static const SaveLoad _edge_desc[] = { */ void SaveLoad_LinkGraph(LinkGraph &lg) { - uint size = lg.Size(); + uint16 size = lg.Size(); for (NodeID from = 0; from < size; ++from) { Node *node = &lg.nodes[from]; SlObject(node, _node_desc); diff --git a/src/story_gui.cpp b/src/story_gui.cpp index 0ed39ba045..ccb9ccf7b8 100644 --- a/src/story_gui.cpp +++ b/src/story_gui.cpp @@ -776,7 +776,7 @@ public: case WID_SB_SEL_PAGE: { /* Get max title width. */ - for (uint16 i = 0; i < this->story_pages.size(); i++) { + for (size_t i = 0; i < this->story_pages.size(); i++) { const StoryPage *s = this->story_pages[i]; if (s->title != nullptr) { @@ -822,7 +822,7 @@ public: if (!list.empty()) { /* Get the index of selected page. */ int selected = 0; - for (uint16 i = 0; i < this->story_pages.size(); i++) { + for (size_t i = 0; i < this->story_pages.size(); i++) { const StoryPage *p = this->story_pages[i]; if (p->index == this->selected_page_id) break; selected++; diff --git a/src/texteff.hpp b/src/texteff.hpp index d122b17e9b..56b5933926 100644 --- a/src/texteff.hpp +++ b/src/texteff.hpp @@ -24,7 +24,7 @@ enum TextEffectMode { INVALID_TE_ID = 0xFFFF, }; -typedef uint16 TextEffectID; +typedef size_t TextEffectID; void MoveAllTextEffects(uint delta_ms); TextEffectID AddTextEffect(StringID msg, int x, int y, uint8 duration, TextEffectMode mode); From ddaedaf32a1981dcd93cafee0cae879f96207fe4 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 11 May 2021 19:36:21 +0200 Subject: [PATCH 195/800] Fix: empty undocumented branches --- src/blitter/32bpp_anim_sse4.cpp | 1 + src/saveload/game_sl.cpp | 3 +-- src/strgen/strgen_base.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index 566ef0c0ff..c6213ce30b 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -155,6 +155,7 @@ bmno_full_transparency: if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { if (src->a == 0) { + /* Complete transparency. */ } else if (src->a == 255) { *anim = *(const uint16*) src_mv; *dst = (src_mv->m >= PALETTE_ANIM_START) ? AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v) : *src; diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index d7bb22a668..00ca6d9ab9 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -70,8 +70,7 @@ static void Load_GSDT() } GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); - if (_game_saveload_name.empty()) { - } else { + if (!_game_saveload_name.empty()) { config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random); if (!config->HasScript()) { /* No version of the GameScript available that can load the data. Try to load the diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 60e27e752b..9d1346e17f 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -457,7 +457,7 @@ void EmitGender(Buffer *buffer, char *buf, int value) /* This is a {G 0 foo bar two} command. * If no relative number exists, default to +0 */ - if (!ParseRelNum(&buf, &argidx, &offset)) {} + ParseRelNum(&buf, &argidx, &offset); const CmdStruct *cmd = _cur_pcs.cmd[argidx]; if (cmd == nullptr || (cmd->flags & C_GENDER) == 0) { From 44ca7d93773fb816da6d353c9cde6ab14dae993a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 9 May 2021 19:02:17 +0200 Subject: [PATCH 196/800] Change: Use gender-neutral pronouns --- changelog.txt | 14 +++++++------- os/emscripten/cmake/FindLibLZMA.cmake | 2 +- src/aircraft_cmd.cpp | 2 +- src/blitter/factory.hpp | 2 +- src/console_internal.h | 2 +- src/economy.cpp | 4 ++-- src/graph_gui.cpp | 2 +- src/heightmap.cpp | 2 +- src/linkgraph/linkgraphjob.cpp | 2 +- src/misc_cmd.cpp | 2 +- src/network/core/tcp_game.h | 2 +- src/network/network.cpp | 6 +++--- src/network/network_chat_gui.cpp | 2 +- src/network/network_gui.h | 2 +- src/network/network_server.cpp | 10 +++++----- src/newgrf.cpp | 2 +- src/newgrf_airporttiles.cpp | 2 +- src/newgrf_commons.cpp | 4 ++-- src/newgrf_industries.cpp | 2 +- src/openttd.cpp | 2 +- src/order_cmd.cpp | 2 +- src/pathfinder/npf/aystar.cpp | 4 ++-- src/rail_gui.cpp | 2 +- src/saveload/afterload.cpp | 2 +- src/saveload/ai_sl.cpp | 2 +- src/saveload/saveload.cpp | 2 +- src/script/api/script_controller.cpp | 2 +- src/script/api/script_object.cpp | 2 +- src/script/api/script_waypointlist.hpp | 4 +++- src/script/script_config.hpp | 2 +- src/script/script_info_dummy.cpp | 2 +- src/script/script_instance.hpp | 2 +- src/settings_type.h | 2 +- src/ship_cmd.cpp | 2 +- src/station_cmd.cpp | 2 +- src/strings.cpp | 2 +- src/table/settings.ini | 2 +- src/train_cmd.cpp | 2 +- 38 files changed, 55 insertions(+), 53 deletions(-) diff --git a/changelog.txt b/changelog.txt index 703f434afa..bf75edde4f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2186,7 +2186,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: [NewGRF] Additional text in fund industry window is NewGRF supplied and thus should have a default colour (r22631) - Fix: Also initialise _old_vds with newgame settings; TTD savegames do not contain these settings [FS#4622] (r22626) - Fix: Do not zero the orders of disaster vehicles when converting savegames [FS#4642] (r22625) -- Fix: When closing an AI company the local player cheated to, we need to cheat him to another company [FS#4654] (r22624, r22623) +- Fix: When closing an AI company the local player cheated to, we need to cheat them to another company [FS#4654] (r22624, r22623) - Fix: When closing down companies their shares in other companies must be sold even if share trading is disabled at that point of time (r22622) - Fix: When asking the user to confirm an unsafe unpausing, there is no need to execute a command if 'no' is chosen. This also prevents crashing when clicking unpause while the confirm window is shown (r22621) - Fix: Enforce refit orders to be 'always go to depot' orders; service-only and stop-in-depot orders make no sense with refitting [FS#4651] (r22620) @@ -2908,7 +2908,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Chat message caused glitch when rejoining a network game [FS#3757] (r19629) - Fix: Desync when a command is received and in the queue while a client starts joining, i.e. save the game state. This can happen in two ways: with frame_freq > 1 a command received in a previous frame might not be executed yet or when a command is received in the same frame as the join but before the savegame is made. In both cases the joining client would not get all commands to get in-sync with the server (and the other clients) (r19620) - Fix: Company related graphs were not updated correctly after changing the company colour [FS#3763] (r19615) -- Fix: Possible invalid read when server moves client to spectators before he finishes joining [FS#3755] (r19613) +- Fix: Possible invalid read when server moves client to spectators before they finish joining [FS#3755] (r19613) - Fix: Crash when opening a savegame with a waypoint from around 0.4.0 [FS#3756] (r19612) - Fix: Improve joining behaviour; kicking clients when entering passwords that was just cleared, 'connection lost' for people failing the password, access restriction circumvention [CVE-2010-0401] [FS#3754] (r19610, r19609, r19608, r19607, r19606) - Fix: Desync debugging; false positives in the cache validity checks and saving/loading the command stream (r19619, r19617, r19602, r19601, r19600, r19596, r19593, r19592, r19589, r19587, r19586) @@ -3263,7 +3263,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Do not account for path reservation costs when entering a signal block via a 'block' signal. This way you will not get double penalties, both red signals and reservation costs, for the block signalled tracks [FS#2722] (r18535) - Fix: [NewGRF] An industry NewGRF that defined a too small size for action0 prop 0A could cause a crash (r18527) - Fix: Allegro does not like to work with extmidi, so warn the user about that [FS#3272] (r18520) -- Fix: When you pass a signal at danger, in a PBS controlled area, do not try to do the 'safe' thing and stop, but continue going; the user wanted the train to pass the signal at danger so (s)he has to suffer the consequences. Of course one can always stop the train manually [FS#2891] (r18515) +- Fix: When you pass a signal at danger, in a PBS controlled area, do not try to do the 'safe' thing and stop, but continue going; the user wanted the train to pass the signal at danger so they have to suffer the consequences. Of course one can always stop the train manually [FS#2891] (r18515) - Fix: No error message was created for the first fatal NewGRF error [FS#3368] (r18506) - Fix: Improve airport movement on several airports [FS#3169] (r18505) - Fix: Autoreplace and autorenew always reset their cargo sub type to 0. Now find a sub cargo type with the exact same name and use that, otherwise fallback to 0. So cargo sub types can be maintained via autoreplace *if* the new vehicle supports the same cargo sub type [FS#3159] (r18499) @@ -3746,7 +3746,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Make the join/spectate command require to be connected to a network game; in SP it could lead to crashes (r15514) - Fix: Generating a map with the original map generator with freeform edges on resulted in a crash [FS#2641] (r15511) - Fix: Pre-0.5 OpenTTD stored new_nonstop and full_load_any in a different way, savegame conversion was not working for them (r15500) -- Fix: Crash when opening the game options when the currently loaded base graphics pack has less than 2 valid graphics files. For example when someone replaces all his/her original base graphics with custom work (but keeps the name) or renames the dos ones to windows or vice versa [FS#2630] (r15476) +- Fix: Crash when opening the game options when the currently loaded base graphics pack has less than 2 valid graphics files. For example when someone replaces all their original base graphics with custom work (but keeps the name) or renames the dos ones to windows or vice versa [FS#2630] (r15476) 0.7.0-beta1 (2009-02-16) @@ -4508,7 +4508,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Switching players (using the cheat) crashed on Big Endian machines [FS#1150] (r11023) - Fix: The canal border determination did not take oil rigs into consideration (r11022) - Fix: Do not display income/expenses when they do not belong to a 'valid' tile, like the money cheat/giving money [FS#1175] (r11021) -- Fix: One could not give money when (s)he had too much money or rather: when casting the amount of money to an int32 becomes negative [FS#1174] (r11020) +- Fix: One could not give money when they had too much money or rather: when casting the amount of money to an int32 becomes negative [FS#1174] (r11020) - Fix: When determining the gender of a string, do not assume that the gender is in the front of the string when there can be case switching code at that location [FS#1104] (r10792) - Fix: Determining whether there is a tunnel going under the lowered area is only needed in two directions instead of all four, so take the directions (one for each axis) to the nearest border (along the given axis) [FS#1058] (r10686) - Fix: Graphical glitches when the 'link landscape toolbar' patch is turned on when opening one of the construction toolbars [FS#1076] (r10685) @@ -4569,7 +4569,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Do not unconditionally assume that a tile has a depot (r11027) - Fix: Give a more correct error when building some things on tile 0 [FS#1173] (r11024) - Fix: Do not display income/expenses when they do not belong to a 'valid' tile, like the money cheat and giving money [FS#1175] (r11021) -- Fix: One could not give money when (s)he had too much money [FS#1174] (r11020) +- Fix: One could not give money when they had too much money [FS#1174] (r11020) - Fix: Disallow buying/selling shares in your own company or a bankrupt company [FS#1169] (r11018) - Fix: Crash when quitting the game in one of the end score windows [FS#1218] (r11071) @@ -5529,7 +5529,7 @@ Note: OpenTTD was migrated to GitHub for 1.9, so SVN revision and FlySpray numbe - Fix: Vehicles slow down under bridge if the track is on a foundation - Fix: You can no longer change name of waypoints whom are owned by somebody else - Fix: Shares are now also sold when a company goes bankrupt [SF#1090313] -- Fix: It is no longer possible to crash trains of other companies by building a depot close to a station; trains do no longer enter tiles that do not belong to his owner [SF#1087701] +- Fix: It is no longer possible to crash trains of other companies by building a depot close to a station; trains do no longer enter tiles that do not belong to their owner [SF#1087701] - Fix: Crashed trains are not reported to have too few orders any more [SF#1087403] - Fix: Backup-order-list was not closed with an OT_NOTHING, [SF#1086375] - Fix: Docks now have a button to display the catchment area [SF#1085255] diff --git a/os/emscripten/cmake/FindLibLZMA.cmake b/os/emscripten/cmake/FindLibLZMA.cmake index 99d1ca640a..e8a024c4ee 100644 --- a/os/emscripten/cmake/FindLibLZMA.cmake +++ b/os/emscripten/cmake/FindLibLZMA.cmake @@ -1,5 +1,5 @@ # LibLZMA is a recent addition to the emscripten SDK, so it is possible -# someone hasn't updated his SDK yet. Test out if the SDK supports LibLZMA. +# someone hasn't updated their SDK yet. Test out if the SDK supports LibLZMA. include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_FLAGS "-sUSE_LIBLZMA=1") diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 2d47b560f8..445798327d 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1025,7 +1025,7 @@ static bool AircraftController(Aircraft *v) if (count == 0) return false; /* If the plane will be a few subpixels away from the destination after - * this movement loop, start nudging him towards the exact position for + * this movement loop, start nudging it towards the exact position for * the whole loop. Otherwise, heavily depending on the speed of the plane, * it is possible we totally overshoot the target, causing the plane to * make a loop, and trying again, and again, and again .. */ diff --git a/src/blitter/factory.hpp b/src/blitter/factory.hpp index 94f3f99988..322b11c953 100644 --- a/src/blitter/factory.hpp +++ b/src/blitter/factory.hpp @@ -91,7 +91,7 @@ public: } /** - * Find the requested blitter and return his class. + * Find the requested blitter and return its class. * @param name the blitter to select. * @post Sets the blitter so GetCurrentBlitter() returns it too. */ diff --git a/src/console_internal.h b/src/console_internal.h index ca2f92193b..80752a08eb 100644 --- a/src/console_internal.h +++ b/src/console_internal.h @@ -29,7 +29,7 @@ enum ConsoleHookResult { * effect they produce are carried out. The arguments to the commands * are given to them, each input word separated by a double-quote (") is an argument * If you want to handle multiple words as one, enclose them in double-quotes - * eg. 'say "hello sexy boy"' + * eg. 'say "hello everybody"' */ typedef bool IConsoleCmdProc(byte argc, char *argv[]); typedef ConsoleHookResult IConsoleHook(bool echo); diff --git a/src/economy.cpp b/src/economy.cpp index ae289a51da..09adf81b99 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -311,7 +311,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) for (const Company *c : Company::Iterate()) { for (i = 0; i < 4; i++) { if (c->share_owners[i] == old_owner) { - /* Sell his shares */ + /* Sell its shares */ CommandCost res = DoCommand(0, c->index, 0, DC_EXEC | DC_BANKRUPT, CMD_SELL_SHARE_IN_COMPANY); /* Because we are in a DoCommand, we can't just execute another one and * expect the money to be removed. We need to do it ourself! */ @@ -337,7 +337,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) } /* Temporarily increase the company's money, to be sure that - * removing his/her property doesn't fail because of lack of money. + * removing their property doesn't fail because of lack of money. * Not too drastically though, because it could overflow */ if (new_owner == INVALID_OWNER) { Company::Get(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index c50027718a..10433fc093 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -1417,7 +1417,7 @@ struct PerformanceRatingDetailWindow : Window { int64 needed = _score_info[score_type].needed; int score = _score_info[score_type].score; - /* SCORE_TOTAL has his own rules ;) */ + /* SCORE_TOTAL has its own rules ;) */ if (score_type == SCORE_TOTAL) { for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) score += _score_info[i].score; needed = SCORE_MAX; diff --git a/src/heightmap.cpp b/src/heightmap.cpp index 7b070f4405..458b0c910a 100644 --- a/src/heightmap.cpp +++ b/src/heightmap.cpp @@ -480,7 +480,7 @@ bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, } /** - * Load a heightmap from file and change the map in his current dimensions + * Load a heightmap from file and change the map in its current dimensions * to a landscape representing the heightmap. * It converts pixels to height. The brighter, the higher. * @param dft Type of image file. diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 6a70e9fb69..8e5ec32838 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -65,7 +65,7 @@ void LinkGraphJob::SpawnThread() * On the other hand, if you want to play games which make this hang noticeably * on a platform without threads then you'll probably get other problems first. * OK: - * If someone comes and tells me that this hangs for him/her, I'll implement a + * If someone comes and tells me that this hangs for them, I'll implement a * smaller grained "Step" method for all handlers and add some more ticks where * "Step" is called. No problem in principle. */ LinkGraphSchedule::Run(this); diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index 2d1bbdf7a7..f9a102d1a1 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -129,7 +129,7 @@ CommandCost CmdDecreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * In case of an unsafe unpause, we want the * user to confirm that it might crash. * @param w unused - * @param confirmed whether the user confirms his/her action + * @param confirmed whether the user confirmed their action */ static void AskUnsafeUnpauseCallback(Window *w, bool confirmed) { diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index 5fe9cd465d..90b7184f0a 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -274,7 +274,7 @@ protected: virtual NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p); /** - * The client is joined and ready to receive his map: + * The client is joined and ready to receive their map: * uint32 Own client ID. * uint32 Generation seed. * string Network ID of the server. diff --git a/src/network/network.cpp b/src/network/network.cpp index 80ecfc2cde..2c5390dc04 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -269,8 +269,8 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, uint NetworkCalculateLag(const NetworkClientSocket *cs) { int lag = cs->last_frame_server - cs->last_frame; - /* This client has missed his ACK packet after 1 DAY_TICKS.. - * so we increase his lag for every frame that passes! + /* This client has missed their ACK packet after 1 DAY_TICKS.. + * so we increase their lag for every frame that passes! * The packet can be out by a max of _net_frame_freq */ if (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq < _frame_counter) { lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq); @@ -680,7 +680,7 @@ public: }; /** - * Query a server to fetch his game-info for the lobby. + * 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) diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index e8fbf0f124..82d9a819bb 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -128,7 +128,7 @@ void NetworkUndrawChatMessage() /* Sometimes we also need to hide the cursor * This is because both textmessage and the cursor take a shot of the * screen before drawing. - * Now the textmessage takes his shot and paints his data before the cursor + * Now the textmessage takes its shot and paints its data before the cursor * does, so in the shot of the cursor is the screen-data of the textmessage * included when the cursor hangs somewhere over the textmessage. To * avoid wrong repaints, we undraw the cursor in that case, and everything diff --git a/src/network/network_gui.h b/src/network/network_gui.h index e4ccf4e783..f435efbcd9 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -32,7 +32,7 @@ struct NetworkCompanyInfo : NetworkCompanyStats { Money company_value; ///< The company value Money money; ///< The amount of money the company has Money income; ///< How much did the company earned last year - uint16 performance; ///< What was his performance last month? + uint16 performance; ///< What was their performance last month? bool use_password; ///< Is there a password char clients[NETWORK_CLIENTS_LENGTH]; ///< The clients that control this company (Name1, name2, ..) }; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 7b77c76c4a..91ab8bd9c6 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -472,7 +472,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err DEBUG(net, 1, "Client %d made an error and has been disconnected: %s", this->client_id, str); } - /* The client made a mistake, so drop his connection now! */ + /* The client made a mistake, so drop the connection now! */ return this->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR); } @@ -858,7 +858,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED NetworkClientInfo *ci = this->GetInfo(); - /* We now want a password from the client else we do not allow him in! */ + /* We now want a password from the client else we do not allow them in! */ if (!_settings_client.network.server_password.empty()) { return this->SendNeedGamePassword(); } @@ -995,7 +995,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWOR NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet *p) { /* The client was never joined.. so this is impossible, right? - * Ignore the packet, give the client a warning, and close his connection */ + * Ignore the packet, give the client a warning, and close the connection */ if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) { return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED); } @@ -1063,7 +1063,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet * NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet *p) { /* The client was never joined.. so this is impossible, right? - * Ignore the packet, give the client a warning, and close his connection */ + * Ignore the packet, give the client a warning, and close the connection */ if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } @@ -1857,7 +1857,7 @@ void NetworkServer_Tick(bool send_frame) * spamming the client. Strictly speaking this variable * tracks when we last received a packet from the client, * but as it is waiting, it will not send us any till we - * start sending him data. */ + * start sending them data. */ cs->last_packet = std::chrono::steady_clock::now(); } break; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index d2b3449c96..5ddfcadddc 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -3185,7 +3185,7 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr /* A copied tile should not have the animation infos copied too. * The anim_state should be left untouched, though - * It is up to the author to animate them himself */ + * It is up to the author to animate them */ tsp->anim_production = INDUSTRYTILE_NOANIM; tsp->anim_next = INDUSTRYTILE_NOANIM; diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index a049064515..221d9aef44 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -155,7 +155,7 @@ static uint32 GetAirportTileIDAtOffset(TileIndex tile, const Station *st, uint32 } } /* The tile has no spritegroup */ - return 0xFF << 8 | ats->grf_prop.subst_id; // so just give him the substitute + return 0xFF << 8 | ats->grf_prop.subst_id; // so just give it the substitute } /* virtual */ uint32 AirportTileScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index 64eed8139a..55674a60db 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -264,7 +264,7 @@ void IndustryOverrideManager::SetEntitySpec(IndustrySpec *inds) if (ind_id == invalid_ID) { /* Not found. - * Or it has already been overridden, so you've lost your place old boy. + * Or it has already been overridden, so you've lost your place. * Or it is a simple substitute. * We need to find a free available slot */ ind_id = this->AddEntityID(inds->grf_prop.local_id, inds->grf_prop.grffile->grfid, inds->grf_prop.subst_id); @@ -319,7 +319,7 @@ void ObjectOverrideManager::SetEntitySpec(ObjectSpec *spec) if (type == invalid_ID) { /* Not found. - * Or it has already been overridden, so you've lost your place old boy. + * Or it has already been overridden, so you've lost your place. * Or it is a simple substitute. * We need to find a free available slot */ type = this->AddEntityID(spec->grf_prop.local_id, spec->grf_prop.grffile->grfid, OBJECT_TRANSMITTER); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index abae446040..55f80e9747 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -85,7 +85,7 @@ uint32 GetIndustryIDAtOffset(TileIndex tile, const Industry *i, uint32 cur_grfid } } /* The tile has no spritegroup */ - return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give him the substitute + return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give it the substitute } static uint32 GetClosestIndustry(TileIndex tile, IndustryType type, const Industry *current) diff --git a/src/openttd.cpp b/src/openttd.cpp index fec8bf9caf..5a4e73593b 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -965,7 +965,7 @@ bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileTy void SwitchToMode(SwitchMode new_mode) { - /* If we are saving something, the network stays in his current state */ + /* If we are saving something, the network stays in its current state */ if (new_mode != SM_SAVE_GAME) { /* If the network is active, make it not-active */ if (_networking) { diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index c4793fa33b..70fce860be 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1039,7 +1039,7 @@ static void CancelLoadingDueToDeletedOrder(Vehicle *v) { assert(v->current_order.IsType(OT_LOADING)); /* NON-stop flag is misused to see if a train is in a station that is - * on his order list or not */ + * on its order list or not */ v->current_order.SetNonStopType(ONSF_STOP_EVERYWHERE); /* When full loading, "cancel" that order so the vehicle doesn't * stay indefinitely at this station anymore. */ diff --git a/src/pathfinder/npf/aystar.cpp b/src/pathfinder/npf/aystar.cpp index b14053b7c0..163d7859ec 100644 --- a/src/pathfinder/npf/aystar.cpp +++ b/src/pathfinder/npf/aystar.cpp @@ -144,14 +144,14 @@ void AyStar::CheckTile(AyStarNode *current, OpenListNode *parent) /* Re-add it in the openlist_queue. */ this->openlist_queue.Push(check, new_f); } else { - /* A new node, add him to the OpenList */ + /* A new node, add it to the OpenList */ this->OpenListAdd(closedlist_parent, current, new_f, new_g); } } /** * This function is the core of %AyStar. It handles one item and checks - * his neighbour items. If they are valid, they are added to be checked too. + * its neighbour items. If they are valid, they are added to be checked too. * @return Possible values: * - #AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path has been found. * - #AYSTAR_LIMIT_REACHED : Indicates that the max_search_nodes limit has been reached. diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 3cb99d785d..e7221d01c4 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -410,7 +410,7 @@ static void HandleAutoSignalPlacement() } /* _settings_client.gui.drag_signals_density is given as a parameter such that each user - * in a network game can specify his/her own signal density */ + * in a network game can specify their own signal density */ DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), p2, _remove_button_clicked ? CMD_REMOVE_SIGNAL_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM) : diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 26c749bf73..f60c12b91b 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -179,7 +179,7 @@ static void UpdateExclusiveRights() * Build an array town_blocked[ town_id ][ company_id ] * that stores if at least one station in that town is blocked for a company * 2.) Go through that array, if you find a town that is not blocked for - * one company, but for all others, then give him exclusivity. + * one company, but for all others, then give it exclusivity. */ } diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index 4c751117f0..3bc1d0f879 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -51,7 +51,7 @@ static void SaveReal_AIPL(int *index_ptr) _ai_saveload_settings = config->SettingsToString(); SlObject(nullptr, _ai_company); - /* If the AI was active, store his data too */ + /* If the AI was active, store its data too */ if (Company::IsValidAiID(index)) AI::Save(index); } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 34982ecfeb..442ab9135c 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -2618,7 +2618,7 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check) fmt = _saveload_formats; for (;;) { if (fmt == endof(_saveload_formats)) { - /* Who removed LZO support? Bad bad boy! */ + /* Who removed LZO support? */ NOT_REACHED(); } if (fmt->tag == TO_BE32X('OTTD')) break; diff --git a/src/script/api/script_controller.cpp b/src/script/api/script_controller.cpp index e74f27e4a4..8af7b87a3c 100644 --- a/src/script/api/script_controller.cpp +++ b/src/script/api/script_controller.cpp @@ -54,7 +54,7 @@ seprintf(log_message, lastof(log_message), "Break: %s", message); ScriptLog::Log(ScriptLog::LOG_SQ_ERROR, log_message); - /* Inform script developer that his script has been paused and + /* Inform script developer that their script has been paused and * needs manual action to continue. */ ShowAIDebugWindow(ScriptObject::GetRootCompany()); diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index 6275d1be38..85a85cca1b 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -365,7 +365,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() IncreaseDoCommandCosts(res.GetCost()); /* Suspend the script player for 1+ ticks, so it simulates multiplayer. This - * both avoids confusion when a developer launched his script in a + * both avoids confusion when a developer launched the script in a * multiplayer game, but also gives time for the GUI and human player * to interact with the game. */ throw Script_Suspend(GetDoCommandDelay(), callback); diff --git a/src/script/api/script_waypointlist.hpp b/src/script/api/script_waypointlist.hpp index 0ee33eff68..f05754b1e0 100644 --- a/src/script/api/script_waypointlist.hpp +++ b/src/script/api/script_waypointlist.hpp @@ -34,7 +34,9 @@ public: class ScriptWaypointList_Vehicle : public ScriptList { public: /** - * @param vehicle_id The vehicle to get the list of waypoints he has in its orders from. + * Get the waypoints from the orders of the given vehicle. Duplicates are + * not added. Waypoints are added in the order of the vehicle's orders. + * @param vehicle_id The vehicle to get the list of waypoints for. */ ScriptWaypointList_Vehicle(VehicleID vehicle_id); }; diff --git a/src/script/script_config.hpp b/src/script/script_config.hpp index 7ddc0ab6a2..13a136cbbf 100644 --- a/src/script/script_config.hpp +++ b/src/script/script_config.hpp @@ -116,7 +116,7 @@ public: void AnchorUnchangeableSettings(); /** - * Get the value of a setting for this config. It might fallback to his + * Get the value of a setting for this config. It might fallback to its * 'info' to find the default value (if not set or if not-custom difficulty * level). * @return The (default) value of the setting, or -1 if the setting was not diff --git a/src/script/script_info_dummy.cpp b/src/script/script_info_dummy.cpp index 063c028cc3..9438b77f09 100644 --- a/src/script/script_info_dummy.cpp +++ b/src/script/script_info_dummy.cpp @@ -15,7 +15,7 @@ #include "../safeguards.h" -/* The reason this exists in C++, is that a user can trash his ai/ or game/ dir, +/* The reason this exists in C++, is that a user can trash their ai/ or game/ dir, * leaving no Scripts available. The complexity to solve this is insane, and * therefore the alternative is used, and make sure there is always a Script * available, no matter what the situation is. By defining it in C++, there diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp index c097e0eb7b..4709c44e2f 100644 --- a/src/script/script_instance.hpp +++ b/src/script/script_instance.hpp @@ -55,7 +55,7 @@ public: virtual class ScriptInfo *FindLibrary(const char *library, int version) = 0; /** - * A script in multiplayer waits for the server to handle his DoCommand. + * A script in multiplayer waits for the server to handle its DoCommand. * It keeps waiting for this until this function is called. */ void Continue(); diff --git a/src/settings_type.h b/src/settings_type.h index bba95ad967..39a73b3ed9 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -125,7 +125,7 @@ struct GUISettings { bool autosave_on_network_disconnect; ///< save an autosave when you get disconnected from a network game with an error? uint8 date_format_in_default_names; ///< should the default savegame/screenshot name use long dates (31th Dec 2008), short dates (31-12-2008) or ISO dates (2008-12-31) byte max_num_autosaves; ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1) - bool population_in_label; ///< show the population of a town in his label? + bool population_in_label; ///< show the population of a town in its label? uint8 right_mouse_btn_emulation; ///< should we emulate right mouse clicking? uint8 scrollwheel_scrolling; ///< scrolling using the scroll wheel? uint8 scrollwheel_multiplier; ///< how much 'wheel' per incoming event from the OS? diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index ca159531a2..415d97ebce 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -257,7 +257,7 @@ Trackdir Ship::GetVehicleTrackdir() const } if (this->state == TRACK_BIT_WORMHOLE) { - /* ship on aqueduct, so just use his direction and assume a diagonal track */ + /* ship on aqueduct, so just use its direction and assume a diagonal track */ return DiagDirToDiagTrackdir(DirToDiagDir(this->direction)); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index eecb08d7cd..d1e12604c9 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3468,7 +3468,7 @@ static void UpdateStationRating(Station *st) for (const CargoSpec *cs : CargoSpec::Iterate()) { GoodsEntry *ge = &st->goods[cs->Index()]; - /* Slowly increase the rating back to his original level in the case we + /* Slowly increase the rating back to its original level in the case we * didn't deliver cargo yet to this station. This happens when a bribe * failed while you didn't moved that cargo yet to a station. */ if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) { diff --git a/src/strings.cpp b/src/strings.cpp index fb19438705..8c9ac0aaf5 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -836,7 +836,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg const char *&str = str_stack.top(); if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) { - /* We need to pass some stuff as it might be modified; oh boy. */ + /* We need to pass some stuff as it might be modified. */ //todo: should argve be passed here too? b = RemapNewGRFStringControlCode(b, buf_start, &buff, &str, (int64 *)args->GetDataPointer(), args->GetDataLeft(), dry_run); if (b == 0) continue; diff --git a/src/table/settings.ini b/src/table/settings.ini index 66dc55e9bb..eea30e003c 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -56,7 +56,7 @@ static bool UpdateClientConfigValues(int32 p1); * It is also a bit tricky since you would think that service_interval * for example doesn't need to be synched. Every client assigns the * service_interval value to the v->service_interval, meaning that every client - * assigns his value. If the setting was company-based, that would mean that + * assigns its own value. If the setting was company-based, that would mean that * vehicles could decide on different moments that they are heading back to a * service depot, causing desyncs on a massive scale. */ const SettingDesc _settings[] = { diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 169fb9d71c..dc87827a75 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4026,7 +4026,7 @@ Trackdir Train::GetVehicleTrackdir() const } if (this->track == TRACK_BIT_WORMHOLE) { - /* train in tunnel or on bridge, so just use his direction and assume a diagonal track */ + /* train in tunnel or on bridge, so just use its direction and assume a diagonal track */ return DiagDirToDiagTrackdir(DirToDiagDir(this->direction)); } From e6703eac6853851f310923760b194ee4c875251b Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 18:12:37 +0200 Subject: [PATCH 197/800] Codechange: [Network] Let NetworkTextMessage use std::string --- src/network/network.cpp | 4 ++-- src/network/network_client.cpp | 4 ++-- src/network/network_internal.h | 2 +- src/network/network_server.cpp | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 2c5390dc04..abc8bdbc0e 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -214,7 +214,7 @@ bool NetworkCompanyIsPassworded(CompanyID company_id) /* This puts a text-message to the console, or in the future, the chat-box, * (to keep it all a bit more general) * If 'self_send' is true, this is the client who is sending the message */ -void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str, int64 data) +void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, int64 data) { StringID strid; switch (action) { @@ -369,7 +369,7 @@ void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode) char buffer[DRAW_STRING_BUFFER]; GetString(buffer, str, lastof(buffer)); - NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, nullptr, buffer); + NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", buffer); break; } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index b6da3dc183..ba9b16d85c 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1078,7 +1078,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Pack NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci != nullptr) { - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, nullptr, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8())); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8())); delete ci; } @@ -1095,7 +1095,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_QUIT(Packet *p) NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci != nullptr) { - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING); delete ci; } else { DEBUG(net, 1, "Unknown client (%d) is leaving the game", client_id); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 7412d9232c..d1db971a32 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -114,7 +114,7 @@ void NetworkFreeLocalCommandQueue(); void NetworkSyncCommandQueue(NetworkClientSocket *cs); void ShowNetworkError(StringID error_string); -void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0); +void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0); uint NetworkCalculateLag(const NetworkClientSocket *cs); StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char *new_name, const char *last); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 91ab8bd9c6..85015fce14 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -262,7 +262,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta this->GetClientName(client_name, lastof(client_name)); - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST); /* Inform other clients of this... strange leaving ;) */ for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) { @@ -453,7 +453,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err if (error == NETWORK_ERROR_KICKED && reason != nullptr) { NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid); } else { - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid); } for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) { @@ -1021,7 +1021,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet * this->GetClientName(client_name, lastof(client_name)); - NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, nullptr, this->client_id); + NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, "", this->client_id); InvalidateWindowData(WC_CLIENT_LIST, 0); /* Mark the client as pre-active, and wait for an ACK @@ -1144,7 +1144,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p DEBUG(net, 1, "'%s' reported an error and is closing its connection: %s", client_name, str); - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid); for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) { if (new_cs->status >= STATUS_AUTHORIZED) { @@ -1170,7 +1170,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p) this->GetClientName(client_name, lastof(client_name)); - NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING); for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) { if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) { From 2e0297b0fa85e0a8130e24122ab93c74b6a83002 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 18:32:58 +0200 Subject: [PATCH 198/800] Add: GetString that returns std::string instead of filling a passed buffer --- src/strings.cpp | 12 ++++++++++++ src/strings_func.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/strings.cpp b/src/strings.cpp index 8c9ac0aaf5..6a0d1a8804 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -285,6 +285,18 @@ char *GetString(char *buffr, StringID string, const char *last) return GetStringWithArgs(buffr, string, &_global_string_params, last); } +/** + * Resolve the given StringID into a std::string with all the associated + * DParam lookups and formatting. + * @param string The unique identifier of the translatable string. + * @return The std::string of the translated string. + */ +std::string GetString(StringID string) +{ + char buffer[DRAW_STRING_BUFFER]; + GetString(buffer, string, lastof(buffer)); + return buffer; +} /** * This function is used to "bind" a C string to a OpenTTD dparam slot. diff --git a/src/strings_func.h b/src/strings_func.h index be59b091a2..11f41d7381 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -172,6 +172,7 @@ public: extern StringParameters _global_string_params; char *GetString(char *buffr, StringID string, const char *last); +std::string GetString(StringID string); char *GetStringWithArgs(char *buffr, StringID string, StringParameters *args, const char *last, uint case_index = 0, bool game_script = false); const char *GetStringPtr(StringID string); From ae85af98eb02831594e4a204348c682b192e83ac Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 18:45:54 +0200 Subject: [PATCH 199/800] Codechange: Use std::string GetString where convenient --- src/company_cmd.cpp | 6 ++---- src/network/network.cpp | 4 +--- src/network/network_admin.cpp | 36 ++++++++++------------------------ src/network/network_server.cpp | 13 ++++-------- src/newgrf.cpp | 4 +--- 5 files changed, 18 insertions(+), 45 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 17923377af..85809544d4 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -1220,13 +1220,11 @@ CommandCost CmdGiveMoney(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 cur_company.Restore(); if (_networking) { - char dest_company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, dest_company); - GetString(dest_company_name, STR_COMPANY_NAME, lastof(dest_company_name)); + std::string dest_company_name = GetString(STR_COMPANY_NAME); - char from_company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, _current_company); - GetString(from_company_name, STR_COMPANY_NAME, lastof(from_company_name)); + std::string from_company_name = GetString(STR_COMPANY_NAME); NetworkTextMessage(NETWORK_ACTION_GIVE_MONEY, GetDrawStringCompanyColour(_current_company), false, from_company_name, dest_company_name, amount.GetCost()); } diff --git a/src/network/network.cpp b/src/network/network.cpp index abc8bdbc0e..19957f7006 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -367,9 +367,7 @@ void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode) str = paused ? STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED : STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED; } - char buffer[DRAW_STRING_BUFFER]; - GetString(buffer, str, lastof(buffer)); - NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", buffer); + NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", GetString(str)); break; } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index dfe09344a9..419de71d1c 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -133,11 +133,9 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode er p->Send_uint8(error); this->SendPacket(p); - char str[100]; - StringID strid = GetNetworkErrorMsg(error); - GetString(str, strid, lastof(str)); + std::string error_message = GetString(GetNetworkErrorMsg(error)); - DEBUG(net, 1, "[admin] The admin '%s' (%s) made an error and has been disconnected: '%s'", this->admin_name, this->admin_version, str); + DEBUG(net, 1, "[admin] The admin '%s' (%s) made an error and has been disconnected: '%s'", this->admin_name, this->admin_version, error_message.c_str()); return this->CloseConnection(true); } @@ -316,20 +314,13 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID comp */ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c) { - char company_name[NETWORK_COMPANY_NAME_LENGTH]; - char manager_name[NETWORK_COMPANY_NAME_LENGTH]; - - SetDParam(0, c->index); - GetString(company_name, STR_COMPANY_NAME, lastof(company_name)); - - SetDParam(0, c->index); - GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name)); - Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO); p->Send_uint8 (c->index); - p->Send_string(company_name); - p->Send_string(manager_name); + SetDParam(0, c->index); + p->Send_string(GetString(STR_COMPANY_NAME)); + SetDParam(0, c->index); + p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_uint8 (c->colour); p->Send_bool (NetworkCompanyIsPassworded(c->index)); p->Send_uint32(c->inaugurated_year); @@ -352,20 +343,13 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company */ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c) { - char company_name[NETWORK_COMPANY_NAME_LENGTH]; - char manager_name[NETWORK_COMPANY_NAME_LENGTH]; - - SetDParam(0, c->index); - GetString(company_name, STR_COMPANY_NAME, lastof(company_name)); - - SetDParam(0, c->index); - GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name)); - Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE); p->Send_uint8 (c->index); - p->Send_string(company_name); - p->Send_string(manager_name); + SetDParam(0, c->index); + p->Send_string(GetString(STR_COMPANY_NAME)); + SetDParam(0, c->index); + p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_uint8 (c->colour); p->Send_bool (NetworkCompanyIsPassworded(c->index)); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 85015fce14..71173a8d52 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -432,7 +432,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error, const char *reason) { - char str[100]; Packet *p = new Packet(PACKET_SERVER_ERROR); p->Send_uint8(error); @@ -440,7 +439,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err this->SendPacket(p); StringID strid = GetNetworkErrorMsg(error); - GetString(str, strid, lastof(str)); /* Only send when the current client was in game */ if (this->status > STATUS_AUTHORIZED) { @@ -448,7 +446,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err this->GetClientName(client_name, lastof(client_name)); - DEBUG(net, 1, "'%s' made an error and has been disconnected: %s", client_name, str); + DEBUG(net, 1, "'%s' made an error and has been disconnected: %s", client_name, GetString(strid).c_str()); if (error == NETWORK_ERROR_KICKED && reason != nullptr) { NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid); @@ -469,7 +467,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err NetworkAdminClientError(this->client_id, error); } else { - DEBUG(net, 1, "Client %d made an error and has been disconnected: %s", this->client_id, str); + DEBUG(net, 1, "Client %d made an error and has been disconnected: %s", this->client_id, GetString(strid).c_str()); } /* The client made a mistake, so drop the connection now! */ @@ -1128,7 +1126,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p { /* This packets means a client noticed an error and is reporting this * to us. Display the error and report it to the other clients */ - char str[100]; char client_name[NETWORK_CLIENT_NAME_LENGTH]; NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8(); @@ -1140,9 +1137,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p this->GetClientName(client_name, lastof(client_name)); StringID strid = GetNetworkErrorMsg(errorno); - GetString(str, strid, lastof(str)); - DEBUG(net, 1, "'%s' reported an error and is closing its connection: %s", client_name, str); + DEBUG(net, 1, "'%s' reported an error and is closing its connection: %s", client_name, GetString(strid).c_str()); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid); @@ -1317,10 +1313,9 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co /* Display the message locally (so you know you have sent it) */ if (ci != nullptr && show_local) { if (from_id == CLIENT_ID_SERVER) { - char name[NETWORK_NAME_LENGTH]; StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; SetDParam(0, ci_to->client_playas); - GetString(name, str, lastof(name)); + std::string name = GetString(str); NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data); } else { for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 5ddfcadddc..29125f158e 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7759,9 +7759,7 @@ static void TranslateGRFStrings(ByteReader *buf) * and disable this file. */ GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LOAD_AFTER); - char tmp[256]; - GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp)); - error->data = tmp; + error->data = GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE); return; } From fab120ee831ff1cdf3d5560b6b87288b07c52084 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 18:22:39 +0200 Subject: [PATCH 200/800] Codechange: [Network] Let chat communication use std::string --- src/network/network_admin.cpp | 7 +++---- src/network/network_admin.h | 4 ++-- src/network/network_chat_gui.cpp | 4 ++-- src/network/network_client.cpp | 14 +++++++------- src/network/network_client.h | 2 +- src/network/network_func.h | 4 ++-- src/network/network_server.cpp | 7 +++---- src/network/network_server.h | 2 +- 8 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 419de71d1c..09b039485a 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -450,7 +450,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats() * @param msg The actual message. * @param data Arbitrary extra data. */ -NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data) +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data) { Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT); @@ -769,8 +769,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) DestType desttype = (DestType)p->Recv_uint8(); int dest = p->Recv_uint32(); - char msg[NETWORK_CHAT_LENGTH]; - p->Recv_string(msg, NETWORK_CHAT_LENGTH); + std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH); switch (action) { case NETWORK_ACTION_CHAT: @@ -902,7 +901,7 @@ void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bc /** * Send chat to the admin network (if they did opt in for the respective update). */ -void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin) +void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data, bool from_admin) { if (from_admin) return; diff --git a/src/network/network_admin.h b/src/network/network_admin.h index cf6cf6e7cc..0e443d08f2 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -61,7 +61,7 @@ public: NetworkRecvStatus SendCompanyEconomy(); NetworkRecvStatus SendCompanyStats(); - NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data); + NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data); NetworkRecvStatus SendRcon(uint16 colour, const char *command); NetworkRecvStatus SendConsole(const char *origin, const char *command); NetworkRecvStatus SendGameScript(const char *json); @@ -106,7 +106,7 @@ void NetworkAdminCompanyInfo(const Company *company, bool new_company); void NetworkAdminCompanyUpdate(const Company *company); void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr); -void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data = 0, bool from_admin = false); +void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data = 0, bool from_admin = false); void NetworkAdminUpdate(AdminUpdateFrequency freq); void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string); void NetworkAdminConsole(const char *origin, const char *string); diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 82d9a819bb..f8eaf3bda6 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -259,9 +259,9 @@ void NetworkDrawChatMessage() * @param type The type of destination. * @param dest The actual destination index. */ -static void SendChat(const char *buf, DestType type, int dest) +static void SendChat(const std::string &buf, DestType type, int dest) { - if (StrEmpty(buf)) return; + if (buf.empty()) return; if (!_network_server) { MyClient::SendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, 0); } else { diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index ba9b16d85c..8cbe76e189 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -450,7 +450,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendCommand(const CommandPacke } /** Send a chat-packet over the network */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data) { Packet *p = new Packet(PACKET_CLIENT_CHAT); @@ -1025,13 +1025,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p) { if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH]; + std::string name; const NetworkClientInfo *ci = nullptr, *ci_to; NetworkAction action = (NetworkAction)p->Recv_uint8(); ClientID client_id = (ClientID)p->Recv_uint32(); bool self_send = p->Recv_bool(); - p->Recv_string(msg, NETWORK_CHAT_LENGTH); + std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH); int64 data = p->Recv_uint64(); ci_to = NetworkClientInfo::GetByClientID(client_id); @@ -1042,7 +1042,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p) switch (action) { case NETWORK_ACTION_CHAT_CLIENT: /* For speaking to client we need the client-name */ - seprintf(name, lastof(name), "%s", ci_to->client_name); + name = ci_to->client_name; ci = NetworkClientInfo::GetByClientID(_network_own_client_id); break; @@ -1051,7 +1051,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p) StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; SetDParam(0, ci_to->client_playas); - GetString(name, str, lastof(name)); + name = GetString(str); ci = NetworkClientInfo::GetByClientID(_network_own_client_id); break; } @@ -1060,7 +1060,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p) } } else { /* Display message from somebody else */ - seprintf(name, lastof(name), "%s", ci_to->client_name); + name = ci_to->client_name; ci = ci_to; } @@ -1385,7 +1385,7 @@ void NetworkUpdateClientName() * @param msg The actual message. * @param data Arbitrary extra data. */ -void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data) +void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data) { MyClient::SendChat(action, type, dest, msg, data); } diff --git a/src/network/network_client.h b/src/network/network_client.h index 7d0d228104..169820d969 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -93,7 +93,7 @@ public: static NetworkRecvStatus SendGamePassword(const std::string &password); static NetworkRecvStatus SendCompanyPassword(const std::string &password); - static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data); + static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data); static NetworkRecvStatus SendSetPassword(const std::string &password); static NetworkRecvStatus SendSetName(const char *name); static NetworkRecvStatus SendRCon(const std::string &password, const char *command); diff --git a/src/network/network_func.h b/src/network/network_func.h index 82a5deb45c..1c5916eda0 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -55,7 +55,7 @@ bool NetworkClientConnectGame(const std::string &connection_string, CompanyID de void NetworkClientJoinGame(); void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); void NetworkClientSendRcon(const std::string &password, const char *command); -void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); +void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); bool NetworkCompanyIsPassworded(CompanyID company_id); bool NetworkMaxCompaniesReached(); @@ -77,7 +77,7 @@ 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 NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &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); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 71173a8d52..f5cd91bd10 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -719,7 +719,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCommand(const CommandPacke * @param msg The actual message. * @param data Arbitrary extra data. */ -NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data) +NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64 data) { if (this->status < STATUS_PRE_ACTIVE) return NETWORK_RECV_STATUS_OKAY; @@ -1235,7 +1235,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p) * @param data Arbitrary data. * @param from_admin Whether the origin is an admin or not. */ -void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin) +void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const std::string &msg, ClientID from_id, int64 data, bool from_admin) { const NetworkClientInfo *ci, *ci_own, *ci_to; @@ -1356,9 +1356,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet *p) NetworkAction action = (NetworkAction)p->Recv_uint8(); DestType desttype = (DestType)p->Recv_uint8(); int dest = p->Recv_uint32(); - char msg[NETWORK_CHAT_LENGTH]; - p->Recv_string(msg, NETWORK_CHAT_LENGTH); + std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH); int64 data = p->Recv_uint64(); NetworkClientInfo *ci = this->GetInfo(); diff --git a/src/network/network_server.h b/src/network/network_server.h index f8f58d1e38..98b2f9b6eb 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -94,7 +94,7 @@ public: NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci); NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason = nullptr); - NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data); + NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64 data); NetworkRecvStatus SendJoin(ClientID client_id); NetworkRecvStatus SendFrame(); NetworkRecvStatus SendSync(); From 2e43f918913e79ea402173f63b692b609a59de09 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 15 May 2021 19:05:41 +0000 Subject: [PATCH 201/800] Update: Translations from eints estonian: 1 change by siimsoni indonesian: 39 changes by w13 --- src/lang/estonian.txt | 2 +- src/lang/indonesian.txt | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index c9acfd0e7d..04ca5f79da 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -2327,7 +2327,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} li STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} liitus vaatlejatega STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} alustas uue ettevõtte (nr {2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} lahkus mängust ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} uus nimi on {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} on muutnud oma nimeks {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} saatis {2:CURRENCY_LONG} ettevõttele {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server sulges sessiooni STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server restardib...{}Palun oota... diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 878cb24d8e..b89f522d6e 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -946,6 +946,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Dollar Taiwan B STR_GAME_OPTIONS_CURRENCY_CNY :Renminbi Cina (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Dollar Hong Kong (HKD) STR_GAME_OPTIONS_CURRENCY_INR :India Rupee (INR) +STR_GAME_OPTIONS_CURRENCY_IDR :Rupiah Indonesia (IDR) STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaysia (MYR) ############ end of currency region @@ -992,6 +993,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Setiap 12 bulan STR_GAME_OPTIONS_LANGUAGE :{BLACK}Bahasa STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Pilih antar muka bahasa yang akan dipergunakan +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% selesai) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Layar Penuh STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Klik cek box ini untuk memainkan OpenTTD dalam layar penuh @@ -999,10 +1001,13 @@ STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Klik cek STR_GAME_OPTIONS_RESOLUTION :{BLACK}Resolusi Layar STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}Pilih resolusi layar yang diinginkan STR_GAME_OPTIONS_RESOLUTION_OTHER :lainnya +STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Akselerasi perangkat keras +STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK} Centang kotak ini untuk mengizinkan OpenTTD mencoba menggunakan akselerasi perangkat keras. Pengaturan yang diubah hanya akan diterapkan saat game dimulai ulang. STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Pengaturan hanya akan berlaku setelah game dimulai ulang +STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Centang kotak ini untuk melakukan sinkronisasi layar (v-sync). Pengaturan yang diubah hanya akan diterapkan saat game dimulai ulang. Hanya berfungsi dengan akselerasi perangkat keras diaktifkan. STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Ukuran antarmuka STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Pilih ukuran elemen antarmuka yang akan digunakan @@ -1023,6 +1028,8 @@ STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :4 kali STR_GAME_OPTIONS_GRAPHICS :{BLACK}Grafik STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Menampilkan kecepatan refresh +STR_GAME_OPTIONS_REFRESH_RATE_OTHER :lain +STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}Kecepatan refresh yang lebih tinggi dari 60Hz dapat memengaruhi kinerja. STR_GAME_OPTIONS_BASE_GRF :{BLACK}Set Grafik Dasar @@ -1133,6 +1140,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Pengatur STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Penyaring kata: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Perluas semua STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Persempit semua +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Atur ulang semua pengaturan STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(penjelasan belum tersedia) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Nilai standar: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipe setting: {ORANGE}{STRING} @@ -1349,6 +1357,8 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Jarak maksimal STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Kilang minyak hanya dibangun pada tepi peta atau pantai STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Tinggi garis salju: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Mengatur ketinggian di mana salju akan muncul. Salju juga akan mempengaruhi pengembangan industri dan persyaratan untuk pertumbuhan kota +STR_CONFIG_SETTING_SNOW_COVERAGE :Cakupan salju: {STRING} +STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_DESERT_COVERAGE :Cakupan gurun: {STRING} STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Kontrol perkiraan jumlah gurun di lanskap tropis. Gurun juga mempengaruhi generasi industri. Hanya digunakan selama pembuatan peta STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% @@ -1467,6 +1477,8 @@ STR_CONFIG_SETTING_EXPENSES_LAYOUT :Kelompokkan pen STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Mendefinisikan tata ruang untuk tetingkap biaya perusahaan STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Secara otomatis menghapus sinyal selama konstruksi rel: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Menghapus sinyal secara otomatis selama konstruksi rel jika sinyal menghalangi. Perhatikan bahwa hal ini berpotensi menyebabkan kecelakaan kereta api. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% kecepatan normal +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :Tanpa batas (secepat komputer Anda memungkinkan) STR_CONFIG_SETTING_SOUND_TICKER :Ticker berita: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Mainkan suara untuk pesanan berita yang diringkas @@ -1800,6 +1812,7 @@ STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}Kehabisa STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Mengalokasikan {BYTES} 'spritecache' gagal. 'Spritecache' dikurangi ke {BYTES}. Ini akan kurangi kinerja OpenTTD. Untuk kurangi kebutuhan memori anda bisa coba matikan grafik 32bpp dan/atau tingkat pembesaran # Video initalization errors +STR_VIDEO_DRIVER_ERROR :{WHITE}Kesalahan dengan pengaturan video... STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... tidak ditemukan GPU yang kompatibel. Akselerasi perangkat keras dinonaktifkan # Intro window @@ -1967,6 +1980,8 @@ STR_FACE_TIE :Dasi: STR_FACE_EARRING :Anting-anting: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ubah dasi atau anting-anting +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privat +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Umum # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Bermain bersama @@ -2030,6 +2045,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nama per STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Atur kata sandi STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Lindungi permainan ini dengan kata kunci jika anda tidak ingin membiarkannya terbuka untuk umum +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Orang lain bisa melihat server Anda di daftar umum STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klien STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimum jumlah klien: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Pilih jumlah klien maksimal. Tidak semua slot harus diisi @@ -2096,8 +2112,21 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Perusaha STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Daftar klien # Network client list +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nama server +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Nama pemain +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Tindakan administratif yang harus dilakukan untuk perusahaan ini +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Kirim pesan ke pemain ini +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Kirim pesan ke semua penonton +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Perusahaan baru) +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Diusir +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Melarang +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Buka pakai kata sandi +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Anda yakin ingin diusir pemain '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Apakah Anda yakin ingin mencekal pemain '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Anda yakin ingin menghapus perusahaan '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Anda yakin ingin menyetel ulang sandi perusahaan '{COMPANY}'? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klien @@ -2142,6 +2171,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Tak dapa STR_NETWORK_ERROR_CLIENT_START :{WHITE}Tak dapat tersambung STR_NETWORK_ERROR_TIMEOUT :{WHITE}Waktu Koneksi #{NUM} telah habis STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Kesalahan protokol, koneksi ditutup +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Nama permainan belum disetel. Nama bisa diatur di bagian atas jendela Multiplayer STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Revisi pada klien tidak sama dengan revisi pada server STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Kata kunci salah STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Server penuh @@ -2176,6 +2206,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :tidak menerima STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :waktu koneksi habis STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :pengunduhan peta memakan banyak waktu STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :pengolahan peta memakan banyak waktu +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nama yang dihubungi tidak valid ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Koneksi mungkin terputus @@ -2835,9 +2866,13 @@ STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Jumlah Kota: STR_MAPGEN_DATE :{BLACK}Tgl: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Jumlah industri: +STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Puncak tertinggi: STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Kurangi satu ketinggian maksimum puncak tertinggi di peta +STR_MAPGEN_SNOW_COVERAGE :{BLACK}Cakupan salju: +STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}Meningkatkan cakupan salju sepuluh persen STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}Kurangi cakupan salju hingga sepuluh persen STR_MAPGEN_DESERT_COVERAGE :{BLACK}Cakupan gurun: +STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Kurangi cakupan gurun pasir sebesar sepuluh persen STR_MAPGEN_LAND_GENERATOR :{BLACK}Algoritma pulau: STR_MAPGEN_TERRAIN_TYPE :{BLACK}Jenis dataran: STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}Area perairan: @@ -2863,6 +2898,7 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nama Pet STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Luas: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} +STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Target ketinggian puncak STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Cakupan salju (dalam %) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Ganti Tahun Permulaan @@ -3155,6 +3191,8 @@ STR_GOALS_CAPTION :{WHITE}{COMPANY STR_GOALS_SPECTATOR_CAPTION :{WHITE}Target Global STR_GOALS_SPECTATOR :Target Global STR_GOALS_GLOBAL_BUTTON :{BLACK}Global +STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}Tunjukkan target global +STR_GOALS_COMPANY_BUTTON :{BLACK}Perusahaan STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_NONE :{ORANGE}- Tidak ada - STR_GOALS_PROGRESS :{ORANGE}{STRING} @@ -4277,6 +4315,7 @@ STR_WARNING_FALLBACK_SOUNDSET :{WHITE}Hanya ef STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}Tangkapan layar besar STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}Resolusi tangkapan layar {COMMA} x {COMMA} piksel. Membuat tangkapan layar akan memakan waktu. Anda ingin melanjutkan? +STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY :{WHITE}Peta ketinggian sudah disimpan sebagai '{STRING}'. Puncak tertinggi adalah {NUM} STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}Pengambilan gambar telah berhasil disimpan sebagai '{STRING}' STR_ERROR_SCREENSHOT_FAILED :{WHITE}Pengambilan gambar gagal From e66e25ff71d67975e4c5ba0df569339270cfafe2 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 15 May 2021 15:50:32 +0200 Subject: [PATCH 202/800] Fix #9269, f6d5c01: Hide windows without abusing WC_INVALID --- src/widgets/dropdown.cpp | 4 ++-- src/window.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index a4bd002593..e838d72315 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -188,7 +188,7 @@ struct DropdownWindow : Window { { /* Make the dropdown "invisible", so it doesn't affect new window placement. * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - this->window_class = WC_INVALID; + *this->z_position = nullptr; this->SetDirty(); Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); @@ -304,7 +304,7 @@ struct DropdownWindow : Window { if (this->click_delay != 0 && --this->click_delay == 0) { /* Make the dropdown "invisible", so it doesn't affect new window placement. * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - this->window_class = WC_INVALID; + *this->z_position = nullptr; this->SetDirty(); w2->OnDropdownSelect(this->parent_button, this->selected_index); diff --git a/src/window.cpp b/src/window.cpp index bb7787581a..036b17bcca 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -3489,6 +3489,6 @@ void RelocateAllWindows(int neww, int newh) */ PickerWindowBase::~PickerWindowBase() { - this->window_class = WC_INVALID; // stop the ancestor from freeing the already (to be) child + *this->z_position = nullptr; // stop the ancestor from freeing the already (to be) child ResetObjectToPlace(); } From 5c01f9ea525616b432968df845a90da1d888631f Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 16 May 2021 07:33:32 +0200 Subject: [PATCH 203/800] Fix #9267, 47a99bb: [Squirrel] Heap use after free Due to 47a99bb the order of elements in the garbage collection chain has changed causing the class to be finalised before the instances of that class. Since the instance's array of member values depends on the size of the values in the class, the class finalisation resetting that size to 0 causes not all finalisations to run, which subsequently causes a heap use after free. So, just set the SQObjectPtrs to 'null' during the finalisation of the SQClass so the SQInstance can release all instance variables during its finalisation. --- src/3rdparty/squirrel/squirrel/sqclass.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/squirrel/squirrel/sqclass.cpp b/src/3rdparty/squirrel/squirrel/sqclass.cpp index aa1bca0443..71743f4644 100644 --- a/src/3rdparty/squirrel/squirrel/sqclass.cpp +++ b/src/3rdparty/squirrel/squirrel/sqclass.cpp @@ -34,7 +34,13 @@ SQClass::SQClass(SQSharedState *ss,SQClass *base) void SQClass::Finalize() { _attributes = _null_; - _defaultvalues.resize(0); + /* SQInstance's Finalize depends on the size of this sqvector, so instead of + * resizing, all SQObjectPtrs are set to "null" so it holds no references to + * other objects anymore. That way everything gets released properly. */ + for (SQUnsignedInteger i = 0; i < _defaultvalues.size(); i++) { + _defaultvalues[i].val = _null_; + _defaultvalues[i].attrs = _null_; + } _methods.resize(0); _metamethods.resize(0); __ObjRelease(_members); From e90b2649b651e3ede41a2a40e70ab79ea4270dfe Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 17:43:23 +0200 Subject: [PATCH 204/800] Codechange: [Network] Let NetworkCompanyInfo use std::string --- src/network/network_client.cpp | 4 ++-- src/network/network_gui.cpp | 4 ++-- src/network/network_gui.h | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 8cbe76e189..78670aa94d 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -618,7 +618,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Pa NetworkCompanyInfo *company_info = GetLobbyCompanyInfo(current); if (company_info == nullptr) return NETWORK_RECV_STATUS_CLOSE_QUERY; - p->Recv_string(company_info->company_name, sizeof(company_info->company_name)); + 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(); @@ -633,7 +633,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Pa } company_info->ai = p->Recv_bool(); - p->Recv_string(company_info->clients, sizeof(company_info->clients)); + company_info->clients = p->Recv_string(NETWORK_CLIENTS_LENGTH); SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 8dec56a6de..f0c28530a6 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1283,7 +1283,7 @@ struct NetworkLobbyWindow : public Window { { /* Scroll through all this->company_info and get the 'pos' item that is not empty. */ for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) { - if (!StrEmpty(this->company_info[i].company_name)) { + if (!this->company_info[i].company_name.empty()) { if (pos-- == 0) return i; } } @@ -1398,7 +1398,7 @@ struct NetworkLobbyWindow : public Window { GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 12, STR_NETWORK_GAME_LOBBY_COMPANY_INFO, TC_FROMSTRING, SA_HOR_CENTER); - if (this->company == INVALID_COMPANY || StrEmpty(this->company_info[this->company].company_name)) return; + if (this->company == INVALID_COMPANY || this->company_info[this->company].company_name.empty()) return; int y = r.top + detail_height + 4; const NetworkGameInfo *gi = &this->server->info; diff --git a/src/network/network_gui.h b/src/network/network_gui.h index f435efbcd9..855d7d53c6 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -27,14 +27,14 @@ void ShowNetworkCompanyPasswordWindow(Window *parent); /** Company information stored at the client side */ struct NetworkCompanyInfo : NetworkCompanyStats { - char company_name[NETWORK_COMPANY_NAME_LENGTH]; ///< Company name - Year inaugurated_year; ///< What year the company started in - Money company_value; ///< The company value - Money money; ///< The amount of money the company has - Money income; ///< How much did the company earned last year - uint16 performance; ///< What was their performance last month? - bool use_password; ///< Is there a password - char clients[NETWORK_CLIENTS_LENGTH]; ///< The clients that control this company (Name1, name2, ..) + std::string company_name; ///< Company name + Year inaugurated_year; ///< What year the company started in + Money company_value; ///< The company value + Money money; ///< The amount of money the company has + Money income; ///< How much did the company earn last year + uint16 performance; ///< What was his performance last month? + bool use_password; ///< Is there a password + std::string clients; ///< The clients that control this company (Name1, name2, ..) }; NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company); From 83679c0e57cb3e13de6d6c5ec33735bc4070da40 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 15 May 2021 08:35:45 +0200 Subject: [PATCH 205/800] Codechange: [Network] Use std::string to populate the client list for company stats --- src/network/network_server.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index f5cd91bd10..0d5eb83fd6 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -372,13 +372,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() NetworkPopulateCompanyStats(company_stats); /* Make a list of all clients per company */ - char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH]; - memset(clients, 0, sizeof(clients)); + std::string clients[MAX_COMPANIES]; /* Add the local player (if not dedicated) */ const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); if (ci != nullptr && Company::IsValidID(ci->client_playas)) { - strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas])); + clients[ci->client_playas] = ci->client_name; } for (NetworkClientSocket *csi : NetworkClientSocket::Iterate()) { @@ -388,11 +387,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() ci = csi->GetInfo(); if (ci != nullptr && Company::IsValidID(ci->client_playas)) { - if (!StrEmpty(clients[ci->client_playas])) { - strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas])); + if (!clients[ci->client_playas].empty()) { + clients[ci->client_playas] += ", "; } - strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas])); + clients[ci->client_playas] += client_name; } } @@ -407,7 +406,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() p->Send_bool (true); this->SendCompanyInformation(p, company, &company_stats[company->index]); - if (StrEmpty(clients[company->index])) { + if (clients[company->index].empty()) { p->Send_string(""); } else { p->Send_string(clients[company->index]); From 4d246cda73d73cbc3f1557dd4ecb1c1d0d451fb0 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 15 May 2021 08:31:45 +0200 Subject: [PATCH 206/800] Codechange: [Network] Let NetworkClientInfo use std::string --- src/network/network.cpp | 2 +- src/network/network_base.h | 8 ++++---- src/network/network_chat_gui.cpp | 2 +- src/network/network_client.cpp | 19 ++++++++----------- src/network/network_server.cpp | 24 ++++++++++++------------ src/script/api/script_client.cpp | 2 +- 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 19957f7006..15e4b8d2a8 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -844,7 +844,7 @@ static void NetworkInitGameInfo() 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.c_str(), lastof(ci->client_name)); + ci->client_name = _settings_client.network.client_name; } /** diff --git a/src/network/network_base.h b/src/network/network_base.h index 9ad0300629..479f340f18 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -22,10 +22,10 @@ extern NetworkClientInfoPool _networkclientinfo_pool; /** Container for all information known about a client. */ struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_pool> { - ClientID client_id; ///< Client identifier (same as ClientState->client_id) - char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client - CompanyID client_playas; ///< As which company is this client playing (CompanyID) - Date join_date; ///< Gamedate the client has joined + ClientID client_id; ///< Client identifier (same as ClientState->client_id) + std::string client_name; ///< Name of the client + CompanyID client_playas; ///< As which company is this client playing (CompanyID) + Date join_date; ///< Gamedate the client has joined /** * Create a new client. diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index f8eaf3bda6..068a5314ee 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -332,7 +332,7 @@ struct NetworkChatWindow : public Window { /* Skip inactive clients */ for (NetworkClientInfo *ci : NetworkClientInfo::Iterate(*item)) { *item = ci->index; - return ci->client_name; + return ci->client_name.c_str(); } *item = MAX_CLIENT_SLOTS; } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 78670aa94d..08a35e980b 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -651,9 +651,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac NetworkClientInfo *ci; ClientID client_id = (ClientID)p->Recv_uint32(); CompanyID playas = (CompanyID)p->Recv_uint8(); - char name[NETWORK_NAME_LENGTH]; - p->Recv_string(name, sizeof(name)); + std::string name = p->Recv_string(NETWORK_NAME_LENGTH); if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; @@ -664,7 +663,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac ci = NetworkClientInfo::GetByClientID(client_id); if (ci != nullptr) { - if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { + if (playas == ci->client_playas && name.compare(ci->client_name) != 0) { /* Client name changed, display the change */ NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name); } else if (playas != ci->client_playas) { @@ -677,7 +676,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac if (client_id == _network_own_client_id) SetLocalCompany(!Company::IsValidID(playas) ? COMPANY_SPECTATOR : playas); ci->client_playas = playas; - strecpy(ci->client_name, name, lastof(ci->client_name)); + ci->client_name = name; InvalidateWindowData(WC_CLIENT_LIST, 0); @@ -696,7 +695,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac ci->client_playas = playas; if (client_id == _network_own_client_id) this->SetInfo(ci); - strecpy(ci->client_name, name, lastof(ci->client_name)); + ci->client_name = name; InvalidateWindowData(WC_CLIENT_LIST, 0); @@ -745,8 +744,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error]; /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */ if (error == NETWORK_ERROR_KICKED && p->CanReadFromPacket(1)) { - char kick_msg[255]; - p->Recv_string(kick_msg, sizeof(kick_msg)); + std::string kick_msg = p->Recv_string(NETWORK_CHAT_LENGTH); SetDParamStr(0, kick_msg); ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL); } else { @@ -1160,10 +1158,9 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_RCON(Packet *p) TextColour colour_code = (TextColour)p->Recv_uint16(); if (!IsValidConsoleColour(colour_code)) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - char rcon_out[NETWORK_RCONCOMMAND_LENGTH]; - p->Recv_string(rcon_out, sizeof(rcon_out)); + std::string rcon_out = p->Recv_string(NETWORK_RCONCOMMAND_LENGTH); - IConsolePrint(colour_code, rcon_out); + IConsolePrint(colour_code, rcon_out.c_str()); return NETWORK_RECV_STATUS_OKAY; } @@ -1370,7 +1367,7 @@ void NetworkUpdateClientName() strecpy(temporary_name, _settings_client.network.client_name.c_str(), lastof(temporary_name)); if (NetworkFindName(temporary_name, lastof(temporary_name))) { NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); - strecpy(ci->client_name, temporary_name, lastof(ci->client_name)); + ci->client_name = temporary_name; NetworkUpdateClientInfo(CLIENT_ID_SERVER); } } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 0d5eb83fd6..3a9128427e 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -927,7 +927,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) NetworkClientInfo *ci = new NetworkClientInfo(this->client_id); this->SetInfo(ci); ci->join_date = _date; - strecpy(ci->client_name, name, lastof(ci->client_name)); + ci->client_name = name; ci->client_playas = playas; DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index); @@ -1413,7 +1413,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet /* Display change */ if (NetworkFindName(client_name, lastof(client_name))) { NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name); - strecpy(ci->client_name, client_name, lastof(ci->client_name)); + ci->client_name = client_name; NetworkUpdateClientInfo(ci->client_id); } } @@ -1689,7 +1689,7 @@ bool NetworkFindName(char *new_name, const char *last) while (!found_name) { found_name = true; for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (strcmp(ci->client_name, new_name) == 0) { + if (ci->client_name.compare(new_name) == 0) { /* Name already in use */ found_name = false; break; @@ -1698,7 +1698,7 @@ bool NetworkFindName(char *new_name, const char *last) /* Check if it is the same as the server-name */ const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); if (ci != nullptr) { - if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use + if (ci->client_name.compare(new_name) == 0) found_name = false; // name already in use } if (!found_name) { @@ -1723,7 +1723,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const char *new_name) { /* Check if the name's already in use */ for (NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (strcmp(ci->client_name, new_name) == 0) return false; + if (ci->client_name.compare(new_name) == 0) return false; } NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); @@ -1731,7 +1731,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const char *new_name) NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name); - strecpy(ci->client_name, new_name, lastof(ci->client_name)); + ci->client_name = new_name; NetworkUpdateClientInfo(client_id); return true; @@ -1963,7 +1963,7 @@ void NetworkServerShowStatusToConsole() status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown"); IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s", - cs->client_id, ci->client_name, status, lag, + cs->client_id, ci->client_name.c_str(), status, lag, ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0), cs->GetClientIP()); } @@ -2135,10 +2135,10 @@ void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char { const NetworkClientInfo *ci = this->GetInfo(); - if (ci == nullptr || StrEmpty(ci->client_name)) { + if (ci == nullptr || ci->client_name.empty()) { seprintf(client_name, last, "Client #%4d", this->client_id); } else { - strecpy(client_name, ci->client_name, last); + strecpy(client_name, ci->client_name.c_str(), last); } } @@ -2151,13 +2151,13 @@ void NetworkPrintClients() if (_network_server) { IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s", ci->client_id, - ci->client_name, + ci->client_name.c_str(), ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0), ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP()); } else { IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d", ci->client_id, - ci->client_name, + ci->client_name.c_str(), ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0)); } } @@ -2182,7 +2182,7 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */ ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); - NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index); + NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name.c_str(), c->index); } /* Announce new company on network. */ diff --git a/src/script/api/script_client.cpp b/src/script/api/script_client.cpp index da646516bc..ede1b925fe 100644 --- a/src/script/api/script_client.cpp +++ b/src/script/api/script_client.cpp @@ -36,7 +36,7 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client) { NetworkClientInfo *ci = FindClientInfo(client); if (ci == nullptr) return nullptr; - return stredup(ci->client_name); + return stredup(ci->client_name.c_str()); } /* static */ ScriptCompany::CompanyID ScriptClient::GetCompany(ScriptClient::ClientID client) From e2e06633c9ff41260d54691f9e7c10dcfe7395fb Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 16 May 2021 19:07:45 +0000 Subject: [PATCH 207/800] Update: Translations from eints norwegian (bokmal): 1 change by Anolitt slovak: 1 change by FuryPapaya --- src/lang/norwegian_bokmal.txt | 2 +- src/lang/slovak.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 882605dcea..6fe947be63 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -2273,7 +2273,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} ha STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} har blitt med som tilskuer STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} har startet et nytt firma (nr. {2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} har forlatt spillet ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} har forandret sitt navn til {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} har endret navnet sitt til {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} ga {2:CURRENCY_LONG} til ditt firma{1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Tjeneren avsluttet spillet STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Tjeneren starter på nytt...{}Vennligst vent... diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 908f055ecf..6eae8a010a 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -4756,7 +4756,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Zatiaľ STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Začnite novú hru po {DATE_SHORT} alebo použite NewGRF, ktoré zabezpečí vozidlá v skoršom čase # Specific vehicle errors -STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemôžeš nechať vlak prejsť cez návestidlo keď hrozí nebezpečenstvo... +STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemožno nechať vlak prejsť návestidlo ak hrozí nebezpečenstvo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nemožno otočiť vlak naopak... STR_ERROR_TRAIN_START_NO_POWER :Vlak nemá energiu From e2dc5aa83e75b2f1f34feaadec3ae8f4e2a484b0 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 16 May 2021 12:10:12 +0200 Subject: [PATCH 208/800] Codechange: [Network] Use C++ string functions to generate company password hash --- src/network/network.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 15e4b8d2a8..53ef645d7b 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -34,6 +34,8 @@ #include "../gfx_func.h" #include "../error.h" #include +#include +#include #include "../safeguards.h" @@ -176,29 +178,31 @@ std::string GenerateCompanyPasswordHash(const std::string &password, const std:: { if (password.empty()) return password; - char salted_password[NETWORK_SERVER_ID_LENGTH]; size_t password_length = password.size(); size_t password_server_id_length = password_server_id.size(); - /* Add the game seed and the server's ID as the salt. */ + std::ostringstream salted_password; + /* Add the password with the server's ID and game seed as the salt. */ for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) { char password_char = (i < password_length ? password[i] : 0); char server_id_char = (i < password_server_id_length ? password_server_id[i] : 0); char seed_char = password_game_seed >> (i % 32); - salted_password[i] = password_char ^ server_id_char ^ seed_char; + salted_password << (char)(password_char ^ server_id_char ^ seed_char); // Cast needed, otherwise interpreted as integer to format } Md5 checksum; uint8 digest[16]; - static char hashed_password[NETWORK_SERVER_ID_LENGTH]; /* Generate the MD5 hash */ - checksum.Append(salted_password, sizeof(salted_password) - 1); + std::string salted_password_string = salted_password.str(); + checksum.Append(salted_password_string.data(), salted_password_string.size()); checksum.Finish(digest); - for (int di = 0; di < 16; di++) seprintf(hashed_password + di * 2, lastof(hashed_password), "%02x", digest[di]); + std::ostringstream hashed_password; + hashed_password << std::hex << std::setfill('0'); + for (int di = 0; di < 16; di++) hashed_password << std::setw(2) << (int)digest[di]; // Cast needed, otherwise interpreted as character to add - return hashed_password; + return hashed_password.str(); } /** From 7caceb26f7a95afe32c242d9c28e8542646a5e6d Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 17 May 2021 19:08:25 +0000 Subject: [PATCH 209/800] Update: Translations from eints korean: 1 change by telk5093 indonesian: 55 changes by NinjaQuince --- src/lang/indonesian.txt | 67 +++++++++++++++++++++++++++++++++-------- src/lang/korean.txt | 2 +- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index b89f522d6e..54974fcb82 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -953,7 +953,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaysi STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Berkendara di lajur kiri STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Berkendara di lajur kanan -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nama kota +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nama kota: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Pilih model nama kota ############ start of townname region @@ -1007,6 +1007,7 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Akselera STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK} Centang kotak ini untuk mengizinkan OpenTTD mencoba menggunakan akselerasi perangkat keras. Pengaturan yang diubah hanya akan diterapkan saat game dimulai ulang. STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Pengaturan hanya akan berlaku setelah game dimulai ulang +STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Centang kotak ini untuk melakukan sinkronisasi layar (v-sync). Pengaturan yang diubah hanya akan diterapkan saat game dimulai ulang. Hanya berfungsi dengan akselerasi perangkat keras diaktifkan. STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Ukuran antarmuka @@ -1028,6 +1029,7 @@ STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :4 kali STR_GAME_OPTIONS_GRAPHICS :{BLACK}Grafik STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Menampilkan kecepatan refresh +STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}Pilih laju penyegaran layar yang akan digunakan STR_GAME_OPTIONS_REFRESH_RATE_OTHER :lain STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}Kecepatan refresh yang lebih tinggi dari 60Hz dapat memengaruhi kinerja. @@ -1149,6 +1151,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Setting permain STR_CONFIG_SETTING_TYPE_GAME_INGAME :Pengaturan permainan (disimpan dalam penyimpanan; hanya mempengaruhi permainan saat ini) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Setting perusahaan (disimpan dalam penyimpanan; hanya mempengaruhi permainan baru) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Setting perusahaan (disimpan dalam penyimpanan; hanya mempengaruhi permainan saat ini) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Peringatan! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Tindakan ini akan mengembalikan semua pengaturan gim ke nilai awalnya.{} Anda yakin ingin melanjutkan? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategori: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Jenis: @@ -1212,7 +1216,9 @@ STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Pilih seberapa STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Ketinggian peta maksimum: {STRING} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Tetapkan ketinggian maksimum medan peta. Dengan "(otomatis)" nilai yang baik akan diambil setelah pembuatan medan -STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Kamu tidak bisa mengubah ketinggian peta maksimum di angka itu. Setidaknya ada satu gunung di peta yang lebih tinggi +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(automatis) +STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Anda tidak dapat menyetel batas ketinggian peta ke nilai ini. Setidaknya harus ada satu gunung di peta yang lebih tinggi STR_CONFIG_SETTING_AUTOSLOPE :Ijinkan pembentukan slop dibawah bangunan, rel, dsb.: {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Ijinkan pembentukan tanah dibawah bangunan dan trek tanpa merusaknya STR_CONFIG_SETTING_CATCHMENT :Ijinkan ukuran jangkauan wilayah lebih realistik: {STRING} @@ -1356,8 +1362,9 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Mengatur berapa STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Jarak maksimal kilang minyak dari batas: {STRING} STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Kilang minyak hanya dibangun pada tepi peta atau pantai STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Tinggi garis salju: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Mengatur ketinggian di mana salju akan muncul. Salju juga akan mempengaruhi pengembangan industri dan persyaratan untuk pertumbuhan kota +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Mengontrol di ketinggian mana salju dimulai pada lanskap sub-arktik. Salju juga berpengaruh pada generasi industri dan syarat pertumbuhan kota. Hanya dapat dimodifikasi melalui Editor Skenario atau dihitung melalui "cakupan salju" STR_CONFIG_SETTING_SNOW_COVERAGE :Cakupan salju: {STRING} +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Mengontrol perkiraan jumlah salju di lanskap sub-arktik. Salju juga berpengaruh pada generasi industri dan syarat pertumbuhan kota. Hanya digunakan selama pembuatan peta. Tanah yang berada tepat di atas permukaan laut selalu tanpa salju STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_DESERT_COVERAGE :Cakupan gurun: {STRING} STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Kontrol perkiraan jumlah gurun di lanskap tropis. Gurun juga mempengaruhi generasi industri. Hanya digunakan selama pembuatan peta @@ -1477,6 +1484,8 @@ STR_CONFIG_SETTING_EXPENSES_LAYOUT :Kelompokkan pen STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Mendefinisikan tata ruang untuk tetingkap biaya perusahaan STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Secara otomatis menghapus sinyal selama konstruksi rel: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Menghapus sinyal secara otomatis selama konstruksi rel jika sinyal menghalangi. Perhatikan bahwa hal ini berpotensi menyebabkan kecelakaan kereta api. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :Batas kecepatan maju cepat: {STRING} +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :Batasi secepat apa permainan melaju saat maju cepat diaktifkan. 0 = tanpa batas (secepat yang bisa diatasi komputermu). Nilai di bawah 100% memperlambat gim. Batas maksimal tergantung pada spesifikasi komputer dan dapat bervariasi tergantung pada gim. STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% kecepatan normal STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :Tanpa batas (secepat komputer Anda memungkinkan) @@ -1670,12 +1679,14 @@ STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Perbesaran view STR_CONFIG_SETTING_ZOOM_MAX :Tingkat zoom out Maksimal: {STRING} STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :Pengecilan maksimum untuk viewport. Semakin kecil semakin tidak jelas STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :Sprite resolusi tertinggi untuk digunakan: {STRING} +STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :Batas resolusi maksimum yang digunakan sprite. Membatasi resolusi sprite akan menghindari penggunaan grafik resolusi tinggi meskipun tersedia. Ini dapat membantu menjaga tampilan gim tetap menyatu saat menggunakan campuran file GRF dengan atau tanpa grafik resolusi tinggi. STR_CONFIG_SETTING_ZOOM_LVL_MIN :4x STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2x STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :Normal STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X :2x STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X :4x STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8x +STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_MIN :4x STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_IN_2X :2x STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_NORMAL :1x STR_CONFIG_SETTING_TOWN_GROWTH :Kecepatan pertumbuhan kota: {STRING} @@ -2045,6 +2056,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nama per STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Atur kata sandi STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Lindungi permainan ini dengan kata kunci jika anda tidak ingin membiarkannya terbuka untuk umum +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibilitas STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Orang lain bisa melihat server Anda di daftar umum STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klien STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimum jumlah klien: @@ -2109,20 +2121,40 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server t STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Perusahaan terkunci, masukkan kata kunci # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Daftar klien +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Pemain Dalam Jaringan # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multipemain +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nama +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nama server tempat Anda bermain +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Mengubah nama server Anda STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nama server +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilitas +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Apakah orang lain dapat melihat server Anda di daftar publik +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Pemain +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nama +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Nama pemain Anda +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Mengubah nama pemain Anda STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Nama pemain +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Tindakan administratif yang harus dilakukan untuk klien ini STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Tindakan administratif yang harus dilakukan untuk perusahaan ini +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Gabung perusahaan ini STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Kirim pesan ke pemain ini +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Kirim pesan ke semua pemain di perusahaan ini STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Kirim pesan ke semua penonton +STR_NETWORK_CLIENT_LIST_SPECTATORS :Penonton STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Perusahaan baru) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Ciptakan perusahaan baru dan bergabung +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Ini adalah Anda +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Ini adalah hos permainan STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Diusir STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Melarang +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Hapus STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Buka pakai kata sandi +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Tindakan Admin STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Anda yakin ingin diusir pemain '{STRING}'? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Apakah Anda yakin ingin mencekal pemain '{STRING}'? STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Anda yakin ingin menghapus perusahaan '{COMPANY}'? @@ -2184,6 +2216,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Jangan t STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Komputer anda terlalu lambat dalam mengikuti server STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Komputer anda terlalu lama untuk mengunduh peta STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Komputer anda terlalu lama untuk bisa bergabung dengan server +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Nama pemain Anda tidak valid +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Server yang diminta terlalu usang untuk klien ini ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :Kesalahan umum @@ -2315,6 +2349,7 @@ STR_MISSING_GRAPHICS_YES_DOWNLOAD :{BLACK}Ya, down STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}Tidak, tutup OpenTTD STR_MISSING_GRAPHICS_ERROR_TITLE :{WHITE}Gagal Mendownload +STR_MISSING_GRAPHICS_ERROR :{BLACK}Gagal mengunduh grafik.{}Silakan unduh grafik secara manual. STR_MISSING_GRAPHICS_ERROR_QUIT :{BLACK}Keluar OpenTTD # Transparency settings window @@ -2495,7 +2530,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Bangun p STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Tempatkan pelampung yang dapat digunakan sebagai petunjuk arah. Shift untuk menampilkan perkiraan biaya STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Membangun jembatan air. Shift untuk menampilkan perkiraan biaya STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Membuat area perairan .{}Membuat kanal, kecuali jika CTRL ditekan pada level yang sejajar dengan laut, maka air akan memenuhi permukaan -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Membuat sungai +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Membuat sungai. Ctrl untuk memilh area secara diagonal # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Orientasi Galangan @@ -2867,12 +2902,16 @@ STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Jumlah K STR_MAPGEN_DATE :{BLACK}Tgl: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Jumlah industri: STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Puncak tertinggi: +STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Menambah satu ketinggian maksimum puncak tertinggi di peta STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Kurangi satu ketinggian maksimum puncak tertinggi di peta STR_MAPGEN_SNOW_COVERAGE :{BLACK}Cakupan salju: STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}Meningkatkan cakupan salju sepuluh persen STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}Kurangi cakupan salju hingga sepuluh persen +STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_DESERT_COVERAGE :{BLACK}Cakupan gurun: +STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}Meningkatkan cakupan gurun sepuluh persen STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Kurangi cakupan gurun pasir sebesar sepuluh persen +STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}Algoritma pulau: STR_MAPGEN_TERRAIN_TYPE :{BLACK}Jenis dataran: STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}Area perairan: @@ -2899,7 +2938,9 @@ STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Luas: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Target ketinggian puncak +STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}Puncak tertinggi STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Cakupan salju (dalam %) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Cakupan gurun (dalam %) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Ganti Tahun Permulaan # SE Map generation @@ -3039,6 +3080,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Peringatan STR_NEWGRF_ERROR_MSG_ERROR :{RED}Kesalahan: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Kesalahan fatal NewGRF telah terjadi:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Terjadi galat pada NewGRF:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} tidak akan bekerja dengan versi TTDPatch yang telah dilaporkan oleh OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} untuk TTD versi {STRING} STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} didesain untuk digunakan dengan {STRING} @@ -3177,13 +3219,13 @@ STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :Danai pembangun STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :Beli hak transportasi eksklusif STR_LOCAL_AUTHORITY_ACTION_BRIBE :Suap pemkot setempat -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}Prakarsai kampanye iklan kecil, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Biaya:{CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}Prakarsai kampanye iklan sedang, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Biaya:{CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}Prakarsai kampanye iklan besar, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Biaya: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}Danai perbaikan jalan. Akan menyebabkan kemacetan arus lalu lintas hingga 6 bulan.{}Biaya: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Bangun patung sebagai kebanggaan perusahaan anda.{}Biaya: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Biayai pembangunan gedung komersil di kota.{}Biaya: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Beli hak monopoli transportasi di kota ini untuk 1 tahun. Penumpang dan kargo di kota ini hanya akan menggunakan stasiun milik perusahaan anda.{} Biaya: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}Prakarsai kampanye iklan kecil, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Memberikan penggalak sementara pada peringkat stasiun dalam radius kecil di sekitar pusat kota.{}Biaya:{CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}Prakarsai kampanye iklan sedang, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Memberikan penggalak sementara pada peringkat stasiun dalam radius sedang di sekitar pusat kota.{}Biaya:{CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}Prakarsai kampanye iklan besar, agar penumpang dan kargo lebih mengutamakan jasa perusahaan transportasi anda.{}Memberikan penggalak sementara pada peringkat stasiun dalam radius besar di sekitar pusat kota.{}Biaya: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}Danai perbaikan jalanan perkotaan.{}Akan menyebabkan kemacetan arus lalu lintas hingga 6 bulan.{}Biaya: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Bangun patung sebagai kebanggaan perusahaan anda.{}Memberikan penggalak permanen pada peringkat stasiun di kota ini.{}Biaya: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Biayai pembangunan gedung baru di kota.{}Memberikan penggalak sementara pada pertumbuhan kota di kota ini,{}Biaya: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Beli hak monopoli transportasi di kota ini untuk 1 tahun.{}Pemerintah kota tidak akan mengizinkan penumpang dan kargo untuk memakai stasiun pesaing Anda.{} Biaya: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Kolusi dengan pemkot agar naik peringkat, beresiko terkena hukuman jika tertangkap.{}Biaya: {CURRENCY_LONG} # Goal window @@ -3193,6 +3235,7 @@ STR_GOALS_SPECTATOR :Target Global STR_GOALS_GLOBAL_BUTTON :{BLACK}Global STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}Tunjukkan target global STR_GOALS_COMPANY_BUTTON :{BLACK}Perusahaan +STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}Tunjukkan target perusahaan STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_NONE :{ORANGE}- Tidak ada - STR_GOALS_PROGRESS :{ORANGE}{STRING} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index a132a0da5c..df83e50fcf 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2682,7 +2682,7 @@ STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}이 지 STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}이 칸의 위치로 이동합니다. CTRL+클릭하면 이 칸의 위치를 기준으로 새로운 외부 화면을 엽니다 STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}초기화 가격: {LTBLUE}없음 STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}초기화 가격: {RED}{CURRENCY_LONG} -STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}제거시 들어오는 환불금: {LTBLUE}{CURRENCY_LONG} +STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}제거하면 회수되는 금액: {LTBLUE}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_OWNER_N_A :없음 STR_LAND_AREA_INFORMATION_OWNER :{BLACK}소유주: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_ROAD_OWNER :{BLACK}도로 소유주: {LTBLUE}{STRING} From 145f2fc43a5d6acd7f104efb2f4b37b961e330f9 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 18 May 2021 19:10:56 +0000 Subject: [PATCH 210/800] Update: Translations from eints indonesian: 14 changes by NinjaQuince --- src/lang/indonesian.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 54974fcb82..0c669357e3 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -55,7 +55,7 @@ STR_CARGO_PLURAL_BUBBLES :Gelembung STR_CARGO_PLURAL_TOFFEE :Gula-gula STR_CARGO_PLURAL_BATTERIES :Baterai STR_CARGO_PLURAL_PLASTIC :Plastik -STR_CARGO_PLURAL_FIZZY_DRINKS :Minuman Berdesis +STR_CARGO_PLURAL_FIZZY_DRINKS :Minuman Ringan # Singular cargo name STR_CARGO_SINGULAR_NOTHING : @@ -89,7 +89,7 @@ STR_CARGO_SINGULAR_BUBBLE :Gelembung STR_CARGO_SINGULAR_TOFFEE :Gula-gula STR_CARGO_SINGULAR_BATTERY :Baterai STR_CARGO_SINGULAR_PLASTIC :Plastik -STR_CARGO_SINGULAR_FIZZY_DRINK :Minuman Berdesis +STR_CARGO_SINGULAR_FIZZY_DRINK :Minuman Ringan # Quantity of cargo STR_QUANTITY_NOTHING : @@ -123,7 +123,7 @@ STR_QUANTITY_BUBBLES :{COMMA} gelembu STR_QUANTITY_TOFFEE :{WEIGHT_LONG} gula-gula STR_QUANTITY_BATTERIES :{COMMA} baterai STR_QUANTITY_PLASTIC :{VOLUME_LONG} plastik -STR_QUANTITY_FIZZY_DRINKS :{COMMA} minuman berdesis +STR_QUANTITY_FIZZY_DRINKS :{COMMA} minuman ringan STR_QUANTITY_N_A :N/A # Two letter abbreviation of cargo name @@ -158,7 +158,7 @@ STR_ABBREV_BUBBLES :{TINY_FONT}GL STR_ABBREV_TOFFEE :{TINY_FONT}GG STR_ABBREV_BATTERIES :{TINY_FONT}BA STR_ABBREV_PLASTIC :{TINY_FONT}PL -STR_ABBREV_FIZZY_DRINKS :{TINY_FONT}MB +STR_ABBREV_FIZZY_DRINKS :{TINY_FONT}MR STR_ABBREV_NONE :{TINY_FONT}TANPA STR_ABBREV_ALL :{TINY_FONT}SMA @@ -180,7 +180,7 @@ STR_COLOUR_LIGHT_BLUE :Biru terang STR_COLOUR_GREEN :Hijau STR_COLOUR_DARK_GREEN :Hijau tua STR_COLOUR_BLUE :Biru -STR_COLOUR_CREAM :Cream +STR_COLOUR_CREAM :Krim STR_COLOUR_MAUVE :Lembayung muda STR_COLOUR_PURPLE :Ungu STR_COLOUR_ORANGE :Oranye @@ -212,8 +212,8 @@ STR_UNITS_VOLUME_SHORT_IMPERIAL :{COMMA}{NBSP}ga STR_UNITS_VOLUME_SHORT_METRIC :{COMMA}{NBSP}l STR_UNITS_VOLUME_SHORT_SI :{COMMA}{NBSP}m³ -STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA}{NBSP}gallon -STR_UNITS_VOLUME_LONG_METRIC :{COMMA}{NBSP}litre +STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA}{NBSP}galon +STR_UNITS_VOLUME_LONG_METRIC :{COMMA}{NBSP}liter STR_UNITS_VOLUME_LONG_SI :{COMMA}{NBSP}m³ STR_UNITS_FORCE_IMPERIAL :{COMMA}{NBSP}lbf @@ -4812,7 +4812,7 @@ STR_INDUSTRY_NAME_COLA_WELLS :Sumur Cola STR_INDUSTRY_NAME_TOY_SHOP :Toko Mainan STR_INDUSTRY_NAME_TOY_FACTORY :Pabrik Mainan STR_INDUSTRY_NAME_PLASTIC_FOUNTAINS :Sumber Mata Air Plastik -STR_INDUSTRY_NAME_FIZZY_DRINK_FACTORY :Pabrik Minuman berdesis +STR_INDUSTRY_NAME_FIZZY_DRINK_FACTORY :Pabrik Minuman Ringan STR_INDUSTRY_NAME_BUBBLE_GENERATOR :Pembangkit Gelembung STR_INDUSTRY_NAME_TOFFEE_QUARRY :Tambang gula-gula STR_INDUSTRY_NAME_SUGAR_MINE :Tambang Gula @@ -4911,7 +4911,7 @@ STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_COLA_TANKER :Gerbong Tangki STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_CANDY_VAN :Gerbong Manisan STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_TOY_VAN :Gerbong Mainan STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_BATTERY_TRUCK :Gerbong Baterai -STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_FIZZY_DRINK_TRUCK :Gerbong Minuman berdesis +STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_FIZZY_DRINK_TRUCK :Gerbong Minuman Ringan STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_PLASTIC_TRUCK :Gerbong Plastik STR_VEHICLE_NAME_TRAIN_ENGINE_MONORAIL_X2001_ELECTRIC :'X2001' (Listrik) STR_VEHICLE_NAME_TRAIN_ENGINE_MONORAIL_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Listrik) @@ -4941,7 +4941,7 @@ STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_COLA_TANKER :Gerbong Cola STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_CANDY_VAN :Gerbong Manisan STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_TOY_VAN :Gerbong Mainan STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_BATTERY_TRUCK :Gerbong Baterai -STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_FIZZY_DRINK_TRUCK :Gerbong Minuman berdesis +STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_FIZZY_DRINK_TRUCK :Gerbong Minuman Ringan STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_PLASTIC_TRUCK :Gerbong Plastik STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Listrik) STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Listrik) @@ -4973,7 +4973,7 @@ STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_COLA_TANKER :Gerbong Cola STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_CANDY_VAN :Gerbong Manisan STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_TOY_VAN :Gerbong Mainan STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_BATTERY_TRUCK :Gerbong Baterai -STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_FIZZY_DRINK_TRUCK :Gerbong Minuman berdesis +STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_FIZZY_DRINK_TRUCK :Gerbong Minuman Ringan STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PLASTIC_TRUCK :Gerbong Plastik STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_REGAL_BUS :Bus MPS Regal STR_VEHICLE_NAME_ROAD_VEHICLE_HEREFORD_LEOPARD_BUS :Bus Hereford Leopard @@ -5054,9 +5054,9 @@ STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_CANDY_TRUCK :Truk Manisan Wi STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_BATTERY_TRUCK :Truk Baterai MightyMover STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_BATTERY_TRUCK :Truk Baterai Powernaught STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_BATTERY_TRUCK :Truk Baterai Wizzowow -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_FIZZY_DRINK :Truk Minuman berdesis MightyMover -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_FIZZY_DRINK :Truk Minuman berdesis Powernaught -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_FIZZY_DRINK_TRUCK :Truk Minuman berdesis Wizzowow +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_FIZZY_DRINK :Truk Minuman Ringan MightyMover +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_FIZZY_DRINK :Truk Minuman Ringan Powernaught +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_FIZZY_DRINK_TRUCK :Truk Minuman Ringan Wizzowow STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_PLASTIC_TRUCK :Truk Plastik MightyMover STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_PLASTIC_TRUCK :Truk Plastik Powernaught STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_PLASTIC_TRUCK :Truk Plastik Wizzowow From ca9f9b84d3f6bad958a5470ac7749066ce966cc8 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 19 May 2021 19:09:28 +0000 Subject: [PATCH 211/800] Update: Translations from eints japanese: 239 changes by akaregi, 18 changes by scabtert --- src/lang/japanese.txt | 411 ++++++++++++++++++++++++++---------------- 1 file changed, 257 insertions(+), 154 deletions(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index b066e74c37..8c26bb4fe6 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -188,11 +188,13 @@ STR_COLOUR_BROWN :茶 STR_COLOUR_GREY :灰 STR_COLOUR_WHITE :白 STR_COLOUR_RANDOM :ランダム +STR_COLOUR_DEFAULT :デフォルト # Units used in OpenTTD STR_UNITS_VELOCITY_IMPERIAL :{COMMA}mph STR_UNITS_VELOCITY_METRIC :{COMMA}km/h STR_UNITS_VELOCITY_SI :{COMMA}m/s +STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}タイル/日 STR_UNITS_POWER_IMPERIAL :{COMMA}英馬力 STR_UNITS_POWER_METRIC :{COMMA}仏馬力 @@ -245,7 +247,7 @@ STR_TOOLTIP_RESIZE :{BLACK}ドラ STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}ウィンドウの大きさを切り替えます STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST :{BLACK}スクロールバーです。リストを縦にスクロールします STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST :{BLACK}スクロールバーです。リストを横にスクロールします -STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}建物などを範囲指定して撤去します。Ctrlを押すと、範囲が斜めになります。Shiftを押しながら決定すると、費用を見積もります +STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}建物などを範囲指定して撤去します。Ctrlで斜めに選択できます。Shiftを押しながら決定すると、費用を見積もります # Show engines button STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN :{BLACK}非表示を表示 @@ -253,10 +255,10 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE :{BLACK}非表 STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP :{BLACK}非表示を表示 STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT :{BLACK}非表示を表示 -STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP :{BLACK}このボタンを押すと、非表示の列車も全て表示されます -STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE_TOOLTIP :{BLACK}このボタンを押すと、非表示の車両も全て表示されます -STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP_TOOLTIP :{BLACK}このボタンを押すと、非表示の船舶も全て表示されます -STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}このボタンを押すと、非表示の航空機も全て表示されます +STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP :{BLACK}このボタンを押すと、非表示の列車もすべて表示されます +STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE_TOOLTIP :{BLACK}このボタンを押すと、非表示の車両もすべて表示されます +STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP_TOOLTIP :{BLACK}このボタンを押すと、非表示の船舶もすべて表示されます +STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}このボタンを押すと、非表示の航空機もすべて表示されます # Query window STR_BUTTON_DEFAULT :{BLACK}デフォルト @@ -284,7 +286,7 @@ STR_SORT_BY_TYPE :種類 STR_SORT_BY_TRANSPORTED :搬送済量 STR_SORT_BY_NUMBER :番号 STR_SORT_BY_PROFIT_LAST_YEAR :昨年の損益 -STR_SORT_BY_PROFIT_THIS_YEAR :今年の損益 +STR_SORT_BY_PROFIT_THIS_YEAR :今年の利益 STR_SORT_BY_AGE :使用年数 STR_SORT_BY_RELIABILITY :信頼性 STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE :貨物種類別の総容量 @@ -313,9 +315,11 @@ STR_SORT_BY_RATING :レーティン STR_SORT_BY_NUM_VEHICLES :車両数 STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :昨年の総利益 STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :今年の総利益 -STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :前年度の平均利益 +STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :前年の平均利益 +STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :今年の平均利益 # Group by options for vehicle list +STR_GROUP_BY_NONE :(なし) STR_GROUP_BY_SHARED_ORDERS :共有注文 # Tooltips for the main toolbar @@ -341,7 +345,8 @@ STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_AIRCRAFT :{BLACK}社有 STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN :{BLACK}ズームインします STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT :{BLACK}ズームアウトします STR_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}鉄道を建設します -STR_TOOLBAR_TOOLTIP_BUILD_ROADS :{BLACK}道路を建設します +STR_TOOLBAR_TOOLTIP_BUILD_ROADS :{BLACK}道路を敷設します +STR_TOOLBAR_TOOLTIP_BUILD_TRAMWAYS :{BLACK}軌道を敷設する STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS :{BLACK}埠頭を建設します STR_TOOLBAR_TOOLTIP_BUILD_AIRPORTS :{BLACK}空港を建設します STR_TOOLBAR_TOOLTIP_LANDSCAPING :{BLACK}地形のツールバーを開きます。整地や植林などを行うことができます。 @@ -359,10 +364,10 @@ STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD :{BLACK}開始 STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE :{BLACK}クリックで開始年を入力できます STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}地図と街の一覧を表示します STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}地形の生成をします -STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}町を生成します +STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}街を生成する STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}産業を生成します -STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を建設します -STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}路面電車建設 +STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を敷設します +STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}軌道敷設 STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Shiftキーを押しながら決定すると費用を見積もります STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}標識を設置します STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Shiftを押しながら決定すると費用を見積もります @@ -439,15 +444,15 @@ STR_INDUSTRY_MENU_FUND_NEW_INDUSTRY :産業の新設 ############ range ends here ############ range for railway construction menu starts -STR_RAIL_MENU_RAILROAD_CONSTRUCTION :鉄道建設 -STR_RAIL_MENU_ELRAIL_CONSTRUCTION :電気鉄道建設 -STR_RAIL_MENU_MONORAIL_CONSTRUCTION :モノレール建設 -STR_RAIL_MENU_MAGLEV_CONSTRUCTION :マグレブ(リニア)建設 +STR_RAIL_MENU_RAILROAD_CONSTRUCTION :鉄道敷設 +STR_RAIL_MENU_ELRAIL_CONSTRUCTION :電気鉄道の敷設 +STR_RAIL_MENU_MONORAIL_CONSTRUCTION :モノレール敷設 +STR_RAIL_MENU_MAGLEV_CONSTRUCTION :マグレブ(リニア)敷設 ############ range ends here ############ range for road construction menu starts -STR_ROAD_MENU_ROAD_CONSTRUCTION :道路建設 -STR_ROAD_MENU_TRAM_CONSTRUCTION :路面電車建設 +STR_ROAD_MENU_ROAD_CONSTRUCTION :道路敷設 +STR_ROAD_MENU_TRAM_CONSTRUCTION :軌道敷設 ############ range ends here ############ range for waterways construction menu starts @@ -570,6 +575,8 @@ STR_MONTH_DEC :12 # Graph window STR_GRAPH_KEY_BUTTON :{BLACK}凡例 STR_GRAPH_KEY_TOOLTIP :{BLACK}この凡例の表示/非表示を切り替えます +STR_GRAPH_X_LABEL_MONTH :{TINY_FONT}{STRING}月 +STR_GRAPH_X_LABEL_MONTH_YEAR :{TINY_FONT}{STRING}月{}{NUM}年 STR_GRAPH_Y_LABEL :{TINY_FONT}{STRING} STR_GRAPH_Y_LABEL_NUMBER :{TINY_FONT}{COMMA} @@ -582,8 +589,8 @@ STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}総資 STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}運送報酬の相場 STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL :{TINY_FONT}{BLACK}輸送時間(日) STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}貨物を10単位(又は10,000リットル)を20マス運送したときの報酬 -STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}全て表示 -STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}全て非表示 +STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}すべて有効化 +STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}すべて無効化 STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}全貨物の運送報酬相場を表示します STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}全貨物の運送報酬相場を非表示にします STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}この貨物の運送報酬相場の表示/非表示を切り替えます @@ -756,8 +763,8 @@ STR_SMALLMAP_INDUSTRY :{TINY_FONT}{STR STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} STR_SMALLMAP_COMPANY :{TINY_FONT}{COMPANY} STR_SMALLMAP_TOWN :{TINY_FONT}{WHITE}{TOWN} -STR_SMALLMAP_DISABLE_ALL :{BLACK}全て非表示 -STR_SMALLMAP_ENABLE_ALL :{BLACK}全て表示 +STR_SMALLMAP_DISABLE_ALL :{BLACK}すべて非表示 +STR_SMALLMAP_ENABLE_ALL :{BLACK}すべて表示 STR_SMALLMAP_SHOW_HEIGHT :{BLACK}標高を表示 STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES :{BLACK}全産業を非表示にします STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES :{BLACK}全産業を表示します @@ -798,7 +805,7 @@ STR_NEWS_AIRCRAFT_CRASH :{BIG_FONT}{BLAC STR_NEWS_PLANE_CRASH_OUT_OF_FUEL :{BIG_FONT}{BLACK}航空機事故発生!{}燃料切れにより航空機が墜落、搭乗していた{COMMA}名が死亡 STR_NEWS_DISASTER_ZEPPELIN :{BIG_FONT}{BLACK}大惨事! {STATION}で飛行船事故! -STR_NEWS_DISASTER_SMALL_UFO :{BIG_FONT}{BLACK}道路車両がUFOとの衝突により大破! +STR_NEWS_DISASTER_SMALL_UFO :{BIG_FONT}{BLACK}車両がUFOとの衝突により大破! STR_NEWS_DISASTER_AIRPLANE_OIL_REFINERY :{BIG_FONT}{BLACK}その瞬間、一面火の海に! {TOWN}付近の石油精製所が爆発! STR_NEWS_DISASTER_HELICOPTER_FACTORY :{BIG_FONT}{BLACK}{TOWN}の工場が突如倒壊 原因は未だ不明! STR_NEWS_DISASTER_BIG_UFO :{BIG_FONT}{BLACK}{TOWN}付近にUFOが着陸! @@ -817,7 +824,7 @@ STR_NEWS_MERGER_TAKEOVER_TITLE :{BIG_FONT}{BLAC STR_PRESIDENT_NAME_MANAGER :{BLACK}{PRESIDENT_NAME}{} (社長) STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{0:STRING}の出資により、新たに{1:TOWN}の開発が始まる! -STR_NEWS_NEW_TOWN_UNSPONSORED :{BLACK} {BIG_FONT} {TOWN}という新しい町が建設されました! +STR_NEWS_NEW_TOWN_UNSPONSORED :{BLACK} {BIG_FONT} {TOWN}という名の新しい街が創設されました! STR_NEWS_INDUSTRY_CONSTRUCTION :{BIG_FONT}{BLACK}新たな{STRING}が{TOWN}付近に開設! STR_NEWS_INDUSTRY_PLANTED :{BIG_FONT}{BLACK}新たな{STRING}が{TOWN}付近に作付け開始! @@ -866,6 +873,7 @@ STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE :{BIG_FONT}{BLAC STR_NEWS_NEW_VEHICLE_TYPE :{BIG_FONT}{BLACK}{ENGINE} STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE :{BLACK}{STRING}が新登場! - {ENGINE} +STR_NEWS_SHOW_VEHICLE_GROUP_TOOLTIP :{BLACK}車両のグループに焦点を合わせたグループウィンドウを開きます STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO :{WHITE}{STATION}は今後{STRING}を受入れません STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO :{WHITE}{STATION}は今後{STRING}と{STRING}を受入れません @@ -938,12 +946,13 @@ STR_GAME_OPTIONS_CURRENCY_CNY :人民元(CNY) STR_GAME_OPTIONS_CURRENCY_HKD :香港ドル(HKD) STR_GAME_OPTIONS_CURRENCY_INR :インドルピー(INR) STR_GAME_OPTIONS_CURRENCY_IDR :インドネシアルピア(IDR) +STR_GAME_OPTIONS_CURRENCY_MYR :マレーシア・リンギット(MYR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :左側通行 STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :右側通行 -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}街名 +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}街の名前: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}街名のスタイルを選択します ############ start of townname region @@ -983,6 +992,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :12ヶ月毎 STR_GAME_OPTIONS_LANGUAGE :{BLACK}言語 STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}ゲームの言語を選択します +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% 完了) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}フルスクリーン STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}OpenTTD をフルスクリーンでプレイするにはチェックします @@ -993,8 +1003,10 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :その他 STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}ハードウェアアクセラレーション +STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}このボックスをオンにすると、OpenTTDがハードウェアアクセラレーションを使用できるようになります。変更された設定は、ゲームの再起動時にのみ適用されます STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK} 垂直同期 +STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}ここをチェックして垂直同期を有効にします。設定はゲームを再起動した後に適用されます。ハードウェアアクセラレーションが有効な環境でしか機能しません。 STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}インターフェイスのサイズ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}インターフェイス上の単位サイズを指定します @@ -1017,6 +1029,7 @@ STR_GAME_OPTIONS_GRAPHICS :{BLACK}グラ STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}画面リフレッシュレート STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}使用する画面のリフレッシュレートを選択します STR_GAME_OPTIONS_REFRESH_RATE_OTHER :その他 +STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}60Hzを超えるリフレッシュレートはパフォーマンスに影響を与える可能性があります。 STR_GAME_OPTIONS_BASE_GRF :{BLACK}基本グラフィックセット @@ -1125,17 +1138,19 @@ STR_WARNING_NO_SUITABLE_AI :{WHITE}適切 # Settings tree window STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}設定 STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}フィルター設定: -STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}全てを開く -STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}全てを折りたたむ +STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}すべて開く +STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}すべて折りたたむ +STR_CONFIG_SETTING_RESET_ALL :{BLACK}すべての値をリセット STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(説明がありません) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}デフォルト設定: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}設定の種類: {ORANGE}{STRING} -STR_CONFIG_SETTING_TYPE_CLIENT :クライアント設定(セーブされませんが全てのゲームに影響) +STR_CONFIG_SETTING_TYPE_CLIENT :クライアント設定(セーブされませんがすべてのゲームに影響します) STR_CONFIG_SETTING_TYPE_GAME_MENU :ゲーム設定(新規ゲームに影響) STR_CONFIG_SETTING_TYPE_GAME_INGAME :ゲーム設定(現在のゲームにのみ影響) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :会社設定(新規ゲームにのみ影響) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :会社設定(現在の会社のみに影響) STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}注意! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}この操作によりゲームのすべての設定が初期値にリセットされます。{}続行してもよろしいでしょうか? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}カテゴリ: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}種類: @@ -1153,9 +1168,9 @@ STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :ゲーム設定 STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :ゲーム設定(保存ゲーム内に記録・今のゲームにのみ影響) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :会社設定(全保存ゲーム内に記録・ニューゲーム時に影響) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :会社設定(保存ゲーム内に記録・今の会社だけに影響) -STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}設定による検索結果を全て表示{}{SILVER}カテゴリ{BLACK}別{WHITE}{STRING} -STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}設定による検索結果を全て表示{}{SILVER}種類{BLACK}別{WHITE}All setting types -STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}設定による検索結果を全て表示{}{SILVER}カテゴリ{BLACK}別{WHITE}{STRING} {BLACK}and {SILVER}Type {BLACK}to {WHITE}All setting types +STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}設定による検索結果をすべて表示{}{SILVER}カテゴリ{BLACK}別{WHITE}{STRING} +STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}設定による検索結果をすべて表示{}{SILVER}種類{BLACK}別{WHITE}すべての設定タイプ +STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}設定による検索結果をすべて表示{}{SILVER}カテゴリ{BLACK}別{WHITE}{STRING} {BLACK}and {SILVER}Type {BLACK}to {WHITE}All setting types STR_CONFIG_SETTINGS_NONE :{WHITE}- なし - STR_CONFIG_SETTING_OFF :無効 @@ -1189,17 +1204,18 @@ STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :助成金対象 STR_CONFIG_SETTING_CONSTRUCTION_COSTS :建設費: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :建設・購入費用のレベルを設定します STR_CONFIG_SETTING_RECESSIONS :景気後退: {STRING} -STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :設定を有効にすると数年おきに短期間、景気の後退が起こる可能性が出ます。景気後退の間は全ての生産がかなりの落ち込みを見せます (景気後退が終わると元のレベルに戻ります) +STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :設定を有効にすると数年おきに短期間、景気の後退が起こる可能性が出ます。景気後退の間はすべての生産がかなりの落ち込みを見せます (景気後退が終わると元のレベルに戻ります)。 STR_CONFIG_SETTING_TRAIN_REVERSING :列車の転回不可: {STRING} STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :設定を有効にすると路線の末端駅でない限り、転回(折り返し)した方が次の目的地に早く着ける場合であっても転回をしなくなります STR_CONFIG_SETTING_DISASTERS :災害: {STRING} STR_CONFIG_SETTING_DISASTERS_HELPTEXT :設定を有効にすると時折、乗り物や交通インフラを遮断・破壊する災害が起きるようになります -STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編に対する町の姿勢: {STRING} +STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編に対する街の姿勢: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街域で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や同じ地域での更なる建設行為に影響するかを設定します STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :マップ高さ限界: {STRING} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(自動) -STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの最高高さをこの値には設定出来ません。少なくとも1箇所以上この値より高い山があります。 +STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの高度限界をこの値に設定できません。より高高度にある山が一つ以上存在します。 STR_CONFIG_SETTING_AUTOSLOPE :建物/路線の自動地形追従: {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :撤去を行わないで建物や路線がある土地の地形を変更することを可能にします。建物/路線は変更された地形に自動で追従します。 STR_CONFIG_SETTING_CATCHMENT :現実的な受入範囲: {STRING} @@ -1213,9 +1229,9 @@ STR_CONFIG_SETTING_TILE_LENGTH :{COMMA}タイ STR_CONFIG_SETTING_SMOKE_AMOUNT :煙・火花の量{STRING} STR_CONFIG_SETTING_SMOKE_AMOUNT_HELPTEXT :輸送機器が故障や事故の際に発する煙や火花の量を設定します STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL :列車の加減速モデル: {STRING} -STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :列車の加減速に対して使用する物理モデルを選択します。「オリジナル」モデルでは勾配でのみ、全ての車両に対し等しく減速がかかります。「リアル」モデルでは勾配とカーブで、編成の様々な要素(編成の長さや機関車の牽引力など)に応じて減速がかかるようになります -STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :道路車両の加減速モデル: {STRING} -STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :車両の加減速に対して使用する物理モデルを選択します。「オリジナル」モデルでは勾配で全ての車両に対し等しく減速がかかります。「リアル」モデルでは勾配で様々な要素(馬力など)に応じて減速がかかるようになります +STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :列車の加減速に対して使用する物理モデルを選択します。「オリジナル」モデルでは勾配でのみ、すべての車両に対し等しく減速がかかります。「リアル」モデルでは勾配とカーブで、編成の様々な要素(編成の長さや機関車の牽引力など)に応じて減速がかかるようになります。 +STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :車両の加減速モデル: {STRING} +STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :車両の加減速に対して使用する物理モデルを選択します。「オリジナル」モデルでは勾配ですべての車両に対し等しく減速がかかります。「リアル」モデルでは勾配で様々な要素(馬力など)に応じて減速がかかるようになります。 STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS :線路の勾配率: {STRING} STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :線路1タイルあたりの勾配率を設定します。数値を上げると急勾配になり、列車が坂を上りにくくなります。 STR_CONFIG_SETTING_PERCENTAGE :{COMMA}% @@ -1230,11 +1246,11 @@ STR_CONFIG_SETTING_INFLATION_HELPTEXT :インフレを STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH :橋梁の最大長:{STRING} STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH_HELPTEXT :橋梁の最大長を設定できます STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT :橋梁の高度: {STRING} -STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT_HELPTEXT :橋梁の建設出来る高さを設定出来ます +STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT_HELPTEXT :橋梁の最大高度を設定できます STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH :トンネルの最大長:{STRING} STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH_HELPTEXT :トンネルの最大長を設定できます STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD :一次産業の開設法: {STRING} -STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :ゲーム中で一次産業をプレイヤーが開設できるかどうかを決めます。「なし」では開設出来ません。「調査/探鉱」では出資することは可能ですが、どこに建設されるかは分かりませんし、失敗することもあります。「他の産業と同様」では一次産業も二次産業同様、好きなところに作ることが出来ます。 +STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :ゲーム中で一次産業をプレイヤーが開設できるかどうかを決めます。「なし」では開設できません。「調査/探鉱」では出資はできますが、どこに建設されるかは分かりませんし、失敗することもあります。「他の産業と同様」では一次産業も二次産業同様、好きなところに作れます。 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE :なし STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL :他の産業と同様 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :調査/探鉱 @@ -1250,7 +1266,7 @@ STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :右 STR_CONFIG_SETTING_SHOWFINANCES :年末の財政ウインドウ表示: {STRING} STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :有効にすると、毎年末に財政ウインドウがポップアップするようになります。企業の財務状況を簡単にチェックするのに便利です。 STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :直行運転をデフォルト化: {STRING} -STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :通常、輸送機器は目的地までの経路上に停留施設があれば必ずそこに止まります。この設定を有効にすると、経路上の全ての停留施設を飛ばし目的地まで直行するようになります。注意: この設定は新規の指令にのみ作用します。またこの設定が有効であっても、個別に解除することは可能です。 +STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :通常、輸送機器は目的地までの経路上に停留施設があれば必ずそこに止まります。この設定を有効にすると、経路上のすべての停留施設を飛ばし目的地まで直行するようになります。注意: この設定は新規の指令にのみ作用します。またこの設定が有効であっても、個別に解除することは可能です。 STR_CONFIG_SETTING_STOP_LOCATION :新規列車の停車位置: プラットホームの{STRING} STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :デフォルトで列車がプラットホームのどの位置に止まるかを設定します。「先端」ではホームの進入地点と列車終端、「中間」ではホームと列車の中間地点、「終端」では進入地点逆端と列車先端がそれぞれ一致する位置に止まります。注意: この設定は新規の指令にのみ作用します。またこの設定が有効であっても、個別に停車位置を設定することは可能です。 STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :先端 @@ -1263,13 +1279,13 @@ STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :する (フル STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :する STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :する (ビューポートでも有効) STR_CONFIG_SETTING_BRIBE :議会の買収: {STRING} -STR_CONFIG_SETTING_BRIBE_HELPTEXT :街で議会買収を企てることが可能になります。成功すれば街での評判が良くなりますが、地元当局に事が発覚した場合、罰金を受けた上評判が悪くなり、その街では半年間何もすることができなくなります +STR_CONFIG_SETTING_BRIBE_HELPTEXT :街で議会買収を企てられるようになります。成功すれば街での評判が良くなりますが、地元当局に事が発覚した場合罰金を受けた上評判が悪くなり、その上その街では半年間何もできなくなります STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :独占運送契約の締結: {STRING} -STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :会社と街との間で独占運送契約を結ぶことが可能になります。この契約が締結されると、その街にある全ての競争相手の停留施設は丸一年間、旅客・貨物問わず何も受け入れできなくなります +STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :会社と街との間で独占運送契約を結ぶことが可能になります。この契約が締結されると、その街にあるすべての競争相手の停留施設は丸一年間、旅客・貨物問わず何も受け入れできなくなります STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :街の開発に出資: {STRING} -STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :街に新たなビルを建てるための開発資金を提供することが可能になります +STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :街に新たなビルを建てるための開発資金を提供できるようになります。 STR_CONFIG_SETTING_ALLOW_FUND_ROAD :街路補修に出資: {STRING} -STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :街の道路補修に資金を提供することが可能になります。半年間街内の不通にして敵を混乱させることはできますが、「街路補修時に道路整理」を有効にしない限り工事自体にメリットはありません +STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :街の道路補修に資金を提供できるようになります。半年間街内の不通にして敵を混乱させることはできますが、「街路補修時に道路整理」を有効にしない限り工事自体にメリットはありません STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :他社への送金: {STRING} STR_CONFIG_SETTING_ALLOW_GIVE_MONEY_HELPTEXT :マルチプレイヤーモードの際に、会社間での資金の受け渡しが可能となります STR_CONFIG_SETTING_FREIGHT_TRAINS :重量乗数: {STRING} @@ -1283,9 +1299,9 @@ STR_CONFIG_SETTING_PLANE_CRASHES_NONE :なし STR_CONFIG_SETTING_PLANE_CRASHES_REDUCED :軽減 STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :通常 STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :街有道路での路側型バス停/荷役所建設: {STRING} -STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :路側型バス停/荷役所を街が所有する道路上に建設することを可能にします +STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :路側型バス停/荷役所を街が所有する道路上に建設できるようにします STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :他社の道路上での路側型バス停/荷役所設置: {STRING} -STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :路側型バス停/荷役所を他社が所有する道路上に建設することを可能にします +STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :路側型バス停/荷役所を他社が所有する道路上に建設できるようにします STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}この設定の変更は既に輸送車両が存在する時には不可能です STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :インフラ補修: {STRING} STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :有効にすると、インフラ設備にも維持費が発生するようになります。維持費はネットワークのサイズに非線形で比例する為、小さい会社よりも大きい会社の方が影響が大きくなります @@ -1329,9 +1345,9 @@ STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :グラフ画面 STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :ビルドビークルウィンドウにNewGRFの名前を表示します:{STRING} STR_CONFIG_SETTING_LANDSCAPE :地形: {STRING} -STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :地形は異なる貨物や街の成長要件の違いによって基本となるプレー法を左右します。但し、NewGRFやスクリプトにより条件が改良されることもあります +STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :地形は様々な貨物と街の成長要件に関する基礎的なゲームプレイシナリオを定義します。NewGRFとゲームスクリプトによってより効果的なコントロールが可能になります。 STR_CONFIG_SETTING_LAND_GENERATOR :地形作成: {STRING} -STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :オリジナルの地形ジェネレーターは基本グラフィックセットに依存し、ある程度固定された地形しか生成出来ません。TerraGenesisはパーリンノイズに基づいた地形ジェネレーターで、より細かい地形生成のパラメータを指定できます +STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :オリジナルの地形ジェネレーターは基本グラフィックセットに依存し、ある程度固定された地形しか生成できません。TerraGenesisはパーリンノイズに基づいた地形ジェネレーターで、より細かい地形生成のパラメータを指定できます STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :オリジナル STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :地形種類: {STRING} @@ -1341,9 +1357,10 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :どの程度の STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :石油精製所のマップ端からの距離: {STRING} STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :石油精製所はマップの外周付近にのみ建設されます。つまり、外周が海のマップでは海岸沿いに建設されるということです STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪線の位置: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪は産業と街の成長に影響があります +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪線は産業生成と街の発展に影響を及ぼします。シナリオエディタを介して変更するか積雪量により計算されます。 STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :亜寒帯の風景のおおよその雪の量を制御します。雪はまた、産業の生成と町の成長要件にも影響を及ぼします。マップの生成中にのみ使用されます。海抜のすぐ上の土地は常に雪がありません STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :熱帯気候でのおおよその砂漠の量を制御します。砂漠は産業生成に影響を及ぼします。マップ生成時にのみ設定が参照されます。 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地形の起伏: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesisのみ) 地形の起伏度を設定します。なだらかな地形では丘陵の数は減り、裾野が長くなります。起伏が多い地形では丘陵が多くなりますが、似たり寄ったりな地形の繰り返しに見えることがあります STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :特になだらか @@ -1355,11 +1372,11 @@ STR_CONFIG_SETTING_VARIETY_HELPTEXT :(TerraGenesis STR_CONFIG_SETTING_RIVER_AMOUNT :川の数: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :どの位の川が生成されるかを設定します STR_CONFIG_SETTING_TREE_PLACER :植林アルゴリズム: {STRING} -STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :マップでの木の分布を設定します。「オリジナル」では全ての樹種がマップ全域に散布するように植えられます。「改良」ではある程度のまとまりで植えられます +STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :マップでの木の分布を設定します。「オリジナル」ではすべての樹種がマップ全域に散布するように植えられます。「改良」ではある程度のまとまりで植えられます STR_CONFIG_SETTING_TREE_PLACER_NONE :なし STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :オリジナル STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :改良版 -STR_CONFIG_SETTING_ROAD_SIDE :道路車両: {STRING} +STR_CONFIG_SETTING_ROAD_SIDE :車両: {STRING} STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :左側/右側通行を設定します STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :ハイトマップの回転方向: {STRING} STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :反時計回り @@ -1388,7 +1405,7 @@ STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップ STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :タイルをまたぐような建設活動の際に、距離や面積、高低差などの情報を表示するようになります STR_CONFIG_SETTING_LIVERIES :輸送機器の個別塗装: {STRING} -STR_CONFIG_SETTING_LIVERIES_HELPTEXT :輸送機器別に特定の塗装色を使うことが可能になります。無効にすると全ての輸送機器は企業色で塗装されます +STR_CONFIG_SETTING_LIVERIES_HELPTEXT :輸送機器別に特定の塗装色を使うことが可能になります。無効にするとすべての輸送機器は企業色で塗装されます STR_CONFIG_SETTING_LIVERIES_NONE :無効 STR_CONFIG_SETTING_LIVERIES_OWN :有効(自社のみ) STR_CONFIG_SETTING_LIVERIES_ALL :有効(全社) @@ -1414,6 +1431,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :コマンド+ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+クリック (Win) STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :切 +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :ウィンドウ内で右クリックしてウィンドウを閉じられます。右クリックでツールチップも無効にできます。 STR_CONFIG_SETTING_AUTOSAVE :オートセーブ: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :オートセーブの間隔を設定します @@ -1453,6 +1471,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :建設ツール STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :橋やトンネルなどを建設した後もツールバーを開いたままにします STR_CONFIG_SETTING_EXPENSES_LAYOUT :財政ウィンドウのグループ分け: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :財政ウィンドウのレイアウトを収入部門・支出部門でグループ分けするかどうかを設定します +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :信号が経路上に存在する場合線路設置の際にすべて自動的に除去されます。鉄道車両の衝突につながる危険性があります。 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :早送りが有効になっている場合のゲームの進行速度を制限します。0 =制限なし(コンピューターが許す限り高速)。100%未満の値は、ゲームの速度を低下させます。上限はコンピュータの仕様によって異なり、ゲームによって異なる場合があります。 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :制限なし(コンピューターが許す限り高速) @@ -1472,7 +1491,7 @@ STR_CONFIG_SETTING_SOUND_DISASTER_HELPTEXT :事故や災害 STR_CONFIG_SETTING_SOUND_VEHICLE :輸送機器: {STRING} STR_CONFIG_SETTING_SOUND_VEHICLE_HELPTEXT :輸送機器関係の効果音を鳴らすかどうかを設定します STR_CONFIG_SETTING_SOUND_AMBIENT :環境音: {STRING} -STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :町や産業、自然環境に関する効果音を鳴らすかどうかを設定します +STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :街や産業、自然環境に関する効果音を鳴らすかどうかを設定します STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING :有効なインフラのみ建設可能: {STRING} STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT :有効にするとその時点で使用可能な設備のみが建設できます。(例: 電気機関車が購入できないときに電気鉄道は建設不可) @@ -1505,6 +1524,7 @@ STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :マルチプレ STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :命令コード処理上限: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :AIやゲームスクリプトが一つの「詰め込み指令」を処理する際に、一度に演算できる命令コード数を設定します。一般に値を小さくした場合、ゲームへの負荷が軽減されます STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :スクリプトあたりの最大メモリ使用量:{STRING} +STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_HELPTEXT :一つのスクリプトが強制終了する前に消費する可能性のあるメモリ量。大規模なマップではメモリ量を拡充したほうが良いかもしれません。 STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB STR_CONFIG_SETTING_SERVINT_ISPERCENT :最大信頼度を点検要件化: {STRING} @@ -1524,7 +1544,7 @@ STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :有効にする STR_CONFIG_SETTING_WAGONSPEEDLIMITS :貨車の上限速度: {STRING} STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :有効にすると、上限速度が設定されている貨車を使用した場合、列車はその速度以上出せなくなります STR_CONFIG_SETTING_DISABLE_ELRAILS :電気鉄道を無効化: {STRING} -STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :この設定を有効にすると電気鉄道を建設できなくなります。ただし電気機関車・電車でも架線のない非電化の線路を走ることができるようになります +STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :この設定を有効にすると電気鉄道を敷設できなくなります。ただし電気機関車・電車は架線のない非電化の線路を走ることができるようになります STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN :停留施設の開業(自社): {STRING} STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN_HELPTEXT :自社の新しい停留施設に最初の列車が到着したときにニュースを表示するかを設定します @@ -1593,7 +1613,7 @@ STR_CONFIG_SETTING_CYCLE_SIGNAL_TYPES :信号種類の STR_CONFIG_SETTING_CYCLE_SIGNAL_TYPES_HELPTEXT :Ctrl+クリックで信号種類を切り替える際に使う、サイクル種類を決定します STR_CONFIG_SETTING_CYCLE_SIGNAL_NORMAL :閉塞・入口・出口・コンボ STR_CONFIG_SETTING_CYCLE_SIGNAL_PBS :パス・一方通行パス -STR_CONFIG_SETTING_CYCLE_SIGNAL_ALL :全て +STR_CONFIG_SETTING_CYCLE_SIGNAL_ALL :すべて STR_CONFIG_SETTING_TOWN_LAYOUT :街の道路配置: {STRING} STR_CONFIG_SETTING_TOWN_LAYOUT_HELPTEXT :街での道路区画計画を設定します @@ -1603,17 +1623,20 @@ STR_CONFIG_SETTING_TOWN_LAYOUT_2X2_GRID :格子状(2x2 STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :格子状(3x3) STR_CONFIG_SETTING_TOWN_LAYOUT_RANDOM :ランダム STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :街路の自動構築: {STRING} -STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :街の自治体が街の成長に応じて街路を自動で拡張するようになります。無効にすると勝手な街路拡張は行われなくなりますが、街を成長させるためにはプレイヤーが街路の建設を行う必要が出てきます +STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :街の自治体が街の成長に応じて街路を自動で拡張するようになります。無効にすると勝手な街路の拡張は行われなくなりますが、街を成長させるためにはプレイヤーが街路を敷設しなければなりません。 STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :街路との平面交差を許可: {STRING} -STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :有効にすると、会社が作る道路と街路とが交差することが可能となります +STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :有効にすると、会社が作る道路と街路とが交差できるようになります STR_CONFIG_SETTING_NOISE_LEVEL :空港建設に対する街の騒音レベル規制: {STRING} STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT :この設定を無効にすると、街に作れる空港は最大2つまでになります。有効にした場合は、各空港の騒音レベルの総和が街の騒音許容レベル以下になるようにしか建てられません。騒音レベルは空港の大きさ・街からの距離により、騒音許容レベルは街の人口により左右されます STR_CONFIG_SETTING_TOWN_FOUNDING :ゲーム中での街新設: {STRING} -STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :有効にすると、ゲーム中でも新規の街を開設するために出資することが可能になります +STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :有効にすると、ゲーム中でも新しく街を開設するために出資できるようになります。 STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :無効 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :有効 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :有効(道路配置も設定可) -STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :町の総人口に対する、町の家によって生産される貨物の量。{}二次成長:2倍の大きさの町は4倍の乗客を生み出します。{}線形成長:2倍の大きさの町は2倍の量を生み出します +STR_CONFIG_SETTING_TOWN_CARGOGENMODE :街の貨物生成: {STRING} +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :街の総人口に対する家屋によって生産される貨物の量。{}二次成長:2倍の大きさの街は4倍の乗客を生み出します。{}線形成長:2倍の大きさの街は2倍の量を生み出します +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :二次的(オリジナル) +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :線形 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :樹木の自然成長: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :ゲーム中、ランダムに生えてくる樹種を設定します。設定によっては樹木の生育に依存する産業に悪影響が生じる可能性があります(「不可」にした場合、亜熱帯地域の伐採所を機能させ続けるためには手動で植林し続ける必要があります) @@ -1637,7 +1660,7 @@ STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :ズームイン STR_CONFIG_SETTING_ZOOM_MAX :最大ズームアウトレベル:{STRING} STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :ズームアウトの最大倍率を設定します。ズームアウトの倍率が大きいと、処理遅延が発生する可能性があります STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :使用する最高解像度のスプライト:{STRING} -STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :スプライトに使用する最大解像度を制限します。 スプライトの解像度を制限すると、使用可能な場合でも高解像度のグラフィックを使用できなくなります。 これにより、高解像度のグラフィックを使用する場合と使用しない場合のGRFファイルを組み合わせて使用する場合に、ゲームの外観を統一することができます。 +STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :スプライトに使用する最大解像度を制限します。 スプライトの解像度を制限すると使用可能な場合でも高解像度のグラフィックを使用できなくなります。 これにより、高解像度のグラフィックを使用する場合と使用しない場合のGRFファイルを組み合わせて使用する場合にゲームの外観を統一できます。 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍 STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍 STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :通常 @@ -1653,12 +1676,12 @@ STR_CONFIG_SETTING_TOWN_GROWTH_SLOW :遅い STR_CONFIG_SETTING_TOWN_GROWTH_NORMAL :普通 STR_CONFIG_SETTING_TOWN_GROWTH_FAST :早い STR_CONFIG_SETTING_TOWN_GROWTH_VERY_FAST :特に早い -STR_CONFIG_SETTING_LARGER_TOWNS :都市になる町の比率: {STRING} -STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :町のうち、成長によってその何分の1が都市になるか(あるいは全くならないか)を設定します。都市になると拡大・成長速度が速くなります +STR_CONFIG_SETTING_LARGER_TOWNS :都市になる街の比率: {STRING} +STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :街のうち、成長によってその何分の1が都市になるか(あるいは全くならないか)を設定します。都市になると拡大・成長速度が速くなります STR_CONFIG_SETTING_LARGER_TOWNS_VALUE :{COMMA}分の1 STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :変化なし STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :初期の都市サイズ乗数: {STRING} -STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :ゲーム開始時に都市が普通の町に比べて平均して何倍の人口規模になるかを設定します +STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :ゲーム開始時に都市が普通の街に比べて平均して何倍の人口規模になるかを設定します STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :分配グラフの更新頻度: {STRING}日 STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :リンクグラフを再計算する時間間隔を設定します。それぞれの再計算では、グラフの単一要素に関わる経路計画だけを計算します。つまり、グラフの一部が更新されるだけで、全体が設定した間隔で更新されるという訳ではありません。この間隔を短くすると再計算のためにCPUへの負荷が大きくなります。長くすると、新たなルートが貨物分配に組み込まれるのに時間がかかるようになります。 @@ -1682,7 +1705,7 @@ STR_CONFIG_SETTING_DEMAND_DISTANCE_HELPTEXT :0より大き STR_CONFIG_SETTING_DEMAND_SIZE :対称分配での戻り量: {STRING} STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :この値を100%未満に設定すると、対称分配の挙動が非対称分配に近くなります。値が小さいほど受け入れ量に対する送り返し量が小さくなります。0%に設定した場合、対称分配と非対称分配の挙動に違いはなくなります STR_CONFIG_SETTING_SHORT_PATH_SATURATION :高収容力経路より速達経路を優先飽和: {STRING} -STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :二つの停留施設間を結ぶ経路が複数存在することが往々にしてあります。そのような場合、貨物分配アルゴリズムは最初に最短となる経路を飽和するまで使用し、次いで2番目の最短経路を使用するというように埋めていきます。飽和したかどうかは、推定収容力、輸送計画によって判断されます。すべての経路を飽和してもまだ需要を満たせない場合、高容量な経路を優先しつつ、すべての経路に負荷を掛けます。しかしほとんどの場合、アルゴリズムは経路の輸送力を正確に見積もることができません。この設定では、高収容力の路線を使用し始める前にどの程度最短経路を飽和するかを設定します。収容力より需要が上回ると推定される時には、停留施設が混み合うのを避けるために100%未満に設定して下さい。 +STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :二つの停留施設間を結ぶ経路が複数存在することは往々にしてあります。そのような場合、貨物分配アルゴリズムは最初に最短となる経路を飽和するまで使用し、次いで2番目の最短経路を使用するというように埋めていきます。飽和したかどうかは、推定収容力、輸送計画によって判断されます。すべての経路を飽和してもまだ需要を満たせない場合、高容量な経路を優先しつつ、すべての経路に負荷を掛けます。しかしほとんどの場合、アルゴリズムは経路の輸送力を正確に見積もることができません。この設定では、高収容力の路線を使用し始める前にどの程度最短経路を飽和するかを設定します。収容力より需要が上回ると推定される時には、停留施設が混み合うのを避けるために100%未満に設定して下さい。 STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :速度単位: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :ゲーム中の速度をいずれの単位系で表すか決定します @@ -1781,6 +1804,7 @@ STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}スプ # Video initalization errors STR_VIDEO_DRIVER_ERROR :{WHITE}ビデオ設定にエラーがあります... +STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... 対応する GPU が見つかりません。ハードウェアアクセラレーションは無効になります。 # Intro window STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} @@ -1824,6 +1848,7 @@ STR_INTRO_TRANSLATION :{BLACK}この # Quit window STR_QUIT_CAPTION :{WHITE}終了 +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}OpenTTD を終了してもよろしいですか? STR_QUIT_YES :{BLACK}はい STR_QUIT_NO :{BLACK}いいえ @@ -1859,14 +1884,14 @@ STR_LIVERY_TRAIN_TOOLTIP :{BLACK}列車 STR_LIVERY_ROAD_VEHICLE_TOOLTIP :{BLACK}車両の塗装色を表示します STR_LIVERY_SHIP_TOOLTIP :{BLACK}船舶用の塗装色を表示します STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}航空機用の塗装色を表示します -STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}選択した輸送機器に使う、塗装の主色を選択します。Ctrl+クリックで、このタブの輸送機器全ての主色をこの色にします -STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}選択した輸送機器に使う、塗装の二次色を選択します。Ctrl+クリックで、このタブの輸送機器全ての二次色をこの色にします +STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}選択した輸送機器に使用する塗装のメインカラーを選択します。Ctrl+クリックで、このタブの輸送機器すべてのメインカラーをこの色にします +STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}選択した輸送機器に使う、塗装のサブカラーを選択します。Ctrl+クリックで、このタブの輸送機器すべてのサブカラーをこの色にします STR_LIVERY_PANEL_TOOLTIP :{BLACK}塗装を変更する輸送機器を選択します。Ctrl+クリックで複数の輸送機器を選択できます。適用状況を切り替えるにはチェックボックスをクリックします STR_LIVERY_DEFAULT :通常の塗装色 STR_LIVERY_STEAM :機関車 (蒸気) -STR_LIVERY_DIESEL :機関車 (ディーゼル) -STR_LIVERY_ELECTRIC :機関車 (電気) +STR_LIVERY_DIESEL :ディーゼル機関車 +STR_LIVERY_ELECTRIC :電気機関車 STR_LIVERY_MONORAIL :機関車 (モノレール) STR_LIVERY_MAGLEV :機関車 (リニア) STR_LIVERY_DMU :気動車 (動力分散式) @@ -1945,6 +1970,7 @@ STR_FACE_TIE :ネクタイ: STR_FACE_EARRING :イヤリング: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}ネクタイ/イヤリングを変更します +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :プライベート # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}マルチプレイヤーゲーム @@ -2006,7 +2032,7 @@ STR_NETWORK_START_SERVER_CAPTION :{WHITE}新規 STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}ゲーム名: STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}ゲーム名を指定します。これはマルチプレイヤーゲームの選択画面に表示される名前になります STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}パスワードを設定 -STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}ゲームをパスワードで保護することができます。一般から公然とアクセスされたくない場合等に設定します +STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}ゲームをパスワードで保護できます。一般から公然とアクセスされたくない場合等に設定します STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}可視性 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}接続者数: {NUM} @@ -2072,14 +2098,37 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}この STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}この会社は保護されています。経営に参画するにはパスワードを入力してください # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :クライアントリスト +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :オンラインのプレイヤー # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}マルチプレイヤー +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}サーバー +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}名前 +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}あなたがプレイしているサーバー名 +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}サーバーの名前を編集する +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :サーバー名 +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}可視性 STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}他の人があなたのサーバーを公開リストで見ることができるかどうか -STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}すべての観客にメッセージを送る +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}プレイヤー +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}名前 +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}あなたのプレイヤー名 +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}プレイヤー名を変更する +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :あなたのプレイヤー名 +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}このクライアントに対して実行する管理アクション +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}この会社に参画する +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}このプレイヤーにメッセージを送信する +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}この会社のすべてのプレイヤーにメッセージを送信する +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}すべての観客にメッセージを送信する +STR_NETWORK_CLIENT_LIST_SPECTATORS :観覧者 +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新規会社) +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}これはあなたです STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}ゲームのホストです +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :キック +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :BAN +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :削除 +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}'{STRING}'をキックしてもよろしいですか? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}プレーヤー「{STRING}」を追放してもよろしいですか? STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}会社 '{COMPANY}'のパスワードをリセットしてもよろしいですか? @@ -2126,6 +2175,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}サー STR_NETWORK_ERROR_CLIENT_START :{WHITE}接続できませんでした STR_NETWORK_ERROR_TIMEOUT :{WHITE}接続 {NUM} でタイムアウトエラーが発生しました STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}プロトコルエラーによって接続が切断されました +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}あなたのプレイヤー名は設定されていません。名前はマルチプレイヤーウィンドウの上部から設定できます。 STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}クライアントバージョンがサーバーバージョンと一致していません STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}不正なパスワードです STR_NETWORK_ERROR_SERVER_FULL :{WHITE}サーバが満員です @@ -2161,6 +2211,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :パスワード STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :一般的なタイムアウト STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :マップのダウンロード時間超過 STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :マップの処理時間超過 +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :不正なクライアント名 ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}接続切断の可能性 @@ -2190,6 +2241,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} が新会社 (#{2:NUM}) を設立しました STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} が退出しました({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} は名前を {STRING} に変更しました +STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} が {1:STRING} に {2:CURRENCY_LONG} を送金してくれました STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}サーバがセッションを終了しました STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}このサーバーは再起動中です…{}しばらくお待ちください… STR_NETWORK_MESSAGE_KICKED :*** {STRING}がキックされました。理由: ({STRING}) @@ -2201,12 +2253,12 @@ STR_CONTENT_TYPE_CAPTION_TOOLTIP :{BLACK}コン STR_CONTENT_NAME_CAPTION :{BLACK}名前 STR_CONTENT_NAME_CAPTION_TOOLTIP :{BLACK}コンテンツ名 STR_CONTENT_MATRIX_TOOLTIP :{BLACK}クリックすると詳細を表示します。{}ダウンロードするにはチェックボックスをオンにします。 -STR_CONTENT_SELECT_ALL_CAPTION :{BLACK}全て選択 -STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP :{BLACK}全項目を選択します +STR_CONTENT_SELECT_ALL_CAPTION :{BLACK}すべて選択 +STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP :{BLACK}すべてのコンテンツをダウンロードする STR_CONTENT_SELECT_UPDATES_CAPTION :{BLACK}アップデートを選択 STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP :{BLACK}既にダウンロードしたコンテンツのアップデートをすべて選択します STR_CONTENT_UNSELECT_ALL_CAPTION :{BLACK}選択を解除 -STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP :{BLACK}全ての選択を解除します +STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP :{BLACK}すべてのコンテンツをダウンロードしない STR_CONTENT_SEARCH_EXTERNAL :{BLACK}外部サイトで検索 STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP :{BLACK}OpenTTDコンテンツサービスに掲載されていないものを外部サイトを使用して検索できます。 STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION :{WHITE}OpenTTDから離脱 @@ -2222,7 +2274,7 @@ STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED :{SILVER}ダウ STR_CONTENT_DETAIL_SUBTITLE_SELECTED :{SILVER}ダウンロード指定されています STR_CONTENT_DETAIL_SUBTITLE_AUTOSELECTED :{SILVER}他との依存関係によりダウンロード指定されています STR_CONTENT_DETAIL_SUBTITLE_ALREADY_HERE :{SILVER}既にダウンロード済です -STR_CONTENT_DETAIL_SUBTITLE_DOES_NOT_EXIST :{SILVER}ファイルが未知の形式のため、OpenTTDからはダウンロード出来ません +STR_CONTENT_DETAIL_SUBTITLE_DOES_NOT_EXIST :{SILVER}ファイルが未知の形式のため、OpenTTDからはダウンロードできません STR_CONTENT_DETAIL_UPDATE :{SILVER}このコンテンツは既にダウンロードされた{STRING}を置き換えます STR_CONTENT_DETAIL_NAME :{SILVER}コンテンツ名: {WHITE}{STRING} STR_CONTENT_DETAIL_VERSION :{SILVER}バージョン: {WHITE}{STRING} @@ -2234,7 +2286,7 @@ STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF :{SILVER}以下 STR_CONTENT_DETAIL_DEPENDENCIES :{SILVER}依存する他コンテンツ: {WHITE}{STRING} STR_CONTENT_DETAIL_TAGS :{SILVER}タグ: {WHITE}{STRING} STR_CONTENT_NO_ZLIB :{WHITE}OpenTTDは"zlib"をサポートしていません -STR_CONTENT_NO_ZLIB_SUB :{WHITE}ダウンロードすることができません! +STR_CONTENT_NO_ZLIB_SUB :{WHITE}ダウンロードできません! # Order of these is important! STR_CONTENT_TYPE_BASE_GRAPHICS :基本グラフィック @@ -2256,11 +2308,11 @@ STR_CONTENT_DOWNLOAD_COMPLETE :{WHITE}ダウ STR_CONTENT_DOWNLOAD_PROGRESS_SIZE :{WHITE}{BYTES} / {BYTES} ダウンロード済 ({NUM} %) # Content downloading error messages -STR_CONTENT_ERROR_COULD_NOT_CONNECT :{WHITE}サーバーに接続することができませんでした... +STR_CONTENT_ERROR_COULD_NOT_CONNECT :{WHITE}サーバーに接続できませんでした STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD :{WHITE}ダウンロード失敗... STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_CONNECTION_LOST :{WHITE}接続が切断されました STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE :{WHITE}ダウンロード先への書込権限がありません -STR_CONTENT_ERROR_COULD_NOT_EXTRACT :{WHITE}ダウンロードしたファイルを開展することができませんでした +STR_CONTENT_ERROR_COULD_NOT_EXTRACT :{WHITE}ダウンロードしたファイルを展開できませんでした STR_MISSING_GRAPHICS_SET_CAPTION :{WHITE}基本グラフィック欠落 STR_MISSING_GRAPHICS_SET_MESSAGE :{BLACK}OpenTTDの動作に必要な基本グラフィックが見つかりません。ダウンロードしてインストールしますか? @@ -2286,7 +2338,7 @@ STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}透過 # Linkgraph legend window STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}貨物流通履歴 -STR_LINKGRAPH_LEGEND_ALL :{BLACK}全て +STR_LINKGRAPH_LEGEND_ALL :{BLACK}すべて STR_LINKGRAPH_LEGEND_NONE :{BLACK}なし STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}表示する会社を選択 STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} @@ -2313,18 +2365,19 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}通過 STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}統合せずに建設 # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}現在このインフラで運用できる車両がないため無効化されています # Rail construction toolbar -STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :鉄道建設 -STR_RAIL_TOOLBAR_ELRAIL_CONSTRUCTION_CAPTION :電気鉄道建設 -STR_RAIL_TOOLBAR_MONORAIL_CONSTRUCTION_CAPTION :モノレール建設 -STR_RAIL_TOOLBAR_MAGLEV_CONSTRUCTION_CAPTION :マグレブ建設 +STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :鉄道敷設 +STR_RAIL_TOOLBAR_ELRAIL_CONSTRUCTION_CAPTION :電気鉄道の敷設 +STR_RAIL_TOOLBAR_MONORAIL_CONSTRUCTION_CAPTION :モノレール敷設 +STR_RAIL_TOOLBAR_MAGLEV_CONSTRUCTION_CAPTION :マグレブ敷設 -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}線路を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}自動線路建設モードで線路を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}線路を敷設します。Ctrlで敷設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}自動的に線路を敷設します。Ctrlで建設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}列車庫を建設します(列車の購入・整備施設になります)。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}線路に通過点を設置します。Ctrlを押しながら決定すると通過点同士を結合できます。Shiftを押しながら決定すると費用の見積が出ます -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}駅を建設します。Ctrlを押しながら決定すると離れた駅等と結合可能です。Shiftを押しながら決定すると費用の見積が出ます +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}駅を建設します。Ctrlを押しながら決定すると離れた駅等と結合できます。Shiftを押しながら決定すると費用を見積もれます STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}鉄道信号を建設します。Ctrlで腕木式と色灯式を切り替えられます。{}ドラックして決定するとその区間に一定間隔で信号が配置されます。このときCtrlを押しておくと、その先分岐か信号に行き着くまで連続配置します。{}Ctrl+クリックで信号種類を選ぶウィンドウが出ます(「信号のGUIを使用」設定オフ時のみ)。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}鉄道橋を建設します。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}鉄道トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます @@ -2332,7 +2385,7 @@ STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}線路 STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}既設の線路をこのレール種に変更します。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_NAME_RAILROAD :鉄道 (非電化) -STR_RAIL_NAME_ELRAIL :鉄道 (電化) +STR_RAIL_NAME_ELRAIL :電気鉄道 STR_RAIL_NAME_MONORAIL :モノレール STR_RAIL_NAME_MAGLEV :マグレブ @@ -2367,13 +2420,13 @@ STR_BUILD_SIGNAL_SEMAPHORE_NORM_TOOLTIP :{BLACK}閉塞 STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP :{BLACK}入口信号 (腕木式){}この信号の先にある出口信号のうち最低でも1つが緑であれば緑になりますが、そうでなければ赤になります。場内信号に良く使われます STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP :{BLACK}出口信号 (腕木式){}動作は普通の閉塞信号と同様ですが、入口/コンボ信号を使用する場合に必要になります。ホームの入り口に良く使われます STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP :{BLACK}コンボ信号 (腕木式){}コンボ信号は入口信号と出口信号の機能を併せ持つ信号です。この信号を使うと多数の分岐のあるような場内信号網を作ることができます -STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP :{BLACK}パス信号 (腕木式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。汎用性は高いですが、一方向式しか使えず信号の背面から進行してくる列車を防護することができません。この信号で列車が停車中に正面から対向列車が来ると問答無用で衝突事故を起こします! +STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP :{BLACK}パス信号 (腕木式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。汎用性は高いですが、一方向式しか使えず信号の背面から進行してくる列車を防護できません。この信号で列車が停車中に正面から対向列車が来ると問答無用で衝突事故を起こします! STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP :{BLACK}一方通行パス信号 (腕木式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。このタイプのパス信号は信号の背面から通過することはできません STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP :{BLACK}閉塞信号 (色灯式){}最も一般的な信号で、1つの閉塞内(信号同士の間の区間)には1編成のみが進入できます。配置した信号をクリックすると信号の向きを「一方向→一方向(逆)→二方向」の順で変えられます。一方向式の信号は背面から通過できません STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP :{BLACK}入口信号 (色灯式){}この信号の先にある出口信号のうち最低でも1つが緑であれば緑になりますが、そうでなければ赤になります。場内信号に良く使われます STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP :{BLACK}出口信号 (色灯式){}動作は普通の閉塞信号と同様ですが、入口/コンボ信号を使用する場合に必要になります。ホームの入り口に良く使われます STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP :{BLACK}コンボ信号 (色灯式){}コンボ信号は入口信号と出口信号の機能を併せ持つ信号です。この信号を使うと多数の分岐のあるような場内信号網を作ることができます -STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP :{BLACK}パス信号 (色灯式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。汎用性は高いですが、一方向式しか使えず信号の背面から進行してくる列車を防護することができません。この信号で列車が停車中に正面から対向列車が来ると問答無用で衝突事故を起こします! +STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP :{BLACK}パス信号 (色灯式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。汎用性は高いですが、一方向式しか使えず信号の背面から進行してくる列車を防護できません。この信号で列車が停車中に正面から対向列車が来ると問答無用で衝突事故を起こします! STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP :{BLACK}一方通行パス信号 (色灯式){}パス信号では、互いに衝突しない経路が確保できる場合には1つの閉塞内に複数の列車が入ることを許容します。このタイプのパス信号は信号の背面から通過することはできません STR_BUILD_SIGNAL_CONVERT_TOOLTIP :{BLACK}信号交換{}既存の信号を今選択している信号に交換します。Ctrl+クリックで種類は替えずに腕木/色灯の形式のみ切り替えます。Shift+クリックで費用を見積もります STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}ドラッグ時の信号設置間隔を指定します @@ -2397,12 +2450,12 @@ STR_BRIDGE_TUBULAR_SILICON :管状橋(シ # Road construction toolbar -STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION :{WHITE}道路建設 -STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION :{WHITE}軌道建設 -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION :{BLACK}道路を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}路面電車の軌道を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}自動建設モードで道路を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}自動建設モードで軌道を建設します。Ctrlで建設/撤去の切り替えができます。Shiftを押しながら決定すると費用の見積が出ます +STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION :{WHITE}道路敷設 +STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION :{WHITE}軌道敷設 +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION :{BLACK}道路を建設します。Ctrlで建設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}路面電車の軌道を敷設します。Ctrlで敷設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}自動的に道路を敷設します。Ctrlで建設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}自動的に軌道を敷設します。Ctrlで建設/撤去を切り替えられます。Shiftを押しながら決定すると費用を見積もれます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}車庫を建設します(バス・トラックの購入・整備施設になります)。Shift+クリックで費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}路面電車庫を建設します(路面電車の購入・修理施設になります)。Shift+クリックで費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION :{BLACK}バス停を建設します。Ctrl+クリックで離れた停留施設と結合可能です。Shift+クリックで費用の見積が出ます @@ -2414,8 +2467,8 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE :{BLACK}道路 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE :{BLACK}軌道用橋を建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}道路トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます -STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の建設/撤去を切り替えます -STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の建設/撤去を切り替えます +STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の敷設/撤去を切り替えます +STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の敷設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの作成/表示を切り替えます STR_ROAD_NAME_ROAD :道路 @@ -2447,7 +2500,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}埠頭 STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}通過点として使えるブイを設置します。Shift+クリックで費用の見積が出ます STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}水路橋を建設します。Shiftを押しながら決定すると費用の見積が出ます STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}水域を作成します。{}通常操作では運河を建設しますが、海水位にある地域でCtrl+クリックするとその地域を水域にします -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}川を造ります +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}川を造成します。Ctrlで斜めに選択できます。 # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}造船所建設 @@ -2485,9 +2538,9 @@ STR_STATION_BUILD_NOISE :{BLACK}騒音 # Landscaping toolbar STR_LANDSCAPING_TOOLBAR :{WHITE}地形 -STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}土地の角を下げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段低い高さに土地をならします。Ctrlで斜めの範囲を選択できます。またShiftを押しながら決定すると工事費用を見積もります -STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}土地の角を上げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段高い高さに土地をならします。Ctrlで斜めの範囲を選択できます。またShiftを押しながら決定すると工事費用を見積もります -STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}最初に選択した土地の高さに選択範囲をならします。Ctrlで斜めの範囲を選択できます。またShiftを押しながら決定すると工事費用を見積もります +STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}土地の角を下げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段低い高さに土地をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります +STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}土地の角を上げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段高い高さに土地をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります +STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}最初に選択した土地の高さに選択範囲をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}将来用に土地を購入します。Shiftを押しながら決定すると費用を見積もります # Object construction window @@ -2548,7 +2601,7 @@ STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}大 STR_FOUND_TOWN_SIZE_RANDOM :{BLACK}ランダム STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}街のサイズを選択します STR_FOUND_TOWN_CITY :{BLACK}都市 -STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}都市は町と比べて、より早く拡大します。{}初期設定によりますが、設立の時点でも人口は町より多くなります +STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}都市は街に比べてより早く成長します。{}初期設定によりますが、人口は設立の時点で街よりも多くなります STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}街の道路配置 STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT :{BLACK}この街の道路配置(区画)を決定します @@ -2561,7 +2614,7 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}ラン # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}新規産業の建設に出資 STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}建設したい産業をリストから選択します -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :多くのランダムな産業 +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}ランダムな産業を生成する STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}マップ全域にランダムに産業を建設します STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}ランダムな産業を作成する STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}ランダムな産業をたくさん作りたいですか? @@ -2569,6 +2622,9 @@ STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}費用: STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}調査/探鉱 STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}建設 STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}出資 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}すべての産業を削除する +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}現在マップに存在するすべての産業を削除する +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}すべての産業を削除する STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}すべての産業を削除してもよろしいですか? # Industry cargoes window @@ -2612,9 +2668,11 @@ STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF: STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}受入れ貨物: {LTBLUE} STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING}) STR_LANG_AREA_INFORMATION_RAIL_TYPE : {BLACK}線路の種類: {LTBLUE}{STRING} +STR_LANG_AREA_INFORMATION_ROAD_TYPE :{BLACK}道路の種類: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}路面軌道の種類: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}線路の制限速度: {LTBLUE}{VELOCITY} STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}道路の最高速度: {LTBLUE}{VELOCITY} +STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}トラムの制限速度:{LTBLUE} {VELOCITY} # Description of land area of different tiles STR_LAI_CLEAR_DESCRIPTION_ROCKS :岩石 @@ -2715,32 +2773,44 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}フレームレート +STR_FRAMERATE_RATE_GAMELOOP :{BLACK}シミュレーションレート: {STRING} +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}一秒あたりに計算されるゲームのティック数。 STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}一秒あたりに描写されるフレームの数。 STR_FRAMERATE_SPEED_FACTOR :{BLACK}現在のゲーム速度:{DECIMAL} x STR_FRAMERATE_CURRENT :{WHITE}現在 STR_FRAMERATE_AVERAGE :{WHITE}平均 STR_FRAMERATE_MEMORYUSE :{WHITE}メモリ +STR_FRAMERATE_DATA_POINTS :{BLACK} {COMMA}測定に基づくデータ STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms STR_FRAMERATE_MS_WARN :{YELLOW} {DECIMAL} ms +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL} ms STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} フレーム/秒 STR_FRAMERATE_FPS_WARN :{YELLOW} {DECIMAL}フレーム/秒 STR_FRAMERATE_FPS_BAD :{RED} {DECIMAL}FPS STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} STR_FRAMERATE_BYTES_WARN :{YELLOW} {BYTES} +STR_FRAMERATE_BYTES_BAD :{RED}{BYTES} +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s ############ Leave those lines in this order!! STR_FRAMERATE_GAMELOOP :{BLACK}ゲームループの合計: STR_FRAMERATE_GL_ECONOMY :{BLACK}貨物の取り扱い: STR_FRAMERATE_GL_TRAINS :{BLACK} 鉄道車両のティック: STR_FRAMERATE_GL_ROADVEHS :{BLACK} 自動車ティック: STR_FRAMERATE_GL_AIRCRAFT :{BLACK}航空機ティック: +STR_FRAMERATE_GL_LANDSCAPE :{BLACK}世界のティック: STR_FRAMERATE_DRAWING :{BLACK}グラフィックレンダリング: +STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK}世界のビューポート: STR_FRAMERATE_VIDEO :{BLACK}ビデオ出力: STR_FRAMERATE_SOUND :{BLACK}サウンドミキサー: +STR_FRAMERATE_GAMESCRIPT :{BLACK} ゲームスクリプト: ############ End of leave-in-this-order ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GAMELOOP :ゲームループ STR_FRAMETIME_CAPTION_GL_ECONOMY :貨物の取り扱い STR_FRAMETIME_CAPTION_GL_TRAINS :切符 +STR_FRAMETIME_CAPTION_GL_ROADVEHS :車両のティック数 STR_FRAMETIME_CAPTION_GL_SHIPS :船のティック STR_FRAMETIME_CAPTION_GL_AIRCRAFT :航空機ティック STR_FRAMETIME_CAPTION_GL_LANDSCAPE :ワールドティック @@ -2748,6 +2818,9 @@ STR_FRAMETIME_CAPTION_GL_LINKGRAPH :リンクグラ STR_FRAMETIME_CAPTION_DRAWING :グラフィックレンダリング STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :ワールドビューポートレンダリング STR_FRAMETIME_CAPTION_VIDEO :ビデオ出力 +STR_FRAMETIME_CAPTION_SOUND :サウンドミキシング +STR_FRAMETIME_CAPTION_ALLSCRIPTS :ゲームスクリプト・AIスクリプトの合計 +STR_FRAMETIME_CAPTION_GAMESCRIPT :ゲームスクリプト STR_FRAMETIME_CAPTION_AI :AI {NUM} {STRING} ############ End of leave-in-this-order @@ -2824,6 +2897,7 @@ STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}サイ STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}ターゲットの最高の高さ +STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}最高峰 STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}積雪量(%) STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}砂漠領域(%) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}開始年の変更 @@ -2965,6 +3039,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}警告: {S STR_NEWGRF_ERROR_MSG_ERROR :{RED}エラー: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}致命的エラー: {SILVER}{STRING} STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}NewGRFに致命的なエラーが発生しました:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRFにエラーが発生しました:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING}はOpenTTDのTTDPatchバージョンには対応していません STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING}はTTDのバージョン{STRING}にのみ対応しています STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING}を使用時には{STRING}を有効にしなければなりません @@ -2984,6 +3059,7 @@ STR_NEWGRF_ERROR_READ_BOUNDS :疑似スプラ STR_NEWGRF_ERROR_GRM_FAILED :要求されたGRFのリソースは使用できません (スプライト {3:NUM}) STR_NEWGRF_ERROR_FORCEFULLY_DISABLED :{1:STRING}は{STRING}により無効にされました STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT :不正なレイアウト書式です (スプライト {3:NUM}) +STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG :プロパティ値リストの要素が多すぎます(スプライト {3:NUM}、プロパティ {4:HEX}) # NewGRF related 'general' warnings STR_NEWGRF_POPUP_CAUTION_CAPTION :{WHITE}注意! @@ -3015,6 +3091,7 @@ STR_NEWGRF_BUGGY :{WHITE}NewGRF{0 STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}{1:ENGINE}の貨物/改造情報が購入時とは異なります。自動更新/置換時に改造に失敗する恐れがあります STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}{1:STRING}が生産コールバック内で無限ループを起こしました STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT :{WHITE}戻り値{1:HEX}が不明/不正の値{2:HEX}を返しました +STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' は {2:HEX} において生産コールバックで不正な貨物タイプを返しました。 # 'User removed essential NewGRFs'-placeholders for stuff without specs STR_NEWGRF_INVALID_CARGO :<無効な貨物> @@ -3039,6 +3116,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}標識 # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}標識を編集 +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}メイン画面をこの標識の場所に移動します。Ctrl+クリックでこの標識の場所を新しなビューポートに表示します。 STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}次の標識へ移動 STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}前の標識へ移動 @@ -3048,7 +3126,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}標識 STR_TOWN_DIRECTORY_CAPTION :{WHITE}街一覧 STR_TOWN_DIRECTORY_NONE :{ORANGE}- なし- STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}町名 - メイン画面を町の場所に移動するには町名をクリックします。Ctrl+クリックで新しいビューポートに表示します +STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}街の名前 - メイン画面を街の場所に移動するには名前をクリックします。Ctrl+クリックで新しいビューポートに表示します STR_TOWN_POPULATION :{BLACK}地域人口: {COMMA}人 # Town view window @@ -3098,18 +3176,20 @@ STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :市街地開発 STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :独占運送契約を締結 STR_LOCAL_AUTHORITY_ACTION_BRIBE :議会を買収 -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街で新聞広告を実施します。{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でラジオCMを実施します{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でTV-CMを開始します{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}街内の道路補修工事に出資します。{}最高6ヶ月間街中の道路交通が途絶します。{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}社を称える彫像を建設します{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}市街地の開発に出資します{} 費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街で新聞広告を実施します。{}より多くの旅客と貨物が自社の交通網を利用するようになります。{}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でラジオCMを実施します{}街の中心部から中範囲にある駅の評価が一時的に高まります。{}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でTV-CMを開始します{}街の中心部の大範囲にある駅の評価が一時的に高まります。{}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}街内の道路補修工事に出資します。最高6ヶ月間街中の道路交通が途絶します。{}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}社を称える彫像を建設します{}この街の駅の評価を恒久的に高めます。{}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}市街地の開発に出資します{}街の成長速度が一時的に早まります。{}費用: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}街と一年間の独占運送契約を締結します。{}乗客や貨物はあなたの会社の運送経路のみを使用するようになります。{} 費用: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}買収を行い、議会内の評判を高めます。注意: 露見した場合は処罰されます{} 費用: {CURRENCY_LONG} # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} 目標 STR_GOALS_SPECTATOR_CAPTION :{WHITE}大目標 +STR_GOALS_SPECTATOR :グローバルな目標 +STR_GOALS_GLOBAL_BUTTON :{BLACK}グローバル STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}グローバルな目標を表示する STR_GOALS_COMPANY_BUTTON :{BLACK}会社 STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}会社の目標を見る @@ -3120,10 +3200,10 @@ STR_GOALS_PROGRESS_COMPLETE :{GREEN}{STRING} STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}クリックするとメイン画面を対象となる産業・街・タイルに移動します。Ctrl+クリックで新たなビューポートを開いて対象を表示します # Goal question window -STR_GOAL_QUESTION_CAPTION_QUESTION :質問 -STR_GOAL_QUESTION_CAPTION_INFORMATION :情報 -STR_GOAL_QUESTION_CAPTION_WARNING :警告 -STR_GOAL_QUESTION_CAPTION_ERROR :エラー +STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}質問 +STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}情報 +STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}警告 +STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}エラー ############ Start of Goal Question button list STR_GOAL_QUESTION_BUTTON_CANCEL :キャンセル @@ -3313,6 +3393,7 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}本社 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}本社ビルを移転します(費用は社の総資産の1%になります)。Shift+クリックで費用を見積もります STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}詳細 STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}インフラ設備の詳細な個数・タイル数を表示します +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}お金を渡す STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}この会社にお金を渡す STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}顔の変更 @@ -3353,6 +3434,9 @@ STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}産業 STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- なし - STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} ({COMMA}% 輸送済み){BLACK} STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} +STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE} {INDUSTRY} {STRING}、{STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} や、 {NUM} そしてもっと... STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}産業の名前です - 名前をクリックするとこの産業拠点の場所にメイン画面を移動します。Ctrl+クリックでこの産業拠点の場所を新たなビューポートに表示します STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}受け取った貨物: {SILVER}{STRING} STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}生産された貨物:{SILVER} {STRING} @@ -3371,6 +3455,7 @@ STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}必要 STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :、{STRING} {STRING} STR_INDUSTRY_VIEW_REQUIRES : {BLACK}必要物資: +STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW} {STRING} {BLACK}:{CARGO_SHORT}待機中{STRING} STR_CONFIG_GAME_PRODUCTION :{WHITE}生産量を変更 (8の倍数、最大2040) @@ -3396,7 +3481,7 @@ STR_VEHICLE_LIST_AVAILABLE_AIRCRAFT :購入可能な STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP :{BLACK}この輸送機関で利用可能な輸送機器の一覧を表示します STR_VEHICLE_LIST_MANAGE_LIST :{BLACK}リストを管理 -STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP :{BLACK}このリスト内のすべての車両にこの指令を送信 +STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP :{BLACK}このリスト内のすべての車両に指令を送信する STR_VEHICLE_LIST_REPLACE_VEHICLES :輸送機器更新 STR_VEHICLE_LIST_SEND_FOR_SERVICING :回送して点検 @@ -3430,20 +3515,21 @@ STR_GROUP_LIVERY_TOOLTIP :{BLACK}選択 STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}このグループ内の輸送機器を全体を対象とする自動交換の際も交換されないようにします STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}グループを削除 -STR_GROUP_DELETE_QUERY_TEXT :{WHITE}このグループとそれに所属する全てを削除してもよろしいですか? +STR_GROUP_DELETE_QUERY_TEXT :{WHITE}このグループとそれに属するすべてを削除してもよろしいですか? STR_GROUP_ADD_SHARED_VEHICLE :共有輸送機器を追加 STR_GROUP_REMOVE_ALL_VEHICLES :全輸送機器を削除 STR_GROUP_RENAME_CAPTION :{BLACK}グループ名を変更 -STR_GROUP_PROFIT_THIS_YEAR :今年の利益: +STR_GROUP_PROFIT_THIS_YEAR :今年の利益: STR_GROUP_PROFIT_LAST_YEAR :昨年の利益: STR_GROUP_OCCUPANCY :選択中: +STR_GROUP_OCCUPANCY_VALUE :{NUM}% # Build vehicle window STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :新規機関車(非電化) -STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION :新規機関車(電化)/電車 +STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION :新規電気機関車・電車 STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :新規モノレール車両 STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :新規リニア車両 @@ -3452,6 +3538,7 @@ STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :新しい路面 ############ range for vehicle availability starts STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :新規列車 +STR_BUY_VEHICLE_ROAD_VEHICLE_ALL_CAPTION :新しい車両 STR_BUY_VEHICLE_SHIP_CAPTION :新規船舶 STR_BUY_VEHICLE_AIRCRAFT_CAPTION :新規航空機 ############ range for vehicle availability ends @@ -3494,14 +3581,19 @@ STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}船舶 STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}航空機を購入 STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購入し改造する +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購入し改造する STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}船の購入と修理 +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}航空機の購入と修理 STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}選択した列車を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}選択した車両を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}選択した船舶を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}選択した航空機を購入します。Shift+クリックで購入費を見積もります +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた車両を購入して改造します。Shift+クリックで購入はせずに推定コストを算出します。 +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた車両を購入して修理します。Shift+クリックで購入はせずに推定コストを算出します。 STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた船を購入して修理します。Shift +クリックすると、購入なしの推定コストが表示されます +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた航空機を購入して再配置します。Shift +クリックすると、購入なしの推定コストが表示されます STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}名称を変更 STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}名称を変更 @@ -3544,7 +3636,7 @@ STR_DEPOT_VEHICLE_TOOLTIP :{BLACK}{ENGINE} STR_DEPOT_VEHICLE_TOOLTIP_CHAIN :{BLACK}{NUM}台{STRING} STR_DEPOT_VEHICLE_TOOLTIP_CARGO :{}{CARGO_LONG} ({CARGO_SHORT}) -STR_DEPOT_TRAIN_LIST_TOOLTIP :{BLACK}列車 - 情報を見るには列車を右クリックします。編成を変更するには各車両をドラッグします。Ctrlを押したままドラッグするとその車両から後続する全ての車両を一度に移動できます +STR_DEPOT_TRAIN_LIST_TOOLTIP :{BLACK}列車 - 情報を見るには列車を右クリックします。編成を変更するには各車両をドラッグします。Ctrlを押したままドラッグするとその車両に続くすべての車両を一度に移動できます。 STR_DEPOT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}車両 - 情報を見るには車両を右クリックします STR_DEPOT_SHIP_LIST_TOOLTIP :{BLACK}船舶 - 情報を見るには船舶を右クリックします STR_DEPOT_AIRCRAFT_LIST_TOOLTIP :{BLACK}航空機 - 情報を見るには航空機を右クリックします @@ -3577,7 +3669,7 @@ STR_DEPOT_SHIP_NEW_VEHICLES_TOOLTIP :{BLACK}新規 STR_DEPOT_AIRCRAFT_NEW_VEHICLES_TOOLTIP :{BLACK}新規航空機を購入します STR_DEPOT_CLONE_TRAIN :{BLACK}列車を複製 -STR_DEPOT_CLONE_ROAD_VEHICLE :{BLACK}道路車両を複製 +STR_DEPOT_CLONE_ROAD_VEHICLE :{BLACK}車両を複製 STR_DEPOT_CLONE_SHIP :{BLACK}船舶を複製 STR_DEPOT_CLONE_AIRCRAFT :{BLACK}航空機を複製 @@ -3613,6 +3705,7 @@ STR_ENGINE_PREVIEW_CAPTION :{WHITE}製造 STR_ENGINE_PREVIEW_MESSAGE :{GOLD}弊社は新たに{STRING}を設計致しました。{}実地でのパフォーマンスなどを検討する為、貴社に独占モニター権を提供したいと考えておりますがいかがでしょうか? STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :列車 +STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE :電気機関車 STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :モノレール列車 STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :リニア列車 @@ -3622,11 +3715,13 @@ STR_ENGINE_PREVIEW_TRAM_VEHICLE :路面電車車 STR_ENGINE_PREVIEW_AIRCRAFT :航空機 STR_ENGINE_PREVIEW_SHIP :船舶 -STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}価格: {CURRENCY_LONG} 重量: {WEIGHT_SHORT}{}最高速度: {VELOCITY}{}出力: {POWER}{}運用費: {CURRENCY_LONG}/年{}収容量: {CARGO_LONG} +STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}費用: {CURRENCY_LONG} 重量: {WEIGHT_SHORT}{} 最高速度: {VELOCITY} 出力: {POWER}{} 維持費: {CURRENCY_LONG} /年{} 容量: {CARGO_LONG} STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}価格: {CURRENCY_LONG} 重量: {WEIGHT_SHORT}{}最高速度: {VELOCITY} 出力: {POWER} 最大牽引力: {6:FORCE}{}運用費: {4:CURRENCY_LONG}/年{}収容量 {5:CARGO_LONG} -STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}価格: {CURRENCY_LONG} 最高速度: {VELOCITY}{}収容量: {CARGO_LONG}{}運用費: {CURRENCY_LONG}/年 -STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}コスト:{CURRENCY_LONG}最大。 速度:{VELOCITY}{}航空機の種類:{STRING}範囲:{COMMA}タイル{}容量:{CARGO_LONG}、{CARGO_LONG}{}ランニングコスト:{CURRENCY_LONG} /年 -STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}コスト:{CURRENCY_LONG}最大。 速度:{VELOCITY}{}航空機の種類:{STRING}範囲:{COMMA}タイル{}容量:{CARGO_LONG}{}ランニングコスト:{CURRENCY_LONG} /年 +STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 容量: {CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING}{} 容量: {CARGO_LONG}, {CARGO_LONG}{} 維持費: {CURRENCY_LONG}/yr +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING}{} 容量: {CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING} 範囲: {COMMA}タイル{} 容量: {CARGO_LONG}、{CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING} 範囲:{COMMA}タイル{} 容量: {CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}{STRING}の自動置換 - {STRING} @@ -3656,16 +3751,17 @@ STR_REPLACE_HELP_STOP_BUTTON :{BLACK}クリ STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK}置換対象を機関車/貨車に切り替えます STR_REPLACE_ENGINES :機関車 STR_REPLACE_WAGONS :貨車 -STR_REPLACE_ALL_RAILTYPE :全ての鉄道車両 +STR_REPLACE_ALL_RAILTYPE :すべての鉄道車両 +STR_REPLACE_ALL_ROADTYPE :すべての車両 STR_REPLACE_HELP_RAILTYPE :{BLACK}置換対象となる線路種類を切り替えます STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}左で選択された機関車の置換対象を(あれば)表示します STR_REPLACE_RAIL_VEHICLES :機関車(非電化) -STR_REPLACE_ELRAIL_VEHICLES :機関車(電化)/電車 +STR_REPLACE_ELRAIL_VEHICLES :電気機関車・電車 STR_REPLACE_MONORAIL_VEHICLES :モノレール車両 STR_REPLACE_MAGLEV_VEHICLES :リニア車両 -STR_REPLACE_ROAD_VEHICLES :道路車両 +STR_REPLACE_ROAD_VEHICLES :車両 STR_REPLACE_TRAM_VEHICLES :路面電車の車両 STR_REPLACE_REMOVE_WAGON :{BLACK}列車の短縮: {ORANGE}{STRING} @@ -3675,6 +3771,7 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}機関 STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}メイン画面を列車に中心します。ダブルクリックで列車をメイン画面で追従します。Ctrl+クリックで列車の場所で新しいビューポートでを開きます。 +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}車両の位置に関する中央のメインビュー。ダブルクリックすると、メインビューで車両が追従します。Ctrl +クリックすると、車両の位置に新しいビューポートが開きます STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}航空機の位置に関する中央のメインビュー。ダブルクリックすると、メインビューで航空機が表示されます。Ctrl +クリックすると、航空機の位置に新しいビューポートが開きます STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}列車を列車庫へ回送します。Ctrl+クリックすると点検後、再出庫します @@ -3689,10 +3786,10 @@ STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}航空 STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}赤信号を無視して進行させます -STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送出来るよう列車を改造します -STR_VEHICLE_VIEW_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送出来るよう車両を改造します -STR_VEHICLE_VIEW_SHIP_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送出来るよう船舶を改造します -STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送出来るよう航空機を改造します +STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送するように列車を改造します +STR_VEHICLE_VIEW_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送するように車両を改造します +STR_VEHICLE_VIEW_SHIP_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送するように船舶を改造します +STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}現在とは異なる種類の貨物を運送するように航空機を改造します STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP :{BLACK}運転方向を反転させます STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP :{BLACK}車両を反転します @@ -3712,6 +3809,7 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}現在 STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}現在の船のアクション-クリックして船を停止/開始します STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}現在の航空機のアクション-クリックして航空機を停止/開始します +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}注文先の中央のメインビュー。Ctrlキーを押しながらクリックすると、注文先の場所に新しいビューポートが開きます # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}積み降ろし中 @@ -3812,7 +3910,7 @@ STR_REFIT_NEW_CAPACITY_COST_OF_REFIT :{BLACK}改造 STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT :{BLACK}改造後の積載量: {GOLD}{CARGO_LONG}{}{BLACK}改造収益: {GREEN}{CURRENCY_LONG} STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT :{BLACK}改造後の積載量: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}改造費用: {RED}{CURRENCY_LONG} STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT :{BLACK}改造後の積載量: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}改造収益: {GREEN}{CURRENCY_LONG} -STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}改造を行う貨車(客車)を選択します。ドラッグで複数の貨車を選択できます。空きスペースをクリックすると全貨車が選択されます。Ctrl+クリックでその貨車から後続する貨車を全て選択します +STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}改造を行う貨車(客車)を選択します。ドラッグで複数の貨車を選択できます。空きスペースをクリックすると全貨車が選択されます。Ctrl+クリックでその貨車に続く貨車をすべて選択します STR_REFIT_TRAIN_LIST_TOOLTIP :{BLACK}この列車が新たに輸送する貨物種類を選択します STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}この車両が新たに輸送する貨物種類を選択します @@ -3824,10 +3922,10 @@ STR_REFIT_ROAD_VEHICLE_REFIT_BUTTON :{BLACK}車両 STR_REFIT_SHIP_REFIT_BUTTON :{BLACK}船舶を改造 STR_REFIT_AIRCRAFT_REFIT_BUTTON :{BLACK}航空機を改造 -STR_REFIT_TRAIN_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するために列車を改造します -STR_REFIT_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するために車両を改造します -STR_REFIT_SHIP_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するために船舶を改造します -STR_REFIT_AIRCRAFT_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するために航空機を改造します +STR_REFIT_TRAIN_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するように列車を改造します +STR_REFIT_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するように車両を改造します +STR_REFIT_SHIP_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するように船舶を改造します +STR_REFIT_AIRCRAFT_REFIT_TOOLTIP :{BLACK}選択した種類の貨物を運送するように航空機を改造します # Order view STR_ORDERS_CAPTION :{WHITE}{VEHICLE} (指令) @@ -3856,9 +3954,9 @@ STR_ORDER_DROP_FULL_LOAD_ANY :いずれかを STR_ORDER_DROP_NO_LOADING :荷積み無し STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}選択した指令先での荷積み方式を変更します -STR_ORDER_TOGGLE_UNLOAD :{BLACK}全て降ろす -STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :受入有なら降ろす -STR_ORDER_DROP_UNLOAD :全て降ろす +STR_ORDER_TOGGLE_UNLOAD :{BLACK}すべて荷降ろしする +STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :貨物を納入できるなら荷降ろしする +STR_ORDER_DROP_UNLOAD :すべて荷降ろしする STR_ORDER_DROP_TRANSFER :転送 STR_ORDER_DROP_NO_UNLOADING :荷下ろし無し STR_ORDER_TOOLTIP_UNLOAD :{BLACK}選択した指令先での荷下ろし方式を変更します @@ -3886,6 +3984,7 @@ STR_ORDER_CONDITIONAL_AGE :使用年数( STR_ORDER_CONDITIONAL_REQUIRES_SERVICE :点検要求 STR_ORDER_CONDITIONAL_UNCONDITIONALLY :常に STR_ORDER_CONDITIONAL_REMAINING_LIFETIME :耐用年数までの残期間(年) +STR_ORDER_CONDITIONAL_MAX_RELIABILITY :最大信頼度 STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP :{BLACK}輸送機器のデータと指定の数値でどのような条件式を組むかを決定します STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS :に等しい @@ -3905,7 +4004,7 @@ STR_ORDERS_SKIP_TOOLTIP :{BLACK}現在 STR_ORDERS_DELETE_BUTTON :{BLACK}削除 STR_ORDERS_DELETE_TOOLTIP :{BLACK}選択した指令を削除します -STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}指令を全て消去 +STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}指令をすべて除去 STR_ORDERS_STOP_SHARING_BUTTON :{BLACK}共有を解除 STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}指令の共有を解除します。Ctrl+クリックで全司令を消去します @@ -4076,7 +4175,7 @@ STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}ゲー STR_ERROR_AI_NO_AI_FOUND :適切なAIが見つかりません。{}このAIはダミーAIで何も行いません。{}AIは「オンラインコンテンツの確認」経由でダウンロード可能です STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}実行中のAIの一つがクラッシュしました。AIの作者にデバッグウインドウのスクリーンショットを付け、ご報告ください -STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}AI/ゲームスクリプトのデバッグウインドウはサーバーでのみ使用することができます +STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}AI/ゲームスクリプトのデバッグウインドウはサーバーでのみ使用できます # AI configuration window STR_AI_CONFIG_CAPTION :{WHITE}AIの設定 @@ -4118,6 +4217,7 @@ STR_AI_LIST_CANCEL :{BLACK}キャ STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}スクリプトを変更しません STR_SCREENSHOT_CAPTION :{WHITE}スクリーンショットを撮る +STR_SCREENSHOT_SCREENSHOT :{BLACK}通常のスクリーンショット STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}スクリーンショットを完全に拡大 STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}地図全体のスクリーンショット STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}ハイトマップスクリーンショット @@ -4224,13 +4324,13 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}平地 STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}土地の傾きが違います STR_ERROR_CAN_T_DO_THIS :{WHITE}それをすることはできません STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}先に建物を撤去しなければなりません -STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}この範囲を撤去することは出来ません +STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}この範囲を撤去することはできません STR_ERROR_SITE_UNSUITABLE :{WHITE}地形が不適当です STR_ERROR_ALREADY_BUILT :{WHITE}既に設置されています STR_ERROR_OWNED_BY :{WHITE}{STRING}の所有設備です STR_ERROR_AREA_IS_OWNED_BY_ANOTHER :{WHITE}この土地は他の会社に所有されています -STR_ERROR_TERRAFORM_LIMIT_REACHED :{WHITE}一度に出来る整地量を越えています -STR_ERROR_CLEARING_LIMIT_REACHED :{WHITE}一度に出来る撤去量を越えています +STR_ERROR_TERRAFORM_LIMIT_REACHED :{WHITE}一度にできる整地量を越えています +STR_ERROR_CLEARING_LIMIT_REACHED :{WHITE}一度にできる撤去量を越えています STR_ERROR_TREE_PLANT_LIMIT_REACHED :{WHITE}木の本数が多すぎます STR_ERROR_NAME_MUST_BE_UNIQUE :{WHITE}名前は重複してはいけません STR_ERROR_GENERIC_OBJECT_IN_THE_WAY :{WHITE}{1:STRING}があります @@ -4278,7 +4378,7 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}マッ STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}他の街に近すぎます STR_ERROR_TOO_MANY_TOWNS :{WHITE}街数の制限を超えています STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}マップに空きスペースがありません -STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}この街は自動では道路を建設しません。「設定→環境→街」から道路の建設を許可できます +STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}この街は自動では道路を敷設しません。「設定→環境→街」から道路の敷設を許可できます STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}道路補修工事中です STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}街を削除できません{}この街名を参照する停留施設・車庫か、街が所有するタイルが除去できません STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}街の中心部に像を建てるのに適した場所がありません @@ -4401,7 +4501,7 @@ STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}道路 STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}このレール種別との平面交差はできません STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}この道路では踏切は作れません STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}ここには信号を設置できません -STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここには線路を建設できません +STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここには線路を敷設できません STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}ここから線路を撤去できません STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}ここから信号を撤去できません STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}この信号を交換できません @@ -4413,14 +4513,15 @@ STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}この # Road construction errors STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}先に道路を撤去しなければなりません STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}一方通行路は交差できません -STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}ここには道路を建設できません -STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}ここには軌道を建設できません +STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}ここには道路を敷設できません +STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}ここには軌道を敷設できません STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}ここから道路を撤去できません STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}ここから軌道を撤去できません STR_ERROR_THERE_IS_NO_ROAD :{WHITE}道路がありません STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}軌道がありません -STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}この道路のタイプは変更できません +STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}この道路の種類は変更できません STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}ここで路面電車の種類を変更できません... +STR_ERROR_NO_SUITABLE_ROAD :{WHITE}適当な道路がありません STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}有効な路面電車がありません STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}軌道に互換性がありません @@ -4475,13 +4576,14 @@ STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}グル STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}グループを削除できません STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}グループ名を変更できません STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}親グループを設定できません +STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}グループ階層のループは許可されていません STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}グループ内の全車両を移動できません STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}この車両をこのグループに追加できません STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}グループに共有車両を追加できません # Generic vehicle errors STR_ERROR_TRAIN_IN_THE_WAY :{WHITE}列車があります -STR_ERROR_ROAD_VEHICLE_IN_THE_WAY :{WHITE}道路車両があります +STR_ERROR_ROAD_VEHICLE_IN_THE_WAY :{WHITE}経路上に車両があります STR_ERROR_SHIP_IN_THE_WAY :{WHITE}船舶があります STR_ERROR_AIRCRAFT_IN_THE_WAY :{WHITE}航空機があります @@ -4548,7 +4650,7 @@ STR_ERROR_AIRCRAFT_IS_IN_FLIGHT :{WHITE}飛行 STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}これ以上の指令を追加できません STR_ERROR_TOO_MANY_ORDERS :{WHITE}指令が多すぎます STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}新規指令を挿入できません -STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}この指令を削除できません +STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}この指令を除去できません STR_ERROR_CAN_T_MODIFY_THIS_ORDER :{WHITE}この指令を変更できません STR_ERROR_CAN_T_MOVE_THIS_ORDER :{WHITE}この指令を移動できません STR_ERROR_CAN_T_SKIP_ORDER :{WHITE}実行中の指令はスキップできません @@ -4585,6 +4687,7 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Transport Tycoo STR_BASESOUNDS_WIN_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 効果音 (Windows) STR_BASESOUNDS_NONE_DESCRIPTION :空の効果音パック STR_BASEMUSIC_WIN_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 音楽 (Windows) +STR_BASEMUSIC_DOS_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 音楽 (DOS) STR_BASEMUSIC_TTO_DESCRIPTION :オリジナルトランスポートタイクーン(オリジナル/ワールドエディター)DOS版の音楽。 STR_BASEMUSIC_NONE_DESCRIPTION :空の音楽パック @@ -4669,10 +4772,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :砂糖鉱山 ##id 0x6000 STR_SV_EMPTY : STR_SV_UNNAMED :[未命名] -STR_SV_TRAIN_NAME :列車{COMMA} -STR_SV_ROAD_VEHICLE_NAME :車両{COMMA} -STR_SV_SHIP_NAME :船舶{COMMA} -STR_SV_AIRCRAFT_NAME :航空機{COMMA} +STR_SV_TRAIN_NAME :列車 #{COMMA} +STR_SV_ROAD_VEHICLE_NAME :車両 #{COMMA} +STR_SV_SHIP_NAME :船舶 #{COMMA} +STR_SV_AIRCRAFT_NAME :航空機 #{COMMA} STR_SV_STNAME :{STRING} STR_SV_STNAME_NORTH :北{STRING} From 3477405e868f9d61cb3ece4f034f3307b14e9e98 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 20 May 2021 19:12:33 +0200 Subject: [PATCH 212/800] Change: [Actions] use newly created Actions instead of custom shell-scripting (#9284) --- .github/workflows/ci-build.yml | 30 ++---------------------- .github/workflows/commit-checker.yml | 34 ++-------------------------- 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index e0707291c3..4dea7350c7 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -326,34 +326,8 @@ jobs: if: always() && github.event_name == 'pull_request' - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - name: Get check suite ID - id: check_suite_id - uses: octokit/request-action@v2.x - with: - route: GET /repos/{repository}/actions/runs/{run_id} - repository: ${{ github.repository }} - run_id: ${{ github.run_id }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Get check runs - id: check_runs - uses: octokit/request-action@v2.x - with: - route: GET /repos/{repository}/check-suites/{check_suite_id}/check-runs - repository: ${{ github.repository }} - check_suite_id: ${{ fromJson(steps.check_suite_id.outputs.data).check_suite_id }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Check annotations - shell: bash - run: | - echo '[ - ${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.title) }}, ${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.summary) }} - ]' | jq '.[0] as $t | .[1] as $s | reduce range(.[0] | length) as $i ([]; . + [if $t[$i] then $t[$i] + ": " + $s[$i] else empty end]) | .[]' - - exit $(echo '${{ toJson(fromJson(steps.check_runs.outputs.data).check_runs.*.output.annotations_count) }}' | jq 'add') + uses: OpenTTD/actions/annotation-check@v2 diff --git a/.github/workflows/commit-checker.yml b/.github/workflows/commit-checker.yml index d83183a467..acf622a87e 100644 --- a/.github/workflows/commit-checker.yml +++ b/.github/workflows/commit-checker.yml @@ -15,37 +15,7 @@ jobs: fetch-depth: 4 - name: Get pull-request commits - run: | - set -x - # actions/checkout did a merge checkout of the pull-request. As such, the first - # commit is the merge commit. This means that on HEAD^ is the base branch, and - # on HEAD^2 are the commits from the pull-request. We now check if those trees - # have a common parent. If not, we fetch a few more commits till we do. In result, - # the log between HEAD^ and HEAD^2 will be the commits in the pull-request. - DEPTH=4 - while [ -z "$(git merge-base HEAD^ HEAD^2)" ]; do - # Prevent infinite recursion - if [ ${DEPTH} -gt 256 ]; then - echo "No common parent between '${GITHUB_HEAD_REF}' and '${GITHUB_BASE_REF}'." >&2 - exit 1 - fi - - git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --deepen=${DEPTH} origin HEAD - DEPTH=$(( ${DEPTH} * 4 )) - done - - # Just to show which commits we are going to evaluate. - git log --oneline HEAD^..HEAD^2 - - - name: Checkout commit-checker - uses: actions/checkout@v2 - with: - repository: OpenTTD/OpenTTD-git-hooks - path: git-hooks - ref: master + uses: OpenTTD/actions/checkout-pull-request@v2 - name: Check commits - run: | - set -x - HOOKS_DIR=./git-hooks/hooks GIT_DIR=.git ./git-hooks/hooks/check-commits.sh HEAD^..HEAD^2 - echo "Commit checks passed" + uses: OpenTTD/OpenTTD-git-hooks@main From 08e71eed8b86eaebb9b6afd834c3b9a548867ebd Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 20 May 2021 19:11:15 +0000 Subject: [PATCH 213/800] Update: Translations from eints japanese: 74 changes by akaregi --- src/lang/japanese.txt | 100 +++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index 8c26bb4fe6..db8e0c5dea 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -264,6 +264,7 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}この STR_BUTTON_DEFAULT :{BLACK}デフォルト STR_BUTTON_CANCEL :{BLACK}キャンセル STR_BUTTON_OK :{BLACK}OK +STR_WARNING_PASSWORD_SECURITY :{YELLOW}警告: サーバーの管理者はここに入力された文章をすべて読めます。 # On screen keyboard window STR_OSK_KEYBOARD_LAYOUT :{NBSP}1234567890-^\qwertyuiop@[asdfghjkl;:] zxcvbnm,./\ @@ -324,7 +325,7 @@ STR_GROUP_BY_SHARED_ORDERS :共有注文 # Tooltips for the main toolbar STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}ゲームをポーズします -STR_TOOLBAR_TOOLTIP_FORWARD :{BLACK}ゲームスピードを早くします +STR_TOOLBAR_TOOLTIP_FORWARD :{BLACK}ゲーム進行速度を早くします STR_TOOLBAR_TOOLTIP_OPTIONS :{BLACK}ゲームオプションの設定画面を開きます STR_TOOLBAR_TOOLTIP_SAVE_GAME_ABANDON_GAME :{BLACK}ゲームのセーブ、中断、OpenTTDの終了ができます STR_TOOLBAR_TOOLTIP_DISPLAY_MAP :{BLACK}地図の表示、ビューポートの表示、標識のリストの表示ができます @@ -1003,7 +1004,8 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :その他 STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}ハードウェアアクセラレーション -STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}このボックスをオンにすると、OpenTTDがハードウェアアクセラレーションを使用できるようになります。変更された設定は、ゲームの再起動時にのみ適用されます +STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}ここをチェックしてOpenTTDがハードウェアアクセラレーションを利用するようにします。設定はゲームを再起動した後に適用されます。 +STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE} この設定は再起動後に適用されます。 STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK} 垂直同期 STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}ここをチェックして垂直同期を有効にします。設定はゲームを再起動した後に適用されます。ハードウェアアクセラレーションが有効な環境でしか機能しません。 @@ -1012,7 +1014,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}イン STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}インターフェイス上の単位サイズを指定します STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO :(自動検出) -STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :通常 +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :ノーマル STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :2倍 STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :4倍 @@ -1082,7 +1084,7 @@ STR_FUNDING_ONLY :出資のみ STR_MINIMAL :最小 STR_NUM_VERY_LOW :特に低い STR_NUM_LOW :低い -STR_NUM_NORMAL :通常 +STR_NUM_NORMAL :普通 STR_NUM_HIGH :高い STR_NUM_CUSTOM :カスタム STR_NUM_CUSTOM_NUMBER :カスタム ({NUM}) @@ -1114,7 +1116,7 @@ STR_RIVERS_LOT :多い STR_DISASTER_NONE :なし STR_DISASTER_REDUCED :軽減 -STR_DISASTER_NORMAL :通常 +STR_DISASTER_NORMAL :普通 STR_SUBSIDY_X1_5 :×1.5 STR_SUBSIDY_X2 :×2 @@ -1213,6 +1215,7 @@ STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編 STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街域で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や同じ地域での更なる建設行為に影響するかを設定します STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :マップ高さ限界: {STRING} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :マップの地形の最高高度を指定します。"(auto)"で地形生成後に適切な値を設定させるようにします。 STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(自動) STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの高度限界をこの値に設定できません。より高高度にある山が一つ以上存在します。 @@ -1297,7 +1300,7 @@ STR_CONFIG_SETTING_PLANE_CRASHES :航空事故数 STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :航空機事故の発生率を定めます STR_CONFIG_SETTING_PLANE_CRASHES_NONE :なし STR_CONFIG_SETTING_PLANE_CRASHES_REDUCED :軽減 -STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :通常 +STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :普通 STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :街有道路での路側型バス停/荷役所建設: {STRING} STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :路側型バス停/荷役所を街が所有する道路上に建設できるようにします STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :他社の道路上での路側型バス停/荷役所設置: {STRING} @@ -1343,6 +1346,7 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :街の名前ラ STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :グラフ線の太さ: {STRING} STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :グラフ画面での折れ線の太さを設定します。細い線では値を精密に読み取りやすくなり、太い線ではグラフ自体が見やすくなり、線色の見分けがつきやすくなります STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :ビルドビークルウィンドウにNewGRFの名前を表示します:{STRING} +STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :購入可能な車両の一覧の詳細部分に由来する NewGRF を表示します STR_CONFIG_SETTING_LANDSCAPE :地形: {STRING} STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :地形は様々な貨物と街の成長要件に関する基礎的なゲームプレイシナリオを定義します。NewGRFとゲームスクリプトによってより効果的なコントロールが可能になります。 @@ -1358,9 +1362,12 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :石油精製所 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :石油精製所はマップの外周付近にのみ建設されます。つまり、外周が海のマップでは海岸沿いに建設されるということです STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪線の位置: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪線は産業生成と街の発展に影響を及ぼします。シナリオエディタを介して変更するか積雪量により計算されます。 +STR_CONFIG_SETTING_SNOW_COVERAGE :降雪量: {STRING} STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :亜寒帯の風景のおおよその雪の量を制御します。雪はまた、産業の生成と町の成長要件にも影響を及ぼします。マップの生成中にのみ使用されます。海抜のすぐ上の土地は常に雪がありません STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% +STR_CONFIG_SETTING_DESERT_COVERAGE :砂漠の範囲: {STRING} STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :熱帯気候でのおおよその砂漠の量を制御します。砂漠は産業生成に影響を及ぼします。マップ生成時にのみ設定が参照されます。 +STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地形の起伏: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesisのみ) 地形の起伏度を設定します。なだらかな地形では丘陵の数は減り、裾野が長くなります。起伏が多い地形では丘陵が多くなりますが、似たり寄ったりな地形の繰り返しに見えることがあります STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :特になだらか @@ -1396,10 +1403,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :ミニマップ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :緑 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :濃緑 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :青紫 -STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :スクロール時の動き +STR_CONFIG_SETTING_SCROLLMODE :ビューポートのスクロール挙動: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :マップのスクロール挙動 STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :右クリックでビューポートを移動し、マウスの位置をロックします STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :右クリックで地図を移動し、マウスの位置をロックします STR_CONFIG_SETTING_SCROLLMODE_RMB :マップを右マウスボタンで動かす +STR_CONFIG_SETTING_SCROLLMODE_LMB :左クリックで地図を動かします STR_CONFIG_SETTING_SMOOTH_SCROLLING :画面のスムーズスクロール: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップでの移動や「現在位置に移動」などのコマンドを使用した際にメイン画面がどのように移動するかを設定します。有効にした場合はスムーズにスクロールして移動します。無効の場合は目的地に直接ジャンプします STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING} @@ -1431,6 +1440,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :コマンド+ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+クリック (Win) STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :切 +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :右クリックでウィンドウを閉じる: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :ウィンドウ内で右クリックしてウィンドウを閉じられます。右クリックでツールチップも無効にできます。 STR_CONFIG_SETTING_AUTOSAVE :オートセーブ: {STRING} @@ -1471,8 +1481,10 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :建設ツール STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :橋やトンネルなどを建設した後もツールバーを開いたままにします STR_CONFIG_SETTING_EXPENSES_LAYOUT :財政ウィンドウのグループ分け: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :財政ウィンドウのレイアウトを収入部門・支出部門でグループ分けするかどうかを設定します +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :線路の敷設中に自動的に信号を除去します: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :信号が経路上に存在する場合線路設置の際にすべて自動的に除去されます。鉄道車両の衝突につながる危険性があります。 -STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :早送りが有効になっている場合のゲームの進行速度を制限します。0 =制限なし(コンピューターが許す限り高速)。100%未満の値は、ゲームの速度を低下させます。上限はコンピュータの仕様によって異なり、ゲームによって異なる場合があります。 +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :ゲーム進行速度の加速制限: {STRING} +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :早送りが有効になっている場合のゲーム進行速度を制限します。0 = 制限なし(コンピュータの許す限り高速にする)。100%より下げると進行速度が遅くなります。制限の上限はコンピュータの仕様によって異なり、ゲームの設定にも依存します。 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :制限なし(コンピューターが許す限り高速) @@ -1584,11 +1596,15 @@ STR_CONFIG_SETTING_NEWS_MESSAGES_FULL :新聞 STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :カラー新聞の開始年: {STRING} STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :新聞がカラー版になる境目の年を設定します STR_CONFIG_SETTING_STARTING_YEAR :開始年: {STRING} -STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :スコアリングの目的でゲームが終了する年。 今年の終わりには、会社のスコアが記録され、ハイスコア画面が表示されますが、プレーヤーはその後もプレイを続けることができます。{}これが開始年より前の場合、ハイスコア画面は表示されません。 +STR_CONFIG_SETTING_ENDING_YEAR :スコア記録の基準年: {STRING} +STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :スコア記録の基準となる基準年。基準年の終わりに会社のスコアがハイスコアに記録・表示されます。プレイヤーはその後もプレイを続けられます。{}基準年が開始年より前の場合、ハイスコア画面は表示されません。 STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} +STR_CONFIG_SETTING_ENDING_YEAR_ZERO :(なし) STR_CONFIG_SETTING_ECONOMY_TYPE :エコノミータイプ:{STRING} +STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :なだらかな経済は生産量の変動をより頻繁に起こすようにします。固定経済は変動と閉鎖の両方を起こさないようにします。産業が NewGRF により提供される場合この設定は影響を及ぼさない場合があります。 STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :オリジナル STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :なだらか +STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :固定 STR_CONFIG_SETTING_ALLOW_SHARES :他社株の取引許容: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :有効にすると、ライバル会社の株式を取引できるようになります。この設定を有効にしても、目的の社が設立から丸5年経過していない場合は取引できません STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :株式を取引するための最低会社年齢:{STRING} @@ -1640,8 +1656,10 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :線形 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :樹木の自然成長: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :ゲーム中、ランダムに生えてくる樹種を設定します。設定によっては樹木の生育に依存する産業に悪影響が生じる可能性があります(「不可」にした場合、亜熱帯地域の伐採所を機能させ続けるためには手動で植林し続ける必要があります) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :成長はするが広がらない {RED}(製材所の機能を止めます) STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :成長するが、熱帯雨林にのみ広がる STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :成長し、どこにでも広がる +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :成長はするが広がらない {RED}(製材所の機能を止めます) STR_CONFIG_SETTING_TOOLBAR_POS :メインツールバーの位置: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :画面上のメインツールバーの位置を決めます @@ -1663,11 +1681,12 @@ STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :使用する最 STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :スプライトに使用する最大解像度を制限します。 スプライトの解像度を制限すると使用可能な場合でも高解像度のグラフィックを使用できなくなります。 これにより、高解像度のグラフィックを使用する場合と使用しない場合のGRFファイルを組み合わせて使用する場合にゲームの外観を統一できます。 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍 STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍 -STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :通常 +STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :普通 STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X :2倍 STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X :4倍 STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8倍 STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_MIN :4倍 +STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_IN_2X :2倍 STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_NORMAL :1倍 STR_CONFIG_SETTING_TOWN_GROWTH :街の成長速度: {STRING} STR_CONFIG_SETTING_TOWN_GROWTH_HELPTEXT :街の成長速度を設定します @@ -1844,6 +1863,7 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}公式 STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}AI/ゲームスクリプトの設定を行います STR_INTRO_TOOLTIP_QUIT :{BLACK}OpenTTD を終了します +STR_INTRO_BASESET :現在選択されているグラフィックのベースセットは {NUM} つのスプライトが欠けています。ベースセットの更新を確認してみてください。 STR_INTRO_TRANSLATION :{BLACK}この言語セットには{NUM}個の未訳文字列があります。翻訳者としてWeb登録し、OpenTTDをより良くする為にご助力下さい。(詳細はreadme.txtをご覧下さい) # Quit window @@ -1971,6 +1991,7 @@ STR_FACE_EARRING :イヤリング STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}ネクタイ/イヤリングを変更します STR_NETWORK_SERVER_VISIBILITY_PRIVATE :プライベート +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :公開 # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}マルチプレイヤーゲーム @@ -2035,6 +2056,7 @@ STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}パス STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}ゲームをパスワードで保護できます。一般から公然とアクセスされたくない場合等に設定します STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}可視性 +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}他のプレイヤーがあなたのサーバーを公開リストで見られるかどうか STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}接続者数: {NUM} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}最大接続数: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}接続できるクライアントの最大数を指定します。必ずしも全スロットを埋める必要はありません @@ -2068,7 +2090,7 @@ STR_NETWORK_GAME_LOBBY_STATIONS :{SILVER}停留 STR_NETWORK_GAME_LOBBY_PLAYERS :{SILVER}プレイヤー数: {WHITE}{STRING} STR_NETWORK_GAME_LOBBY_NEW_COMPANY :{BLACK}新規会社 -STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP :{BLACK}新規に会社を設立します +STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP :{BLACK}新しく会社を設立します STR_NETWORK_GAME_LOBBY_SPECTATE_GAME :{BLACK}ゲームを観覧 STR_NETWORK_GAME_LOBBY_SPECTATE_GAME_TOOLTIP :{BLACK}観覧者としてゲームを観戦します STR_NETWORK_GAME_LOBBY_JOIN_COMPANY :{BLACK}経営に参画 @@ -2108,28 +2130,33 @@ STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}あな STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}サーバーの名前を編集する STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :サーバー名 STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}可視性 -STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}他の人があなたのサーバーを公開リストで見ることができるかどうか +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}他のプレイヤーがあなたのサーバーを公開リストで見られるかどうか STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}プレイヤー STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}名前 STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}あなたのプレイヤー名 STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}プレイヤー名を変更する STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :あなたのプレイヤー名 STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}このクライアントに対して実行する管理アクション +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}この会社に対して実行する管理アクション STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}この会社に参画する STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}このプレイヤーにメッセージを送信する STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}この会社のすべてのプレイヤーにメッセージを送信する STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}すべての観客にメッセージを送信する STR_NETWORK_CLIENT_LIST_SPECTATORS :観覧者 STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新規会社) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}新しく会社を設立し参画します STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}これはあなたです STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}ゲームのホストです STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :キック STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :BAN STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :削除 +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :パスワードのアンロック +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}管理者アクション STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}'{STRING}'をキックしてもよろしいですか? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}プレーヤー「{STRING}」を追放してもよろしいですか? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}会社 '{COMPANY}' を削除してもよろしいですか? STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}会社 '{COMPANY}'のパスワードをリセットしてもよろしいですか? STR_NETWORK_SERVER :サーバー @@ -2189,6 +2216,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}サー STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}マップのダウンロード時間が規定を超過しました STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}タイムアウトによりサーバーへの接続を確立できません STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}プレイヤー名が無効です +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}サーバーが現在使用中のクライアントに対して古すぎます ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :一般エラー @@ -2382,7 +2410,7 @@ STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}鉄道 STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}鉄道橋を建設します。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}鉄道トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}線路・信号・駅・中継駅の建設/撤去を切り替えます。{}Ctrlを押したままにすると駅・通過点の撤去時に線路ごと撤去されます -STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}既設の線路をこのレール種に変更します。Shiftを押しながら決定すると費用の見積が出ます +STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}既設の線路をこのレール種に変更します。Shiftを押しながら決定すると費用を見積もれます。 STR_RAIL_NAME_RAILROAD :鉄道 (非電化) STR_RAIL_NAME_ELRAIL :電気鉄道 @@ -2469,7 +2497,8 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}道路 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の敷設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の敷設/撤去を切り替えます -STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの作成/表示を切り替えます +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします。Shift を押しながら決定するとコスト見積もりの作成/表示を切り替えられます +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}軌道の種類を変更・アップグレードします。Shift を押しながら決定するとコスト見積もりの作成/表示を切り替えられます STR_ROAD_NAME_ROAD :道路 STR_ROAD_NAME_TRAM :トラムウェイ @@ -2560,9 +2589,11 @@ STR_TREES_RANDOM_TYPE :{BLACK}ラン STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ランダムな樹類で植林します。Shift+クリックで費用を見積もります STR_TREES_RANDOM_TREES_BUTTON :{BLACK}ランダムに広域植林 STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}地表全体にランダムに植林します +STR_TREES_MODE_NORMAL_BUTTON :{BLACK}普通 STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}風景の上をドラッグして、単一の木を植えます。 STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}グローブ STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}風景をドラッグして小さな森を植えます +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}森林 STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}風景の上をドラッグして、大きな森を植えます。 # Land generation window (SE) @@ -2615,9 +2646,9 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}ラン STR_FUND_INDUSTRY_CAPTION :{WHITE}新規産業の建設に出資 STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}建設したい産業をリストから選択します STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}ランダムな産業を生成する -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}マップ全域にランダムに産業を建設します -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}ランダムな産業を作成する -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}ランダムな産業をたくさん作りたいですか? +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}マップ全域にランダムに産業を生成します +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}ランダムに産業を生成する +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}ランダムに多くの産業を生成してもよろしいですか? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}費用: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}調査/探鉱 STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}建設 @@ -2773,6 +2804,7 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}フレームレート +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) STR_FRAMERATE_RATE_GAMELOOP :{BLACK}シミュレーションレート: {STRING} STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}一秒あたりに計算されるゲームのティック数。 STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING} @@ -2798,20 +2830,24 @@ STR_FRAMERATE_GAMELOOP :{BLACK}ゲー STR_FRAMERATE_GL_ECONOMY :{BLACK}貨物の取り扱い: STR_FRAMERATE_GL_TRAINS :{BLACK} 鉄道車両のティック: STR_FRAMERATE_GL_ROADVEHS :{BLACK} 自動車ティック: +STR_FRAMERATE_GL_SHIPS :{BLACK}船舶のティック数: STR_FRAMERATE_GL_AIRCRAFT :{BLACK}航空機ティック: STR_FRAMERATE_GL_LANDSCAPE :{BLACK}世界のティック: +STR_FRAMERATE_GL_LINKGRAPH :{BLACK} リンクグラフの遅延: STR_FRAMERATE_DRAWING :{BLACK}グラフィックレンダリング: STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK}世界のビューポート: STR_FRAMERATE_VIDEO :{BLACK}ビデオ出力: STR_FRAMERATE_SOUND :{BLACK}サウンドミキサー: +STR_FRAMERATE_ALLSCRIPTS :{BLACK} ゲームスクリプト・AIの合計: STR_FRAMERATE_GAMESCRIPT :{BLACK} ゲームスクリプト: +STR_FRAMERATE_AI :{BLACK} AI {NUM} {STRING} ############ End of leave-in-this-order ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GAMELOOP :ゲームループ STR_FRAMETIME_CAPTION_GL_ECONOMY :貨物の取り扱い STR_FRAMETIME_CAPTION_GL_TRAINS :切符 STR_FRAMETIME_CAPTION_GL_ROADVEHS :車両のティック数 -STR_FRAMETIME_CAPTION_GL_SHIPS :船のティック +STR_FRAMETIME_CAPTION_GL_SHIPS :船舶のティック数 STR_FRAMETIME_CAPTION_GL_AIRCRAFT :航空機ティック STR_FRAMETIME_CAPTION_GL_LANDSCAPE :ワールドティック STR_FRAMETIME_CAPTION_GL_LINKGRAPH :リンクグラフの遅延 @@ -2819,7 +2855,7 @@ STR_FRAMETIME_CAPTION_DRAWING :グラフィッ STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :ワールドビューポートレンダリング STR_FRAMETIME_CAPTION_VIDEO :ビデオ出力 STR_FRAMETIME_CAPTION_SOUND :サウンドミキシング -STR_FRAMETIME_CAPTION_ALLSCRIPTS :ゲームスクリプト・AIスクリプトの合計 +STR_FRAMETIME_CAPTION_ALLSCRIPTS :ゲームスクリプト・AIの合計 STR_FRAMETIME_CAPTION_GAMESCRIPT :ゲームスクリプト STR_FRAMETIME_CAPTION_AI :AI {NUM} {STRING} ############ End of leave-in-this-order @@ -2850,7 +2886,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}フィルター: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}ファイルを上書きする STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}既存のファイルを上書きしてもよろしいですか? -STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Parent directory) +STR_SAVELOAD_DIRECTORY :{STRING} (ディレクトリ) +STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (親ディレクトリ) STR_SAVELOAD_OSKTITLE :{BLACK}保存名を入力 @@ -2863,12 +2900,14 @@ STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}街数: STR_MAPGEN_DATE :{BLACK}日付: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}産業数: STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰: -STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}マップの最高峰の最大の高さを1減らします。 +STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}マップの最高峰の値を1増やします +STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}マップの最高峰の値を1減らします STR_MAPGEN_SNOW_COVERAGE :{BLACK}降雪量: +STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}積雪量を10%増やします STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}積雪量を10%減らします STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK} {NUM}% STR_MAPGEN_DESERT_COVERAGE :{BLACK}砂漠の範囲: -STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}砂漠の割合を10%増やします +STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}砂漠の範囲を10%増やします STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}砂漠の範囲を10%減らします STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}地形作成: @@ -2899,7 +2938,7 @@ STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}ターゲットの最高の高さ STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}最高峰 STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}積雪量(%) -STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}砂漠領域(%) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}砂漠の範囲(%) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}開始年の変更 # SE Map generation @@ -3060,6 +3099,7 @@ STR_NEWGRF_ERROR_GRM_FAILED :要求された STR_NEWGRF_ERROR_FORCEFULLY_DISABLED :{1:STRING}は{STRING}により無効にされました STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT :不正なレイアウト書式です (スプライト {3:NUM}) STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG :プロパティ値リストの要素が多すぎます(スプライト {3:NUM}、プロパティ {4:HEX}) +STR_NEWGRF_ERROR_INDPROD_CALLBACK :不正な産業生産コールバック(スプライト {3:NUM}, "{2:STRING}") # NewGRF related 'general' warnings STR_NEWGRF_POPUP_CAUTION_CAPTION :{WHITE}注意! @@ -3126,12 +3166,13 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}標識 STR_TOWN_DIRECTORY_CAPTION :{WHITE}街一覧 STR_TOWN_DIRECTORY_NONE :{ORANGE}- なし- STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (都市){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}街の名前 - メイン画面を街の場所に移動するには名前をクリックします。Ctrl+クリックで新しいビューポートに表示します STR_TOWN_POPULATION :{BLACK}地域人口: {COMMA}人 # Town view window STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} -STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN}(市) +STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (都市) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}人口: {ORANGE}{COMMA}人{BLACK} 建物: {ORANGE}{COMMA}戸 STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK} {CARGO_LIST}先月:{ORANGE} {COMMA} {BLACK}最大:{ORANGE} {COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}街の成長に必要な物資: @@ -3436,6 +3477,7 @@ STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_L STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING} STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE} {INDUSTRY} {STRING}、{STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PROD3 :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} や、 {NUM} そしてもっと... STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}産業の名前です - 名前をクリックするとこの産業拠点の場所にメイン画面を移動します。Ctrl+クリックでこの産業拠点の場所を新たなビューポートに表示します STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}受け取った貨物: {SILVER}{STRING} @@ -3452,6 +3494,7 @@ STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}生産 STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}この産業拠点は間もなく閉鎖されます! STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}必要条件:{YELLOW} {STRING} {STRING} +STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}生産: {YELLOW}{STRING}{STRING} STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :、{STRING} {STRING} STR_INDUSTRY_VIEW_REQUIRES : {BLACK}必要物資: @@ -3506,6 +3549,7 @@ STR_GROUP_DEFAULT_ROAD_VEHICLES :グループ化 STR_GROUP_DEFAULT_SHIPS :グループ化されていない船舶 STR_GROUP_DEFAULT_AIRCRAFTS :グループ化されていない航空機 +STR_GROUP_COUNT_WITH_SUBGROUP :{TINY_FONT}{COMMA} (+{COMMA}) STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}グループ - クリックするとこのグループに所属する全車両一覧を表示します。ドラック&ドロップで順序を並べ替えられます STR_GROUP_CREATE_TOOLTIP :{BLACK}新規のグループを作成します @@ -3680,7 +3724,7 @@ STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}航空 STR_DEPOT_TRAIN_LOCATION_TOOLTIP :{BLACK}メイン画面を列車庫の場所に移動します。Ctrl+クリックで新規のビューポートに表示します STR_DEPOT_ROAD_VEHICLE_LOCATION_TOOLTIP :{BLACK}メイン画面を車庫の場所に移動します。Ctrl+クリックで新規のビューポートに表示します -STR_DEPOT_SHIP_LOCATION_TOOLTIP :{BLACK}メイン画面を造船所の場所に移動します。Ctrl+クリックで新規のビューポートに表示します +STR_DEPOT_SHIP_LOCATION_TOOLTIP :{BLACK}メイン画面を造船所の場所に移動します。Ctrl+クリックで造船所の場所に新しくビューポートを開きます STR_DEPOT_AIRCRAFT_LOCATION_TOOLTIP :{BLACK}メイン画面を格納庫の場所に移動します。Ctrl+クリックで新規のビューポートに表示します STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TOOLTIP :{BLACK}選択中の列車庫が指令リストに入っている全列車のリストを表示します @@ -3702,7 +3746,7 @@ STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}庫内 # Engine preview window STR_ENGINE_PREVIEW_CAPTION :{WHITE}製造会社からのメッセージ -STR_ENGINE_PREVIEW_MESSAGE :{GOLD}弊社は新たに{STRING}を設計致しました。{}実地でのパフォーマンスなどを検討する為、貴社に独占モニター権を提供したいと考えておりますがいかがでしょうか? +STR_ENGINE_PREVIEW_MESSAGE :{GOLD}弊社は新たに{STRING}を設計いたしました。{}実地試験を行うにあたって貴社にご協力いただきたく、一年間の独占的使用権を提供したいと考えておりますがいかがでしょうか? STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :列車 STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE :電気機関車 @@ -3755,6 +3799,7 @@ STR_REPLACE_ALL_RAILTYPE :すべての鉄 STR_REPLACE_ALL_ROADTYPE :すべての車両 STR_REPLACE_HELP_RAILTYPE :{BLACK}置換対象となる線路種類を切り替えます +STR_REPLACE_HELP_ROADTYPE :{BLACK}置換対象となる道路種類を切り替えます STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}左で選択された機関車の置換対象を(あれば)表示します STR_REPLACE_RAIL_VEHICLES :機関車(非電化) STR_REPLACE_ELRAIL_VEHICLES :電気機関車・電車 @@ -3772,6 +3817,7 @@ STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}メイン画面を列車に中心します。ダブルクリックで列車をメイン画面で追従します。Ctrl+クリックで列車の場所で新しいビューポートでを開きます。 STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}車両の位置に関する中央のメインビュー。ダブルクリックすると、メインビューで車両が追従します。Ctrl +クリックすると、車両の位置に新しいビューポートが開きます +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}メイン画面を船舶の場所に移動します。ダブルクリックでメイン画面が船舶を追従するようになります。Ctrl+クリックで船舶の場所に新しくビューポートを開きます STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}航空機の位置に関する中央のメインビュー。ダブルクリックすると、メインビューで航空機が表示されます。Ctrl +クリックすると、航空機の位置に新しいビューポートが開きます STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}列車を列車庫へ回送します。Ctrl+クリックすると点検後、再出庫します @@ -4219,6 +4265,7 @@ STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}スク STR_SCREENSHOT_CAPTION :{WHITE}スクリーンショットを撮る STR_SCREENSHOT_SCREENSHOT :{BLACK}通常のスクリーンショット STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}スクリーンショットを完全に拡大 +STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT :{BLACK}デフォルトの拡大率のスクリーンショット STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}地図全体のスクリーンショット STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}ハイトマップスクリーンショット STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}ミニマップのスクリーンショット @@ -4309,6 +4356,7 @@ STR_WARNING_FALLBACK_SOUNDSET :{WHITE}フェ STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}巨大なスクリーンショット STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}このスクリーンショットのサイズは {COMMA}×{COMMA} ピクセルになります。このまま続行してもよろしいですか? +STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY :{WHITE}ハイトマップは正常に '{STRING}' として保存されました。最高峰は {NUM} です。 STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}スクリーンショットを'{STRING}'に正常に保存しました STR_ERROR_SCREENSHOT_FAILED :{WHITE}スクリーンショットの保存に失敗しました! From 7b58bfaf6c26ed8c600bd4323f4125691449630c Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 21 May 2021 19:16:19 +0000 Subject: [PATCH 214/800] Update: Translations from eints japanese: 42 changes by akaregi --- src/lang/japanese.txt | 82 ++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index db8e0c5dea..03c7f3d0a1 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -230,7 +230,7 @@ STR_LIST_FILTER_OSKTITLE :{BLACK}フィ STR_LIST_FILTER_TOOLTIP :{BLACK}フィルタリングするキーワードを入力します STR_TOOLTIP_GROUP_ORDER :{BLACK}グループの整列法を選択 -STR_TOOLTIP_SORT_ORDER :{BLACK}並べ替えの順序を選択します。(昇順/降順) +STR_TOOLTIP_SORT_ORDER :{BLACK}並べ替えの順序を選択します (昇順 / 降順) STR_TOOLTIP_SORT_CRITERIA :{BLACK}並べ替えの基準を選択します STR_TOOLTIP_FILTER_CRITERIA :{BLACK}フィルタリングの基準を選択します STR_BUTTON_SORT_BY :{BLACK}並べ替え @@ -612,7 +612,7 @@ STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :運送調整役 STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :経路監督 STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR :理事 STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE :取締役 -STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :座長 +STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :会長役 STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT :総長 STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON :巨頭 @@ -686,7 +686,7 @@ STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLA STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}プレイリスト - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}消去 STR_PLAYLIST_CHANGE_SET :{BLACK}セットの変更 -STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します。(カスタム1/2 のみ) +STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します (カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}音楽の選択を別のインストール済みセットに変更する STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストに追加します。(カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストから削除します。(カスタム1/2 のみ) @@ -908,46 +908,46 @@ STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}通貨 ############ start of currency region STR_GAME_OPTIONS_CURRENCY_GBP :英ポンド(£) STR_GAME_OPTIONS_CURRENCY_USD :米ドル($) -STR_GAME_OPTIONS_CURRENCY_EUR :ユーロ(€) +STR_GAME_OPTIONS_CURRENCY_EUR :欧州連合・ユーロ(€) STR_GAME_OPTIONS_CURRENCY_JPY :日本円(¥) -STR_GAME_OPTIONS_CURRENCY_ATS :オーストリアシリング(ATS) -STR_GAME_OPTIONS_CURRENCY_BEF :ベルギーフランク(BEF) -STR_GAME_OPTIONS_CURRENCY_CHF :スイスフランク(CHF) -STR_GAME_OPTIONS_CURRENCY_CZK :チェココルナ(CZK) -STR_GAME_OPTIONS_CURRENCY_DEM :ドイツマルク(DEM) -STR_GAME_OPTIONS_CURRENCY_DKK :デンマーククローネ(DKK) -STR_GAME_OPTIONS_CURRENCY_ESP :スペインペセタ(₧) -STR_GAME_OPTIONS_CURRENCY_FIM :フィンランドマーカ(FIM) -STR_GAME_OPTIONS_CURRENCY_FRF :フランスフラン(₣) -STR_GAME_OPTIONS_CURRENCY_GRD :ギリシアドラクマ(GRD) -STR_GAME_OPTIONS_CURRENCY_HUF :ハンガリーフォリント(HUF) -STR_GAME_OPTIONS_CURRENCY_ISK :アイスランドクローナ(ISK) -STR_GAME_OPTIONS_CURRENCY_ITL :イタリアリラ(ITL) -STR_GAME_OPTIONS_CURRENCY_NLG :オランダギルダー(NLG) -STR_GAME_OPTIONS_CURRENCY_NOK :ノルウェイクローネ(NOK) -STR_GAME_OPTIONS_CURRENCY_PLN :ポーランドズロティ(PLN) -STR_GAME_OPTIONS_CURRENCY_RON :ルーマニアレイ(RON) -STR_GAME_OPTIONS_CURRENCY_RUR :ロシアルーブル(RUR) -STR_GAME_OPTIONS_CURRENCY_SIT :スロベニアトラール(SIT) -STR_GAME_OPTIONS_CURRENCY_SEK :スウェーデンクローナ(SEK) -STR_GAME_OPTIONS_CURRENCY_TRY :トルコリラ(TL) -STR_GAME_OPTIONS_CURRENCY_SKK :スロバキアコルナ(SKK) -STR_GAME_OPTIONS_CURRENCY_BRL :ブラジルレアル(BRL) -STR_GAME_OPTIONS_CURRENCY_EEK :エストニアクローン(EEK) -STR_GAME_OPTIONS_CURRENCY_LTL :リトアニアリタス (LTL) -STR_GAME_OPTIONS_CURRENCY_KRW :韓国ウォン (KRW) +STR_GAME_OPTIONS_CURRENCY_ATS :オーストリア・シリング(ATS) +STR_GAME_OPTIONS_CURRENCY_BEF :ベルギー・フラン(BEF) +STR_GAME_OPTIONS_CURRENCY_CHF :スイス・フラン(CHF) +STR_GAME_OPTIONS_CURRENCY_CZK :チェコ・コルナ(CZK) +STR_GAME_OPTIONS_CURRENCY_DEM :ドイツ・マルク(DEM) +STR_GAME_OPTIONS_CURRENCY_DKK :デンマーク・クローネ(DKK) +STR_GAME_OPTIONS_CURRENCY_ESP :スペイン・ペセタ(₧) +STR_GAME_OPTIONS_CURRENCY_FIM :フィンランド・マーカ(FIM) +STR_GAME_OPTIONS_CURRENCY_FRF :フランス・フラン(₣) +STR_GAME_OPTIONS_CURRENCY_GRD :ギリシャ・ドラクマ(₯) +STR_GAME_OPTIONS_CURRENCY_HUF :ハンガリー・フォリント(HUF) +STR_GAME_OPTIONS_CURRENCY_ISK :アイスランド・クローナ(ISK) +STR_GAME_OPTIONS_CURRENCY_ITL :イタリア・リラ(ITL) +STR_GAME_OPTIONS_CURRENCY_NLG :オランダ・ギルダー(ƒ) +STR_GAME_OPTIONS_CURRENCY_NOK :ノルウェー・クローネ(NOK) +STR_GAME_OPTIONS_CURRENCY_PLN :ポーランド・ズウォティ(PLN) +STR_GAME_OPTIONS_CURRENCY_RON :ルーマニア・レウ(RON) +STR_GAME_OPTIONS_CURRENCY_RUR :ロシア・ルーブル(₽) +STR_GAME_OPTIONS_CURRENCY_SIT :スロベニア・トラール(SIT) +STR_GAME_OPTIONS_CURRENCY_SEK :スウェーデン・クローナ(SEK) +STR_GAME_OPTIONS_CURRENCY_TRY :トルコ・リラ(₺) +STR_GAME_OPTIONS_CURRENCY_SKK :スロバキア・コルナ(SKK) +STR_GAME_OPTIONS_CURRENCY_BRL :ブラジル・レアル(R$) +STR_GAME_OPTIONS_CURRENCY_EEK :エストニア・クローン(EEK) +STR_GAME_OPTIONS_CURRENCY_LTL :リトアニア・リタス(LTL) +STR_GAME_OPTIONS_CURRENCY_KRW :韓国・ウォン(₩) STR_GAME_OPTIONS_CURRENCY_ZAR :南アフリカランド (ZAR) STR_GAME_OPTIONS_CURRENCY_CUSTOM :カスタム… -STR_GAME_OPTIONS_CURRENCY_GEL :グルジア ラリー(GEL) -STR_GAME_OPTIONS_CURRENCY_IRR :イラン リアル(IRR) +STR_GAME_OPTIONS_CURRENCY_GEL :グルジア・ラリー(GEL) +STR_GAME_OPTIONS_CURRENCY_IRR :イラン・リアル(IRR) STR_GAME_OPTIONS_CURRENCY_RUB :新ロシアルーブル(RUB) -STR_GAME_OPTIONS_CURRENCY_MXN :メキシコペソ(MXN) +STR_GAME_OPTIONS_CURRENCY_MXN :メキシコ・ペソ(MXN) STR_GAME_OPTIONS_CURRENCY_NTD :新台湾ドル(ntd) -STR_GAME_OPTIONS_CURRENCY_CNY :人民元(CNY) +STR_GAME_OPTIONS_CURRENCY_CNY :中国・人民元(CNY) STR_GAME_OPTIONS_CURRENCY_HKD :香港ドル(HKD) STR_GAME_OPTIONS_CURRENCY_INR :インドルピー(INR) -STR_GAME_OPTIONS_CURRENCY_IDR :インドネシアルピア(IDR) -STR_GAME_OPTIONS_CURRENCY_MYR :マレーシア・リンギット(MYR) +STR_GAME_OPTIONS_CURRENCY_IDR :インドネシア・ルピア(IDR) +STR_GAME_OPTIONS_CURRENCY_MYR :マレーシア・リンギット(MYR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :左側通行 @@ -1223,6 +1223,7 @@ STR_CONFIG_SETTING_AUTOSLOPE :建物/路線 STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :撤去を行わないで建物や路線がある土地の地形を変更することを可能にします。建物/路線は変更された地形に自動で追従します。 STR_CONFIG_SETTING_CATCHMENT :現実的な受入範囲: {STRING} STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :駅や空港の種類の違いによって受入範囲が変動するようになります +STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :会社の駅が中立の専用荷役所を持つ産業からサービスを受けられるようにする: {STRING} STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :有効にすると、駅が接続されている産業(石油掘削装置など)にも、近くに建設された会社が所有している駅がサービスを提供する場合があります。無効になっている場合、これらの産業は、接続されているステーションによってのみサービスを受けることができます。近くの会社のステーションはそれらにサービスを提供できず、接続されたステーションは業界以外のものにサービスを提供しません STR_CONFIG_SETTING_EXTRADYNAMITE :街有道路・橋・トンネルの撤去容認: {STRING} STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :街有の交通インフラや建物の撤去をより容易にします @@ -1485,7 +1486,7 @@ STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :線路の敷設 STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :信号が経路上に存在する場合線路設置の際にすべて自動的に除去されます。鉄道車両の衝突につながる危険性があります。 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :ゲーム進行速度の加速制限: {STRING} STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :早送りが有効になっている場合のゲーム進行速度を制限します。0 = 制限なし(コンピュータの許す限り高速にする)。100%より下げると進行速度が遅くなります。制限の上限はコンピュータの仕様によって異なり、ゲームの設定にも依存します。 -STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度 +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :通常の {NUM}% まで STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :制限なし(コンピューターが許す限り高速) STR_CONFIG_SETTING_SOUND_TICKER :ニュース表示: {STRING} @@ -2415,7 +2416,7 @@ STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}既設 STR_RAIL_NAME_RAILROAD :鉄道 (非電化) STR_RAIL_NAME_ELRAIL :電気鉄道 STR_RAIL_NAME_MONORAIL :モノレール -STR_RAIL_NAME_MAGLEV :マグレブ +STR_RAIL_NAME_MAGLEV :リニア # Rail depot construction window STR_BUILD_DEPOT_TRAIN_ORIENTATION_CAPTION :{WHITE}列車庫建設 @@ -2810,6 +2811,7 @@ STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}一秒 STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING} STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}一秒あたりに描写されるフレームの数。 STR_FRAMERATE_SPEED_FACTOR :{BLACK}現在のゲーム速度:{DECIMAL} x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}通常の速度に比べたゲーム進行速度の加速率 STR_FRAMERATE_CURRENT :{WHITE}現在 STR_FRAMERATE_AVERAGE :{WHITE}平均 STR_FRAMERATE_MEMORYUSE :{WHITE}メモリ @@ -4733,11 +4735,11 @@ STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Transport Tycoo STR_BASEGRAPHICS_WIN_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 グラフィック (Windows) STR_BASESOUNDS_DOS_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 効果音 (DOS) STR_BASESOUNDS_WIN_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 効果音 (Windows) -STR_BASESOUNDS_NONE_DESCRIPTION :空の効果音パック +STR_BASESOUNDS_NONE_DESCRIPTION :音源の含まれない効果音セット STR_BASEMUSIC_WIN_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 音楽 (Windows) STR_BASEMUSIC_DOS_DESCRIPTION :Transport Tycoon Deluxe オリジナル版 音楽 (DOS) STR_BASEMUSIC_TTO_DESCRIPTION :オリジナルトランスポートタイクーン(オリジナル/ワールドエディター)DOS版の音楽。 -STR_BASEMUSIC_NONE_DESCRIPTION :空の音楽パック +STR_BASEMUSIC_NONE_DESCRIPTION :音源の含まれない音楽セット ##id 0x2000 # Town building names From 4f7d6cf1baae8536c1d3a32a83f2291e04aec239 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 22 May 2021 19:12:46 +0000 Subject: [PATCH 215/800] Update: Translations from eints japanese: 4 changes by akaregi korean: 2 changes by telk5093 --- src/lang/japanese.txt | 8 ++++---- src/lang/korean.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index 03c7f3d0a1..412c4ba88c 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -4943,10 +4943,10 @@ STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_TOY_VAN :玩具車 STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_BATTERY_TRUCK :電池車 STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_FIZZY_DRINK_TRUCK :炭酸飲料車 STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_PLASTIC_TRUCK :プラスチック貨車 -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV1_LEVIATHAN_ELECTRIC :Lev1 Leviathan (電気) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 Cyclops (電気) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV3_PEGASUS_ELECTRIC :Lev3 Pegasus (電気) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV4_CHIMAERA_ELECTRIC :Lev4 Chimaera (電気) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV1_LEVIATHAN_ELECTRIC :Lev1 リヴァイアサン (リニア) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 サイクロプス (リニア) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV3_PEGASUS_ELECTRIC :Lev3 ペガサス (リニア) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV4_CHIMAERA_ELECTRIC :Lev4 キマイラ (リニア) STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_WIZZOWOW_ROCKETEER :ピューピュー社 ロケッター STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PASSENGER_CAR :客車 STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_MAIL_VAN :郵便車 diff --git a/src/lang/korean.txt b/src/lang/korean.txt index df83e50fcf..391f343574 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3047,8 +3047,8 @@ STR_NEWGRF_PARAMETERS_NUM_PARAM :{LTBLUE}매개 # NewGRF inspect window STR_NEWGRF_INSPECT_CAPTION :{WHITE}NEWGRF 검사 - {STRING} -STR_NEWGRF_INSPECT_PARENT_BUTTON :{BLACK}상위 단계 -STR_NEWGRF_INSPECT_PARENT_TOOLTIP :{BLACK}상위 단계 범위의 오브젝트를 검사합니다. +STR_NEWGRF_INSPECT_PARENT_BUTTON :{BLACK}상위 +STR_NEWGRF_INSPECT_PARENT_TOOLTIP :{BLACK}상위 단계 범위의 오브젝트를 검사합니다 STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT :{STRING}, {HEX}에서 STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT :오브젝트 From 97722931a976dc3e6603611b8ec48f10920960e4 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 19 May 2021 21:39:58 +0200 Subject: [PATCH 216/800] Fix: [OpenGL] Increase timeout when waiting for the GPU to be done with the drawing buffer. The old timeout could be too short if v-sync was on on lower refresh rates. --- src/video/opengl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index ecafeb6138..df0d12d072 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1150,7 +1150,7 @@ void OpenGLBackend::ClearCursorCache() void *OpenGLBackend::GetVideoBuffer() { #ifndef NO_GL_BUFFER_SYNC - if (this->sync_vid_mapping != nullptr) _glClientWaitSync(this->sync_vid_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 10000000); + if (this->sync_vid_mapping != nullptr) _glClientWaitSync(this->sync_vid_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 100000000); // 100ms timeout. #endif if (!this->persistent_mapping_supported) { @@ -1174,7 +1174,7 @@ uint8 *OpenGLBackend::GetAnimBuffer() if (this->anim_pbo == 0) return nullptr; #ifndef NO_GL_BUFFER_SYNC - if (this->sync_anim_mapping != nullptr) _glClientWaitSync(this->sync_anim_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 10000000); + if (this->sync_anim_mapping != nullptr) _glClientWaitSync(this->sync_anim_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 100000000); // 100ms timeout. #endif if (!this->persistent_mapping_supported) { From 33d99d27f4426e7d087b7ea3ed8e84d1059e1b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0efl?= Date: Sat, 15 May 2021 17:23:23 +0200 Subject: [PATCH 217/800] Fix: Encountering two-way red signals could prune unrelated branches. The intermediate node branch is now only pruned if the node is on the path leading to the two-way red signal. --- src/pathfinder/yapf/yapf_base.hpp | 9 ++++++--- src/pathfinder/yapf/yapf_costrail.hpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pathfinder/yapf/yapf_base.hpp b/src/pathfinder/yapf/yapf_base.hpp index b34e40a673..41c38ab34d 100644 --- a/src/pathfinder/yapf/yapf_base.hpp +++ b/src/pathfinder/yapf/yapf_base.hpp @@ -207,11 +207,14 @@ public: * remain the best intermediate node, and thus the vehicle would still * go towards the red EOL signal. */ - void PruneIntermediateNodeBranch() + void PruneIntermediateNodeBranch(Node *n) { - while (Yapf().m_pBestIntermediateNode != nullptr && (Yapf().m_pBestIntermediateNode->m_segment->m_end_segment_reason & ESRB_CHOICE_FOLLOWS) == 0) { - Yapf().m_pBestIntermediateNode = Yapf().m_pBestIntermediateNode->m_parent; + bool intermediate_on_branch = false; + while (n != nullptr && (n->m_segment->m_end_segment_reason & ESRB_CHOICE_FOLLOWS) == 0) { + if (n == Yapf().m_pBestIntermediateNode) intermediate_on_branch = true; + n = n->m_parent; } + if (intermediate_on_branch) Yapf().m_pBestIntermediateNode = n; } /** diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index b50300b618..908814c8cd 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -199,7 +199,7 @@ public: * was it first signal which is two-way? */ if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) { /* yes, the first signal is two-way red signal => DEAD END. Prune this branch... */ - Yapf().PruneIntermediateNodeBranch(); + Yapf().PruneIntermediateNodeBranch(&n); n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; Yapf().m_stopped_on_first_two_way_signal = true; return -1; From a896753ecc231b31464c71347a2e948a960a3547 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 15 May 2021 22:32:50 +0100 Subject: [PATCH 218/800] Fix #9264: Do not attach temporary wagons to free wagon chains when autoreplacing --- src/train_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index dc87827a75..3b16670948 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1178,7 +1178,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* if nothing is selected as destination, try and find a matching vehicle to drag to. */ Train *dst; if (d == INVALID_VEHICLE) { - dst = src->IsEngine() ? nullptr : FindGoodVehiclePos(src); + dst = (src->IsEngine() || (flags & DC_AUTOREPLACE)) ? nullptr : FindGoodVehiclePos(src); } else { dst = Train::GetIfValid(d); if (dst == nullptr) return CMD_ERROR; From 64be66216cb53a3272210e17ea49f6176b774ad3 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 23 May 2021 19:20:55 +0000 Subject: [PATCH 219/800] Update: Translations from eints chinese (traditional): 3 changes by benny30111 --- src/lang/traditional_chinese.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 7384d0a45b..d1464d983e 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -920,6 +920,7 @@ STR_GAME_OPTIONS_CURRENCY_ZAR :南非蘭特 (Z STR_GAME_OPTIONS_CURRENCY_CUSTOM :自訂... STR_GAME_OPTIONS_CURRENCY_GEL :喬治亞拉里 (GEL) STR_GAME_OPTIONS_CURRENCY_IRR :伊朗里亞爾 (IRR) +STR_GAME_OPTIONS_CURRENCY_HKD :港幣 (HKD) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :靠左行駛 @@ -2661,6 +2662,7 @@ STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}沒有 STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF:{WHITE}{STRING} STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}覆蓋檔案 +STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}你確定要覆蓋現有存檔嗎? STR_SAVELOAD_DIRECTORY :{STRING} (路徑) STR_SAVELOAD_OSKTITLE :{BLACK}為存檔輸入一個名稱 @@ -3224,6 +3226,7 @@ STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}將工 STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}產出等級:{YELLOW}{COMMA}% STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}該工業已宣佈關閉! +STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}需要: {YELLOW}{STRING}{STRING} STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :,{STRING}{STRING} From e99352a5d9dea15f3d405f0551fd1b828124fe62 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 22 May 2021 16:51:18 +0200 Subject: [PATCH 220/800] Change: Unhide Ctrl effect for group replace protection --- src/lang/english.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index f0ac1df382..f38a4e46c9 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3558,7 +3558,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Click to STR_GROUP_DELETE_TOOLTIP :{BLACK}Delete the selected group STR_GROUP_RENAME_TOOLTIP :{BLACK}Rename the selected group STR_GROUP_LIVERY_TOOLTIP :{BLACK}Change livery of the selected group -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Click to protect this group from global autoreplace +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Click to protect this group from global autoreplace. Ctrl+Click to also protect sub-groups. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Delete Group STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Are you sure you want to delete this group and any descendants? From 7c0762da65e1a568d686505ea5caad729cc659d5 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sun, 23 May 2021 16:23:33 +0200 Subject: [PATCH 221/800] Change: Show what is affected by "wagon removal" toggle --- src/autoreplace_gui.cpp | 19 ++++++++++++++++++- src/lang/english.txt | 3 ++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index e04eba302a..a4d7bcb7d4 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -379,11 +379,14 @@ public: const Group *g = Group::GetIfValid(this->sel_group); if (g != nullptr) { remove_wagon = HasBit(g->flags, GroupFlags::GF_REPLACE_WAGON_REMOVAL); + SetDParam(0, STR_GROUP_NAME); + SetDParam(1, sel_group); } else { const Company *c = Company::Get(_local_company); remove_wagon = c->settings.renew_keep_length; + SetDParam(0, STR_GROUP_DEFAULT_TRAINS + this->window_number); } - SetDParam(0, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); + SetDParam(2, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); break; } @@ -642,6 +645,20 @@ public: } } + bool OnTooltip(Point pt, int widget, TooltipCloseCondition close_cond) override + { + if (widget != WID_RV_TRAIN_WAGONREMOVE_TOGGLE) return false; + + if (Group::IsValidID(this->sel_group)) { + uint64 params[1]; + params[0] = STR_REPLACE_REMOVE_WAGON_HELP; + GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_GROUP_HELP, 1, params, close_cond); + } else { + GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_HELP, 0, nullptr, close_cond); + } + return true; + } + void OnResize() override { this->vscroll[0]->SetCapacityFromWidget(this, WID_RV_LEFT_MATRIX); diff --git a/src/lang/english.txt b/src/lang/english.txt index f38a4e46c9..db74c230bd 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3811,8 +3811,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles STR_REPLACE_ROAD_VEHICLES :Road Vehicles STR_REPLACE_TRAM_VEHICLES :Tramway Vehicles -STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal: {ORANGE}{STRING} +STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal ({STRING1}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing wagons (starting at the front), if replacing the engine would make the train longer +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+Click to also apply to sub-groups # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} From 36bcd2956a0354d4d051f4c6cef95698b3ab7327 Mon Sep 17 00:00:00 2001 From: milek7 Date: Thu, 20 May 2021 22:21:38 +0000 Subject: [PATCH 222/800] Fix: Building on Haiku --- CMakeLists.txt | 4 ++++ cmake/CompileFlags.cmake | 2 +- src/music/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6957c85c28..c8c6f040ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,10 @@ target_link_libraries(openttd Threads::Threads ) +if(HAIKU) + target_link_libraries(openttd "be" "network" "midi") +endif() + if(IPO_FOUND) set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE True) set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL True) diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index 2f7528fe3c..659a9ca724 100644 --- a/cmake/CompileFlags.cmake +++ b/cmake/CompileFlags.cmake @@ -158,7 +158,7 @@ macro(compile_flags) message(FATAL_ERROR "No warning flags are set for this compiler yet; please consider creating a Pull Request to add support for this compiler.") endif() - if(NOT WIN32) + if(NOT WIN32 AND NOT HAIKU) # rdynamic is used to get useful stack traces from crash reports. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") endif() diff --git a/src/music/CMakeLists.txt b/src/music/CMakeLists.txt index b20f8aaf7c..8f87a9c936 100644 --- a/src/music/CMakeLists.txt +++ b/src/music/CMakeLists.txt @@ -34,7 +34,7 @@ if(NOT OPTION_DEDICATED) add_files( bemidi.cpp bemidi.h - CONDITION OPTION_HAIKU + CONDITION HAIKU ) add_files( From 886f5c104a1853f1ece9e8ed834c6481dbcb550e Mon Sep 17 00:00:00 2001 From: milek7 Date: Thu, 20 May 2021 22:22:28 +0000 Subject: [PATCH 223/800] Fix: Workarounds for BeMidi driver to work properly on Haiku --- src/music/bemidi.cpp | 37 +++++++++++++++++++++++++------------ src/music/bemidi.h | 8 ++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/music/bemidi.cpp b/src/music/bemidi.cpp index 4175f526b0..3e4f5b311c 100644 --- a/src/music/bemidi.cpp +++ b/src/music/bemidi.cpp @@ -13,14 +13,8 @@ #include "../base_media_base.h" #include "midifile.hpp" -/* BeOS System Includes */ -#include - #include "../safeguards.h" -/** The file we're playing. */ -static BMidiSynthFile midiSynthFile; - /** Factory for BeOS' midi player. */ static FMusicDriver_BeMidi iFMusicDriver_BeMidi; @@ -31,7 +25,7 @@ const char *MusicDriver_BeMidi::Start(const StringList &parm) void MusicDriver_BeMidi::Stop() { - midiSynthFile.UnloadFile(); + this->StopSong(); } void MusicDriver_BeMidi::PlaySong(const MusicSongInfo &song) @@ -39,25 +33,44 @@ void MusicDriver_BeMidi::PlaySong(const MusicSongInfo &song) std::string filename = MidiFile::GetSMFFile(song); this->Stop(); + this->midi_synth_file = new BMidiSynthFile(); if (!filename.empty()) { entry_ref midiRef; get_ref_for_path(filename.c_str(), &midiRef); - midiSynthFile.LoadFile(&midiRef); - midiSynthFile.Start(); + if (this->midi_synth_file->LoadFile(&midiRef) == B_OK) { + this->midi_synth_file->SetVolume(this->current_volume); + this->midi_synth_file->Start(); + this->just_started = true; + } else { + this->Stop(); + } } } void MusicDriver_BeMidi::StopSong() { - midiSynthFile.UnloadFile(); + /* Reusing BMidiSynthFile can cause stuck notes when switching + * tracks, just delete whole object entirely. */ + delete this->midi_synth_file; + this->midi_synth_file = nullptr; } bool MusicDriver_BeMidi::IsSongPlaying() { - return !midiSynthFile.IsFinished(); + if (this->midi_synth_file == nullptr) return false; + + /* IsFinished() returns true for a moment after Start() + * but before it really starts playing, use just_started flag + * to prevent accidental track skipping. */ + if (this->just_started) { + if (!this->midi_synth_file->IsFinished()) this->just_started = false; + return true; + } + return !this->midi_synth_file->IsFinished(); } void MusicDriver_BeMidi::SetVolume(byte vol) { - fprintf(stderr, "BeMidi: Set volume not implemented\n"); + this->current_volume = vol / 128.0; + if (this->midi_synth_file != nullptr) this->midi_synth_file->SetVolume(this->current_volume); } diff --git a/src/music/bemidi.h b/src/music/bemidi.h index 8e96acc8d7..c4ab1f3599 100644 --- a/src/music/bemidi.h +++ b/src/music/bemidi.h @@ -12,6 +12,9 @@ #include "music_driver.hpp" +/* For BMidiSynthFile */ +#include + /** The midi player for BeOS. */ class MusicDriver_BeMidi : public MusicDriver { public: @@ -27,6 +30,11 @@ public: void SetVolume(byte vol) override; const char *GetName() const override { return "bemidi"; } + +private: + BMidiSynthFile *midi_synth_file = nullptr; + double current_volume = 1.0; + bool just_started = false; }; /** Factory for the BeOS midi player. */ From 760727738083e6b6a23eb913ca149a1f80bc1596 Mon Sep 17 00:00:00 2001 From: milek7 Date: Thu, 20 May 2021 23:34:50 +0000 Subject: [PATCH 224/800] Fix: Network on Haiku, remove old code for BeOS --- src/network/core/host.cpp | 67 +------------------------------ src/network/core/os_abstraction.h | 7 ++++ src/stdafx.h | 1 + 3 files changed, 9 insertions(+), 66 deletions(-) diff --git a/src/network/core/host.cpp b/src/network/core/host.cpp index 54a97aff01..4ff77a1414 100644 --- a/src/network/core/host.cpp +++ b/src/network/core/host.cpp @@ -20,72 +20,7 @@ */ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast); -#if defined(__HAIKU__) /* doesn't have neither getifaddrs or net/if.h */ -/* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */ -extern "C" int _netstat(int fd, char **output, int verbose); - -int seek_past_header(char **pos, const char *header) -{ - char *new_pos = strstr(*pos, header); - if (new_pos == 0) { - return B_ERROR; - } - *pos += strlen(header) + new_pos - *pos + 1; - return B_OK; -} - -static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // BEOS implementation -{ - int sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (sock < 0) { - DEBUG(net, 0, "Could not create socket: %s", NetworkError::GetLast().AsString()); - return; - } - - char *output_pointer = nullptr; - int output_length = _netstat(sock, &output_pointer, 1); - if (output_length < 0) { - DEBUG(net, 0, "Error running _netstat()"); - return; - } - - char **output = &output_pointer; - if (seek_past_header(output, "IP Interfaces:") == B_OK) { - for (;;) { - uint32 n; - int fields, read; - uint8 i1, i2, i3, i4, j1, j2, j3, j4; - uint32 ip; - uint32 netmask; - - fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n", - &n, &i1, &i2, &i3, &i4, &j1, &j2, &j3, &j4, &read); - read += 1; - if (fields != 9) { - break; - } - - ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4; - netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4; - - if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) { - sockaddr_storage address; - memset(&address, 0, sizeof(address)); - ((sockaddr_in*)&address)->sin_addr.s_addr = htonl(ip | ~netmask); - NetworkAddress addr(address, sizeof(sockaddr)); - if (std::none_of(broadcast->begin(), broadcast->end(), [&addr](NetworkAddress const& elem) -> bool { return elem == addr; })) broadcast->push_back(addr); - } - if (read < 0) { - break; - } - *output += read; - } - closesocket(sock); - } -} - -#elif defined(HAVE_GETIFADDRS) +#if defined(HAVE_GETIFADDRS) static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // GETIFADDRS implementation { struct ifaddrs *ifap, *ifa; diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index 55d7335017..8cf8202550 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -108,6 +108,13 @@ typedef unsigned long in_addr_t; # undef FD_SETSIZE # define FD_SETSIZE 64 # endif + +/* Haiku says it supports FD_SETSIZE fds, but it really only supports 512. */ +# if defined(__HAIKU__) +# undef FD_SETSIZE +# define FD_SETSIZE 512 +# endif + #endif /* UNIX */ /* OS/2 stuff */ diff --git a/src/stdafx.h b/src/stdafx.h index 319d94edf2..78188f8fa1 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -33,6 +33,7 @@ #if defined(__HAIKU__) # include # include +# define _DEFAULT_SOURCE # define _GNU_SOURCE # define TROUBLED_INTS #endif From 6b24cd2516ce4000d5e303c94e5e912102218d7e Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 24 May 2021 19:18:21 +0000 Subject: [PATCH 225/800] Update: Translations from eints swedish: 50 changes by joeax910 --- src/lang/afrikaans.txt | 1 - src/lang/arabic_egypt.txt | 1 - src/lang/basque.txt | 1 - src/lang/belarusian.txt | 1 - src/lang/brazilian_portuguese.txt | 1 - src/lang/bulgarian.txt | 1 - src/lang/catalan.txt | 1 - src/lang/croatian.txt | 1 - src/lang/czech.txt | 1 - src/lang/danish.txt | 1 - src/lang/dutch.txt | 1 - src/lang/english_AU.txt | 1 - src/lang/english_US.txt | 1 - src/lang/esperanto.txt | 1 - src/lang/estonian.txt | 1 - src/lang/faroese.txt | 1 - src/lang/finnish.txt | 1 - src/lang/french.txt | 1 - src/lang/gaelic.txt | 1 - src/lang/galician.txt | 1 - src/lang/german.txt | 1 - src/lang/greek.txt | 1 - src/lang/hebrew.txt | 1 - src/lang/hungarian.txt | 1 - src/lang/icelandic.txt | 1 - src/lang/indonesian.txt | 1 - src/lang/irish.txt | 1 - src/lang/italian.txt | 1 - src/lang/japanese.txt | 1 - src/lang/korean.txt | 1 - src/lang/latin.txt | 1 - src/lang/latvian.txt | 1 - src/lang/lithuanian.txt | 1 - src/lang/luxembourgish.txt | 1 - src/lang/malay.txt | 1 - src/lang/norwegian_bokmal.txt | 1 - src/lang/norwegian_nynorsk.txt | 1 - src/lang/polish.txt | 1 - src/lang/portuguese.txt | 1 - src/lang/romanian.txt | 1 - src/lang/russian.txt | 1 - src/lang/serbian.txt | 1 - src/lang/simplified_chinese.txt | 1 - src/lang/slovak.txt | 1 - src/lang/slovenian.txt | 1 - src/lang/spanish.txt | 1 - src/lang/spanish_MX.txt | 1 - src/lang/swedish.txt | 59 ++++++++++++++++++++++++++----- src/lang/tamil.txt | 1 - src/lang/thai.txt | 1 - src/lang/traditional_chinese.txt | 1 - src/lang/turkish.txt | 1 - src/lang/ukrainian.txt | 1 - src/lang/vietnamese.txt | 1 - src/lang/welsh.txt | 1 - 55 files changed, 50 insertions(+), 63 deletions(-) diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index 4390a75a0d..a3ef0aac4a 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -3617,7 +3617,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Voertuie STR_REPLACE_ROAD_VEHICLES :Padvoertuie STR_REPLACE_TRAM_VEHICLES :Tremweg voertuie -STR_REPLACE_REMOVE_WAGON :{BLACK}Wa verwydering: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Maak autovervanging die lengte van 'n trein dieselfde hou deur verwydering waens (deur voor te begin), indien die enjin vervanging die trein langer sal maak # Vehicle view diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index eb9abb14ea..f17f8c4084 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -3144,7 +3144,6 @@ STR_REPLACE_MAGLEV_VEHICLES :مركبات م STR_REPLACE_TRAM_VEHICLES :مركبات الترام -STR_REPLACE_REMOVE_WAGON :{BLACK} إزالة العربات: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK} المحافظة على طول القطار بازالة عربات ابتداء من المقدمة عند التبديل - عندما يكون التبدل ينتج قطارا اطول. # Vehicle view diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 4223e9f9cc..00570926f6 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -3372,7 +3372,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Tren magnetikoa STR_REPLACE_TRAM_VEHICLES :Tranbia ibilgailuak -STR_REPLACE_REMOVE_WAGON :{BLACK}Bagoiak ezabatu: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ordezkatze automatikoari agindu trenaren luzera errespetatzea, bagoiak ezabatuz luzera handitzen badute (trenaren hasierako bagoietik hasita) # Vehicle view diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 519a4bf547..4d6856f6a4 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -3945,7 +3945,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Маґнітн STR_REPLACE_ROAD_VEHICLES :Аўтатранспарт STR_REPLACE_TRAM_VEHICLES :Трамваі -STR_REPLACE_REMOVE_WAGON :{BLACK}Выдаленьне ваґонаў: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Дазволіць пры аўтазамене захоўваць даўжыню цягнікоў шляхам выдаленьня ваґонаў (пачынаючы з галавы цягніка), калі пры аўтазамене лякаматыва павялічыцца даўжыня цягніка. # Vehicle view diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 3cf4a64be0..386701dc15 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevs STR_REPLACE_ROAD_VEHICLES :Veículos terrestres STR_REPLACE_TRAM_VEHICLES :Bondes -STR_REPLACE_REMOVE_WAGON :{BLACK}Remoção de vagões: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Faz autosubstituição manter o tamanho do trem removendo vagões (começando pela frente), se ao substituir a locomotiva o trem ficar maior # Vehicle view diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 9ddda2dc28..533ca83adc 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -3447,7 +3447,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Монорел STR_REPLACE_MAGLEV_VEHICLES :Маглев влакове -STR_REPLACE_REMOVE_WAGON :{BLACK}Премахване на вагон: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Автоматичната замяна ще запази дължината на влака като премахне вагони (започвайки от предните), ако замяната довежда до по-дълъг влак. # Vehicle view diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 9c666cd112..45eb3a9951 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Trens maglev STR_REPLACE_ROAD_VEHICLES :Automòbils STR_REPLACE_TRAM_VEHICLES :Tramvies -STR_REPLACE_REMOVE_WAGON :{BLACK}Treure vagons: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fer que la substitució automàtica mantingui la llargada del tren eliminant vagons (començant pel front), si substituint la màquina el tren es fa més llarg # Vehicle view diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index ab7f63301a..1dbf6d265a 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -3748,7 +3748,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Željeznička v STR_REPLACE_ROAD_VEHICLES :Cestovna vozila STR_REPLACE_TRAM_VEHICLES :Tramvaji -STR_REPLACE_REMOVE_WAGON :{BLACK}Uklanjanje vagona: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automatska zamjena zadržava istu dužinu vlaka tako da ukloni suvišne vagone (počevši od naprijed), ako bi zamjena lokomotive učinila vlak dužim # Vehicle view diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 8650bf7f3c..96bcc65df5 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -3859,7 +3859,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Lokomotivy Magl STR_REPLACE_ROAD_VEHICLES :Silniční vozidla STR_REPLACE_TRAM_VEHICLES :Tramvaje -STR_REPLACE_REMOVE_WAGON :{BLACK}Odebírání vagonů: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Funkce automatického vylepšování vlaků může udržovat stejnou délku vlaku odstraňovaním vagonů (od začátku vlaku), pokud by změna mašiny vlak prodloužila # Vehicle view diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 8a34c16c57..f2b4987183 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -3660,7 +3660,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnetskinnetog STR_REPLACE_ROAD_VEHICLES :Vejkøretøjer STR_REPLACE_TRAM_VEHICLES :Sporvogne -STR_REPLACE_REMOVE_WAGON :{BLACK}Fjern vogn: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Få autoudskift til at bevare længden af tog ved at fjerne vogne (startende fra fronten), hvis autoudskiftningen gør toget længere. # Vehicle view diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index c1f03eab95..9798a97823 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -3811,7 +3811,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magneetzweefspo STR_REPLACE_ROAD_VEHICLES :Wegvoertuigen STR_REPLACE_TRAM_VEHICLES :Trams -STR_REPLACE_REMOVE_WAGON :{BLACK}Wagons verwijderen: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}De te vervangen trein behoudt zijn lengte door wagons weg te halen (startend aan de voorkant), als het vervangen de trein langer zou maken # Vehicle view diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index 085e982fa3..d645ee56e1 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -3425,7 +3425,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Monorail Vehicl STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles -STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing wagons (starting at the front), if replacing the engine would make the train longer # Vehicle view diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 4aebf0230f..2b5fd29afd 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -3811,7 +3811,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles STR_REPLACE_ROAD_VEHICLES :Road Vehicles STR_REPLACE_TRAM_VEHICLES :Streetcars -STR_REPLACE_REMOVE_WAGON :{BLACK}Car removal: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing cars (starting at the front), if replacing the engine would make the train longer # Vehicle view diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index 99473e3e4e..ae6d42ada0 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -2912,7 +2912,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Unurelaj Veturi STR_REPLACE_MAGLEV_VEHICLES :Maglevaj Veturiloj -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagonforigo: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ĉe aŭtomata anstataŭigo tenu saman longecon de la trajno per forigo de vagonoj (defronte), se per nova maŝino la trajno plilongiĝas # Vehicle view diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 04ca5f79da..b30da7c16d 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -3869,7 +3869,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnethõljukve STR_REPLACE_ROAD_VEHICLES :Maanteesõidukid STR_REPLACE_TRAM_VEHICLES :Trammid -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagunite kõrvaldamine: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automaatne asendamine hoiab rongi pikkuse samana, vajadusel kõrvaldab vaguneid (alates esiotsast), kui muidu rongikoosseis suureneks # Vehicle view diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index 5820f62ead..4508d9723f 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -3095,7 +3095,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Einsporaði jar STR_REPLACE_MAGLEV_VEHICLES :Maglev flutningstól -STR_REPLACE_REMOVE_WAGON :{BLACK}Vogn burturrudding: {ORANGE}{STRING} # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 99c5da4087..ace3ace672 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -3811,7 +3811,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev-junat STR_REPLACE_ROAD_VEHICLES :Ajoneuvot STR_REPLACE_TRAM_VEHICLES :Raitiovaunut -STR_REPLACE_REMOVE_WAGON :{BLACK}Vaunun poisto: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automaattikorvauksessa junapituus pidetään samana poistamalla vaunuja (edestä) jos veturi pidentäisi junaa # Vehicle view diff --git a/src/lang/french.txt b/src/lang/french.txt index 20f49c90f0..d63f6f164c 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Véhicules Magl STR_REPLACE_ROAD_VEHICLES :Véhicules routiers STR_REPLACE_TRAM_VEHICLES :Tramways -STR_REPLACE_REMOVE_WAGON :{BLACK}Retrait de wagon{NBSP}: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Si l'autoremplacement de la locomotive provoque un accroissement de la longueur du train, alors sa longueur initiale sera retrouvée en retirant automatiquement des wagons (d'abord par la tête) # Vehicle view diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index d6609eb0d6..1f8bdda035 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -3761,7 +3761,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Carbadan aona-r STR_REPLACE_MAGLEV_VEHICLES :Carbadan magnaiteach -STR_REPLACE_REMOVE_WAGON :{BLACK}A' toirt air falbh carbad: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Glèidh faide aig trèan nuair a thèid fhèin-leasachadh le toirt air falbh nan carbadan (bho thoiseach na trèan a-mach) ma dh'fhàsas an trèan nas fhaide le einnsean ùr # Vehicle view diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 864bcdb043..7d53f3328c 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -3640,7 +3640,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Vehículos magl STR_REPLACE_ROAD_VEHICLES :Vehículos de estrada STR_REPLACE_TRAM_VEHICLES :Tranvías -STR_REPLACE_REMOVE_WAGON :{BLACK}Eliminar os vagóns: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Facer que a autosubstitución manteña a lonxitude do tren quitando vagóns (empezando pola cabeza), se ao substituír a locomotora o tren se fixera máis longo. # Vehicle view diff --git a/src/lang/german.txt b/src/lang/german.txt index ae1255d25c..7751cae58e 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnetschwebeba STR_REPLACE_ROAD_VEHICLES :Straßenfahrzeuge STR_REPLACE_TRAM_VEHICLES :Straßenbahnfahrzeuge -STR_REPLACE_REMOVE_WAGON :{BLACK}Waggon-Entfernung: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ursprüngliche Länge des Zugs beibehalten, indem (vorne beginnend) Waggons entfernt werden, falls das Ersetzen der Lokomotive den Zug verlängern würde # Vehicle view diff --git a/src/lang/greek.txt b/src/lang/greek.txt index 15c9734628..9c42988eef 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -3771,7 +3771,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Οχήματα STR_REPLACE_TRAM_VEHICLES :Οχήματα τροχιοδρόμου -STR_REPLACE_REMOVE_WAGON :{BLACK}Αφαίρεση βαγονιού: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Υποχρεώνει την αυτόματη αντικατάσταση να διατηρεί σταθερό το μήκος του τρένου αφαιρώντας βαγόνια (ξεκινώντας από μπροστά), όταν η αντικατάσταση της μηχανής κάνει το τρένο μεγαλύτερο # Vehicle view diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index eee6f1e00f..9822890e8e 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -3539,7 +3539,6 @@ STR_REPLACE_MONORAIL_VEHICLES :רכבות חד STR_REPLACE_MAGLEV_VEHICLES :רכבות פס-מגנטי -STR_REPLACE_REMOVE_WAGON :{ORANGE}{STRING}{BLACK} : הסרת קרונות STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}שמור על האורך המקורי של הרכבת בעת שימוש בהחלפה אוטומטית, במידה והקטר מאריך את הרכבת הסר קרונות מתחילת הרכבת # Vehicle view diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index b34b36e94a..37eb09b1f4 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -3875,7 +3875,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Járműv STR_REPLACE_ROAD_VEHICLES :Közúti járművek STR_REPLACE_TRAM_VEHICLES :Villamosok -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagon törlés: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Az automatikus cserénél a szerelvény hosszának a megtartása vagonok eltávolításával (mozdony utántól kezdve), ha a csere után a szerelvény hosszabb lenne # Vehicle view diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index f22328c20f..43735cbc36 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -3254,7 +3254,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Einteinungsvagn STR_REPLACE_MAGLEV_VEHICLES :Segulsvifvagnar -STR_REPLACE_REMOVE_WAGON :{BLACK}Selja lestarvagna: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Heldur lengd lestar með því að fjarlægja vagna (framan frá), ef útskipting dráttarvagna myndi lengja hana # Vehicle view diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 0c669357e3..895775d2ca 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -3811,7 +3811,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Kereta Maglev STR_REPLACE_ROAD_VEHICLES :Kendaraan Jalan Raya STR_REPLACE_TRAM_VEHICLES :Kendaraan Jalan Trem -STR_REPLACE_REMOVE_WAGON :{BLACK}Membuang gerbong: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Membuat panjang kereta tetap sama saat penggantian secara otomatis dengan cara membuang gerbong(dihitung dari bagian depan), jika penggantian lokomotif membuat kereta lebih panjang # Vehicle view diff --git a/src/lang/irish.txt b/src/lang/irish.txt index da17c26811..562a258671 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -3468,7 +3468,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Feithiclí Aonr STR_REPLACE_MAGLEV_VEHICLES :Feithiclí Maglev -STR_REPLACE_REMOVE_WAGON :{BLACK}Vaigíní a bhaint: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ceangail ar uath-athsholáthar fad na traenach a choinneáil mar an gcéanna trí vaigíní a bhaint (ag tosú ag an tosach), má tharlaíonn sé go mbeadh an traein níos faide tar éis an t-inneall a athsholáthar. # Vehicle view diff --git a/src/lang/italian.txt b/src/lang/italian.txt index 8841f3e711..d1d635ae4a 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -3782,7 +3782,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Veicoli maglev STR_REPLACE_ROAD_VEHICLES :Veicoli stradali STR_REPLACE_TRAM_VEHICLES :Veicoli tranviari -STR_REPLACE_REMOVE_WAGON :{BLACK}Rimozione vagoni: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fa sì che il rimpiazzamento automatico mantenga costante la lunghezza dei treni rimuovendo vagoni (iniziando dalla testa) nel caso in cui la sostituzione della locomotiva rendesse il treno più lungo # Vehicle view diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index 412c4ba88c..c51e915f18 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -3811,7 +3811,6 @@ STR_REPLACE_MAGLEV_VEHICLES :リニア車両 STR_REPLACE_ROAD_VEHICLES :車両 STR_REPLACE_TRAM_VEHICLES :路面電車の車両 -STR_REPLACE_REMOVE_WAGON :{BLACK}列車の短縮: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}機関車の交換で列車長が長くなる場合、列車長を維持する為に客車/貨車を減らすことができます。外されるのは従属部分の先頭からになります # Vehicle view diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 391f343574..6b509c0a1e 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :자기부상 STR_REPLACE_ROAD_VEHICLES :자동차 STR_REPLACE_TRAM_VEHICLES :전차 차량 -STR_REPLACE_REMOVE_WAGON :{BLACK}화물차 제거: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}자동 교체시 열차의 길이가 교체 전보다 길어지면 객차/화차를 (앞쪽부터) 제거하여 열차의 전체 길이가 달라지지 않도록 합니다 # Vehicle view diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 4d7f6a2980..4322ae03b8 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -3756,7 +3756,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Vehicula Monoor STR_REPLACE_MAGLEV_VEHICLES :Vehicula Maglev -STR_REPLACE_REMOVE_WAGON :{BLACK}Ablatio curruum: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Facere ut automutatio longitudinem traminis contineat ablatione curruum (primo primorum), si tramen longius fiat mutatione hamaxae # Vehicle view diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index 5fbf0616c0..dbc16f5c16 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -3722,7 +3722,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magleva transpo STR_REPLACE_ROAD_VEHICLES :Autotransporta līdzekļi STR_REPLACE_TRAM_VEHICLES :Tramvaji -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagona noņemšana: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automātiskā aizvietošana saglabās esošo vilciena garumu noņemot vagonus (sākot no priekšgala), ja mainot lokomotīvi tas kļūtu garāks # Vehicle view diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index b90ee4e996..3df9612fb3 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -4020,7 +4020,6 @@ STR_REPLACE_MAGLEV_VEHICLES :„Maglev“ tr STR_REPLACE_ROAD_VEHICLES :Automobilius STR_REPLACE_TRAM_VEHICLES :Tramvajinės transporto priemonės -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagono pašalinimas: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Pakeitimo metu išlaikyti traukinio ilgį atjungiant vagonus (pradedant nuo priekio), jeigu pakeitus garvežį traukinys pailgėtų # Vehicle view diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index 1730014d4a..2d642a2cba 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -3763,7 +3763,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnéitbunn Ge STR_REPLACE_ROAD_VEHICLES :Stroossegefierer STR_REPLACE_TRAM_VEHICLES :Tram-Gefierer -STR_REPLACE_REMOVE_WAGON :{BLACK}Waggon raushuelen: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Mécht dass d'automatescht Austauschen d'Längt vum Zuch behält, an dem e Waggonen (vu lénks un) wechhëllt, wann d'Lok den Zuch ze laang mécht # Vehicle view diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 1507365150..96c4382319 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -3167,7 +3167,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Monorel Kendera STR_REPLACE_MAGLEV_VEHICLES :Kenderaan Maglev -STR_REPLACE_REMOVE_WAGON :{BLACK}Penghapusan wagon: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Membuat penukaran secara automatik menyimpan kepanjangan keretapi yang sama dengan mengeluarkan gerabak (bermula dari bahagian hadapan), sekiranya menyebabkan kereta api lebih panjang # Vehicle view diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 6fe947be63..5b675a667d 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -3815,7 +3815,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev-kjøret STR_REPLACE_ROAD_VEHICLES :Veikjøretøy STR_REPLACE_TRAM_VEHICLES :Trikkekjøretøy -STR_REPLACE_REMOVE_WAGON :{BLACK}Vognfjerning: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}La autoerstatningen beholde lengen på toget ved å fjerne vogner (fra første vogn), hvis utskiftningen gjør toget lengre. # Vehicle view diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index 515ffbed97..f1cef4c1fc 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -3388,7 +3388,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Monorail-køyre STR_REPLACE_MAGLEV_VEHICLES :Maglev-køyretøy -STR_REPLACE_REMOVE_WAGON :{BLACK}Vognfjerning: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Lat den automatiske utskiftinga behalde lengda på toget ved å fjerne vogner (frå første vogn), dersom utskiftinga gjer toget lenger. # Vehicle view diff --git a/src/lang/polish.txt b/src/lang/polish.txt index d6af6dc64d..2bf694bc02 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -4155,7 +4155,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Kolej Maglev STR_REPLACE_ROAD_VEHICLES :Pojazdy drogowe STR_REPLACE_TRAM_VEHICLES :Tramwaje -STR_REPLACE_REMOVE_WAGON :{BLACK}Usunięcie wagonów: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Autowymiana zachowuje długość pociągu poprzez usuwanie wagonów (począwszy od początku), jeśli wymiana lokomotywy spowoduje wydłużenie pociągu # Vehicle view diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 2e7f686ac2..60843a38dc 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevs STR_REPLACE_ROAD_VEHICLES :Veículos rodoviários STR_REPLACE_TRAM_VEHICLES :Elétricos -STR_REPLACE_REMOVE_WAGON :{BLACK}Remover vagões: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Forçar a substituição automática a manter o comprimento do comboio, removendo vagões (do início), nas situações em que a substituição da locomotiva pode resultar num comboio mais comprido. # Vehicle view diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index fe070471dc..87cfb6c7c9 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -3628,7 +3628,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Vehicule Pernă STR_REPLACE_ROAD_VEHICLES :Autovehicule STR_REPLACE_TRAM_VEHICLES :Tramvaie -STR_REPLACE_REMOVE_WAGON :{BLACK}Retragere vagoane: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fă optiunea de autoînlocuire să păstreze identică lungimea unui tren prin eliminarea vagoanelor (începând din faţă) dacă înlocuirea locomotivei ar face trenul mai lung # Vehicle view diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 49828c53e5..6695bacb61 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -3998,7 +3998,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Магнитн STR_REPLACE_ROAD_VEHICLES :Автотранспорт STR_REPLACE_TRAM_VEHICLES :Трамваи -STR_REPLACE_REMOVE_WAGON :{BLACK}Удаление вагонов: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Разрешить при автозамене сохранять длину поездов путём удаления вагонов (начиная с головы поезда), если при автозамене локомотива увеличится длина состава. # Vehicle view diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 5079e879b7..19c3d6e9fb 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -3974,7 +3974,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnetnošinska STR_REPLACE_ROAD_VEHICLES :Drumska vozila STR_REPLACE_TRAM_VEHICLES :Tramvajska vozila -STR_REPLACE_REMOVE_WAGON :{BLACK}Ukanjanje vagona: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ukoliko bi se zamenom kompozicija produžila, automatska obnova će ukloniti vagone (sa početka) kako bi se zadržala dužina kompozicije # Vehicle view diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 993736cc8f..ca97a96c4f 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -3768,7 +3768,6 @@ STR_REPLACE_MAGLEV_VEHICLES :磁悬浮列车 STR_REPLACE_ROAD_VEHICLES :路面交通工具 STR_REPLACE_TRAM_VEHICLES :电车 -STR_REPLACE_REMOVE_WAGON :{BLACK}清理挂车:{ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}当车辆升级可能造成列车变长时{}自动从最前面的挂车去掉若干节以保证列车长度不变 # Vehicle view diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 6eae8a010a..a7806930b9 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -3879,7 +3879,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Lokomotíva pre STR_REPLACE_ROAD_VEHICLES :Automobily STR_REPLACE_TRAM_VEHICLES :Električky -STR_REPLACE_REMOVE_WAGON :{BLACK}Odstránenie vagónu: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Zachovanie pôvodnej dĺžky vlaku, odstránením vagónov (odpredu), keď by funkcia automatickej zmeny rušňa vlak predĺžila # Vehicle view diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index c75a000e0b..885bcd3587 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -3625,7 +3625,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Enotirna vozila STR_REPLACE_MAGLEV_VEHICLES :Magnetna tirna vozila -STR_REPLACE_REMOVE_WAGON :{BLACK}Odstranitev vagonov: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Dovoli samozamenjavi, da z odstranitvijo vagonov, začenši na začetku, ohrani isto dolžino vlaka, če bi ga menjava lokomotive podaljšala # Vehicle view diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index e891400928..2513b7acdb 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Vehículos Magl STR_REPLACE_ROAD_VEHICLES :Vehículos de Carretera STR_REPLACE_TRAM_VEHICLES :Tranvías -STR_REPLACE_REMOVE_WAGON :{BLACK}Retirar vagones: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fuerza que el reemplazo automático mantenga la longitud del tren, quitando vagones (empezando por la parte delantera) si el reemplazo de vehículos produce un tren más largo # Vehicle view diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 6cae2f782f..4762f6f893 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Trenes maglev STR_REPLACE_ROAD_VEHICLES :Vehículos de carretera STR_REPLACE_TRAM_VEHICLES :Vehículos de tranvía -STR_REPLACE_REMOVE_WAGON :{BLACK}Quitar vagón: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Hacer que el reemplazo automático mantenga la longitud del tren quitando vagones (empezando por el frente), si el cambio de locomotora produce un tren más largo # Vehicle view diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index d28125b9b1..fd80799d34 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -953,7 +953,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk Ringg STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Kör på vänster sida STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Kör på höger sida -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Stadsnamn +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Stadsnamn: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Välj typ av stadsnamn ############ start of townname region @@ -993,6 +993,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Var 12:e månad STR_GAME_OPTIONS_LANGUAGE :{BLACK}Språk STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Välj vilket språk som ska användas +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% färdigt) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Helskärm STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Kryssa i den här rutan för att spela OpenTTD i helskärmsläge @@ -1990,6 +1991,8 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Örhänge: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ändra slips eller örhänge +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privat +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Offentlig # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Flera spelare @@ -2049,10 +2052,12 @@ STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}IP-adres STR_NETWORK_START_SERVER_CAPTION :{WHITE}Starta ett nytt spel i flerspelarläge STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Namn: -STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Namnet på nätverksspelet kommer att synas för andra spelare i multiplayer menyn +STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Namnet på nätverksspelet kommer att synas för andra spelare i flerspelarmenyn STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Bestäm lösenord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Skydda spelet med ett lösenord så att inte andra än dem som har lösenordet kan gå med i spelet +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Synlighet +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Huruvida andra människor kan se din server i den offentliga listan STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Max antal tillåtna klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Välj max antal tillåtna klienter. Alla platser måste inte fyllas. @@ -2116,11 +2121,43 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servern STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Företaget är skyddat. Ange lösenord # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klientlista +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelare online # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Flera spelare +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Namn +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Namnet på servern du spelar på +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Ändra din servers namn +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Serverns namn +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Synlighet +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Huruvida andra människor kan se din server i den offentliga listan +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Spelare +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Namn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ditt spelarnamn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Ändra ditt spelarnamn +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ditt spelarnamn +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrativa handlingar att utföra för denna klient +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrativa handlingar att utföra för detta företag +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Gå med i detta företag +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Skicka ett meddelande till denna spelare +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Skicka ett meddelande till alla spelare i detta företag +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Skicka ett meddelande till alla åskådare +STR_NETWORK_CLIENT_LIST_SPECTATORS :Åskådare +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt företag) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Skapa ett nytt företag och gå med i det +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Det här är du +STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Det här är spelets värd +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kasta ut +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannlys +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Ta bort +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Administratörshandling +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Är du säker på att du vill kasta ut spelaren '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Är du säker på att du vill bannlysa spelaren '{STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Är du säker på att du vill ta bort företaget {COMPANY}? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Är du säker på att du vill återställa företaget {COMPANY}s lösenord? STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient @@ -2165,7 +2202,8 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Kunde in STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kunde inte ansluta. STR_NETWORK_ERROR_TIMEOUT :{WHITE}Nätverkskoppling #{NUM} timeout STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ett protokollfel uppstod och anslutningen stängdes. -STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Servern har en annan version än denna klient. +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Du har inte angivit något spelarnamn. Namninställning kan göras högst upp i flerspelarfönstret +STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Servern har en annan version än denna klient STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Fel lösenord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Servern är full STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Du är bannlyst från den här servern @@ -2177,6 +2215,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Du tog f STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Din dator tog för lång tid på sig för att ansluta STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Du tog för lång tid på dig att ladda ner kartan STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Du tog för lång tid på dig att ansluta till servern +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Ditt spelarnamn är inte tillåtet +STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Servern som fick förfrågan är för gammal för denna klient ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :allmänt fel @@ -2199,6 +2239,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :inget lösenord STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :generell timeout STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :nedladdning av kartan tog för lång tid STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :bearbetning av kartan tog för lång tid +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :ogiltigt klientnamn ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Anslutningen har troligtvis försvunnit @@ -2227,7 +2268,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} ha STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} har gått med som åskådare STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} har startat ett nytt företag (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} har lämnat spelet ({2:STRING}) -STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} har ändrat hans/hennes namn till {STRING} +STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} har ändrat sitt namn till {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} gav {2:CURRENCY_LONG} till {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Servern avslutade sessionen STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Servern startar om...{}Var vänlig vänta... @@ -2487,7 +2528,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DEPOT_TOOLTIP :{BLACK}Bygg ske STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Bygg hamn. Ctrl aktiverar sammansättning av stationer. Shift växlar mellan att bygga/visa beräknad kostnad STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Placera en boj som kan som kan användas som riktmärke. Shift växlar mellan att bygga/visa beräknad kostnad STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Bygg akvedukt. Shift växlar mellan att bygga/visa beräknad kostnad -STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Definiera vattenyta.{}Skapa en kanal, om inte CTRL är nedhållen vid havsnivå, då den kommer att översvämma närliggande områden istället +STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Definiera vattenyta.{}Skapa en kanal, såvida inte Ctrl är nedtryckt vid havsnivå, då den istället kommer att översvämma närliggande områden STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Placera flod. Ctrl markerar ytan diagonalt # Ship depot construction window @@ -3037,7 +3078,8 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING STR_NEWGRF_ERROR_MSG_WARNING :{RED}Varning: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fel: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatalt: {SILVER}{STRING} -STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ett fatalt NewGRF fel har uppstått:{}{STRING} +STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ett fatalt NewGRF-fel har uppstått:{}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}Ett NewGRF-fel har uppstått:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} kommer inte att fungera med den TTDPatchversion som rapporterades av OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} är för {STRING}versionen av TTD STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} är designat för att användas med {STRING} @@ -3768,7 +3810,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevfordon STR_REPLACE_ROAD_VEHICLES :Vägfordon STR_REPLACE_TRAM_VEHICLES :Spårvägsfordon -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagnborttagning: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Gör så att automatiskt utbyte behåller ett tågs längd genom att ta bort vagnar (med början längst fram) om utbytandet av loket skulle göra tåget längre # Vehicle view @@ -4176,7 +4217,7 @@ STR_AI_DEBUG_CONTINUE :{BLACK}Fortsät STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Opausa och fortsätt datorspelaren STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Visa debug-utskrifter för denna datorspelare STR_AI_GAME_SCRIPT :{BLACK}Spelskript -STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Visa debug-utskrifter för spelskript +STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Visa felsökningsutskrifter för spelskript STR_ERROR_AI_NO_AI_FOUND :Ingen passande datorspelare hittades.{}Denna datorspelare är en test-datorspelare och kommer inte göra någonting.{}Du kan ladda ner nya datorspelare genom spelets 'Online-innehåll'-system STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}Ett av skripten som körs har kraschat. Vänligen rapportera detta till datorspelarens skapare med en skärmdump av förstret 'Felsökning av datorspelare / spelskript' diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index bfdd69caa2..d267768f00 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -3288,7 +3288,6 @@ STR_REPLACE_MAGLEV_VEHICLES :மேக்ல STR_REPLACE_ROAD_VEHICLES :சாலை வாகனங்கள் STR_REPLACE_TRAM_VEHICLES :அமிழ் தண்டூர்தி வாகனங்கள் -STR_REPLACE_REMOVE_WAGON :{BLACK}பெட்டி நீக்கம்: {ORANGE}{STRING} # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 9bc03a74b3..2cd77a140e 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -3392,7 +3392,6 @@ STR_REPLACE_MONORAIL_VEHICLES :ยานพา STR_REPLACE_MAGLEV_VEHICLES :รถไฟพลังงานแม่แหล็ก -STR_REPLACE_REMOVE_WAGON :{BLACK}ขายรถพ่วง: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}ทำให้การแทนที่ขบวนรถไฟทำให้ความยาวของขบวนยังเท่าเดิม # Vehicle view diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index d1464d983e..e70c5beb5a 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -3508,7 +3508,6 @@ STR_REPLACE_MONORAIL_VEHICLES :單軌列車 STR_REPLACE_MAGLEV_VEHICLES :磁浮列車 -STR_REPLACE_REMOVE_WAGON :{BLACK}移除車廂:{ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}如果替換後的車廂較長的話,讓自動替換功能移除多餘的車廂 (從頭開始) 以便維持列車長度 # Vehicle view diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index 76d30a7a6c..5bdb533ff2 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -3812,7 +3812,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Araçlar STR_REPLACE_ROAD_VEHICLES :Yol Araçları STR_REPLACE_TRAM_VEHICLES :Tramvay Araçları -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagon kaldırma: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Otomatik yenilemede tren boyutunun artması gerekiyorsa vagonları kaldır (en önden başlayarak yeterli sayıda vagon silinir) # Vehicle view diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index 4ce593db54..740fa37aa7 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -3894,7 +3894,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Магнітн STR_REPLACE_ROAD_VEHICLES :Авто STR_REPLACE_TRAM_VEHICLES :Трамвайні транспортні засоби -STR_REPLACE_REMOVE_WAGON :{BLACK}Ліквідація зайвих вагонів: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Дозволити автооновленню видаляти вагони, зберігаючи довжину потягу (починаючи спереду), якщо оновлення робить поїзд довшим # Vehicle view diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 389a8f4a19..0f60717951 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -3766,7 +3766,6 @@ STR_REPLACE_MAGLEV_VEHICLES :Đầu máy đ STR_REPLACE_ROAD_VEHICLES :Các xe ô-tô STR_REPLACE_TRAM_VEHICLES :Các xe điện -STR_REPLACE_REMOVE_WAGON :{BLACK}Xoá bỏ toa xe: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Tự động thay thế sẽ giữ nguyên độ dài đoàn tàu bằng cách bỏ bớt toa xe (bỏ từ phía đầu), nếu như việc thay thế đầu máy làm đoàn tàu dài hơn. # Vehicle view diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index cff7088277..c2ef7f65c9 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -3501,7 +3501,6 @@ STR_REPLACE_MONORAIL_VEHICLES :Cerbydau Monore STR_REPLACE_MAGLEV_VEHICLES :Cerbydau Maglef -STR_REPLACE_REMOVE_WAGON :{BLACK}Tynnu wagenni: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Gwneud i awtoddisodli gadw hyd y trên yr un peth drwy dynnu wagenni (gan ddechrau yn y blaen), os byddai newid yr injan yn gwneud y trên yn hirach # Vehicle view From c96945fa2b0487c7ccd5d7c14399e1b95e60c8c4 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 25 May 2021 19:16:10 +0000 Subject: [PATCH 226/800] Update: Translations from eints swedish: 27 changes by joeax910 spanish (mexican): 1 change by absay korean: 4 changes by telk5093 german: 3 changes by Wuzzy2 finnish: 3 changes by hpiirai french: 3 changes by glx22 portuguese: 3 changes by azulcosta --- src/lang/finnish.txt | 4 +++- src/lang/french.txt | 4 +++- src/lang/german.txt | 4 +++- src/lang/korean.txt | 6 +++-- src/lang/portuguese.txt | 4 +++- src/lang/spanish_MX.txt | 1 + src/lang/swedish.txt | 51 ++++++++++++++++++++++------------------- 7 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index ace3ace672..f18298b802 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -3558,7 +3558,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Luo ryhm STR_GROUP_DELETE_TOOLTIP :{BLACK}Poista valittu ryhmä STR_GROUP_RENAME_TOOLTIP :{BLACK}Nimeä valittu ryhmä STR_GROUP_LIVERY_TOOLTIP :{BLACK}Muuta valitun ryhmän väritystä -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Poista ryhmä automaattisesti korvattavien joukosta +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Napsauta suojataksesi tämä ryhmä yleiseltä automaattikorvaukselta. Ctrl+napsautus suojaa myös aliryhmät. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Poista ryhmä STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Haluatko varmasti poistaa tämän ryhmän ja sen alaryhmät? @@ -3811,7 +3811,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev-junat STR_REPLACE_ROAD_VEHICLES :Ajoneuvot STR_REPLACE_TRAM_VEHICLES :Raitiovaunut +STR_REPLACE_REMOVE_WAGON :{BLACK}Vaunun poisto ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automaattikorvauksessa junapituus pidetään samana poistamalla vaunuja (edestä) jos veturi pidentäisi junaa +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+napsautus kohdistaaksesi myös aliryhmiin. # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/french.txt b/src/lang/french.txt index d63f6f164c..5b766de94e 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Créer u STR_GROUP_DELETE_TOOLTIP :{BLACK}Supprimer le groupe sélectionné STR_GROUP_RENAME_TOOLTIP :{BLACK}Renommer le groupe sélectionné STR_GROUP_LIVERY_TOOLTIP :{BLACK}Changer la couleur du groupe sélectionné -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Cliquer pour protéger ce groupe contre l'auto-remplacement global +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Cliquer pour protéger ce groupe contre l'auto-remplacement global. Ctrl-clic pour protéger aussi les sous-groupes. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Supprimer un groupe STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Êtes-vous sûr de vouloir supprimer ce groupe et ses descendants{NBSP}? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Véhicules Magl STR_REPLACE_ROAD_VEHICLES :Véhicules routiers STR_REPLACE_TRAM_VEHICLES :Tramways +STR_REPLACE_REMOVE_WAGON :{BLACK}Retrait de wagon ({STRING}){NBSP}: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Si l'autoremplacement de la locomotive provoque un accroissement de la longueur du train, alors sa longueur initiale sera retrouvée en retirant automatiquement des wagons (d'abord par la tête) +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl-clic pour appliquer aussi aux sous-groupes # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/german.txt b/src/lang/german.txt index 7751cae58e..7088b47303 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Neue Gru STR_GROUP_DELETE_TOOLTIP :{BLACK}Ausgewählte Gruppe löschen STR_GROUP_RENAME_TOOLTIP :{BLACK}Ausgewählte Gruppe umbenennen STR_GROUP_LIVERY_TOOLTIP :{BLACK}Farbschema der ausgewählten Gruppe ändern -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Diese Gruppe von der automatischen Fahrzeugersetzung ausschließen +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klicken, um diese Gruppe vor der globalen Autoersetzung zu schützen. Strg+Klick, um außerdem Untergruppen zu schützen STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Gruppe löschen STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Sicher, dass diese Gruppe inklusive aller Untergruppen gelöscht werden soll? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Magnetschwebeba STR_REPLACE_ROAD_VEHICLES :Straßenfahrzeuge STR_REPLACE_TRAM_VEHICLES :Straßenbahnfahrzeuge +STR_REPLACE_REMOVE_WAGON :{BLACK}Waggon-Entfernung ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ursprüngliche Länge des Zugs beibehalten, indem (vorne beginnend) Waggons entfernt werden, falls das Ersetzen der Lokomotive den Zug verlängern würde +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Strg+Klick, um auch an Untergruppen anzuwenden # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 6b509c0a1e..c34def59aa 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3275,7 +3275,7 @@ STR_SUBSIDIES_CAPTION :{WHITE}보조 STR_SUBSIDIES_OFFERED_TITLE :{BLACK}지급 대기 중인 보조금: STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{1:STRING}에서 {2:STRING}까지 {0:STRING} 수송{YELLOW} ({3:DATE_SHORT}까지) STR_SUBSIDIES_NONE :{ORANGE}없음 -STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}이미 지급 중인 보조금: +STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}이미 지급된 보조금: STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{1:STRING}에서 {2:STRING}까지 {0:STRING} 수송{YELLOW} ({3:COMPANY}{YELLOW}, {DATE_SHORT}까지) STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}산업시설/도시의 위치로 시점을 변경하려면 클릭하세요. CTRL+클릭하면 이 산업시설/도시의 위치를 기준으로 새로운 외부 화면을 엽니다 @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}클릭 STR_GROUP_DELETE_TOOLTIP :{BLACK}선택한 그룹을 삭제합니다 STR_GROUP_RENAME_TOOLTIP :{BLACK}선택한 그룹의 이름을 바꿉니다 STR_GROUP_LIVERY_TOOLTIP :{BLACK}선택한 그룹의 차량 색상을 변경합니다 -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}클릭해서 전체 자동 교체로부터 이 그룹을 보호합니다 +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}클릭하면 전체 자동 교체로부터 이 그룹을 보호합니다. CTRL+클릭하면 하위 그룹도 보호합니다. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}그룹 삭제 STR_GROUP_DELETE_QUERY_TEXT :{WHITE}이 그룹과 하위 그룹을 정말 삭제하시겠습니까? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :자기부상 STR_REPLACE_ROAD_VEHICLES :자동차 STR_REPLACE_TRAM_VEHICLES :전차 차량 +STR_REPLACE_REMOVE_WAGON :{BLACK}화물차 제거 ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}자동 교체시 열차의 길이가 교체 전보다 길어지면 객차/화차를 (앞쪽부터) 제거하여 열차의 전체 길이가 달라지지 않도록 합니다 +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. CTRL+클릭하면 하위 그룹에도 적용됩니다 # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 60843a38dc..4bf74f6f32 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Clique p STR_GROUP_DELETE_TOOLTIP :{BLACK}Remover o grupo seleccionado STR_GROUP_RENAME_TOOLTIP :{BLACK}Mudar o nome do grupo seleccionado STR_GROUP_LIVERY_TOOLTIP :{BLACK}Alterar a imagem do grupo selecionado -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para proteger este grupo da autosubstituição global +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para proteger este grupo da auto-substituição global. Ctrl+Clique para proteger também sub-grupos. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Apagar Grupo STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Tem a certeza de que quer apagar este grupo e quaisquer descendentes? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevs STR_REPLACE_ROAD_VEHICLES :Veículos rodoviários STR_REPLACE_TRAM_VEHICLES :Elétricos +STR_REPLACE_REMOVE_WAGON :{BLACK}Remover vagões ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Forçar a substituição automática a manter o comprimento do comboio, removendo vagões (do início), nas situações em que a substituição da locomotiva pode resultar num comboio mais comprido. +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+Clique para aplicar também a sub-grupos # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 4762f6f893..310fa82d5e 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -3812,6 +3812,7 @@ STR_REPLACE_MAGLEV_VEHICLES :Trenes maglev STR_REPLACE_ROAD_VEHICLES :Vehículos de carretera STR_REPLACE_TRAM_VEHICLES :Vehículos de tranvía +STR_REPLACE_REMOVE_WAGON :{BLACK}Quitar vagó ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Hacer que el reemplazo automático mantenga la longitud del tren quitando vagones (empezando por el frente), si el cambio de locomotora produce un tren más largo # Vehicle view diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index fd80799d34..03ea486cb9 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -353,7 +353,7 @@ STR_TOOLBAR_TOOLTIP_BUILD_AIRPORTS :{BLACK}Bygg fly STR_TOOLBAR_TOOLTIP_LANDSCAPING :{BLACK}Öppna landskapsarkitektursverktygen för att höja/sänka land, plantera träd, etc. STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Visa ljud-/musikfönster STR_TOOLBAR_TOOLTIP_SHOW_LAST_MESSAGE_NEWS :{BLACK}Visa senaste meddelandet/nyheten, visa meddelandeinställningar -STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION :{BLACK}Markinformation, konsoll, skript-felsökning, skärmdumpar, om OpenTTD +STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION :{BLACK}Markinformation, konsol, felsökning av skript, skärmdumpar, om OpenTTD STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR :{BLACK}Byt verktygsrad # Extra tooltips for the scenario editor toolbar @@ -906,7 +906,7 @@ STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Valutaen STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Välj valutaenhet ############ start of currency region -STR_GAME_OPTIONS_CURRENCY_GBP :Brittisk pund (£) +STR_GAME_OPTIONS_CURRENCY_GBP :Brittiskt pund (£) STR_GAME_OPTIONS_CURRENCY_USD :Amerikansk dollar (USD) STR_GAME_OPTIONS_CURRENCY_EUR :Euro (EUR) STR_GAME_OPTIONS_CURRENCY_JPY :Japansk yen (¥) @@ -942,12 +942,12 @@ STR_GAME_OPTIONS_CURRENCY_GEL :Georgisk lari ( STR_GAME_OPTIONS_CURRENCY_IRR :Iransk rial (IRR) STR_GAME_OPTIONS_CURRENCY_RUB :Ny rysk rubel (RUB) STR_GAME_OPTIONS_CURRENCY_MXN :Mexikansk peso (MXN) -STR_GAME_OPTIONS_CURRENCY_NTD :Nya Taiwanesisk dollar (NTD) -STR_GAME_OPTIONS_CURRENCY_CNY :Kinesisk Renminbi (CNY) +STR_GAME_OPTIONS_CURRENCY_NTD :Ny taiwanesisk dollar (NTD) +STR_GAME_OPTIONS_CURRENCY_CNY :Kinesisk renminbi (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Hongkongdollar (HKD) STR_GAME_OPTIONS_CURRENCY_INR :Indisk rupie (INR) -STR_GAME_OPTIONS_CURRENCY_IDR :Indonesisk Rupiah (IDR) -STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk Ringgit (MYR) +STR_GAME_OPTIONS_CURRENCY_IDR :Indonesisk rupie (IDR) +STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk ringgit (MYR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Kör på vänster sida @@ -1055,9 +1055,9 @@ STR_ERROR_FULLSCREEN_FAILED :{WHITE}Fullskä STR_CURRENCY_WINDOW :{WHITE}Egen valuta STR_CURRENCY_EXCHANGE_RATE :{LTBLUE}Växlingskurs: {ORANGE}{CURRENCY_LONG} = £ {COMMA} -STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP :{BLACK}Minska värdet för din valuta med ett Pund (£) -STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP :{BLACK}Öka värdet för din valuta med ett Pund (£) -STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP :{BLACK}Sätt växelkursen för din valuta mot ett Pund (£) +STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP :{BLACK}Minska värdet för din valuta med ett pund (£) +STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP :{BLACK}Öka värdet för din valuta med ett pund (£) +STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP :{BLACK}Sätt växelkursen för din valuta mot ett pund (£) STR_CURRENCY_SEPARATOR :{LTBLUE}Avskiljare: {ORANGE}{STRING} STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP :{BLACK}Sätt separatorn för din valuta @@ -1074,7 +1074,7 @@ STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Byt till STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Byt till euron senare STR_CURRENCY_PREVIEW :{LTBLUE}Förhandsgranska: {ORANGE}{CURRENCY_LONG} -STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP :{BLACK}10000 Pund (£) i din valuta +STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP :{BLACK}10000 pund (£) i din valuta STR_CURRENCY_CHANGE_PARAMETER :{BLACK}Ändra valutaparametrar STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS :{LTBLUE}Max antal motståndare: {ORANGE}{COMMA} @@ -1317,7 +1317,7 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS :Flygplatser bli STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT :Aktivering av denna inställning gör så att alla flygplatstyper finns kvar i obegränsad tid efter att de blivit tillgängliga STR_CONFIG_SETTING_WARN_LOST_VEHICLE :Varna om fordon är vilse: {STRING} -STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Aktiverar meddelanden om fordon som är oförmögna att hitta vägen till deras destination. +STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Aktiverar meddelanden om fordon som är oförmögna att hitta vägen till sin destination. STR_CONFIG_SETTING_ORDER_REVIEW :Granska fordonens destinationer: {STRING} STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Om det är aktiverat så kontrolleras fordonens order periodiskt och när uppenbara problem identifieras rapporteras detta med ett nyhetsmeddelande STR_CONFIG_SETTING_ORDER_REVIEW_OFF :Nej @@ -2152,6 +2152,7 @@ STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Det här STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kasta ut STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannlys STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Ta bort +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Lås upp med lösenord STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Administratörshandling STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Är du säker på att du vill kasta ut spelaren '{STRING}'? @@ -2360,8 +2361,8 @@ STR_TRANSPARENT_INDUSTRIES_TOOLTIP :{BLACK}Växla g STR_TRANSPARENT_BUILDINGS_TOOLTIP :{BLACK}Växla genomskinlighet för byggnader såsom stationer, depåer och riktmärken. Ctrl+klick för att låsa STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Växla genomskinlighet för broar. Ctrl+klick för att låsa STR_TRANSPARENT_STRUCTURES_TOOLTIP :{BLACK}Växla genomskinlighet för byggnader såsom fyrar och antenner. Ctrl+klick för att låsa -STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Växla genomskinlighet för kontaktledning. CTRL+klick för att låsa -STR_TRANSPARENT_LOADING_TOOLTIP :{BLACK}Växla genomskinlighet för lastningsindikatörer. CTRL+klick för att låsa +STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Växla genomskinlighet för kontaktledning. Ctrl+klick för att låsa +STR_TRANSPARENT_LOADING_TOOLTIP :{BLACK}Växla genomskinlighet för lastningsindikatorer. Ctrl+klick för att låsa STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}Gör object osynliga istället för genomskinliga # Linkgraph legend window @@ -2632,7 +2633,7 @@ STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}Stor STR_FOUND_TOWN_SIZE_RANDOM :{BLACK}Slumpa STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Välj stadsstorlek STR_FOUND_TOWN_CITY :{BLACK}Stad -STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Stora städer växer snabbare än vanliga städer{}Beroende på inställningarna så är de större när de grundas +STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Storstäder växer snabbare än vanliga städer{}Beroende på inställningarna så är de större när de grundas STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Utformning av stadens vägnät: STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT :{BLACK}Välj vägnätets utformning för denna stad @@ -3400,7 +3401,7 @@ STR_FINANCES_LOAN_TITLE :{WHITE}Lån STR_FINANCES_MAX_LOAN :{WHITE}Maxlån: {BLACK}{CURRENCY_LONG} STR_FINANCES_TOTAL_CURRENCY :{BLACK}{CURRENCY_LONG} STR_FINANCES_BORROW_BUTTON :{BLACK}Låna {CURRENCY_LONG} -STR_FINANCES_BORROW_TOOLTIP :{BLACK}Öka lånets storlek. Ctrl + Klick lånar så mycket som möjligt +STR_FINANCES_BORROW_TOOLTIP :{BLACK}Öka lånets storlek. Ctrl+klick lånar så mycket som möjligt STR_FINANCES_REPAY_BUTTON :{BLACK}Återbetala {CURRENCY_LONG} STR_FINANCES_REPAY_TOOLTIP :{BLACK}Återbetala en del av lånet. Ctrl+klick återbetalar så mycket som är möjligt STR_FINANCES_INFRASTRUCTURE_BUTTON :{BLACK}Infrastruktur @@ -3557,7 +3558,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Klicka f STR_GROUP_DELETE_TOOLTIP :{BLACK}Ta bort vald grupp STR_GROUP_RENAME_TOOLTIP :{BLACK}Byt namn på vald grupp STR_GROUP_LIVERY_TOOLTIP :{BLACK}Byt färgschema på vald grupp -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klicka för att skydda denna grupp mot allmän autoreplace +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klicka för att skydda denna grupp mot allmän automatisk förnyelse. Ctrl+klicka för att också skydda undergrupper. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Ta bort grupp STR_GROUP_DELETE_QUERY_TEXT :{WHITE} Är du säker på att du vill ta bort denna grupp och alla efterkommande? @@ -3810,7 +3811,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevfordon STR_REPLACE_ROAD_VEHICLES :Vägfordon STR_REPLACE_TRAM_VEHICLES :Spårvägsfordon +STR_REPLACE_REMOVE_WAGON :{BLACK}Vagnborttagning ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Gör så att automatiskt utbyte behåller ett tågs längd genom att ta bort vagnar (med början längst fram) om utbytandet av loket skulle göra tåget längre +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+klicka för att också tillämpa det på undergrupper # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} @@ -3818,7 +3821,7 @@ STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Centrera huvudvyn på tågets position. Dubbelklicka för att följa tåget i huvudvyn. Ctrl+klicka öppnar ett nytt fönster över tågets position STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Centrera huvudvyn på fordonets position. Dubbelklicka för att följa fordonet i huvudvyn. Ctrl+klicka öppnar ett nytt fönster över fordonets position STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Centrera huvudvyn på fartygets position. Dubbelklicka för att följa fartyget i huvudvyn. Ctrl+klicka öppnar ett nytt fönster över fartygets position -STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Centrera huvudvyn på flyplanets position. Dubbelklicka för att följa flyplanet i huvudvyn. Ctrl+klicka öppnar ett nytt fönster över flygplanets position +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Centrera huvudvyn på flygplanets position. Dubbelklicka för att följa flygplanet i huvudvyn. Ctrl+klicka öppnar ett nytt fönster över flygplanets position STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Skicka tåg till depå. Ctrl+klick skickar tåget enbart på service STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Skicka fordon till depå. Ctrl+klick servar endast @@ -3855,7 +3858,7 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Aktuell STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Aktuell fartygsåtgärd - Tryck för att stoppa/starta fartyg STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Aktuell flygplansåtgärd - Tryck för att stoppa/starta flygplanet -STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Centrera huvudvyn på ordens destination. Ctrl+klick öppnar en ny vy över ordens destination +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Centrera huvudvyn på orderns destination. Ctrl+klick öppnar en ny vy över orderns destination # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Lastar / lastar av @@ -3864,7 +3867,7 @@ STR_VEHICLE_STATUS_CRASHED :{RED}Kraschad! STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Motorstopp STR_VEHICLE_STATUS_STOPPED :{RED}Stoppat STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL :{RED}Stannar, {VELOCITY} -STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}Ingen Kraft +STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}Ingen kraft STR_VEHICLE_STATUS_TRAIN_STUCK :{ORANGE}Väntar på ledig väg STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR :{ORANGE}Nästa destination ligger för långt bort @@ -4046,7 +4049,7 @@ STR_ORDER_CONDITIONAL_VALUE_TOOLTIP :{BLACK}Värde a STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Skriv in värde att jämföra mot STR_ORDERS_SKIP_BUTTON :{BLACK}Skippa -STR_ORDERS_SKIP_TOOLTIP :{BLACK}Hoppa över nuvarande order och starta nästa. CTRL + klick hoppar över till vald order +STR_ORDERS_SKIP_TOOLTIP :{BLACK}Hoppa över nuvarande order och starta nästa. Ctrl+klick hoppar över till vald order STR_ORDERS_DELETE_BUTTON :{BLACK}Ta bort STR_ORDERS_DELETE_TOOLTIP :{BLACK}Ta bort markerad order @@ -4153,7 +4156,7 @@ STR_TIMETABLE_DAYS :{COMMA}{NBSP}da STR_TIMETABLE_TICKS :{COMMA}{NBSP}tick STR_TIMETABLE_TOTAL_TIME :{BLACK}Den här tidtabellen kommer ta {STRING} att slutföra -STR_TIMETABLE_TOTAL_TIME_INCOMPLETE :{BLACK}Denna tidtabell kommer att ta åtminstonde {STRING} att slutföra (allt är inte inlagt i en tidtabell) +STR_TIMETABLE_TOTAL_TIME_INCOMPLETE :{BLACK}Denna tidtabell kommer att ta åtminstone {STRING} att slutföra (allt är inte inlagt i en tidtabell) STR_TIMETABLE_STATUS_ON_TIME :{BLACK}Detta fordon kör enligt tidtabellen STR_TIMETABLE_STATUS_LATE :{BLACK}Detta fordon är för tillfället {STRING} sen @@ -4819,7 +4822,7 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sockergruva ############ These strings may never get a new id, or savegames will break! ##id 0x6000 STR_SV_EMPTY : -STR_SV_UNNAMED :Inget namn +STR_SV_UNNAMED :Utan namn STR_SV_TRAIN_NAME :Tåg #{COMMA} STR_SV_ROAD_VEHICLE_NAME :Vägfordon #{COMMA} STR_SV_SHIP_NAME :Skepp #{COMMA} @@ -4834,10 +4837,10 @@ STR_SV_STNAME_CENTRAL :{STRING} centra STR_SV_STNAME_TRANSFER :{STRING} övergång STR_SV_STNAME_HALT :{STRING} hållplats STR_SV_STNAME_VALLEY :{STRING} dal -STR_SV_STNAME_HEIGHTS :{STRING} Höjder +STR_SV_STNAME_HEIGHTS :{STRING} höjder STR_SV_STNAME_WOODS :{STRING} skog STR_SV_STNAME_LAKESIDE :{STRING} sjöstrand -STR_SV_STNAME_EXCHANGE :{STRING} Växel +STR_SV_STNAME_EXCHANGE :{STRING} växel STR_SV_STNAME_AIRPORT :{STRING} flygplats STR_SV_STNAME_OILFIELD :{STRING} oljefält STR_SV_STNAME_MINES :{STRING} gruva From 3ce7e31f64d86b3ca58be61407a33380cda072b4 Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Mon, 24 May 2021 23:03:04 +0100 Subject: [PATCH 227/800] Feature: Sign Windows builds --- .github/workflows/release.yml | 32 ++++++++++++++++++++++++++++++++ cmake/InstallAndPackage.cmake | 7 +++++++ os/windows/sign.bat | 18 ++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 os/windows/sign.bat diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 894e9b9eb7..447b165f9c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -746,6 +746,21 @@ jobs: with: arch: ${{ matrix.host }} + - name: Import code signing certificate + shell: powershell + # If this is run on a fork, there may not be a certificate set up - continue in this case + continue-on-error: true + run: | + $tempFile = [System.IO.Path]::GetTempFileName() + $bytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_P12) + [IO.File]::WriteAllBytes($tempFile, $bytes) + $pwd = ConvertTo-SecureString $env:WINDOWS_CERTIFICATE_PASSWORD -AsPlainText -Force + Import-PfxCertificate -FilePath $tempFile -CertStoreLocation Cert:\CurrentUser\My -Password $pwd + Remove-Item $tempFile + env: + WINDOWS_CERTIFICATE_P12: ${{ secrets.WINDOWS_CERTIFICATE_P12 }} + WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} + - name: Build (with installer) if: needs.source.outputs.is_tag == 'true' shell: bash @@ -761,12 +776,15 @@ jobs: -DOPTION_USE_NSIS=ON \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ # EOF echo "::endgroup::" echo "::group::Build" cmake --build . echo "::endgroup::" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} - name: Build (without installer) if: needs.source.outputs.is_tag != 'true' @@ -782,12 +800,15 @@ jobs: -DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ # EOF echo "::endgroup::" echo "::group::Build" cmake --build . echo "::endgroup::" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} - name: Create bundles shell: bash @@ -809,6 +830,17 @@ jobs: rm -f bundles/*.sha256 echo "::endgroup::" + - name: Sign installer + if: needs.source.outputs.is_tag == 'true' + shell: bash + # If this is run on a fork, there may not be a certificate set up - continue in this case + continue-on-error: true + run: | + cd ${GITHUB_WORKSPACE}/build/bundles + ../../os/windows/sign.bat *.exe "${WINDOWS_CERTIFICATE_COMMON_NAME}" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} + - name: Store bundles uses: actions/upload-artifact@v2 with: diff --git a/cmake/InstallAndPackage.cmake b/cmake/InstallAndPackage.cmake index 9b7d657887..057f0934f8 100644 --- a/cmake/InstallAndPackage.cmake +++ b/cmake/InstallAndPackage.cmake @@ -138,6 +138,13 @@ elseif(WIN32) endif() set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-windows-${CPACK_SYSTEM_NAME}") + + if(WINDOWS_CERTIFICATE_COMMON_NAME) + add_custom_command(TARGET openttd + POST_BUILD + COMMAND "${CMAKE_SOURCE_DIR}/os/windows/sign.bat" "$" "${WINDOWS_CERTIFICATE_COMMON_NAME}" + ) + endif() elseif(UNIX) # With FHS, we can create deb/rpm/... Without it, they would be horribly broken # and not work. The other way around is also true; with FHS they are not diff --git a/os/windows/sign.bat b/os/windows/sign.bat new file mode 100644 index 0000000000..0e4291f9b8 --- /dev/null +++ b/os/windows/sign.bat @@ -0,0 +1,18 @@ +@echo off +REM Signing script +REM Arguments: sign.bat exe_to_sign certificate_subject_name + +REM This is a loose wrapper around the Microsoft signtool application (included in the Windows SDK). +REM See https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe for more details. + +REM Path to signtool.exe +IF NOT DEFINED SIGNTOOL_PATH (SET SIGNTOOL_PATH=signtool) + +REM URL of the timestamp server +IF NOT DEFINED SIGNTOOL_TIMESTAMP_URL (SET SIGNTOOL_TIMESTAMP_URL=http://timestamp.digicert.com) + +REM Sign with SHA-1 for Windows 7 and below +"%SIGNTOOL_PATH%" sign -v -n %2 -t %SIGNTOOL_TIMESTAMP_URL% %1 + +REM Sign with SHA-256 for Windows 8 and above +"%SIGNTOOL_PATH%" sign -v -n %2 -tr %SIGNTOOL_TIMESTAMP_URL% -fd sha256 -td sha256 -as %1 From 35dbd53682bd8e14fd0726480e47587b27a0d9ae Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 26 May 2021 19:32:03 +0000 Subject: [PATCH 228/800] Update: Translations from eints russian: 3 changes by Ln-Wolf slovak: 3 changes by FuryPapaya spanish: 3 changes by MontyMontana --- src/lang/russian.txt | 4 +++- src/lang/slovak.txt | 4 +++- src/lang/spanish.txt | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 6695bacb61..b9b5bc5fb6 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -3733,7 +3733,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Созд STR_GROUP_DELETE_TOOLTIP :{BLACK}Удалить выбранную группу STR_GROUP_RENAME_TOOLTIP :{BLACK}Переименовать выбранную группу STR_GROUP_LIVERY_TOOLTIP :{BLACK}Изменить цвет выбранной группы -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Защита транспорта в группе от глобальной автозамены +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Защита транспорта в группе от глобальной автозамены. Ctrl+щелчок - защита также и вложенных групп. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Удаление группы STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Удалить эту и все вложенные группы? @@ -3998,7 +3998,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Магнитн STR_REPLACE_ROAD_VEHICLES :Автотранспорт STR_REPLACE_TRAM_VEHICLES :Трамваи +STR_REPLACE_REMOVE_WAGON :{BLACK}Удаление вагонов ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Разрешить при автозамене сохранять длину поездов путём удаления вагонов (начиная с головы поезда), если при автозамене локомотива увеличится длина состава. +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}{}Ctrl+щелчок - применить также и к вложенным группам. # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index a7806930b9..f9eb2453b9 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -2311,7 +2311,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :spracovanie map STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :Neplatný názov klienta ############ End of leave-in-this-order -STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Možná ztráta pripojenia +STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Možná strata pripojenia STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION :{WHITE}Posledných {NUM} sekúnd nedorazili zo servera žiadne dáta # Network related errors @@ -3879,7 +3879,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Lokomotíva pre STR_REPLACE_ROAD_VEHICLES :Automobily STR_REPLACE_TRAM_VEHICLES :Električky +STR_REPLACE_REMOVE_WAGON :{BLACK}Odstránenie vagónu ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Zachovanie pôvodnej dĺžky vlaku, odstránením vagónov (odpredu), keď by funkcia automatickej zmeny rušňa vlak predĺžila +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+klik aplikuje aj na podskupiny # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 2513b7acdb..8bdbbe7a76 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Clica pa STR_GROUP_DELETE_TOOLTIP :{BLACK}Borra el grupo seleccionado STR_GROUP_RENAME_TOOLTIP :{BLACK}Renombra el grupo seleccionado STR_GROUP_LIVERY_TOOLTIP :{BLACK}Cambia el color del grupo seleccionado -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clic para proteger este grupo del auto reemplazado global +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clica para proteger este grupo del autorreemplazo global. Ctrl+clic protege también los subgrupos. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Borrar Grupo STR_GROUP_DELETE_QUERY_TEXT :{WHITE}¿Estás seguro de borrar este grupo y todos sus subgrupos? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Vehículos Magl STR_REPLACE_ROAD_VEHICLES :Vehículos de Carretera STR_REPLACE_TRAM_VEHICLES :Tranvías +STR_REPLACE_REMOVE_WAGON :{BLACK}Retirar vagones ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fuerza que el reemplazo automático mantenga la longitud del tren, quitando vagones (empezando por la parte delantera) si el reemplazo de vehículos produce un tren más largo +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+clic para aplicar también a subgrupos # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} From eaa3df1e8e3c9c6f6a22e95d0d4ed8ff251d4af9 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 20:49:22 +0200 Subject: [PATCH 229/800] Fix: part of a tile might not be marked dirty upon terraforming --- src/terraform_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index 0a1c6e857a..bc4df173db 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -310,7 +310,7 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Mark affected areas dirty. */ for (TileIndexSet::const_iterator it = ts.dirty_tiles.begin(); it != ts.dirty_tiles.end(); it++) { MarkTileDirtyByTile(*it); - TileIndexToHeightMap::const_iterator new_height = ts.tile_to_new_height.find(tile); + TileIndexToHeightMap::const_iterator new_height = ts.tile_to_new_height.find(*it); if (new_height == ts.tile_to_new_height.end()) continue; MarkTileDirtyByTile(*it, 0, new_height->second); } From b791ffc6de6dcc33739bb36bec4824dc44417961 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 20:51:17 +0200 Subject: [PATCH 230/800] Fix: do not hide parameter by local variable with the same name --- src/blitter/common.hpp | 56 ++++++++++++++++----------------- src/company_gui.cpp | 6 ++-- src/industry_gui.cpp | 12 +++---- src/network/network_content.cpp | 10 +++--- src/newgrf_station.cpp | 20 ++++++------ src/rail_cmd.cpp | 12 +++---- src/smallmap_gui.cpp | 4 +-- src/station_cmd.cpp | 12 +++---- src/terraform_cmd.cpp | 40 +++++++++++------------ src/town_cmd.cpp | 20 ++++++------ src/train_cmd.cpp | 2 +- src/tree_cmd.cpp | 32 +++++++++---------- src/viewport.cpp | 4 +-- src/water_cmd.cpp | 30 +++++++++--------- 14 files changed, 130 insertions(+), 130 deletions(-) diff --git a/src/blitter/common.hpp b/src/blitter/common.hpp index aaf63cd6a9..cd3b6276a4 100644 --- a/src/blitter/common.hpp +++ b/src/blitter/common.hpp @@ -16,14 +16,14 @@ #include template -void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel) +void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel) { int dy; int dx; int stepx; int stepy; - dy = (y2 - y) * 2; + dy = (y2 - y1) * 2; if (dy < 0) { dy = -dy; stepy = -1; @@ -31,7 +31,7 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in stepy = 1; } - dx = (x2 - x) * 2; + dx = (x2 - x1) * 2; if (dx < 0) { dx = -dx; stepx = -1; @@ -41,7 +41,7 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in if (dx == 0 && dy == 0) { /* The algorithm below cannot handle this special case; make it work at least for line width 1 */ - if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) set_pixel(x, y); + if (x1 >= 0 && x1 < screen_width && y1 >= 0 && y1 < screen_height) set_pixel(x1, y1); return; } @@ -67,14 +67,14 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in int dash_count = 0; if (dx > dy) { if (stepx < 0) { - std::swap(x, x2); - std::swap(y, y2); + std::swap(x1, x2); + std::swap(y1, y2); stepy = -stepy; } - if (x2 < 0 || x >= screen_width) return; + if (x2 < 0 || x1 >= screen_width) return; - int y_low = y; - int y_high = y; + int y_low = y1; + int y_high = y1; int frac_low = dy - frac_diff / 2; int frac_high = dy + frac_diff / 2; @@ -87,10 +87,10 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in y_high += stepy; } - if (x < 0) { - dash_count = (-x) % (dash + gap); + if (x1 < 0) { + dash_count = (-x1) % (dash + gap); auto adjust_frac = [&](int64 frac, int &y_bound) -> int { - frac -= ((int64) dy) * ((int64) x); + frac -= ((int64) dy) * ((int64) x1); if (frac >= 0) { int quotient = frac / dx; int remainder = frac % dx; @@ -101,17 +101,17 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in }; frac_low = adjust_frac(frac_low, y_low); frac_high = adjust_frac(frac_high, y_high); - x = 0; + x1 = 0; } x2++; if (x2 > screen_width) { x2 = screen_width; } - while (x != x2) { + while (x1 != x2) { if (dash_count < dash) { for (int y = y_low; y != y_high; y += stepy) { - if (y >= 0 && y < screen_height) set_pixel(x, y); + if (y >= 0 && y < screen_height) set_pixel(x1, y); } } if (frac_low >= 0) { @@ -122,21 +122,21 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in y_high += stepy; frac_high -= dx; } - x++; + x1++; frac_low += dy; frac_high += dy; if (++dash_count >= dash + gap) dash_count = 0; } } else { if (stepy < 0) { - std::swap(x, x2); - std::swap(y, y2); + std::swap(x1, x2); + std::swap(y1, y2); stepx = -stepx; } - if (y2 < 0 || y >= screen_height) return; + if (y2 < 0 || y1 >= screen_height) return; - int x_low = x; - int x_high = x; + int x_low = x1; + int x_high = x1; int frac_low = dx - frac_diff / 2; int frac_high = dx + frac_diff / 2; @@ -149,10 +149,10 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in x_high += stepx; } - if (y < 0) { - dash_count = (-y) % (dash + gap); + if (y1 < 0) { + dash_count = (-y1) % (dash + gap); auto adjust_frac = [&](int64 frac, int &x_bound) -> int { - frac -= ((int64) dx) * ((int64) y); + frac -= ((int64) dx) * ((int64) y1); if (frac >= 0) { int quotient = frac / dy; int remainder = frac % dy; @@ -163,17 +163,17 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in }; frac_low = adjust_frac(frac_low, x_low); frac_high = adjust_frac(frac_high, x_high); - y = 0; + y1 = 0; } y2++; if (y2 > screen_height) { y2 = screen_height; } - while (y != y2) { + while (y1 != y2) { if (dash_count < dash) { for (int x = x_low; x != x_high; x += stepx) { - if (x >= 0 && x < screen_width) set_pixel(x, y); + if (x >= 0 && x < screen_width) set_pixel(x, y1); } } if (frac_low >= 0) { @@ -184,7 +184,7 @@ void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, in x_high += stepx; frac_high -= dy; } - y++; + y1++; frac_low += dx; frac_high += dx; if (++dash_count >= dash + gap) dash_count = 0; diff --git a/src/company_gui.cpp b/src/company_gui.cpp index f9eceba177..a23bda7bd7 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -776,11 +776,11 @@ public: case WID_SCL_PRI_COL_DROPDOWN: { this->square = GetSpriteSize(SPR_SQUARE); - int padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10; + int string_padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10; for (const StringID *id = _colour_dropdown; id != endof(_colour_dropdown); id++) { - size->width = std::max(size->width, GetStringBoundingBox(*id).width + padding); + size->width = std::max(size->width, GetStringBoundingBox(*id).width + string_padding); } - size->width = std::max(size->width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + padding); + size->width = std::max(size->width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding); break; } } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index b1768af1f0..fd5f5d4872 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2700,14 +2700,14 @@ struct IndustryCargoesWindow : public Window { /** * Compute what and where to display for industry type \a it. - * @param it Industry type to display. + * @param displayed_it Industry type to display. */ - void ComputeIndustryDisplay(IndustryType it) + void ComputeIndustryDisplay(IndustryType displayed_it) { this->GetWidget(WID_IC_CAPTION)->widget_data = STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION; - this->ind_cargo = it; + this->ind_cargo = displayed_it; _displayed_industries.reset(); - _displayed_industries.set(it); + _displayed_industries.set(displayed_it); this->fields.clear(); CargoesRow &row = this->fields.emplace_back(); @@ -2717,7 +2717,7 @@ struct IndustryCargoesWindow : public Window { row.columns[3].MakeEmpty(CFT_SMALL_EMPTY); row.columns[4].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); - const IndustrySpec *central_sp = GetIndustrySpec(it); + const IndustrySpec *central_sp = GetIndustrySpec(displayed_it); bool houses_supply = HousesCanSupply(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)); bool houses_accept = HousesCanAccept(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)); /* Make a field consisting of two cargo columns. */ @@ -2734,7 +2734,7 @@ struct IndustryCargoesWindow : public Window { } /* Add central industry. */ int central_row = 1 + num_indrows / 2; - this->fields[central_row].columns[2].MakeIndustry(it); + this->fields[central_row].columns[2].MakeIndustry(displayed_it); this->fields[central_row].ConnectIndustryProduced(2); this->fields[central_row].ConnectIndustryAccepted(2); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 2b90cf4153..e09b05ec76 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -1010,9 +1010,9 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci) /* First check whether anything depends on us */ int sel_count = 0; bool force_selection = false; - for (const ContentInfo *ci : parents) { - if (ci->IsSelected()) sel_count++; - if (ci->state == ContentInfo::SELECTED) force_selection = true; + for (const ContentInfo *parent_ci : parents) { + if (parent_ci->IsSelected()) sel_count++; + if (parent_ci->state == ContentInfo::SELECTED) force_selection = true; } if (sel_count == 0) { /* Nothing depends on us */ @@ -1027,8 +1027,8 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci) this->ReverseLookupTreeDependency(parents, c); /* Is there anything that is "force" selected?, if so... we're done. */ - for (const ContentInfo *ci : parents) { - if (ci->state != ContentInfo::SELECTED) continue; + for (const ContentInfo *parent_ci : parents) { + if (parent_ci->state != ContentInfo::SELECTED) continue; force_selection = true; break; diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index fbc6f5c600..c66b53d3fc 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -550,16 +550,16 @@ uint32 StationResolverObject::GetDebugID() const /** * Resolver for stations. * @param statspec Station (type) specification. - * @param st Instance of the station. + * @param base_station Instance of the station. * @param tile %Tile of the station. * @param callback Callback ID. * @param callback_param1 First parameter (var 10) of the callback. * @param callback_param2 Second parameter (var 18) of the callback. */ -StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseStation *st, TileIndex tile, +StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseStation *base_station, TileIndex tile, CallbackID callback, uint32 callback_param1, uint32 callback_param2) : ResolverObject(statspec->grf_prop.grffile, callback, callback_param1, callback_param2), - station_scope(*this, statspec, st, tile), town_scope(nullptr) + station_scope(*this, statspec, base_station, tile), town_scope(nullptr) { /* Invalidate all cached vars */ _svc.valid = 0; @@ -921,7 +921,7 @@ void AnimateStationTile(TileIndex tile) StationAnimationBase::AnimateTile(ss, BaseStation::GetByTile(tile), tile, HasBit(ss->flags, SSF_CB141_RANDOM_BITS)); } -void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type) +void TriggerStationAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoID cargo_type) { /* List of coverage areas for each animation trigger */ static const TriggerArea tas[] = { @@ -929,14 +929,14 @@ void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTr }; /* Get Station if it wasn't supplied */ - if (st == nullptr) st = BaseStation::GetByTile(tile); + if (st == nullptr) st = BaseStation::GetByTile(trigger_tile); /* Check the cached animation trigger bitmask to see if we need * to bother with any further processing. */ if (!HasBit(st->cached_anim_triggers, trigger)) return; uint16 random_bits = Random(); - ETileArea area = ETileArea(st, tile, tas[trigger]); + ETileArea area = ETileArea(st, trigger_tile, tas[trigger]); /* Check all tiles over the station to check if the specindex is still in use */ for (TileIndex tile : area) { @@ -958,11 +958,11 @@ void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTr /** * Trigger station randomisation * @param st station being triggered - * @param tile specific tile of platform to trigger + * @param trigger_tile specific tile of platform to trigger * @param trigger trigger type * @param cargo_type cargo type causing trigger */ -void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type) +void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoID cargo_type) { /* List of coverage areas for each animation trigger */ static const TriggerArea tas[] = { @@ -970,7 +970,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg }; /* Get Station if it wasn't supplied */ - if (st == nullptr) st = Station::GetByTile(tile); + if (st == nullptr) st = Station::GetByTile(trigger_tile); /* Check the cached cargo trigger bitmask to see if we need * to bother with any further processing. */ @@ -978,7 +978,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg if (cargo_type != CT_INVALID && !HasBit(st->cached_cargo_triggers, cargo_type)) return; uint32 whole_reseed = 0; - ETileArea area = ETileArea(st, tile, tas[trigger]); + ETileArea area = ETileArea(st, trigger_tile, tas[trigger]); CargoTypes empty_mask = 0; if (trigger == SRT_CARGO_TAKEN) { diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 888b98e943..72ae0724c8 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1359,11 +1359,11 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin for (;;) { /* only build/remove signals with the specified density */ if (remove || minimise_gaps || signal_ctr % signal_density == 0) { - uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3); - SB(p1, 3, 1, mode); - SB(p1, 4, 1, semaphores); - SB(p1, 5, 3, sigtype); - if (!remove && signal_ctr == 0) SetBit(p1, 17); + uint32 param1 = GB(TrackdirToTrack(trackdir), 0, 3); + SB(param1, 3, 1, mode); + SB(param1, 4, 1, semaphores); + SB(param1, 5, 3, sigtype); + if (!remove && signal_ctr == 0) SetBit(param1, 17); /* Pick the correct orientation for the track direction */ signals = 0; @@ -1372,7 +1372,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin /* Test tiles in between for suitability as well if minimising gaps. */ bool test_only = !remove && minimise_gaps && signal_ctr < (last_used_ctr + signal_density); - CommandCost ret = DoCommand(tile, p1, signals, test_only ? flags & ~DC_EXEC : flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); + CommandCost ret = DoCommand(tile, param1, signals, test_only ? flags & ~DC_EXEC : flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); if (ret.Succeeded()) { /* Remember last track piece where we can place a signal. */ diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 17d1d25cb0..bc0a7b447d 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1436,8 +1436,8 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) case WID_SM_ZOOM_IN: case WID_SM_ZOOM_OUT: { const NWidgetBase *wid = this->GetWidget(WID_SM_MAP); - Point pt = { (int)wid->current_x / 2, (int)wid->current_y / 2}; - this->SetZoomLevel((widget == WID_SM_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt); + Point zoom_pt = { (int)wid->current_x / 2, (int)wid->current_y / 2}; + this->SetZoomLevel((widget == WID_SM_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &zoom_pt); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); break; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index d1e12604c9..d9529da11d 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -498,16 +498,16 @@ static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *c /** * Get the cargo types being produced around the tile (in a rectangle). - * @param tile Northtile of area + * @param north_tile Northern most tile of area * @param w X extent of the area * @param h Y extent of the area * @param rad Search radius in addition to the given area */ -CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) +CargoArray GetProductionAroundTiles(TileIndex north_tile, int w, int h, int rad) { CargoArray produced; std::set industries; - TileArea ta = TileArea(tile, w, h).Expand(rad); + TileArea ta = TileArea(north_tile, w, h).Expand(rad); /* Loop over all tiles to get the produced cargo of * everything except industries */ @@ -535,19 +535,19 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) /** * Get the acceptance of cargoes around the tile in 1/8. - * @param tile Center of the search area + * @param center_tile Center of the search area * @param w X extent of area * @param h Y extent of area * @param rad Search radius in addition to given area * @param always_accepted bitmask of cargo accepted by houses and headquarters; can be nullptr * @param ind Industry associated with neutral station (e.g. oil rig) or nullptr */ -CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted) +CargoArray GetAcceptanceAroundTiles(TileIndex center_tile, int w, int h, int rad, CargoTypes *always_accepted) { CargoArray acceptance; if (always_accepted != nullptr) *always_accepted = 0; - TileArea ta = TileArea(tile, w, h).Expand(rad); + TileArea ta = TileArea(center_tile, w, h).Expand(rad); for (TileIndex tile : ta) { /* Ignore industry if it has a neutral station. */ diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index bc4df173db..a23e02ab91 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -226,18 +226,18 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * Pass == 1: Collect the actual cost. */ for (int pass = 0; pass < 2; pass++) { for (TileIndexSet::const_iterator it = ts.dirty_tiles.begin(); it != ts.dirty_tiles.end(); it++) { - TileIndex tile = *it; + TileIndex t = *it; - assert(tile < MapSize()); + assert(t < MapSize()); /* MP_VOID tiles can be terraformed but as tunnels and bridges * cannot go under / over these tiles they don't need checking. */ - if (IsTileType(tile, MP_VOID)) continue; + if (IsTileType(t, MP_VOID)) continue; /* Find new heights of tile corners */ - int z_N = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0)); - int z_W = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0)); - int z_S = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1)); - int z_E = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1)); + int z_N = TerraformGetHeightOfTile(&ts, t + TileDiffXY(0, 0)); + int z_W = TerraformGetHeightOfTile(&ts, t + TileDiffXY(1, 0)); + int z_S = TerraformGetHeightOfTile(&ts, t + TileDiffXY(1, 1)); + int z_E = TerraformGetHeightOfTile(&ts, t + TileDiffXY(0, 1)); /* Find min and max height of tile */ int z_min = std::min({z_N, z_W, z_S, z_E}); @@ -252,31 +252,31 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (pass == 0) { /* Check if bridge would take damage */ - if (IsBridgeAbove(tile)) { - int bridge_height = GetBridgeHeight(GetSouthernBridgeEnd(tile)); + if (IsBridgeAbove(t)) { + int bridge_height = GetBridgeHeight(GetSouthernBridgeEnd(t)); /* Check if bridge would take damage. */ if (direction == 1 && bridge_height <= z_max) { - _terraform_err_tile = tile; // highlight the tile under the bridge + _terraform_err_tile = t; // highlight the tile under the bridge return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); } /* Is the bridge above not too high afterwards? */ if (direction == -1 && bridge_height > (z_min + _settings_game.construction.max_bridge_height)) { - _terraform_err_tile = tile; + _terraform_err_tile = t; return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND); } } /* Check if tunnel would take damage */ - if (direction == -1 && IsTunnelInWay(tile, z_min)) { - _terraform_err_tile = tile; // highlight the tile above the tunnel + if (direction == -1 && IsTunnelInWay(t, z_min)) { + _terraform_err_tile = t; // highlight the tile above the tunnel return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE); } } /* Is the tile already cleared? */ - const ClearedObjectArea *coa = FindClearedObject(tile); - bool indirectly_cleared = coa != nullptr && coa->first_tile != tile; + const ClearedObjectArea *coa = FindClearedObject(t); + bool indirectly_cleared = coa != nullptr && coa->first_tile != t; /* Check tiletype-specific things, and add extra-cost */ const bool curr_gen = _generating_world; @@ -288,13 +288,13 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin } CommandCost cost; if (indirectly_cleared) { - cost = DoCommand(tile, 0, 0, tile_flags, CMD_LANDSCAPE_CLEAR); + cost = DoCommand(t, 0, 0, tile_flags, CMD_LANDSCAPE_CLEAR); } else { - cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, tile_flags, z_min, tileh); + cost = _tile_type_procs[GetTileType(t)]->terraform_tile_proc(t, tile_flags, z_min, tileh); } _generating_world = curr_gen; if (cost.Failed()) { - _terraform_err_tile = tile; + _terraform_err_tile = t; return cost; } if (pass == 1) total_cost.AddCost(cost); @@ -318,10 +318,10 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* change the height */ for (TileIndexToHeightMap::const_iterator it = ts.tile_to_new_height.begin(); it != ts.tile_to_new_height.end(); it++) { - TileIndex tile = it->first; + TileIndex t = it->first; int height = it->second; - SetTileHeight(tile, (uint)height); + SetTileHeight(t, (uint)height); } if (c != nullptr) c->terraform_limit -= (uint32)ts.tile_to_new_height.size() << 16; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 033d042486..177b507e42 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2988,27 +2988,27 @@ CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * these do not directly have an owner so we need to check adjacent * tiles. This won't work correctly in the same loop if the adjacent * tile was already deleted earlier in the loop. */ - for (TileIndex tile = 0; tile < MapSize(); ++tile) { - if (IsTileType(tile, MP_TUNNELBRIDGE) && TestTownOwnsBridge(tile, t)) { - CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + for (TileIndex current_tile = 0; current_tile < MapSize(); ++current_tile) { + if (IsTileType(current_tile, MP_TUNNELBRIDGE) && TestTownOwnsBridge(current_tile, t)) { + CommandCost ret = DoCommand(current_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; } } /* Check all remaining tiles for town ownership. */ - for (TileIndex tile = 0; tile < MapSize(); ++tile) { + for (TileIndex current_tile = 0; current_tile < MapSize(); ++current_tile) { bool try_clear = false; - switch (GetTileType(tile)) { + switch (GetTileType(current_tile)) { case MP_ROAD: - try_clear = HasTownOwnedRoad(tile) && GetTownIndex(tile) == t->index; + try_clear = HasTownOwnedRoad(current_tile) && GetTownIndex(current_tile) == t->index; break; case MP_HOUSE: - try_clear = GetTownIndex(tile) == t->index; + try_clear = GetTownIndex(current_tile) == t->index; break; case MP_INDUSTRY: - try_clear = Industry::GetByTile(tile)->town == t; + try_clear = Industry::GetByTile(current_tile)->town == t; break; case MP_OBJECT: @@ -3016,7 +3016,7 @@ CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* No towns will be left, remove it! */ try_clear = true; } else { - Object *o = Object::GetByTile(tile); + Object *o = Object::GetByTile(current_tile); if (o->town == t) { if (o->type == OBJECT_STATUE) { /* Statue... always remove. */ @@ -3033,7 +3033,7 @@ CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 break; } if (try_clear) { - CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + CommandCost ret = DoCommand(current_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; } } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3b16670948..0a3a5db9ef 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1391,7 +1391,7 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint3 } CommandCost cost(EXPENSES_NEW_VEHICLES); - for (Train *t = sell_head; t != nullptr; t = t->Next()) cost.AddCost(-t->value); + for (Train *part = sell_head; part != nullptr; part = part->Next()) cost.AddCost(-part->value); /* do it? */ if (flags & DC_EXEC) { diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 9798c2bb56..baf149f5f1 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -392,11 +392,11 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16)); TileArea ta(tile, p2); - for (TileIndex tile : ta) { - switch (GetTileType(tile)) { + for (TileIndex current_tile : ta) { + switch (GetTileType(current_tile)) { case MP_TREES: /* no more space for trees? */ - if (GetTreeCount(tile) == 4) { + if (GetTreeCount(current_tile) == 4) { msg = STR_ERROR_TREE_ALREADY_HERE; continue; } @@ -408,8 +408,8 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 } if (flags & DC_EXEC) { - AddTreeCount(tile, 1); - MarkTileDirtyByTile(tile); + AddTreeCount(current_tile, 1); + MarkTileDirtyByTile(current_tile); if (c != nullptr) c->tree_limit -= 1 << 16; } /* 2x as expensive to add more trees to an existing tile */ @@ -417,14 +417,14 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 break; case MP_WATER: - if (!IsCoast(tile) || IsSlopeWithOneCornerRaised(GetTileSlope(tile))) { + if (!IsCoast(current_tile) || IsSlopeWithOneCornerRaised(GetTileSlope(current_tile))) { msg = STR_ERROR_CAN_T_BUILD_ON_WATER; continue; } FALLTHROUGH; case MP_CLEAR: { - if (IsBridgeAbove(tile)) { + if (IsBridgeAbove(current_tile)) { msg = STR_ERROR_SITE_UNSUITABLE; continue; } @@ -433,11 +433,11 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* Be a bit picky about which trees go where. */ if (_settings_game.game_creation.landscape == LT_TROPIC && treetype != TREE_INVALID && ( /* No cacti outside the desert */ - (treetype == TREE_CACTUS && GetTropicZone(tile) != TROPICZONE_DESERT) || + (treetype == TREE_CACTUS && GetTropicZone(current_tile) != TROPICZONE_DESERT) || /* No rain forest trees outside the rain forest, except in the editor mode where it makes those tiles rain forest tile */ - (IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(tile) != TROPICZONE_RAINFOREST && _game_mode != GM_EDITOR) || + (IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(current_tile) != TROPICZONE_RAINFOREST && _game_mode != GM_EDITOR) || /* And no subtropical trees in the desert/rain forest */ - (IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(tile) != TROPICZONE_NORMAL))) { + (IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(current_tile) != TROPICZONE_NORMAL))) { msg = STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE; continue; } @@ -453,7 +453,7 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 switch (GetRawClearGround(tile)) { case CLEAR_FIELDS: case CLEAR_ROCKS: { - CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + CommandCost ret = DoCommand(current_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); break; @@ -464,24 +464,24 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 } if (_game_mode != GM_EDITOR && Company::IsValidID(_current_company)) { - Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority); + Town *t = ClosestTownFromTile(current_tile, _settings_game.economy.dist_local_authority); if (t != nullptr) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM, flags); } if (flags & DC_EXEC) { if (treetype == TREE_INVALID) { - treetype = GetRandomTreeType(tile, GB(Random(), 24, 8)); + treetype = GetRandomTreeType(current_tile, GB(Random(), 24, 8)); if (treetype == TREE_INVALID) treetype = TREE_CACTUS; } /* Plant full grown trees in scenario editor */ - PlantTreesOnTile(tile, treetype, 0, _game_mode == GM_EDITOR ? 3 : 0); - MarkTileDirtyByTile(tile); + PlantTreesOnTile(current_tile, treetype, 0, _game_mode == GM_EDITOR ? 3 : 0); + MarkTileDirtyByTile(current_tile); if (c != nullptr) c->tree_limit -= 1 << 16; /* When planting rainforest-trees, set tropiczone to rainforest in editor. */ if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) { - SetTropicZone(tile, TROPICZONE_RAINFOREST); + SetTropicZone(current_tile, TROPICZONE_RAINFOREST); } } cost.AddCost(_price[PR_BUILD_TREES]); diff --git a/src/viewport.cpp b/src/viewport.cpp index 4344eac2a3..7217cbc451 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -245,8 +245,8 @@ void InitializeWindowViewport(Window *w, int x, int y, veh = Vehicle::Get(vp->follow_vehicle); pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); } else { - uint x = TileX(follow_flags) * TILE_SIZE; - uint y = TileY(follow_flags) * TILE_SIZE; + x = TileX(follow_flags) * TILE_SIZE; + y = TileY(follow_flags) * TILE_SIZE; vp->follow_vehicle = INVALID_VEHICLE; pt = MapXYZToViewport(vp, x, y, GetSlopePixelZ(x, y)); diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 8c8a438a58..dfbed60127 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -467,19 +467,19 @@ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 } for (; *iter != INVALID_TILE; ++(*iter)) { - TileIndex tile = *iter; + TileIndex current_tile = *iter; CommandCost ret; - Slope slope = GetTileSlope(tile); + Slope slope = GetTileSlope(current_tile); if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); } /* can't make water of water! */ - if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue; + if (IsTileType(current_tile, MP_WATER) && (!IsTileOwner(current_tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue; - bool water = IsWaterTile(tile); - ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR); + bool water = IsWaterTile(current_tile); + ret = DoCommand(current_tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; if (!water) cost.AddCost(ret); @@ -487,31 +487,31 @@ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (flags & DC_EXEC) { switch (wc) { case WATER_CLASS_RIVER: - MakeRiver(tile, Random()); + MakeRiver(current_tile, Random()); if (_game_mode == GM_EDITOR) { - TileIndex tile2 = tile; + TileIndex tile2 = current_tile; CircularTileSearch(&tile2, RIVER_OFFSET_DESERT_DISTANCE, RiverModifyDesertZone, nullptr); } break; case WATER_CLASS_SEA: - if (TileHeight(tile) == 0) { - MakeSea(tile); + if (TileHeight(current_tile) == 0) { + MakeSea(current_tile); break; } FALLTHROUGH; default: - MakeCanal(tile, _current_company, Random()); + MakeCanal(current_tile, _current_company, Random()); if (Company::IsValidID(_current_company)) { Company::Get(_current_company)->infrastructure.water++; DirtyCompanyInfrastructureWindows(_current_company); } break; } - MarkTileDirtyByTile(tile); - MarkCanalsAndRiversAroundDirty(tile); - CheckForDockingTile(tile); + MarkTileDirtyByTile(current_tile); + MarkCanalsAndRiversAroundDirty(current_tile); + CheckForDockingTile(current_tile); } cost.AddCost(_price[PR_BUILD_CANAL]); @@ -1044,8 +1044,8 @@ static void FloodVehicles(TileIndex tile) if (IsAirportTile(tile)) { const Station *st = Station::GetByTile(tile); - for (TileIndex tile : st->airport) { - if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc); + for (TileIndex airport_tile : st->airport) { + if (st->TileBelongsToAirport(airport_tile)) FindVehicleOnPos(airport_tile, &z, &FloodVehicleProc); } /* No vehicle could be flooded on this airport anymore */ From b9797a81c055c62c97d1838649466abd3a517a08 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 20:55:45 +0200 Subject: [PATCH 231/800] Codechange: pass large parameter by reference instead of value, especially in a recursive function --- src/core/kdtree.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/kdtree.hpp b/src/core/kdtree.hpp index 392e31b8ec..cb864e04d7 100644 --- a/src/core/kdtree.hpp +++ b/src/core/kdtree.hpp @@ -274,7 +274,7 @@ class Kdtree { } template - void FindContainedRecursive(CoordT p1[2], CoordT p2[2], size_t node_idx, int level, Outputter outputter) const + void FindContainedRecursive(CoordT p1[2], CoordT p2[2], size_t node_idx, int level, const Outputter &outputter) const { /* Dimension index of current level */ int dim = level % 2; @@ -458,7 +458,7 @@ public: * @param outputter Callback used to return values from the search. */ template - void FindContained(CoordT x1, CoordT y1, CoordT x2, CoordT y2, Outputter outputter) const + void FindContained(CoordT x1, CoordT y1, CoordT x2, CoordT y2, const Outputter &outputter) const { assert(x1 < x2); assert(y1 < y2); From b280f163168f6c1036d7a3b0dee552ac68abddf4 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 21:27:28 +0200 Subject: [PATCH 232/800] Codechange: remove unneeded comparison and casts Division by resize_y is already yielding an unsigned number, so when clicking in the WD_FRAMERECT_TOP you would already get a huge value, so sel would never be negative. So, leave sel an unsigned number and remove the <= check. --- src/order_gui.cpp | 6 +++--- src/timetable_gui.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index bd11656220..8504ee16f1 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -548,13 +548,13 @@ private: VehicleOrderID GetOrderFromPt(int y) { NWidgetBase *nwid = this->GetWidget(WID_O_ORDER_LIST); - int sel = (y - nwid->pos_y - WD_FRAMERECT_TOP) / nwid->resize_y; // Selected line in the WID_O_ORDER_LIST panel. + uint sel = (y - nwid->pos_y - WD_FRAMERECT_TOP) / nwid->resize_y; // Selected line in the WID_O_ORDER_LIST panel. - if ((uint)sel >= this->vscroll->GetCapacity()) return INVALID_VEH_ORDER_ID; + if (sel >= this->vscroll->GetCapacity()) return INVALID_VEH_ORDER_ID; sel += this->vscroll->GetPosition(); - return (sel <= vehicle->GetNumOrders() && sel >= 0) ? sel : INVALID_VEH_ORDER_ID; + return (sel <= vehicle->GetNumOrders()) ? sel : INVALID_VEH_ORDER_ID; } /** diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index af90adc448..fa0e4d114f 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -211,13 +211,13 @@ struct TimetableWindow : Window { int GetOrderFromTimetableWndPt(int y, const Vehicle *v) { - int sel = (y - this->GetWidget(WID_VT_TIMETABLE_PANEL)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; + uint sel = (y - this->GetWidget(WID_VT_TIMETABLE_PANEL)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; - if ((uint)sel >= this->vscroll->GetCapacity()) return INVALID_ORDER; + if (sel >= this->vscroll->GetCapacity()) return INVALID_ORDER; sel += this->vscroll->GetPosition(); - return (sel < v->GetNumOrders() * 2 && sel >= 0) ? sel : INVALID_ORDER; + return (sel < v->GetNumOrders() * 2u) ? sel : INVALID_ORDER; } /** From ed9e38221a63133abd9caa97d1eff51a05deb4c2 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 21:28:13 +0200 Subject: [PATCH 233/800] Cleanup: remove dead code; ++ on ostreambuf_iterator is a no-op --- src/newgrf_text.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index fcbca12b69..f1fac8b510 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -398,7 +398,6 @@ std::string TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_n int index = (code == 0x10 ? *src++ : 0); if (mapping->strings.find(index) != mapping->strings.end()) { grfmsg(1, "duplicate choice list string, ignoring"); - d++; } else { d = std::ostreambuf_iterator(mapping->strings[index]); } From 6fe4d4ad7b055393ed04d11c58bc330c539aa31e Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 21:32:43 +0200 Subject: [PATCH 234/800] Codechange: linkgraph always iterates with NodeIDs over the Size(), so make Size() the same type to prevent infinite loops --- src/linkgraph/linkgraph.h | 2 +- src/linkgraph/linkgraphjob.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index 4f44db8276..32f94a3c8c 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -495,7 +495,7 @@ public: * Get the current size of the component. * @return Size. */ - inline uint16 Size() const { return (uint16)this->nodes.size(); } + inline NodeID Size() const { return (NodeID)this->nodes.size(); } /** * Get date of last compression. diff --git a/src/linkgraph/linkgraphjob.h b/src/linkgraph/linkgraphjob.h index 4913b5a357..f434fa8097 100644 --- a/src/linkgraph/linkgraphjob.h +++ b/src/linkgraph/linkgraphjob.h @@ -332,7 +332,7 @@ public: * Get the size of the underlying link graph. * @return Size. */ - inline uint Size() const { return this->link_graph.Size(); } + inline NodeID Size() const { return this->link_graph.Size(); } /** * Get the cargo of the underlying link graph. From 9197de39e4bf4c17ba6da82c2ed1b858603a443a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 21:47:13 +0200 Subject: [PATCH 235/800] Cleanup: remove unused copy-constructor without copy-assignment --- src/misc/dbg_helpers.h | 6 ------ src/pathfinder/yapf/yapf_node_rail.hpp | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/misc/dbg_helpers.h b/src/misc/dbg_helpers.h index f9d251b8a9..53033110d8 100644 --- a/src/misc/dbg_helpers.h +++ b/src/misc/dbg_helpers.h @@ -106,12 +106,6 @@ struct DumpTarget { , m_ptr(ptr) {} - KnownStructKey(const KnownStructKey &src) - { - m_type_id = src.m_type_id; - m_ptr = src.m_ptr; - } - bool operator<(const KnownStructKey &other) const { if ((size_t)m_ptr < (size_t)other.m_ptr) return true; diff --git a/src/pathfinder/yapf/yapf_node_rail.hpp b/src/pathfinder/yapf/yapf_node_rail.hpp index df369fcdd7..9d33ab7a7a 100644 --- a/src/pathfinder/yapf/yapf_node_rail.hpp +++ b/src/pathfinder/yapf/yapf_node_rail.hpp @@ -15,8 +15,6 @@ struct CYapfRailSegmentKey { uint32 m_value; - inline CYapfRailSegmentKey(const CYapfRailSegmentKey &src) : m_value(src.m_value) {} - inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir &node_key) { Set(node_key); From db54e208256958f721bf74bf058b45039be5b488 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 26 May 2021 21:48:28 +0200 Subject: [PATCH 236/800] Change: mark copy-assignment as deleted for classes with a copy-constructor that is not trivial This to prevent the default copy-assignment getting used when during the assignment also some other memory needs to be allocated as that would otherwise be freed. --- src/error.h | 3 +++ src/newgrf_config.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/error.h b/src/error.h index 6dd4b02342..9c445fc48e 100644 --- a/src/error.h +++ b/src/error.h @@ -44,6 +44,9 @@ public: ~ErrorMessageData(); ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration = 0, int x = 0, int y = 0, const GRFFile *textref_stack_grffile = nullptr, uint textref_stack_size = 0, const uint32 *textref_stack = nullptr); + /* Remove the copy assignment, as the default implementation will not do the right thing. */ + ErrorMessageData &operator=(ErrorMessageData &rhs) = delete; + /** Check whether error window shall display a company manager face */ bool HasFace() const { return face != INVALID_COMPANY; } diff --git a/src/newgrf_config.h b/src/newgrf_config.h index ef71289052..1588f8c3ab 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -113,6 +113,9 @@ struct GRFError { GRFError(StringID severity, StringID message = 0); GRFError(const GRFError &error); + /* Remove the copy assignment, as the default implementation will not do the right thing. */ + GRFError &operator=(GRFError &rhs) = delete; + std::string custom_message; ///< Custom message (if present) std::string data; ///< Additional data for message and custom_message StringID message; ///< Default message @@ -154,6 +157,9 @@ struct GRFConfig : ZeroedMemoryAllocator { GRFConfig(const GRFConfig &config); ~GRFConfig(); + /* Remove the copy assignment, as the default implementation will not do the right thing. */ + GRFConfig &operator=(GRFConfig &rhs) = delete; + GRFIdentifier ident; ///< grfid and md5sum to uniquely identify newgrfs uint8 original_md5sum[16]; ///< MD5 checksum of original file if only a 'compatible' file was loaded char *filename; ///< Filename - either with or without full path From 91b3d697c506473deb47d70a31de5d5a7a063483 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 10:47:12 +0200 Subject: [PATCH 237/800] Codechange: make SettingDesc an instance in the setting table to allow for sub classes --- src/settings.cpp | 92 ++++++++++++++++++++--------------- src/settings_internal.h | 7 +-- src/table/settings.h.preamble | 12 ++--- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 15d90f312b..2c7d3aefe8 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -100,7 +100,7 @@ static bool IsSignedVarMemType(VarType vt); const SettingDesc *GetSettingDescription(uint index) { if (index >= _settings.size()) return nullptr; - return &_settings.begin()[index]; + return _settings.begin()[index].get(); } /** @@ -111,7 +111,7 @@ const SettingDesc *GetSettingDescription(uint index) static const SettingDesc *GetCompanySettingDescription(uint index) { if (index >= _company_settings.size()) return nullptr; - return &_company_settings.begin()[index]; + return _company_settings.begin()[index].get(); } /** @@ -563,11 +563,11 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co IniGroup *group_def = ini->GetGroup(grpname); for (auto &sd : settings_table) { - const SettingDesc *sdb = &sd; - const SaveLoad *sld = &sd.save; + const SettingDesc *sdb = sd.get(); + const SaveLoad *sld = &sd->save; if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; - if (sd.startup != only_startup) continue; + if (sd->startup != only_startup) continue; /* For settings.xx.yy load the settings from [xx] yy = ? */ std::string s{ sdb->name }; @@ -600,11 +600,11 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co case SDT_NUMX: case SDT_ONEOFMANY: case SDT_MANYOFMANY: - Write_ValidateSetting(ptr, &sd, (int32)(size_t)p); + Write_ValidateSetting(ptr, sd.get(), (int32)(size_t)p); break; case SDT_STDSTRING: - Write_ValidateStdString(ptr, &sd, (const char *)p); + Write_ValidateStdString(ptr, sd.get(), (const char *)p); break; case SDT_INTLIST: { @@ -615,8 +615,8 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co /* Use default */ LoadIntList((const char*)sdb->def, ptr, sld->length, GetVarMemType(sld->conv)); - } else if (sd.proc_cnvt != nullptr) { - sd.proc_cnvt((const char*)p); + } else if (sd->proc_cnvt != nullptr) { + sd->proc_cnvt((const char*)p); } break; } @@ -645,8 +645,8 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void *ptr; for (auto &sd : settings_table) { - const SettingDesc *sdb = &sd; - const SaveLoad *sld = &sd.save; + const SettingDesc *sdb = sd.get(); + const SaveLoad *sld = &sd->save; /* If the setting is not saved to the configuration * file, just continue with the next setting */ @@ -1964,6 +1964,22 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 return CommandCost(); } +/** + * Get the index of the given setting in the setting table. + * @param settings The settings to look through. + * @param setting The setting to look for. + * @return The index, or UINT32_MAX when it has not been found. + */ +static uint GetSettingIndex(const SettingTable &settings, const SettingDesc *setting) +{ + uint index = 0; + for (auto &sd : settings) { + if (sd.get() == setting) return index; + index++; + } + return UINT32_MAX; +} + /** * Get the index of the setting with this description. * @param sd the setting to get the index for. @@ -1972,7 +1988,7 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 uint GetSettingIndex(const SettingDesc *sd) { assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) == 0); - return sd - _settings.begin(); + return GetSettingIndex(_settings, sd); } /** @@ -1983,7 +1999,7 @@ uint GetSettingIndex(const SettingDesc *sd) static uint GetCompanySettingIndex(const SettingDesc *sd) { assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) != 0); - return sd - _company_settings.begin(); + return GetSettingIndex(_company_settings, sd); } /** @@ -2048,8 +2064,8 @@ void SetDefaultCompanySettings(CompanyID cid) { Company *c = Company::Get(cid); for (auto &sd : _company_settings) { - void *var = GetVariableAddress(&c->settings, &sd.save); - Write_ValidateSetting(var, &sd, (int32)(size_t)sd.def); + void *var = GetVariableAddress(&c->settings, &sd->save); + Write_ValidateSetting(var, sd.get(), (int32)(size_t)sd->def); } } @@ -2060,10 +2076,10 @@ void SyncCompanySettings() { uint i = 0; for (auto &sd : _company_settings) { - const void *old_var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd.save); - const void *new_var = GetVariableAddress(&_settings_client.company, &sd.save); - uint32 old_value = (uint32)ReadValue(old_var, sd.save.conv); - uint32 new_value = (uint32)ReadValue(new_var, sd.save.conv); + const void *old_var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); + const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save); + uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv); + uint32 new_value = (uint32)ReadValue(new_var, sd->save.conv); if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company); i++; } @@ -2113,25 +2129,25 @@ const SettingDesc *GetSettingFromName(const char *name) { /* First check all full names */ for (auto &sd : _settings) { - if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; - if (strcmp(sd.name, name) == 0) return &sd; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (strcmp(sd->name, name) == 0) return sd.get(); } /* Then check the shortcut variant of the name. */ for (auto &sd : _settings) { - if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; - const char *short_name = strchr(sd.name, '.'); + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + const char *short_name = strchr(sd->name, '.'); if (short_name != nullptr) { short_name++; - if (strcmp(short_name, name) == 0) return &sd; + if (strcmp(short_name, name) == 0) return sd.get(); } } if (strncmp(name, "company.", 8) == 0) name += 8; /* And finally the company-based settings */ for (auto &sd : _company_settings) { - if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; - if (strcmp(sd.name, name) == 0) return &sd; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (strcmp(sd->name, name) == 0) return sd.get(); } return nullptr; @@ -2221,19 +2237,19 @@ void IConsoleListSettings(const char *prefilter) IConsolePrintF(CC_WARNING, "All settings with their current value:"); for (auto &sd : _settings) { - if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; - if (prefilter != nullptr && strstr(sd.name, prefilter) == nullptr) continue; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (prefilter != nullptr && strstr(sd->name, prefilter) == nullptr) continue; char value[80]; - const void *ptr = GetVariableAddress(&GetGameSettings(), &sd.save); + const void *ptr = GetVariableAddress(&GetGameSettings(), &sd->save); - if (sd.cmd == SDT_BOOLX) { + if (sd->cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); - } else if (sd.cmd == SDT_STDSTRING) { + } else if (sd->cmd == SDT_STDSTRING) { seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); } else { - seprintf(value, lastof(value), sd.min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd.save.conv)); + seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); } - IConsolePrintF(CC_DEFAULT, "%s = %s", sd.name, value); + IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name, value); } IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); @@ -2248,11 +2264,11 @@ void IConsoleListSettings(const char *prefilter) static void LoadSettings(const SettingTable &settings, void *object) { for (auto &osd : settings) { - const SaveLoad *sld = &osd.save; + const SaveLoad *sld = &osd->save; void *ptr = GetVariableAddress(object, sld); if (!SlObjectMember(ptr, sld)) continue; - if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, &osd, ReadValue(ptr, sld->conv)); + if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, osd.get(), ReadValue(ptr, sld->conv)); } } @@ -2268,13 +2284,13 @@ static void SaveSettings(const SettingTable &settings, void *object) * SlCalcLength() because we have a different format. So do this manually */ size_t length = 0; for (auto &sd : settings) { - length += SlCalcObjMemberLength(object, &sd.save); + length += SlCalcObjMemberLength(object, &sd->save); } SlSetLength(length); for (auto &sd : settings) { - void *ptr = GetVariableAddress(object, &sd.save); - SlObjectMember(ptr, &sd.save); + void *ptr = GetVariableAddress(object, &sd->save); + SlObjectMember(ptr, &sd->save); } } diff --git a/src/settings_internal.h b/src/settings_internal.h index fca85de0c7..4aebe6b79c 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -82,7 +82,7 @@ typedef bool OnChange(int32 var); ///< callback prototype on data modi typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error /** Properties of config file settings. */ -struct SettingDescBase { +struct SettingDesc { const char *name; ///< name of the setting. Used in configuration file and for console const void *def; ///< default value given when none is present SettingDescType cmd; ///< various flags for the variable @@ -98,16 +98,13 @@ struct SettingDescBase { OnConvert *proc_cnvt; ///< callback procedure when loading value mechanism fails SettingCategory cat; ///< assigned categories of the setting bool startup; ///< setting has to be loaded directly at startup? -}; - -struct SettingDesc : SettingDescBase { SaveLoad save; ///< Internal structure (going to savegame, parts to config) bool IsEditable(bool do_command = false) const; SettingType GetType() const; }; -typedef std::initializer_list SettingTable; +typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame = false); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index f9bb279020..dbd302a1c8 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -54,13 +54,13 @@ static size_t ConvertLandscape(const char *value); * on the appropriate macro. */ -#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup)\ - {name, (const void*)(size_t)(def), cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup} +#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup, saveload)\ + std::unique_ptr(new SettingDesc{name, (const void*)(size_t)(def), cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup, saveload}) /* Macros for various objects to go in the configuration file. * This section is for global variables */ #define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat, startup), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to, extra)} + NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat, startup, SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to, extra)) #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) @@ -81,12 +81,12 @@ static size_t ConvertLandscape(const char *value); SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) #define SDTG_NULL(length, from, to)\ - {{"", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false}, SLEG_NULL(length, from, to)} + NSD_GENERAL("", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false, SLEG_NULL(length, from, to)) /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ #define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extra, startup)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat, startup), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to, extra)} + NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat, startup, SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to, extra)) #define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) @@ -107,7 +107,7 @@ static size_t ConvertLandscape(const char *value); SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) #define SDT_NULL(length, from, to)\ - {{"", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false}, SLE_CONDNULL(length, from, to)} + NSD_GENERAL("", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false, SLE_CONDNULL(length, from, to)) #define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ From d8125fa46e090f25f3fffbc0202bb971b914a3b4 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 19:00:43 +0200 Subject: [PATCH 238/800] Codechange: make sub classes of SettingDesc for the different types of settings --- src/settings_internal.h | 42 ++++++++++++++++++++++- src/table/currency_settings.ini | 2 +- src/table/gameopt_settings.ini | 19 ++++------- src/table/misc_settings.ini | 12 +++---- src/table/settings.h.preamble | 60 ++++++++++++++------------------- src/table/settings.ini | 6 ++-- 6 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/settings_internal.h b/src/settings_internal.h index 4aebe6b79c..1accc47ed8 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -16,7 +16,7 @@ * Convention/Type of settings. This is then further specified if necessary * with the SLE_ (SLE_VAR/SLE_FILE) enums in saveload.h * @see VarTypes - * @see SettingDescBase + * @see SettingDesc */ enum SettingDescType : byte { SDT_NUMX = 0, ///< any number-type @@ -25,6 +25,7 @@ enum SettingDescType : byte { SDT_MANYOFMANY = 3, ///< bitmasked number where MULTIPLE bits may be set SDT_INTLIST = 4, ///< list of integers separated by a comma ',' SDT_STDSTRING = 6, ///< \c std::string + SDT_NULL = 7, ///< an old setting that has been removed but could still be in savegames }; enum SettingGuiFlag : uint16 { @@ -83,6 +84,13 @@ typedef size_t OnConvert(const char *value); ///< callback prototype for convers /** Properties of config file settings. */ struct SettingDesc { + SettingDesc(SaveLoad save, const char *name, const void *def, SettingDescType cmd, SettingGuiFlag flags, + int32 min, uint32 max, int32 interval, const char *many, StringID str, StringID str_help, + StringID str_val, OnChange *proc, OnConvert *proc_cnvt, SettingCategory cat, bool startup) : + name(name), def(def), cmd(cmd), flags(flags), min(min), max(max), interval(interval), many(many), str(str), + str_help(str_help), str_val(str_val), proc(proc), proc_cnvt(proc_cnvt), cat(cat), startup(startup), save(save) {} + virtual ~SettingDesc() {} + const char *name; ///< name of the setting. Used in configuration file and for console const void *def; ///< default value given when none is present SettingDescType cmd; ///< various flags for the variable @@ -104,6 +112,38 @@ struct SettingDesc { SettingType GetType() const; }; +/** Integer type, including boolean, settings. Only these are shown in the settings UI. */ +struct IntSettingDesc : SettingDesc { + IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, + int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, + SettingCategory cat, OnChange *proc, const char *many = nullptr, OnConvert *many_cnvt = nullptr) : + SettingDesc(save, name, (void*)(size_t)def, cmd, flags, min, max, interval, many, str, str_help, str_val, + proc, many_cnvt, cat, startup) {} + virtual ~IntSettingDesc() {} +}; + +/** String settings. */ +struct StringSettingDesc : SettingDesc { + StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, + uint32 max_length, OnChange proc) : + SettingDesc(save, name, def, cmd, flags, 0, max_length, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} + virtual ~StringSettingDesc() {} +}; + +/** List/array settings. */ +struct ListSettingDesc : SettingDesc { + ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def) : + SettingDesc(save, name, def, cmd, flags, 0, 0, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} + virtual ~ListSettingDesc() {} +}; + +/** Placeholder for settings that have been removed, but might still linger in the savegame. */ +struct NullSettingDesc : SettingDesc { + NullSettingDesc(SaveLoad save) : + SettingDesc(save, "", nullptr, SDT_NULL, SGF_NONE, 0, 0, 0, nullptr, 0, 0, 0, nullptr, nullptr, SC_NONE, false) {} + virtual ~NullSettingDesc() {} +}; + typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 613f9bfa55..76eecc1043 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -10,7 +10,7 @@ static const SettingTable _currency_settings{ }; [templates] SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $proc, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 39caa45c95..1e60770f21 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -36,9 +36,9 @@ static const SettingTable _gameopt_settings{ [post-amble] }; [templates] -SDTG_GENERAL = SDTG_GENERAL($name, $sdt_cmd, $sle_cmd, $type, $flags, $guiflags, $var, $length, $def, $min, $max, $interval, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_NULL = SDT_NULL($length, $from, $to), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_NULL = SDT_NULL( $length, $from, $to), SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), @@ -68,7 +68,7 @@ startup = false -[SDTG_GENERAL] +[SDTG_LIST] name = ""diff_custom"" sdt_cmd = SDT_INTLIST sle_cmd = SL_ARR @@ -76,13 +76,10 @@ type = SLE_FILE_I16 | SLE_VAR_U16 flags = SLF_NOT_IN_CONFIG var = _old_diff_custom length = 17 -def = 0 -min = 0 -max = 0 -full = nullptr +def = nullptr to = SLV_4 -[SDTG_GENERAL] +[SDTG_LIST] name = ""diff_custom"" sdt_cmd = SDT_INTLIST sle_cmd = SL_ARR @@ -90,9 +87,7 @@ type = SLE_UINT16 flags = SLF_NOT_IN_CONFIG var = _old_diff_custom length = 18 -def = 0 -min = 0 -max = 0 +def = nullptr full = nullptr from = SLV_4 diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 4e1c3482ec..a3efbc65e8 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -20,12 +20,12 @@ static const SettingTable _misc_settings{ [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $proc, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index dbd302a1c8..6b4dc5e39f 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -54,74 +54,66 @@ static size_t ConvertLandscape(const char *value); * on the appropriate macro. */ -#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup, saveload)\ - std::unique_ptr(new SettingDesc{name, (const void*)(size_t)(def), cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, startup, saveload}) +#define NSD(type, ...) std::unique_ptr(new type##SettingDesc(__VA_ARGS__)) /* Macros for various objects to go in the configuration file. * This section is for global variables */ -#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat, startup, SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to, extra)) - #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) + NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) + NSD(Int, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, SDT_BOOLX, startup, def, 0, 1, 0, str, strhelp, strval, cat, proc) -#define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ + NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, SDT_INTLIST, startup, def) -#define SDTG_SSTR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, proc, from, to, cat, extra, startup)\ + NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, SDT_STDSTRING, startup, def, max_length, proc) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) + NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full) #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) + NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full) #define SDTG_NULL(length, from, to)\ - NSD_GENERAL("", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false, SLEG_NULL(length, from, to)) + NSD(Null, SLEG_NULL(length, from, to)) /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ -#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extra, startup)\ - NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat, startup, SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to, extra)) - #define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) + NSD(Int, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, SDT_BOOLX, startup, def, 0, 1, 0, str, strhelp, strval, cat, proc) -#define SDT_LIST(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) +#define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ + NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_INTLIST, startup, def) -#define SDT_SSTR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) +#define SDT_SSTR(base, var, type, flags, guiflags, def, proc, from, to, cat, extra, startup)\ + NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_STDSTRING, startup, def, 0, proc) #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, load, from, to, cat, extra, startup) + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full, load) #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra, startup)\ - SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, nullptr, from, to, cat, extra, startup) + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full, nullptr) #define SDT_NULL(length, from, to)\ - NSD_GENERAL("", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false, SLE_CONDNULL(length, from, to)) + NSD(Null, SLE_CONDNULL(length, from, to)) #define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) + SDTG_VAR(#var, type, flags, guiflags, _settings_client.var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup) #define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) + SDTG_BOOL(#var, flags, guiflags, _settings_client.var, def, str, strhelp, strval, proc, from, to, cat, extra, startup) -#define SDTC_LIST(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_LIST(var, type, flags, guiflags, def, from, to, cat, extra, startup)\ + SDTG_LIST(#var, type, flags, guiflags, _settings_client.var, def, lengthof(_settings_client.var), from, to, cat, extra, startup) -#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, max_length, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, proc, from, to, cat, extra, startup)\ + SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, proc, from, to, cat, extra, startup)\ #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) - + SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index ed07dfb118..4f105b5f66 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -67,13 +67,13 @@ SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $proc, $from, $to, $cat, $extra, $startup), SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $proc, $from, $to, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL($length, $from, $to), From c3cd4a683d34191ff9619ef962060abc1acc5fe3 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 13:39:41 +0200 Subject: [PATCH 239/800] Codechange: make formatting of values into strings a method of SettingDesc --- src/settings.cpp | 94 +++++++++++++++++++++-------------------- src/settings_internal.h | 17 ++++++++ 2 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 2c7d3aefe8..2964bad640 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -285,13 +285,13 @@ static bool LoadIntList(const char *str, void *array, int nelems, VarType type) * @param nelems the number of elements the array holds. * @param type the type of elements the array holds (eg INT8, UINT16, etc.) */ -static void MakeIntList(char *buf, const char *last, const void *array, int nelems, VarType type) +void ListSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { + const byte *p = static_cast(GetVariableAddress(object, &this->save)); int i, v = 0; - const byte *p = (const byte *)array; - for (i = 0; i != nelems; i++) { - switch (GetVarMemType(type)) { + for (i = 0; i != this->save.length; i++) { + switch (GetVarMemType(this->save.conv)) { case SLE_VAR_BL: case SLE_VAR_I8: v = *(const int8 *)p; p += 1; break; case SLE_VAR_U8: v = *(const uint8 *)p; p += 1; break; @@ -301,9 +301,9 @@ static void MakeIntList(char *buf, const char *last, const void *array, int nele case SLE_VAR_U32: v = *(const uint32 *)p; p += 4; break; default: NOT_REACHED(); } - if (IsSignedVarMemType(type)) { + if (IsSignedVarMemType(this->save.conv)) { buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v); - } else if (type & SLF_HEX) { + } else if (this->save.conv & SLF_HEX) { buf += seprintf(buf, last, (i == 0) ? "0x%X" : ",0x%X", v); } else { buf += seprintf(buf, last, (i == 0) ? "%u" : ",%u", v); @@ -548,6 +548,16 @@ static void Write_ValidateStdString(void *ptr, const SettingDesc *sd, const char } } +/** + * Read the string from the the actual setting. + * @param object The object the setting is to be saved in. + * @return The value of the saved string. + */ +const std::string &StringSettingDesc::Read(const void *object) const +{ + return *reinterpret_cast(GetVariableAddress(object, &this->save)); +} + /** * Load values from a group of an IniFile structure into the internal representation * @param ini pointer to IniFile structure that holds administrative information @@ -665,11 +675,11 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co } item = group->GetItem(s, true); - ptr = GetVariableAddress(object, sld); if (item->value.has_value()) { /* check if the value is the same as the old value */ const void *p = StringToVal(sdb, item->value->c_str()); + ptr = GetVariableAddress(object, sld); /* The main type of a variable/setting is in bytes 8-15 * The subtype (what kind of numbers do we have there) is in 0-7 */ @@ -707,51 +717,43 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co } /* Value has changed, get the new value and put it into a buffer */ - switch (sdb->cmd) { - case SDT_BOOLX: - case SDT_NUMX: - case SDT_ONEOFMANY: - case SDT_MANYOFMANY: { - uint32 i = (uint32)ReadValue(ptr, sld->conv); - - switch (sdb->cmd) { - case SDT_BOOLX: strecpy(buf, (i != 0) ? "true" : "false", lastof(buf)); break; - case SDT_NUMX: seprintf(buf, lastof(buf), IsSignedVarMemType(sld->conv) ? "%d" : (sld->conv & SLF_HEX) ? "%X" : "%u", i); break; - case SDT_ONEOFMANY: MakeOneOfMany(buf, lastof(buf), sdb->many, i); break; - case SDT_MANYOFMANY: MakeManyOfMany(buf, lastof(buf), sdb->many, i); break; - default: NOT_REACHED(); - } - break; - } - - case SDT_STDSTRING: - switch (GetVarMemType(sld->conv)) { - case SLE_VAR_STR: strecpy(buf, reinterpret_cast(ptr)->c_str(), lastof(buf)); break; - - case SLE_VAR_STRQ: - if (reinterpret_cast(ptr)->empty()) { - buf[0] = '\0'; - } else { - seprintf(buf, lastof(buf), "\"%s\"", reinterpret_cast(ptr)->c_str()); - } - break; - - default: NOT_REACHED(); - } - break; - - case SDT_INTLIST: - MakeIntList(buf, lastof(buf), ptr, sld->length, sld->conv); - break; - - default: NOT_REACHED(); - } + sdb->FormatValue(buf, lastof(buf), object); /* The value is different, that means we have to write it to the ini */ item->value.emplace(buf); } } +void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const +{ + uint32 i = (uint32)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + switch (this->cmd) { + case SDT_BOOLX: strecpy(buf, (i != 0) ? "true" : "false", last); break; + case SDT_NUMX: seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); break; + case SDT_ONEOFMANY: MakeOneOfMany(buf, last, this->many, i); break; + case SDT_MANYOFMANY: MakeManyOfMany(buf, last, this->many, i); break; + default: NOT_REACHED(); + } +} + +void StringSettingDesc::FormatValue(char *buf, const char *last, const void *object) const +{ + const std::string &str = this->Read(object); + switch (GetVarMemType(this->save. conv)) { + case SLE_VAR_STR: strecpy(buf, str.c_str(), last); break; + + case SLE_VAR_STRQ: + if (str.empty()) { + buf[0] = '\0'; + } else { + seprintf(buf, last, "\"%s\"", str.c_str()); + } + break; + + default: NOT_REACHED(); + } +} + /** * Loads all items from a 'grpname' section into a list * The list parameter can be a nullptr pointer, in this case nothing will be diff --git a/src/settings_internal.h b/src/settings_internal.h index 1accc47ed8..ee8b59be18 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -110,6 +110,14 @@ struct SettingDesc { bool IsEditable(bool do_command = false) const; SettingType GetType() const; + + /** + * Format the value of the setting associated with this object. + * @param buf The before of the buffer to format into. + * @param last The end of the buffer to format into. + * @param object The object the setting is in. + */ + virtual void FormatValue(char *buf, const char *last, const void *object) const = 0; }; /** Integer type, including boolean, settings. Only these are shown in the settings UI. */ @@ -120,6 +128,8 @@ struct IntSettingDesc : SettingDesc { SettingDesc(save, name, (void*)(size_t)def, cmd, flags, min, max, interval, many, str, str_help, str_val, proc, many_cnvt, cat, startup) {} virtual ~IntSettingDesc() {} + + void FormatValue(char *buf, const char *last, const void *object) const override; }; /** String settings. */ @@ -128,6 +138,9 @@ struct StringSettingDesc : SettingDesc { uint32 max_length, OnChange proc) : SettingDesc(save, name, def, cmd, flags, 0, max_length, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} virtual ~StringSettingDesc() {} + + void FormatValue(char *buf, const char *last, const void *object) const override; + const std::string &Read(const void *object) const; }; /** List/array settings. */ @@ -135,6 +148,8 @@ struct ListSettingDesc : SettingDesc { ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def) : SettingDesc(save, name, def, cmd, flags, 0, 0, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} virtual ~ListSettingDesc() {} + + void FormatValue(char *buf, const char *last, const void *object) const override; }; /** Placeholder for settings that have been removed, but might still linger in the savegame. */ @@ -142,6 +157,8 @@ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : SettingDesc(save, "", nullptr, SDT_NULL, SGF_NONE, 0, 0, 0, nullptr, 0, 0, 0, nullptr, nullptr, SC_NONE, false) {} virtual ~NullSettingDesc() {} + + void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } }; typedef std::initializer_list> SettingTable; From 024e584904bc9ee4ac63a8c84fa37a065974fcdc Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 13:46:39 +0200 Subject: [PATCH 240/800] Cleanup: use (config) formatting for console settings functions --- src/settings.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 2964bad640..f5d4a96605 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2204,26 +2204,20 @@ void IConsoleSetSetting(const char *name, int value) */ void IConsoleGetSetting(const char *name, bool force_newgame) { - char value[20]; const SettingDesc *sd = GetSettingFromName(name); - const void *ptr; - if (sd == nullptr) { IConsolePrintF(CC_WARNING, "'%s' is an unknown setting.", name); return; } - ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); + const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game; if (sd->cmd == SDT_STDSTRING) { + const void *ptr = GetVariableAddress(object, &sd->save); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); } else { - if (sd->cmd == SDT_BOOLX) { - seprintf(value, lastof(value), (*(const bool*)ptr != 0) ? "on" : "off"); - } else { - seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); - } - + char value[20]; + sd->FormatValue(value, lastof(value), object); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)", name, value, (sd->flags & SGF_0ISDISABLED) ? "(0) " : "", sd->min, sd->max); } @@ -2242,15 +2236,7 @@ void IConsoleListSettings(const char *prefilter) if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (prefilter != nullptr && strstr(sd->name, prefilter) == nullptr) continue; char value[80]; - const void *ptr = GetVariableAddress(&GetGameSettings(), &sd->save); - - if (sd->cmd == SDT_BOOLX) { - seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); - } else if (sd->cmd == SDT_STDSTRING) { - seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); - } else { - seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); - } + sd->FormatValue(value, lastof(value), &GetGameSettings()); IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name, value); } From be28c95b30eb433de5e7b9831657af551ef236f9 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 20:44:09 +0200 Subject: [PATCH 241/800] Codechange: make Write_ValidateSetting a function of IntSettingDesc --- src/settings.cpp | 185 +++++++++++++++++++--------------------- src/settings_internal.h | 5 ++ 2 files changed, 94 insertions(+), 96 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index f5d4a96605..8bdfced960 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -446,33 +446,22 @@ static const void *StringToVal(const SettingDesc *desc, const char *orig_str) } /** - * Set the value of a setting and if needed clamp the value to - * the preset minimum and maximum. - * @param ptr the variable itself - * @param sd pointer to the 'information'-database of the variable - * @param val signed long version of the new value - * @pre SettingDesc is of type SDT_BOOLX, SDT_NUMX, - * SDT_ONEOFMANY or SDT_MANYOFMANY. Other types are not supported as of now + * Set the value of a setting and if needed clamp the value to the preset minimum and maximum. + * @param object The object the setting is to be saved in. + * @param val Signed version of the new value. */ -static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) +void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const { - const SettingDesc *sdb = sd; - - if (sdb->cmd != SDT_BOOLX && - sdb->cmd != SDT_NUMX && - sdb->cmd != SDT_ONEOFMANY && - sdb->cmd != SDT_MANYOFMANY) { - return; - } + void *ptr = GetVariableAddress(object, &this->save); /* We cannot know the maximum value of a bitset variable, so just have faith */ - if (sdb->cmd != SDT_MANYOFMANY) { + if (this->cmd != SDT_MANYOFMANY) { /* We need to take special care of the uint32 type as we receive from the function * a signed integer. While here also bail out on 64-bit settings as those are not * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed * 32-bit variable * TODO: Support 64-bit settings/variables */ - switch (GetVarMemType(sd->save.conv)) { + switch (GetVarMemType(this->save.conv)) { case SLE_VAR_NULL: return; case SLE_VAR_BL: case SLE_VAR_I8: @@ -481,13 +470,13 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) case SLE_VAR_U16: case SLE_VAR_I32: { /* Override the minimum value. No value below sdb->min, except special value 0 */ - if (!(sdb->flags & SGF_0ISDISABLED) || val != 0) { - if (!(sdb->flags & SGF_MULTISTRING)) { + if (!(this->flags & SGF_0ISDISABLED) || val != 0) { + if (!(this->flags & SGF_MULTISTRING)) { /* Clamp value-type setting to its valid range */ - val = Clamp(val, sdb->min, sdb->max); - } else if (val < sdb->min || val > (int32)sdb->max) { + val = Clamp(val, this->min, this->max); + } else if (val < this->min || val > (int32)this->max) { /* Reset invalid discrete setting (where different values change gameplay) to its default value */ - val = (int32)(size_t)sdb->def; + val = (int32)(size_t)this->def; } } break; @@ -495,13 +484,13 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) case SLE_VAR_U32: { /* Override the minimum value. No value below sdb->min, except special value 0 */ uint32 uval = (uint32)val; - if (!(sdb->flags & SGF_0ISDISABLED) || uval != 0) { - if (!(sdb->flags & SGF_MULTISTRING)) { + if (!(this->flags & SGF_0ISDISABLED) || uval != 0) { + if (!(this->flags & SGF_MULTISTRING)) { /* Clamp value-type setting to its valid range */ - uval = ClampU(uval, sdb->min, sdb->max); - } else if (uval < (uint)sdb->min || uval > sdb->max) { + uval = ClampU(uval, this->min, this->max); + } else if (uval < (uint)this->min || uval > this->max) { /* Reset invalid discrete setting to its default value */ - uval = (uint32)(size_t)sdb->def; + uval = (uint32)(size_t)this->def; } } WriteValue(ptr, SLE_VAR_U32, (int64)uval); @@ -513,7 +502,7 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) } } - WriteValue(ptr, sd->save.conv, (int64)val); + WriteValue(ptr, this->save.conv, (int64)val); } /** @@ -610,7 +599,7 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co case SDT_NUMX: case SDT_ONEOFMANY: case SDT_MANYOFMANY: - Write_ValidateSetting(ptr, sd.get(), (int32)(size_t)p); + sd->AsIntSetting()->Write_ValidateSetting(object, (int32)(size_t)p); break; case SDT_STDSTRING: @@ -846,6 +835,24 @@ SettingType SettingDesc::GetType() const return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; } +/** + * Check whether this setting is an integer type setting. + * @return True when the underlying type is an integer. + */ +bool SettingDesc::IsIntSetting() const { + return this->cmd == SDT_BOOLX || this->cmd == SDT_NUMX || this->cmd == SDT_ONEOFMANY || this->cmd == SDT_MANYOFMANY; +} + +/** + * Get the setting description of this setting as an integer setting. + * @return The integer setting description. + */ +const IntSettingDesc *SettingDesc::AsIntSetting() const +{ + assert(this->IsIntSetting()); + return static_cast(this); +} + /* Begin - Callback Functions for the various settings. */ /** Reposition the main toolbar as the setting changed. */ @@ -1451,8 +1458,8 @@ static void HandleOldDiffCustom(bool savegame) const SettingDesc *sd = GetSettingDescription(i); /* Skip deprecated options */ if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - void *var = GetVariableAddress(savegame ? &_settings_game : &_settings_newgame, &sd->save); - Write_ValidateSetting(var, sd, (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i])); + int32 value = (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]); + sd->AsIntSetting()->Write_ValidateSetting(savegame ? &_settings_game : &_settings_newgame, value); } } @@ -1879,6 +1886,40 @@ void DeleteGRFPresetFromConfig(const char *config_name) delete ini; } +/** + * Handle changing a value. This performs validation of the input value and + * calls the appropriate callbacks, and saves it when the value is changed. + * @param object The object the setting is in. + * @param newval The new value for the setting. + */ +void IntSettingDesc::ChangeValue(const void *object, int32 newval) const +{ + void *var = GetVariableAddress(object, &this->save); + + int32 oldval = (int32)ReadValue(var, this->save.conv); + + this->Write_ValidateSetting(object, newval); + newval = (int32)ReadValue(var, this->save.conv); + + if (oldval == newval) return; + + if (this->proc != nullptr && !this->proc(newval)) { + /* The change was not allowed, so revert. */ + WriteValue(var, this->save.conv, (int64)oldval); + return; + } + + if (this->flags & SGF_NO_NETWORK) { + GamelogStartAction(GLAT_SETTING); + GamelogSetting(this->name, oldval, newval); + GamelogStopAction(); + } + + SetWindowClassesDirty(WC_GAME_OPTIONS); + + if (_save_config) SaveToConfig(); +} + /** * Network-safe changing of settings (server-only). * @param tile unused @@ -1896,34 +1937,12 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (sd == nullptr) return CMD_ERROR; if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR; + if (!sd->IsIntSetting()) return CMD_ERROR; if (!sd->IsEditable(true)) return CMD_ERROR; if (flags & DC_EXEC) { - void *var = GetVariableAddress(&GetGameSettings(), &sd->save); - - int32 oldval = (int32)ReadValue(var, sd->save.conv); - int32 newval = (int32)p2; - - Write_ValidateSetting(var, sd, newval); - newval = (int32)ReadValue(var, sd->save.conv); - - if (oldval == newval) return CommandCost(); - - if (sd->proc != nullptr && !sd->proc(newval)) { - WriteValue(var, sd->save.conv, (int64)oldval); - return CommandCost(); - } - - if (sd->flags & SGF_NO_NETWORK) { - GamelogStartAction(GLAT_SETTING); - GamelogSetting(sd->name, oldval, newval); - GamelogStopAction(); - } - - SetWindowClassesDirty(WC_GAME_OPTIONS); - - if (_save_config) SaveToConfig(); + sd->AsIntSetting()->ChangeValue(&GetGameSettings(), p2); } return CommandCost(); @@ -1943,24 +1962,10 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 { const SettingDesc *sd = GetCompanySettingDescription(p1); if (sd == nullptr) return CMD_ERROR; + if (!sd->IsIntSetting()) return CMD_ERROR; if (flags & DC_EXEC) { - void *var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); - - int32 oldval = (int32)ReadValue(var, sd->save.conv); - int32 newval = (int32)p2; - - Write_ValidateSetting(var, sd, newval); - newval = (int32)ReadValue(var, sd->save.conv); - - if (oldval == newval) return CommandCost(); - - if (sd->proc != nullptr && !sd->proc(newval)) { - WriteValue(var, sd->save.conv, (int64)oldval); - return CommandCost(); - } - - SetWindowClassesDirty(WC_GAME_OPTIONS); + sd->AsIntSetting()->ChangeValue(&Company::Get(_current_company)->settings, p2); } return CommandCost(); @@ -2013,14 +2018,13 @@ static uint GetCompanySettingIndex(const SettingDesc *sd) */ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) { - if ((sd->flags & SGF_PER_COMPANY) != 0) { + const IntSettingDesc *setting = sd->AsIntSetting(); + if ((setting->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { - return DoCommandP(0, GetCompanySettingIndex(sd), value, CMD_CHANGE_COMPANY_SETTING); + return DoCommandP(0, GetCompanySettingIndex(setting), value, CMD_CHANGE_COMPANY_SETTING); } - void *var = GetVariableAddress(&_settings_client.company, &sd->save); - Write_ValidateSetting(var, sd, value); - if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv)); + setting->ChangeValue(&_settings_client.company, value); return true; } @@ -2028,33 +2032,22 @@ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) * (if any) to change. Also *hack*hack* we update the _newgame version * of settings because changing a company-based setting in a game also * changes its defaults. At least that is the convention we have chosen */ - if (sd->save.conv & SLF_NO_NETWORK_SYNC) { - void *var = GetVariableAddress(&GetGameSettings(), &sd->save); - Write_ValidateSetting(var, sd, value); - + if (setting->save.conv & SLF_NO_NETWORK_SYNC) { if (_game_mode != GM_MENU) { - void *var2 = GetVariableAddress(&_settings_newgame, &sd->save); - Write_ValidateSetting(var2, sd, value); + setting->ChangeValue(&_settings_newgame, value); } - if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv)); - - SetWindowClassesDirty(WC_GAME_OPTIONS); - - if (_save_config) SaveToConfig(); + setting->ChangeValue(&GetGameSettings(), value); return true; } if (force_newgame) { - void *var2 = GetVariableAddress(&_settings_newgame, &sd->save); - Write_ValidateSetting(var2, sd, value); - - if (_save_config) SaveToConfig(); + setting->ChangeValue(&_settings_newgame, value); return true; } /* send non-company-based settings over the network */ if (!_networking || (_networking && _network_server)) { - return DoCommandP(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); + return DoCommandP(0, GetSettingIndex(setting), value, CMD_CHANGE_SETTING); } return false; } @@ -2066,8 +2059,8 @@ void SetDefaultCompanySettings(CompanyID cid) { Company *c = Company::Get(cid); for (auto &sd : _company_settings) { - void *var = GetVariableAddress(&c->settings, &sd->save); - Write_ValidateSetting(var, sd.get(), (int32)(size_t)sd->def); + const IntSettingDesc *int_setting = sd->AsIntSetting(); + int_setting->Write_ValidateSetting(&c->settings, (int32)(size_t)int_setting->def); } } @@ -2256,7 +2249,7 @@ static void LoadSettings(const SettingTable &settings, void *object) void *ptr = GetVariableAddress(object, sld); if (!SlObjectMember(ptr, sld)) continue; - if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, osd.get(), ReadValue(ptr, sld->conv)); + if (osd->IsIntSetting()) osd->AsIntSetting()->Write_ValidateSetting(object, ReadValue(ptr, sld->conv)); } } diff --git a/src/settings_internal.h b/src/settings_internal.h index ee8b59be18..7b37ac2676 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -110,6 +110,8 @@ struct SettingDesc { bool IsEditable(bool do_command = false) const; SettingType GetType() const; + bool IsIntSetting() const; + const struct IntSettingDesc *AsIntSetting() const; /** * Format the value of the setting associated with this object. @@ -129,6 +131,9 @@ struct IntSettingDesc : SettingDesc { proc, many_cnvt, cat, startup) {} virtual ~IntSettingDesc() {} + void ChangeValue(const void *object, int32 newvalue) const; + void Write_ValidateSetting(const void *object, int32 value) const; + void FormatValue(char *buf, const char *last, const void *object) const override; }; From 1f8ff0e4f9895538a98f2a22b2f6b6e62310aae9 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 20:52:24 +0200 Subject: [PATCH 242/800] Codechange: make Write_ValidateSetting a function of StringSettingDesc --- src/settings.cpp | 60 ++++++++++++++++++++++++++++++----------- src/settings_internal.h | 5 ++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 8bdfced960..cedfdf5af0 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -507,26 +507,25 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const /** * Set the string value of a setting. - * @param ptr Pointer to the std::string. - * @param sd Pointer to the information for the conversions and limitations to apply. - * @param p The string to save. + * @param object The object the setting is to be saved in. + * @param str The string to save. */ -static void Write_ValidateStdString(void *ptr, const SettingDesc *sd, const char *p) +void StringSettingDesc::Write_ValidateSetting(const void *object, const char *str) const { - std::string *dst = reinterpret_cast(ptr); + std::string *dst = reinterpret_cast(GetVariableAddress(object, &this->save)); - switch (GetVarMemType(sd->save.conv)) { + switch (GetVarMemType(this->save.conv)) { case SLE_VAR_STR: case SLE_VAR_STRQ: - if (p != nullptr) { - if (sd->max != 0 && strlen(p) >= sd->max) { + if (str != nullptr) { + if (this->max != 0 && strlen(str) >= this->max) { /* In case a maximum length is imposed by the setting, the length * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ - std::string str(p, sd->max - 1); - dst->assign(str_validate(str, SVS_NONE)); + std::string stdstr(str, this->max - 1); + dst->assign(str_validate(stdstr, SVS_NONE)); } else { - dst->assign(p); + dst->assign(str); } } else { dst->clear(); @@ -603,7 +602,7 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co break; case SDT_STDSTRING: - Write_ValidateStdString(ptr, sd.get(), (const char *)p); + sd->AsStringSetting()->Write_ValidateSetting(object, (const char *)p); break; case SDT_INTLIST: { @@ -843,6 +842,14 @@ bool SettingDesc::IsIntSetting() const { return this->cmd == SDT_BOOLX || this->cmd == SDT_NUMX || this->cmd == SDT_ONEOFMANY || this->cmd == SDT_MANYOFMANY; } +/** + * Check whether this setting is an string type setting. + * @return True when the underlying type is a string. + */ +bool SettingDesc::IsStringSetting() const { + return this->cmd == SDT_STDSTRING; +} + /** * Get the setting description of this setting as an integer setting. * @return The integer setting description. @@ -853,6 +860,16 @@ const IntSettingDesc *SettingDesc::AsIntSetting() const return static_cast(this); } +/** + * Get the setting description of this setting as a string setting. + * @return The string setting description. + */ +const StringSettingDesc *SettingDesc::AsStringSetting() const +{ + assert(this->IsStringSetting()); + return static_cast(this); +} + /* Begin - Callback Functions for the various settings. */ /** Reposition the main toolbar as the setting changed. */ @@ -2105,12 +2122,23 @@ bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgam value = nullptr; } - void *ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); - Write_ValidateStdString(ptr, sd, value); - if (sd->proc != nullptr) sd->proc(0); + const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game; + sd->AsStringSetting()->ChangeValue(object, value); + return true; +} + +/** + * Handle changing a string value. This performs validation of the input value + * and calls the appropriate callbacks, and saves it when the value is changed. + * @param object The object the setting is in. + * @param newval The new value for the setting. + */ +void StringSettingDesc::ChangeValue(const void *object, const char *newval) const +{ + this->Write_ValidateSetting(object, newval); + if (this->proc != nullptr) this->proc(0); if (_save_config) SaveToConfig(); - return true; } /** diff --git a/src/settings_internal.h b/src/settings_internal.h index 7b37ac2676..33910e066b 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -111,7 +111,9 @@ struct SettingDesc { bool IsEditable(bool do_command = false) const; SettingType GetType() const; bool IsIntSetting() const; + bool IsStringSetting() const; const struct IntSettingDesc *AsIntSetting() const; + const struct StringSettingDesc *AsStringSetting() const; /** * Format the value of the setting associated with this object. @@ -144,6 +146,9 @@ struct StringSettingDesc : SettingDesc { SettingDesc(save, name, def, cmd, flags, 0, max_length, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} virtual ~StringSettingDesc() {} + void ChangeValue(const void *object, const char *newval) const; + void Write_ValidateSetting(const void *object, const char *str) const; + void FormatValue(char *buf, const char *last, const void *object) const override; const std::string &Read(const void *object) const; }; From f6723b53dabfb7d0610fb1a482ea34a933b5fae7 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 20:57:41 +0200 Subject: [PATCH 243/800] Codechange: make parsing of IniItems overridable functions of SettingDesc --- src/settings.cpp | 176 +++++++++++++++++----------------------- src/settings_internal.h | 28 +++++++ 2 files changed, 104 insertions(+), 100 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index cedfdf5af0..a99b196b4c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -374,75 +374,70 @@ static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 } /** - * Convert a string representation (external) of a setting to the internal rep. - * @param desc SettingDesc struct that holds all information about the variable - * @param orig_str input string that will be parsed based on the type of desc - * @return return the parsed value of the setting + * Convert a string representation (external) of an integer-like setting to an integer. + * @param str Input string that will be parsed based on the type of desc. + * @return The value from the parse string, or the default value of the setting. */ -static const void *StringToVal(const SettingDesc *desc, const char *orig_str) +size_t IntSettingDesc::ParseValue(const char *str) const { - const char *str = orig_str == nullptr ? "" : orig_str; - - switch (desc->cmd) { + switch (this->cmd) { case SDT_NUMX: { char *end; size_t val = strtoul(str, &end, 0); if (end == str) { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); msg.SetDParamStr(0, str); - msg.SetDParamStr(1, desc->name); + msg.SetDParamStr(1, this->name); _settings_error_list.push_back(msg); - return desc->def; + break; } if (*end != '\0') { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS); - msg.SetDParamStr(0, desc->name); + msg.SetDParamStr(0, this->name); _settings_error_list.push_back(msg); } - return (void*)val; + return val; } case SDT_ONEOFMANY: { - size_t r = LookupOneOfMany(desc->many, str); + size_t r = LookupOneOfMany(this->many, str); /* if the first attempt of conversion from string to the appropriate value fails, * look if we have defined a converter from old value to new value. */ - if (r == (size_t)-1 && desc->proc_cnvt != nullptr) r = desc->proc_cnvt(str); - if (r != (size_t)-1) return (void*)r; // and here goes converted value + if (r == (size_t)-1 && this->proc_cnvt != nullptr) r = this->proc_cnvt(str); + if (r != (size_t)-1) return r; // and here goes converted value ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); msg.SetDParamStr(0, str); - msg.SetDParamStr(1, desc->name); + msg.SetDParamStr(1, this->name); _settings_error_list.push_back(msg); - return desc->def; + break; } case SDT_MANYOFMANY: { - size_t r = LookupManyOfMany(desc->many, str); - if (r != (size_t)-1) return (void*)r; + size_t r = LookupManyOfMany(this->many, str); + if (r != (size_t)-1) return r; ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); msg.SetDParamStr(0, str); - msg.SetDParamStr(1, desc->name); + msg.SetDParamStr(1, this->name); _settings_error_list.push_back(msg); - return desc->def; + break; } case SDT_BOOLX: { - if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return (void*)true; - if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return (void*)false; + if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return true; + if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return false; ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); msg.SetDParamStr(0, str); - msg.SetDParamStr(1, desc->name); + msg.SetDParamStr(1, this->name); _settings_error_list.push_back(msg); - return desc->def; + break; } - case SDT_STDSTRING: return orig_str; - case SDT_INTLIST: return str; - default: break; + default: NOT_REACHED(); } - return nullptr; + return (size_t)this->def; } /** @@ -590,36 +585,33 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co if (sc != std::string::npos) item = ini->GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1), false); } - const void *p = (item == nullptr) ? sdb->def : StringToVal(sdb, item->value.has_value() ? item->value->c_str() : nullptr); - void *ptr = GetVariableAddress(object, sld); + sdb->ParseValue(item, object); + } +} - switch (sdb->cmd) { - case SDT_BOOLX: // All four are various types of (integer) numbers - case SDT_NUMX: - case SDT_ONEOFMANY: - case SDT_MANYOFMANY: - sd->AsIntSetting()->Write_ValidateSetting(object, (int32)(size_t)p); - break; +void IntSettingDesc::ParseValue(const IniItem *item, void *object) const +{ + size_t val = (item == nullptr) ? (size_t)this->def : this->ParseValue(item->value.has_value() ? item->value->c_str() : ""); + this->Write_ValidateSetting(object, (int32)val); +} - case SDT_STDSTRING: - sd->AsStringSetting()->Write_ValidateSetting(object, (const char *)p); - break; +void StringSettingDesc::ParseValue(const IniItem *item, void *object) const +{ + const char *str = (item == nullptr) ? (const char *)this->def : item->value.has_value() ? item->value->c_str() : nullptr; + this->Write_ValidateSetting(object, str); +} - case SDT_INTLIST: { - if (!LoadIntList((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) { - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY); - msg.SetDParamStr(0, sdb->name); - _settings_error_list.push_back(msg); +void ListSettingDesc::ParseValue(const IniItem *item, void *object) const +{ + const char *str = (item == nullptr) ? (const char *)this->def : item->value.has_value() ? item->value->c_str() : nullptr; + void *ptr = GetVariableAddress(object, &this->save); + if (!LoadIntList(str, ptr, this->save.length, GetVarMemType(this->save.conv))) { + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY); + msg.SetDParamStr(0, this->name); + _settings_error_list.push_back(msg); - /* Use default */ - LoadIntList((const char*)sdb->def, ptr, sld->length, GetVarMemType(sld->conv)); - } else if (sd->proc_cnvt != nullptr) { - sd->proc_cnvt((const char*)p); - } - break; - } - default: NOT_REACHED(); - } + /* Use default */ + LoadIntList((const char*)this->def, ptr, this->save.length, GetVarMemType(this->save.conv)); } } @@ -640,7 +632,6 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co IniGroup *group_def = nullptr, *group; IniItem *item; char buf[512]; - void *ptr; for (auto &sd : settings_table) { const SettingDesc *sdb = sd.get(); @@ -664,51 +655,13 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co item = group->GetItem(s, true); - if (item->value.has_value()) { - /* check if the value is the same as the old value */ - const void *p = StringToVal(sdb, item->value->c_str()); - ptr = GetVariableAddress(object, sld); + if (!item->value.has_value() || !sdb->IsSameValue(item, object)) { + /* Value has changed, get the new value and put it into a buffer */ + sdb->FormatValue(buf, lastof(buf), object); - /* The main type of a variable/setting is in bytes 8-15 - * The subtype (what kind of numbers do we have there) is in 0-7 */ - switch (sdb->cmd) { - case SDT_BOOLX: - case SDT_NUMX: - case SDT_ONEOFMANY: - case SDT_MANYOFMANY: - switch (GetVarMemType(sld->conv)) { - case SLE_VAR_BL: - if (*(bool*)ptr == (p != nullptr)) continue; - break; - - case SLE_VAR_I8: - case SLE_VAR_U8: - if (*(byte*)ptr == (byte)(size_t)p) continue; - break; - - case SLE_VAR_I16: - case SLE_VAR_U16: - if (*(uint16*)ptr == (uint16)(size_t)p) continue; - break; - - case SLE_VAR_I32: - case SLE_VAR_U32: - if (*(uint32*)ptr == (uint32)(size_t)p) continue; - break; - - default: NOT_REACHED(); - } - break; - - default: break; // Assume the other types are always changed - } + /* The value is different, that means we have to write it to the ini */ + item->value.emplace(buf); } - - /* Value has changed, get the new value and put it into a buffer */ - sdb->FormatValue(buf, lastof(buf), object); - - /* The value is different, that means we have to write it to the ini */ - item->value.emplace(buf); } } @@ -724,10 +677,17 @@ void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object } } +bool IntSettingDesc::IsSameValue(const IniItem *item, void *object) const +{ + int64 item_value = this->ParseValue(item->value->c_str()); + int64 object_value = ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + return item_value == object_value; +} + void StringSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { const std::string &str = this->Read(object); - switch (GetVarMemType(this->save. conv)) { + switch (GetVarMemType(this->save.conv)) { case SLE_VAR_STR: strecpy(buf, str.c_str(), last); break; case SLE_VAR_STRQ: @@ -742,6 +702,22 @@ void StringSettingDesc::FormatValue(char *buf, const char *last, const void *obj } } +bool StringSettingDesc::IsSameValue(const IniItem *item, void *object) const +{ + /* The ini parsing removes the quotes, which are needed to retain the spaces in STRQs, + * so those values are always different in the parsed ini item than they should be. */ + if (GetVarMemType(this->save.conv) == SLE_VAR_STRQ) return false; + + const std::string &str = this->Read(object); + return item->value->compare(str) == 0; +} + +bool ListSettingDesc::IsSameValue(const IniItem *item, void *object) const +{ + /* Checking for equality is way more expensive than just writing the value. */ + return false; +} + /** * Loads all items from a 'grpname' section into a list * The list parameter can be a nullptr pointer, in this case nothing will be diff --git a/src/settings_internal.h b/src/settings_internal.h index 33910e066b..0914f2803f 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -79,6 +79,7 @@ enum SettingType { ST_ALL, ///< Used in setting filter to match all types. }; +struct IniItem; typedef bool OnChange(int32 var); ///< callback prototype on data modification typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error @@ -122,6 +123,24 @@ struct SettingDesc { * @param object The object the setting is in. */ virtual void FormatValue(char *buf, const char *last, const void *object) const = 0; + + /** + * Parse/read the value from the Ini item into the setting associated with this object. + * @param item The Ini item with the content of this setting. + * @param object The object the setting is in. + */ + virtual void ParseValue(const IniItem *item, void *object) const = 0; + + /** + * Check whether the value in the Ini item is the same as is saved in this setting in the object. + * It might be that determining whether the value is the same is way more expensive than just + * writing the value. In those cases this function may unconditionally return false even though + * the value might be the same as in the Ini item. + * @param item The Ini item with the content of this setting. + * @param object The object the setting is in. + * @return True if the value is definitely the same (might be false when the same). + */ + virtual bool IsSameValue(const IniItem *item, void *object) const = 0; }; /** Integer type, including boolean, settings. Only these are shown in the settings UI. */ @@ -136,7 +155,10 @@ struct IntSettingDesc : SettingDesc { void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; + size_t ParseValue(const char *str) const; void FormatValue(char *buf, const char *last, const void *object) const override; + void ParseValue(const IniItem *item, void *object) const override; + bool IsSameValue(const IniItem *item, void *object) const override; }; /** String settings. */ @@ -150,6 +172,8 @@ struct StringSettingDesc : SettingDesc { void Write_ValidateSetting(const void *object, const char *str) const; void FormatValue(char *buf, const char *last, const void *object) const override; + void ParseValue(const IniItem *item, void *object) const override; + bool IsSameValue(const IniItem *item, void *object) const override; const std::string &Read(const void *object) const; }; @@ -160,6 +184,8 @@ struct ListSettingDesc : SettingDesc { virtual ~ListSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override; + void ParseValue(const IniItem *item, void *object) const override; + bool IsSameValue(const IniItem *item, void *object) const override; }; /** Placeholder for settings that have been removed, but might still linger in the savegame. */ @@ -169,6 +195,8 @@ struct NullSettingDesc : SettingDesc { virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } + void ParseValue(const IniItem *item, void *object) const override { NOT_REACHED(); } + bool IsSameValue(const IniItem *item, void *object) const override { NOT_REACHED(); } }; typedef std::initializer_list> SettingTable; From f58611298e17e925f98e9e36d1297f47650d4067 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 11:37:56 +0200 Subject: [PATCH 244/800] Codechange: use IntSettingDesc in the settings GUI --- src/settings_gui.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index f4570624d7..ef1024278f 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -74,7 +74,7 @@ static const StringID _font_zoom_dropdown[] = { static Dimension _circle_size; ///< Dimension of the circle +/- icon. This is here as not all users are within the class of the settings window. -static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd); +static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const IntSettingDesc *sd); /** * Get index of the current screen resolution. @@ -824,8 +824,8 @@ protected: /** Standard setting */ struct SettingEntry : BaseSettingEntry { - const char *name; ///< Name of the setting - const SettingDesc *setting; ///< Setting description of the setting + const char *name; ///< Name of the setting + const IntSettingDesc *setting; ///< Setting description of the setting SettingEntry(const char *name); @@ -1029,8 +1029,7 @@ SettingEntry::SettingEntry(const char *name) void SettingEntry::Init(byte level) { BaseSettingEntry::Init(level); - this->setting = GetSettingFromName(this->name); - assert(this->setting != nullptr); + this->setting = GetSettingFromName(this->name)->AsIntSetting(); } /* Sets the given setting entry to its default value */ @@ -1078,7 +1077,7 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const if (mode == RM_ALL) return true; GameSettings *settings_ptr = &GetGameSettings(); - const SettingDesc *sd = this->setting; + const IntSettingDesc *sd = this->setting; if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0; if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0; @@ -1122,7 +1121,7 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) bool visible = true; - const SettingDesc *sd = this->setting; + const IntSettingDesc *sd = this->setting; if (!force_visible && !filter.string.IsEmpty()) { /* Process the search text filter for this item. */ filter.string.ResetState(); @@ -1149,7 +1148,7 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) return visible; } -static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd) +static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const IntSettingDesc *sd) { if ((sd->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { @@ -1194,7 +1193,7 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const */ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const { - const SettingDesc *sd = this->setting; + const IntSettingDesc *sd = this->setting; const void *var = ResolveVariableAddress(settings_ptr, sd); int state = this->flags & SEF_BUTTONS_MASK; @@ -2075,7 +2074,7 @@ struct GameSettingsWindow : Window { case WID_GS_HELP_TEXT: if (this->last_clicked != nullptr) { - const SettingDesc *sd = this->last_clicked->setting; + const IntSettingDesc *sd = this->last_clicked->setting; int y = r.top; switch (sd->GetType()) { @@ -2179,7 +2178,7 @@ struct GameSettingsWindow : Window { SettingEntry *pe = dynamic_cast(clicked_entry); assert(pe != nullptr); - const SettingDesc *sd = pe->setting; + const IntSettingDesc *sd = pe->setting; /* return if action is only active in network, or only settable by server */ if (!sd->IsEditable()) { @@ -2314,7 +2313,7 @@ struct GameSettingsWindow : Window { if (str == nullptr) return; assert(this->valuewindow_entry != nullptr); - const SettingDesc *sd = this->valuewindow_entry->setting; + const IntSettingDesc *sd = this->valuewindow_entry->setting; int32 value; if (!StrEmpty(str)) { @@ -2361,7 +2360,7 @@ struct GameSettingsWindow : Window { if (widget < 0) { /* Deal with drop down boxes on the panel. */ assert(this->valuedropdown_entry != nullptr); - const SettingDesc *sd = this->valuedropdown_entry->setting; + const IntSettingDesc *sd = this->valuedropdown_entry->setting; assert(sd->flags & SGF_MULTISTRING); SetSettingValue(sd, index); From 0d6597a9e6255193c306537aa0061b5a89b7c658 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 21:09:30 +0200 Subject: [PATCH 245/800] Codechange: move bits of SettingDesc down to the appropriate sub classes And by doing so remove the hack where ints were put into pointers so "def" could either be an int or a string --- src/settings.cpp | 27 ++++++++++----------- src/settings_gui.cpp | 10 ++++---- src/settings_internal.h | 52 ++++++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index a99b196b4c..df064499a9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -403,7 +403,7 @@ size_t IntSettingDesc::ParseValue(const char *str) const size_t r = LookupOneOfMany(this->many, str); /* if the first attempt of conversion from string to the appropriate value fails, * look if we have defined a converter from old value to new value. */ - if (r == (size_t)-1 && this->proc_cnvt != nullptr) r = this->proc_cnvt(str); + if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str); if (r != (size_t)-1) return r; // and here goes converted value ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); @@ -437,7 +437,7 @@ size_t IntSettingDesc::ParseValue(const char *str) const default: NOT_REACHED(); } - return (size_t)this->def; + return this->def; } /** @@ -471,7 +471,7 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const val = Clamp(val, this->min, this->max); } else if (val < this->min || val > (int32)this->max) { /* Reset invalid discrete setting (where different values change gameplay) to its default value */ - val = (int32)(size_t)this->def; + val = this->def; } } break; @@ -485,7 +485,7 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const uval = ClampU(uval, this->min, this->max); } else if (uval < (uint)this->min || uval > this->max) { /* Reset invalid discrete setting to its default value */ - uval = (uint32)(size_t)this->def; + uval = (uint32)this->def; } } WriteValue(ptr, SLE_VAR_U32, (int64)uval); @@ -513,11 +513,11 @@ void StringSettingDesc::Write_ValidateSetting(const void *object, const char *st case SLE_VAR_STR: case SLE_VAR_STRQ: if (str != nullptr) { - if (this->max != 0 && strlen(str) >= this->max) { + if (this->max_length != 0 && strlen(str) >= this->max_length) { /* In case a maximum length is imposed by the setting, the length * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ - std::string stdstr(str, this->max - 1); + std::string stdstr(str, this->max_length - 1); dst->assign(str_validate(stdstr, SVS_NONE)); } else { dst->assign(str); @@ -591,19 +591,19 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::ParseValue(const IniItem *item, void *object) const { - size_t val = (item == nullptr) ? (size_t)this->def : this->ParseValue(item->value.has_value() ? item->value->c_str() : ""); + size_t val = (item == nullptr) ? this->def : this->ParseValue(item->value.has_value() ? item->value->c_str() : ""); this->Write_ValidateSetting(object, (int32)val); } void StringSettingDesc::ParseValue(const IniItem *item, void *object) const { - const char *str = (item == nullptr) ? (const char *)this->def : item->value.has_value() ? item->value->c_str() : nullptr; + const char *str = (item == nullptr) ? this->def : item->value.has_value() ? item->value->c_str() : nullptr; this->Write_ValidateSetting(object, str); } void ListSettingDesc::ParseValue(const IniItem *item, void *object) const { - const char *str = (item == nullptr) ? (const char *)this->def : item->value.has_value() ? item->value->c_str() : nullptr; + const char *str = (item == nullptr) ? this->def : item->value.has_value() ? item->value->c_str() : nullptr; void *ptr = GetVariableAddress(object, &this->save); if (!LoadIntList(str, ptr, this->save.length, GetVarMemType(this->save.conv))) { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY); @@ -611,7 +611,7 @@ void ListSettingDesc::ParseValue(const IniItem *item, void *object) const _settings_error_list.push_back(msg); /* Use default */ - LoadIntList((const char*)this->def, ptr, this->save.length, GetVarMemType(this->save.conv)); + LoadIntList(this->def, ptr, this->save.length, GetVarMemType(this->save.conv)); } } @@ -2053,7 +2053,7 @@ void SetDefaultCompanySettings(CompanyID cid) Company *c = Company::Get(cid); for (auto &sd : _company_settings) { const IntSettingDesc *int_setting = sd->AsIntSetting(); - int_setting->Write_ValidateSetting(&c->settings, (int32)(size_t)int_setting->def); + int_setting->Write_ValidateSetting(&c->settings, int_setting->def); } } @@ -2212,11 +2212,12 @@ void IConsoleGetSetting(const char *name, bool force_newgame) if (sd->cmd == SDT_STDSTRING) { const void *ptr = GetVariableAddress(object, &sd->save); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); - } else { + } else if (sd->IsIntSetting()) { char value[20]; sd->FormatValue(value, lastof(value), object); + const IntSettingDesc *int_setting = sd->AsIntSetting(); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)", - name, value, (sd->flags & SGF_0ISDISABLED) ? "(0) " : "", sd->min, sd->max); + name, value, (sd->flags & SGF_0ISDISABLED) ? "(0) " : "", int_setting->min, int_setting->max); } } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index ef1024278f..18beb690a8 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1035,8 +1035,7 @@ void SettingEntry::Init(byte level) /* Sets the given setting entry to its default value */ void SettingEntry::ResetAll() { - int32 default_value = ReadValue(&this->setting->def, this->setting->save.conv); - SetSettingValue(this->setting, default_value); + SetSettingValue(this->setting, this->setting->def); } /** @@ -1092,7 +1091,7 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const /* This entry shall only be visible, if the value deviates from its default value. */ /* Read the default value. */ - filter_value = ReadValue(&sd->def, sd->save.conv); + filter_value = sd->def; } else { assert(mode == RM_CHANGED_AGAINST_NEW); /* This entry shall only be visible, if the value deviates from @@ -2086,8 +2085,7 @@ struct GameSettingsWindow : Window { DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE); y += FONT_HEIGHT_NORMAL; - int32 default_value = ReadValue(&sd->def, sd->save.conv); - this->last_clicked->SetValueDParams(0, default_value); + this->last_clicked->SetValueDParams(0, sd->def); DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE); y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL; @@ -2324,7 +2322,7 @@ struct GameSettingsWindow : Window { value = (int32)ClampToI32(llvalue); } else { - value = (int32)(size_t)sd->def; + value = sd->def; } SetSettingValue(this->valuewindow_entry->setting, value); diff --git a/src/settings_internal.h b/src/settings_internal.h index 0914f2803f..be1dfbd936 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -85,27 +85,13 @@ typedef size_t OnConvert(const char *value); ///< callback prototype for convers /** Properties of config file settings. */ struct SettingDesc { - SettingDesc(SaveLoad save, const char *name, const void *def, SettingDescType cmd, SettingGuiFlag flags, - int32 min, uint32 max, int32 interval, const char *many, StringID str, StringID str_help, - StringID str_val, OnChange *proc, OnConvert *proc_cnvt, SettingCategory cat, bool startup) : - name(name), def(def), cmd(cmd), flags(flags), min(min), max(max), interval(interval), many(many), str(str), - str_help(str_help), str_val(str_val), proc(proc), proc_cnvt(proc_cnvt), cat(cat), startup(startup), save(save) {} + SettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup) : + name(name), flags(flags), cmd(cmd), startup(startup), save(save) {} virtual ~SettingDesc() {} const char *name; ///< name of the setting. Used in configuration file and for console - const void *def; ///< default value given when none is present - SettingDescType cmd; ///< various flags for the variable SettingGuiFlag flags; ///< handles how a setting would show up in the GUI (text/currency, etc.) - int32 min; ///< minimum values - uint32 max; ///< maximum values - int32 interval; ///< the interval to use between settings in the 'settings' window. If interval is '0' the interval is dynamically determined - const char *many; ///< ONE/MANY_OF_MANY: string of possible values for this type - StringID str; ///< (translated) string with descriptive text; gui and console - StringID str_help; ///< (Translated) string with help text; gui only. - StringID str_val; ///< (Translated) first string describing the value. - OnChange *proc; ///< callback procedure for when the value is changed - OnConvert *proc_cnvt; ///< callback procedure when loading value mechanism fails - SettingCategory cat; ///< assigned categories of the setting + SettingDescType cmd; ///< various flags for the variable bool startup; ///< setting has to be loaded directly at startup? SaveLoad save; ///< Internal structure (going to savegame, parts to config) @@ -146,12 +132,24 @@ struct SettingDesc { /** Integer type, including boolean, settings. Only these are shown in the settings UI. */ struct IntSettingDesc : SettingDesc { IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, - int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, - SettingCategory cat, OnChange *proc, const char *many = nullptr, OnConvert *many_cnvt = nullptr) : - SettingDesc(save, name, (void*)(size_t)def, cmd, flags, min, max, interval, many, str, str_help, str_val, - proc, many_cnvt, cat, startup) {} + int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, + SettingCategory cat, OnChange *proc, const char *many = nullptr, OnConvert *many_cnvt = nullptr) : + SettingDesc(save, name, flags, cmd, startup), def(def), min(min), max(max), interval(interval), + str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc), many(many), many_cnvt(many_cnvt) {} virtual ~IntSettingDesc() {} + int32 def; ///< default value given when none is present + int32 min; ///< minimum values + uint32 max; ///< maximum values + int32 interval; ///< the interval to use between settings in the 'settings' window. If interval is '0' the interval is dynamically determined + StringID str; ///< (translated) string with descriptive text; gui and console + StringID str_help; ///< (Translated) string with help text; gui only. + StringID str_val; ///< (Translated) first string describing the value. + SettingCategory cat; ///< assigned categories of the setting + OnChange *proc; ///< callback procedure for when the value is changed + const char *many; ///< ONE/MANY_OF_MANY: string of possible values for this type + OnConvert *many_cnvt; ///< callback procedure when loading value mechanism fails + void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; @@ -165,9 +163,13 @@ struct IntSettingDesc : SettingDesc { struct StringSettingDesc : SettingDesc { StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, uint32 max_length, OnChange proc) : - SettingDesc(save, name, def, cmd, flags, 0, max_length, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} + SettingDesc(save, name, flags, cmd, startup), def(def), max_length(max_length), proc(proc) {} virtual ~StringSettingDesc() {} + const char *def; ///< default value given when none is present + uint32 max_length; ///< maximum length of the string, 0 means no maximum length + OnChange *proc; ///< callback procedure for when the value is changed + void ChangeValue(const void *object, const char *newval) const; void Write_ValidateSetting(const void *object, const char *str) const; @@ -180,9 +182,11 @@ struct StringSettingDesc : SettingDesc { /** List/array settings. */ struct ListSettingDesc : SettingDesc { ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def) : - SettingDesc(save, name, def, cmd, flags, 0, 0, 0, nullptr, 0, 0, 0, proc, nullptr, SC_NONE, startup) {} + SettingDesc(save, name, flags, cmd, startup), def(def) {} virtual ~ListSettingDesc() {} + const char *def; ///< default value given when none is present + void FormatValue(char *buf, const char *last, const void *object) const override; void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; @@ -191,7 +195,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, "", nullptr, SDT_NULL, SGF_NONE, 0, 0, 0, nullptr, 0, 0, 0, nullptr, nullptr, SC_NONE, false) {} + SettingDesc(save, "", SGF_NONE, SDT_NULL, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } From 72ec81325b201931525e5c5f79abc6eb1de8d7a8 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 11:55:22 +0200 Subject: [PATCH 246/800] Cleanup: remove unneeded temporary variables and casts --- src/network/network_gui.cpp | 4 ++-- src/settings.cpp | 39 +++++++++++++++---------------------- src/settings_internal.h | 4 ++-- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index e37843db84..3c61cf77aa 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2199,7 +2199,7 @@ public: case WID_CL_SERVER_NAME_EDIT: { if (!_network_server) break; - SetSettingValue(GetSettingFromName("network.server_name"), StrEmpty(str) ? "Unnamed Server" : str); + SetSettingValue(GetSettingFromName("network.server_name")->AsStringSetting(), StrEmpty(str) ? "Unnamed Server" : str); this->InvalidateData(); break; } @@ -2208,7 +2208,7 @@ public: std::string client_name(str); if (!NetworkValidateClientName(client_name)) break; - SetSettingValue(GetSettingFromName("network.client_name"), client_name.c_str()); + SetSettingValue(GetSettingFromName("network.client_name")->AsStringSetting(), client_name.c_str()); this->InvalidateData(); break; } diff --git a/src/settings.cpp b/src/settings.cpp index df064499a9..3a71c6d2ec 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -556,14 +556,11 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co IniGroup *group_def = ini->GetGroup(grpname); for (auto &sd : settings_table) { - const SettingDesc *sdb = sd.get(); - const SaveLoad *sld = &sd->save; - - if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (sd->startup != only_startup) continue; /* For settings.xx.yy load the settings from [xx] yy = ? */ - std::string s{ sdb->name }; + std::string s{ sd->name }; auto sc = s.find('.'); if (sc != std::string::npos) { group = ini->GetGroup(s.substr(0, sc)); @@ -585,7 +582,7 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co if (sc != std::string::npos) item = ini->GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1), false); } - sdb->ParseValue(item, object); + sd->ParseValue(item, object); } } @@ -634,16 +631,13 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co char buf[512]; for (auto &sd : settings_table) { - const SettingDesc *sdb = sd.get(); - const SaveLoad *sld = &sd->save; - /* If the setting is not saved to the configuration * file, just continue with the next setting */ - if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; - if (sld->conv & SLF_NOT_IN_CONFIG) continue; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (sd->save.conv & SLF_NOT_IN_CONFIG) continue; /* XXX - wtf is this?? (group override?) */ - std::string s{ sdb->name }; + std::string s{ sd->name }; auto sc = s.find('.'); if (sc != std::string::npos) { group = ini->GetGroup(s.substr(0, sc)); @@ -655,9 +649,9 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co item = group->GetItem(s, true); - if (!item->value.has_value() || !sdb->IsSameValue(item, object)) { + if (!item->value.has_value() || !sd->IsSameValue(item, object)) { /* Value has changed, get the new value and put it into a buffer */ - sdb->FormatValue(buf, lastof(buf), object); + sd->FormatValue(buf, lastof(buf), object); /* The value is different, that means we have to write it to the ini */ item->value.emplace(buf); @@ -2009,7 +2003,7 @@ static uint GetCompanySettingIndex(const SettingDesc *sd) * @param value new value of the setting * @param force_newgame force the newgame settings */ -bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) +bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) { const IntSettingDesc *setting = sd->AsIntSetting(); if ((setting->flags & SGF_PER_COMPANY) != 0) { @@ -2090,7 +2084,7 @@ uint GetCompanySettingIndex(const char *name) * @param force_newgame force the newgame settings * @note Strings WILL NOT be synced over the network */ -bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame) +bool SetSettingValue(const StringSettingDesc *sd, const char *value, bool force_newgame) { assert(sd->save.conv & SLF_NO_NETWORK_SYNC); @@ -2165,7 +2159,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) bool success; if (sd->cmd == SDT_STDSTRING) { - success = SetSettingValue(sd, value, force_newgame); + success = SetSettingValue(sd->AsStringSetting(), value, force_newgame); } else { uint32 val; extern bool GetArgumentInteger(uint32 *value, const char *arg); @@ -2175,7 +2169,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) return; } - success = SetSettingValue(sd, val, force_newgame); + success = SetSettingValue(sd->AsIntSetting(), val, force_newgame); } if (!success) { @@ -2191,7 +2185,7 @@ void IConsoleSetSetting(const char *name, int value) { const SettingDesc *sd = GetSettingFromName(name); assert(sd != nullptr); - SetSettingValue(sd, value); + SetSettingValue(sd->AsIntSetting(), value); } /** @@ -2250,11 +2244,10 @@ void IConsoleListSettings(const char *prefilter) static void LoadSettings(const SettingTable &settings, void *object) { for (auto &osd : settings) { - const SaveLoad *sld = &osd->save; - void *ptr = GetVariableAddress(object, sld); + void *ptr = GetVariableAddress(object, &osd->save); - if (!SlObjectMember(ptr, sld)) continue; - if (osd->IsIntSetting()) osd->AsIntSetting()->Write_ValidateSetting(object, ReadValue(ptr, sld->conv)); + if (!SlObjectMember(ptr, &osd->save)) continue; + if (osd->IsIntSetting()) osd->AsIntSetting()->Write_ValidateSetting(object, ReadValue(ptr, osd->save.conv)); } } diff --git a/src/settings_internal.h b/src/settings_internal.h index be1dfbd936..5e653ec656 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -206,8 +206,8 @@ struct NullSettingDesc : SettingDesc { typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); -bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame = false); -bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame = false); +bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame = false); +bool SetSettingValue(const StringSettingDesc *sd, const char *value, bool force_newgame = false); uint GetSettingIndex(const SettingDesc *sd); #endif /* SETTINGS_INTERNAL_H */ From 860003458fc17f02e44b50f98ef570aff824142a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 18:20:49 +0200 Subject: [PATCH 247/800] Codechange: make BoolSettingDesc its own sub class --- src/settings.cpp | 30 ++++++++++++++++++------------ src/settings_internal.h | 15 +++++++++++++-- src/table/settings.h.preamble | 4 ++-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 3a71c6d2ec..f26e566867 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -423,23 +423,24 @@ size_t IntSettingDesc::ParseValue(const char *str) const break; } - case SDT_BOOLX: { - if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return true; - if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return false; - - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } - default: NOT_REACHED(); } return this->def; } +size_t BoolSettingDesc::ParseValue(const char *str) const +{ + if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return true; + if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return false; + + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); + return this->def; +} + /** * Set the value of a setting and if needed clamp the value to the preset minimum and maximum. * @param object The object the setting is to be saved in. @@ -663,7 +664,6 @@ void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object { uint32 i = (uint32)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); switch (this->cmd) { - case SDT_BOOLX: strecpy(buf, (i != 0) ? "true" : "false", last); break; case SDT_NUMX: seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); break; case SDT_ONEOFMANY: MakeOneOfMany(buf, last, this->many, i); break; case SDT_MANYOFMANY: MakeManyOfMany(buf, last, this->many, i); break; @@ -671,6 +671,12 @@ void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object } } +void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const +{ + bool val = ReadValue(GetVariableAddress(object, &this->save), this->save.conv) != 0; + strecpy(buf, val ? "true" : "false", last); +} + bool IntSettingDesc::IsSameValue(const IniItem *item, void *object) const { int64 item_value = this->ParseValue(item->value->c_str()); diff --git a/src/settings_internal.h b/src/settings_internal.h index 5e653ec656..1174a1f63a 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -129,7 +129,7 @@ struct SettingDesc { virtual bool IsSameValue(const IniItem *item, void *object) const = 0; }; -/** Integer type, including boolean, settings. Only these are shown in the settings UI. */ +/** Base integer type, including boolean, settings. Only these are shown in the settings UI. */ struct IntSettingDesc : SettingDesc { IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, @@ -153,12 +153,23 @@ struct IntSettingDesc : SettingDesc { void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; - size_t ParseValue(const char *str) const; + virtual size_t ParseValue(const char *str) const; void FormatValue(char *buf, const char *last, const void *object) const override; void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; }; +/** Boolean setting. */ +struct BoolSettingDesc : IntSettingDesc { + BoolSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, bool def, + StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc) : + IntSettingDesc(save, name, flags, cmd, startup, def, 0, 1, 0, str, str_help, str_val, cat, proc) {} + virtual ~BoolSettingDesc() {} + + size_t ParseValue(const char *str) const override; + void FormatValue(char *buf, const char *last, const void *object) const override; +}; + /** String settings. */ struct StringSettingDesc : SettingDesc { StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 6b4dc5e39f..c6788f707e 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -62,7 +62,7 @@ static size_t ConvertLandscape(const char *value); NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, SDT_BOOLX, startup, def, 0, 1, 0, str, strhelp, strval, cat, proc) + NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, SDT_BOOLX, startup, def, str, strhelp, strval, cat, proc) #define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, SDT_INTLIST, startup, def) @@ -85,7 +85,7 @@ static size_t ConvertLandscape(const char *value); NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, SDT_BOOLX, startup, def, 0, 1, 0, str, strhelp, strval, cat, proc) + NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, SDT_BOOLX, startup, def, str, strhelp, strval, cat, proc) #define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_INTLIST, startup, def) From 425d50372fab501acc97981953a6c002c0a750cf Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 09:51:33 +0200 Subject: [PATCH 248/800] Codechange: let SettingDesc extend SettingDescBase --- src/saveload/linkgraph_sl.cpp | 2 +- src/script/api/script_gamesettings.cpp | 6 +- src/settings.cpp | 78 +++++++++++++------------- src/settings_gui.cpp | 36 ++++++------ src/settings_internal.h | 3 +- 5 files changed, 62 insertions(+), 63 deletions(-) diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index e46054cf0f..3abf986e0f 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -75,7 +75,7 @@ const SaveLoad *GetLinkGraphJobDesc() int setting = 0; const SettingDesc *desc = GetSettingDescription(setting); while (desc->save.cmd != SL_END) { - if (desc->desc.name != nullptr && strncmp(desc->desc.name, prefix, prefixlen) == 0) { + if (desc->name != nullptr && strncmp(desc->name, prefix, prefixlen) == 0) { SaveLoad sl = desc->save; sl.address_proc = proc; saveloads.push_back(sl); diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 12435d253f..f96048e153 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -18,7 +18,7 @@ /* static */ bool ScriptGameSettings::IsValid(const char *setting) { const SettingDesc *sd = GetSettingFromName(setting); - return sd != nullptr && sd->desc.cmd != SDT_STDSTRING; + return sd != nullptr && sd->cmd != SDT_STDSTRING; } /* static */ int32 ScriptGameSettings::GetValue(const char *setting) @@ -28,7 +28,7 @@ const SettingDesc *sd = GetSettingFromName(setting); void *ptr = GetVariableAddress(&_settings_game, &sd->save); - if (sd->desc.cmd == SDT_BOOLX) return *(bool*)ptr; + if (sd->cmd == SDT_BOOLX) return *(bool*)ptr; return (int32)ReadValue(ptr, sd->save.conv); } @@ -40,7 +40,7 @@ const SettingDesc *sd = GetSettingFromName(setting); if ((sd->save.conv & SLF_NO_NETWORK_SYNC) != 0) return false; - if (sd->desc.cmd != SDT_BOOLX && sd->desc.cmd != SDT_NUMX) return false; + if (sd->cmd != SDT_BOOLX && sd->cmd != SDT_NUMX) return false; return ScriptObject::DoCommand(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); } diff --git a/src/settings.cpp b/src/settings.cpp index 5d4e92b358..2133fd63b4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -434,7 +434,7 @@ static const void *StringToVal(const SettingDescBase *desc, const char *orig_str */ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) { - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; if (sdb->cmd != SDT_BOOLX && sdb->cmd != SDT_NUMX && @@ -508,11 +508,11 @@ static void Write_ValidateStdString(void *ptr, const SettingDesc *sd, const char case SLE_VAR_STR: case SLE_VAR_STRQ: if (p != nullptr) { - if (sd->desc.max != 0 && strlen(p) >= sd->desc.max) { + if (sd->max != 0 && strlen(p) >= sd->max) { /* In case a maximum length is imposed by the setting, the length * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ - std::string str(p, sd->desc.max - 1); + std::string str(p, sd->max - 1); dst->assign(str_validate(str, SVS_NONE)); } else { dst->assign(p); @@ -541,11 +541,11 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp IniGroup *group_def = ini->GetGroup(grpname); for (; sd->save.cmd != SL_END; sd++) { - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; const SaveLoad *sld = &sd->save; if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; - if (sd->desc.startup != only_startup) continue; + if (sd->startup != only_startup) continue; /* For settings.xx.yy load the settings from [xx] yy = ? */ std::string s{ sdb->name }; @@ -593,8 +593,8 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp /* Use default */ LoadIntList((const char*)sdb->def, ptr, sld->length, GetVarMemType(sld->conv)); - } else if (sd->desc.proc_cnvt != nullptr) { - sd->desc.proc_cnvt((const char*)p); + } else if (sd->proc_cnvt != nullptr) { + sd->proc_cnvt((const char*)p); } break; } @@ -623,7 +623,7 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp void *ptr; for (; sd->save.cmd != SL_END; sd++) { - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; const SaveLoad *sld = &sd->save; /* If the setting is not saved to the configuration @@ -802,13 +802,13 @@ void IniSaveWindowSettings(IniFile *ini, const char *grpname, void *desc) */ bool SettingDesc::IsEditable(bool do_command) const { - if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->desc.flags & SGF_PER_COMPANY)) return false; - if ((this->desc.flags & SGF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false; - if ((this->desc.flags & SGF_NO_NETWORK) && _networking) return false; - if ((this->desc.flags & SGF_NEWGAME_ONLY) && + if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SGF_PER_COMPANY)) return false; + if ((this->flags & SGF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false; + if ((this->flags & SGF_NO_NETWORK) && _networking) return false; + if ((this->flags & SGF_NEWGAME_ONLY) && (_game_mode == GM_NORMAL || - (_game_mode == GM_EDITOR && !(this->desc.flags & SGF_SCENEDIT_TOO)))) return false; - if ((this->desc.flags & SGF_SCENEDIT_ONLY) && _game_mode != GM_EDITOR) return false; + (_game_mode == GM_EDITOR && !(this->flags & SGF_SCENEDIT_TOO)))) return false; + if ((this->flags & SGF_SCENEDIT_ONLY) && _game_mode != GM_EDITOR) return false; return true; } @@ -818,7 +818,7 @@ bool SettingDesc::IsEditable(bool do_command) const */ SettingType SettingDesc::GetType() const { - if (this->desc.flags & SGF_PER_COMPANY) return ST_COMPANY; + if (this->flags & SGF_PER_COMPANY) return ST_COMPANY; return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; } @@ -1892,14 +1892,14 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (oldval == newval) return CommandCost(); - if (sd->desc.proc != nullptr && !sd->desc.proc(newval)) { + if (sd->proc != nullptr && !sd->proc(newval)) { WriteValue(var, sd->save.conv, (int64)oldval); return CommandCost(); } - if (sd->desc.flags & SGF_NO_NETWORK) { + if (sd->flags & SGF_NO_NETWORK) { GamelogStartAction(GLAT_SETTING); - GamelogSetting(sd->desc.name, oldval, newval); + GamelogSetting(sd->name, oldval, newval); GamelogStopAction(); } @@ -1937,7 +1937,7 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 if (oldval == newval) return CommandCost(); - if (sd->desc.proc != nullptr && !sd->desc.proc(newval)) { + if (sd->proc != nullptr && !sd->proc(newval)) { WriteValue(var, sd->save.conv, (int64)oldval); return CommandCost(); } @@ -1955,7 +1955,7 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 */ uint GetSettingIndex(const SettingDesc *sd) { - assert((sd->desc.flags & SGF_PER_COMPANY) == 0); + assert((sd->flags & SGF_PER_COMPANY) == 0); return sd - _settings; } @@ -1968,14 +1968,14 @@ uint GetSettingIndex(const SettingDesc *sd) */ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) { - if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { + if ((sd->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { return DoCommandP(0, sd - _company_settings, value, CMD_CHANGE_COMPANY_SETTING); } void *var = GetVariableAddress(&_settings_client.company, &sd->save); Write_ValidateSetting(var, sd, value); - if (sd->desc.proc != nullptr) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); + if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv)); return true; } @@ -1991,7 +1991,7 @@ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) void *var2 = GetVariableAddress(&_settings_newgame, &sd->save); Write_ValidateSetting(var2, sd, value); } - if (sd->desc.proc != nullptr) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); + if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv)); SetWindowClassesDirty(WC_GAME_OPTIONS); @@ -2023,7 +2023,7 @@ void SetDefaultCompanySettings(CompanyID cid) const SettingDesc *sd; for (sd = _company_settings; sd->save.cmd != SL_END; sd++) { void *var = GetVariableAddress(&c->settings, &sd->save); - Write_ValidateSetting(var, sd, (int32)(size_t)sd->desc.def); + Write_ValidateSetting(var, sd, (int32)(size_t)sd->def); } } @@ -2051,7 +2051,7 @@ void SyncCompanySettings() uint GetCompanySettingIndex(const char *name) { const SettingDesc *sd = GetSettingFromName(name); - assert(sd != nullptr && (sd->desc.flags & SGF_PER_COMPANY) != 0); + assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) != 0); return sd - _company_settings; } @@ -2072,7 +2072,7 @@ bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgam void *ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); Write_ValidateStdString(ptr, sd, value); - if (sd->desc.proc != nullptr) sd->desc.proc(0); + if (sd->proc != nullptr) sd->proc(0); if (_save_config) SaveToConfig(); return true; @@ -2090,13 +2090,13 @@ const SettingDesc *GetSettingFromName(const char *name) /* First check all full names */ for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->desc.name, name) == 0) return sd; + if (strcmp(sd->name, name) == 0) return sd; } /* Then check the shortcut variant of the name. */ for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - const char *short_name = strchr(sd->desc.name, '.'); + const char *short_name = strchr(sd->name, '.'); if (short_name != nullptr) { short_name++; if (strcmp(short_name, name) == 0) return sd; @@ -2107,7 +2107,7 @@ const SettingDesc *GetSettingFromName(const char *name) /* And finally the company-based settings */ for (const SettingDesc *sd = _company_settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->desc.name, name) == 0) return sd; + if (strcmp(sd->name, name) == 0) return sd; } return nullptr; @@ -2125,7 +2125,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) } bool success; - if (sd->desc.cmd == SDT_STDSTRING) { + if (sd->cmd == SDT_STDSTRING) { success = SetSettingValue(sd, value, force_newgame); } else { uint32 val; @@ -2173,17 +2173,17 @@ void IConsoleGetSetting(const char *name, bool force_newgame) ptr = GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->save); - if (sd->desc.cmd == SDT_STDSTRING) { + if (sd->cmd == SDT_STDSTRING) { IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); } else { - if (sd->desc.cmd == SDT_BOOLX) { + if (sd->cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool*)ptr != 0) ? "on" : "off"); } else { - seprintf(value, lastof(value), sd->desc.min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); + seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); } IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)", - name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max); + name, value, (sd->flags & SGF_0ISDISABLED) ? "(0) " : "", sd->min, sd->max); } } @@ -2198,18 +2198,18 @@ void IConsoleListSettings(const char *prefilter) for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (prefilter != nullptr && strstr(sd->desc.name, prefilter) == nullptr) continue; + if (prefilter != nullptr && strstr(sd->name, prefilter) == nullptr) continue; char value[80]; const void *ptr = GetVariableAddress(&GetGameSettings(), &sd->save); - if (sd->desc.cmd == SDT_BOOLX) { + if (sd->cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); - } else if (sd->desc.cmd == SDT_STDSTRING) { + } else if (sd->cmd == SDT_STDSTRING) { seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); } else { - seprintf(value, lastof(value), sd->desc.min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); + seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); } - IConsolePrintF(CC_DEFAULT, "%s = %s", sd->desc.name, value); + IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name, value); } IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index b069d27066..edde335601 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -843,7 +843,7 @@ struct SettingEntry : BaseSettingEntry { */ inline StringID GetHelpText() const { - return this->setting->desc.str_help; + return this->setting->str_help; } void SetValueDParams(uint first_param, int32 value) const; @@ -1036,7 +1036,7 @@ void SettingEntry::Init(byte level) /* Sets the given setting entry to its default value */ void SettingEntry::ResetAll() { - int32 default_value = ReadValue(&this->setting->desc.def, this->setting->save.conv); + int32 default_value = ReadValue(&this->setting->def, this->setting->save.conv); SetSettingValue(this->setting, default_value); } @@ -1080,8 +1080,8 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const GameSettings *settings_ptr = &GetGameSettings(); const SettingDesc *sd = this->setting; - if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0; - if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0; + if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0; + if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0; /* Read the current value. */ const void *var = ResolveVariableAddress(settings_ptr, sd); @@ -1093,7 +1093,7 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const /* This entry shall only be visible, if the value deviates from its default value. */ /* Read the default value. */ - filter_value = ReadValue(&sd->desc.def, sd->save.conv); + filter_value = ReadValue(&sd->def, sd->save.conv); } else { assert(mode == RM_CHANGED_AGAINST_NEW); /* This entry shall only be visible, if the value deviates from @@ -1127,7 +1127,7 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) /* Process the search text filter for this item. */ filter.string.ResetState(); - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; SetDParam(0, STR_EMPTY); filter.string.AddLine(sdb->str); @@ -1153,7 +1153,7 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd) { - if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { + if ((sd->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { return GetVariableAddress(&Company::Get(_local_company)->settings, &sd->save); } else { @@ -1171,7 +1171,7 @@ static const void *ResolveVariableAddress(const GameSettings *settings_ptr, cons */ void SettingEntry::SetValueDParams(uint first_param, int32 value) const { - const SettingDescBase *sdb = &this->setting->desc; + const SettingDescBase *sdb = this->setting; if (sdb->cmd == SDT_BOOLX) { SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); } else { @@ -1198,7 +1198,7 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const { const SettingDesc *sd = this->setting; - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; const void *var = ResolveVariableAddress(settings_ptr, sd); int state = this->flags & SEF_BUTTONS_MASK; @@ -2091,7 +2091,7 @@ struct GameSettingsWindow : Window { DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE); y += FONT_HEIGHT_NORMAL; - int32 default_value = ReadValue(&sd->desc.def, sd->save.conv); + int32 default_value = ReadValue(&sd->def, sd->save.conv); this->last_clicked->SetValueDParams(0, default_value); DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE); y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL; @@ -2195,8 +2195,8 @@ struct GameSettingsWindow : Window { int32 value = (int32)ReadValue(var, sd->save.conv); /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */ - if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) { - const SettingDescBase *sdb = &sd->desc; + if (x < SETTING_BUTTON_WIDTH && (sd->flags & SGF_MULTISTRING)) { + const SettingDescBase *sdb = sd; this->SetDisplayedHelpText(pe); if (this->valuedropdown_entry == pe) { @@ -2234,7 +2234,7 @@ struct GameSettingsWindow : Window { this->SetDirty(); } else if (x < SETTING_BUTTON_WIDTH) { this->SetDisplayedHelpText(pe); - const SettingDescBase *sdb = &sd->desc; + const SettingDescBase *sdb = sd; int32 oldvalue = value; switch (sdb->cmd) { @@ -2291,10 +2291,10 @@ struct GameSettingsWindow : Window { } } else { /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */ - if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) { + if (this->last_clicked == pe && sd->cmd != SDT_BOOLX && !(sd->flags & SGF_MULTISTRING)) { int64 value64 = value; /* Show the correct currency-translated value */ - if (sd->desc.flags & SGF_CURRENCY) value64 *= _currency->rate; + if (sd->flags & SGF_CURRENCY) value64 *= _currency->rate; this->valuewindow_entry = pe; SetDParam(0, value64); @@ -2327,11 +2327,11 @@ struct GameSettingsWindow : Window { long long llvalue = atoll(str); /* Save the correct currency-translated value */ - if (sd->desc.flags & SGF_CURRENCY) llvalue /= _currency->rate; + if (sd->flags & SGF_CURRENCY) llvalue /= _currency->rate; value = (int32)ClampToI32(llvalue); } else { - value = (int32)(size_t)sd->desc.def; + value = (int32)(size_t)sd->def; } SetSettingValue(this->valuewindow_entry->setting, value); @@ -2368,7 +2368,7 @@ struct GameSettingsWindow : Window { /* Deal with drop down boxes on the panel. */ assert(this->valuedropdown_entry != nullptr); const SettingDesc *sd = this->valuedropdown_entry->setting; - assert(sd->desc.flags & SGF_MULTISTRING); + assert(sd->flags & SGF_MULTISTRING); SetSettingValue(sd, index); this->SetDirty(); diff --git a/src/settings_internal.h b/src/settings_internal.h index fc8e0a1e30..f92480a764 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -100,8 +100,7 @@ struct SettingDescBase { bool startup; ///< setting has to be loaded directly at startup? }; -struct SettingDesc { - SettingDescBase desc; ///< Settings structure (going to configuration file) +struct SettingDesc : SettingDescBase { SaveLoad save; ///< Internal structure (going to savegame, parts to config) bool IsEditable(bool do_command = false) const; From e666a962b1f0f8eeb3bab2232ce77556ddab974a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 19:16:56 +0200 Subject: [PATCH 249/800] Codechange: let OneOfMany and ManyOfMany be their own classes as well --- src/settings.cpp | 192 ++++++++++++--------------------- src/settings_internal.h | 41 ++++++- src/table/gameopt_settings.ini | 20 ++-- src/table/misc_settings.ini | 5 +- src/table/settings.h.preamble | 8 +- 5 files changed, 123 insertions(+), 143 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index f26e566867..24950e779e 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -127,31 +127,23 @@ static const char * const _list_group_names[] = { /** * Find the index value of a ONEofMANY type in a string separated by | + * @param str the current value of the setting for which a value needs found + * @param len length of the string * @param many full domain of values the ONEofMANY setting can have - * @param one the current value of the setting for which a value needs found - * @param onelen force calculation of the *one parameter * @return the integer index of the full-list, or -1 if not found */ -static size_t LookupOneOfMany(const char *many, const char *one, size_t onelen = 0) +size_t OneOfManySettingDesc::ParseSingleValue(const char *str, size_t len, const std::vector &many) { - const char *s; - size_t idx; - - if (onelen == 0) onelen = strlen(one); - /* check if it's an integer */ - if (*one >= '0' && *one <= '9') return strtoul(one, nullptr, 0); + if (isdigit(*str)) return strtoul(str, nullptr, 0); - idx = 0; - for (;;) { - /* find end of item */ - s = many; - while (*s != '|' && *s != 0) s++; - if ((size_t)(s - many) == onelen && !memcmp(one, many, onelen)) return idx; - if (*s == 0) return (size_t)-1; - many = s + 1; + size_t idx = 0; + for (auto one : many) { + if (one.size() == len && strncmp(one.c_str(), str, len) == 0) return idx; idx++; } + + return (size_t)-1; } /** @@ -161,7 +153,7 @@ static size_t LookupOneOfMany(const char *many, const char *one, size_t onelen = * of separated by a whitespace,tab or | character * @return the 'fully' set integer, or -1 if a set is not found */ -static size_t LookupManyOfMany(const char *many, const char *str) +static size_t LookupManyOfMany(const std::vector &many, const char *str) { const char *s; size_t r; @@ -175,7 +167,7 @@ static size_t LookupManyOfMany(const char *many, const char *str) s = str; while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++; - r = LookupOneOfMany(many, str, s - str); + r = OneOfManySettingDesc::ParseSingleValue(str, s - str, many); if (r == (size_t)-1) return r; SetBit(res, (uint8)r); // value found, set it @@ -311,66 +303,30 @@ void ListSettingDesc::FormatValue(char *buf, const char *last, const void *objec } } -/** - * Convert a ONEofMANY structure to a string representation. - * @param buf output buffer where the string-representation will be stored - * @param last last item to write to in the output buffer - * @param many the full-domain string of possible values - * @param id the value of the variable and whose string-representation must be found - */ -static void MakeOneOfMany(char *buf, const char *last, const char *many, int id) +char *OneOfManySettingDesc::FormatSingleValue(char *buf, const char *last, uint id) const { - int orig_id = id; - - /* Look for the id'th element */ - while (--id >= 0) { - for (; *many != '|'; many++) { - if (*many == '\0') { // not found - seprintf(buf, last, "%d", orig_id); - return; - } - } - many++; // pass the |-character + if (id >= this->many.size()) { + return buf + seprintf(buf, last, "%d", id); } - - /* copy string until next item (|) or the end of the list if this is the last one */ - while (*many != '\0' && *many != '|' && buf < last) *buf++ = *many++; - *buf = '\0'; + return strecpy(buf, this->many[id].c_str(), last); } -/** - * Convert a MANYofMANY structure to a string representation. - * @param buf output buffer where the string-representation will be stored - * @param last last item to write to in the output buffer - * @param many the full-domain string of possible values - * @param x the value of the variable and whose string-representation must - * be found in the bitmasked many string - */ -static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 x) +void OneOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - const char *start; - int i = 0; - bool init = true; + uint id = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + this->FormatSingleValue(buf, last, id); +} - for (; x != 0; x >>= 1, i++) { - start = many; - while (*many != 0 && *many != '|') many++; // advance to the next element - - if (HasBit(x, 0)) { // item found, copy it - if (!init) buf += seprintf(buf, last, "|"); - init = false; - if (start == many) { - buf += seprintf(buf, last, "%d", i); - } else { - memcpy(buf, start, many - start); - buf += many - start; - } - } - - if (*many == '|') many++; +void ManyOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const +{ + uint bitmask = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + uint id = 0; + bool first = true; + FOR_EACH_SET_BIT(id, bitmask) { + if (!first) buf = strecpy(buf, "|", last); + buf = this->FormatSingleValue(buf, last, id); + first = false; } - - *buf = '\0'; } /** @@ -380,52 +336,46 @@ static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 */ size_t IntSettingDesc::ParseValue(const char *str) const { - switch (this->cmd) { - case SDT_NUMX: { - char *end; - size_t val = strtoul(str, &end, 0); - if (end == str) { - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } - if (*end != '\0') { - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS); - msg.SetDParamStr(0, this->name); - _settings_error_list.push_back(msg); - } - return val; - } - - case SDT_ONEOFMANY: { - size_t r = LookupOneOfMany(this->many, str); - /* if the first attempt of conversion from string to the appropriate value fails, - * look if we have defined a converter from old value to new value. */ - if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str); - if (r != (size_t)-1) return r; // and here goes converted value - - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } - - case SDT_MANYOFMANY: { - size_t r = LookupManyOfMany(this->many, str); - if (r != (size_t)-1) return r; - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } - - default: NOT_REACHED(); + char *end; + size_t val = strtoul(str, &end, 0); + if (end == str) { + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); + return this->def; } + if (*end != '\0') { + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS); + msg.SetDParamStr(0, this->name); + _settings_error_list.push_back(msg); + } + return val; +} +size_t OneOfManySettingDesc::ParseValue(const char *str) const +{ + size_t r = OneOfManySettingDesc::ParseSingleValue(str, strlen(str), this->many); + /* if the first attempt of conversion from string to the appropriate value fails, + * look if we have defined a converter from old value to new value. */ + if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str); + if (r != (size_t)-1) return r; // and here goes converted value + + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); + return this->def; +} + +size_t ManyOfManySettingDesc::ParseValue(const char *str) const +{ + size_t r = LookupManyOfMany(this->many, str); + if (r != (size_t)-1) return r; + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); return this->def; } @@ -663,12 +613,7 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { uint32 i = (uint32)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); - switch (this->cmd) { - case SDT_NUMX: seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); break; - case SDT_ONEOFMANY: MakeOneOfMany(buf, last, this->many, i); break; - case SDT_MANYOFMANY: MakeManyOfMany(buf, last, this->many, i); break; - default: NOT_REACHED(); - } + seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); } void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const @@ -1263,7 +1208,8 @@ static bool CheckRoadSide(int p1) static size_t ConvertLandscape(const char *value) { /* try with the old values */ - return LookupOneOfMany("normal|hilly|desert|candy", value); + static std::vector _old_landscape_values{"normal", "hilly", "desert", "candy"}; + return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values); } static bool CheckFreeformEdges(int32 p1) diff --git a/src/settings_internal.h b/src/settings_internal.h index 1174a1f63a..488b85441d 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -133,9 +133,9 @@ struct SettingDesc { struct IntSettingDesc : SettingDesc { IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, - SettingCategory cat, OnChange *proc, const char *many = nullptr, OnConvert *many_cnvt = nullptr) : + SettingCategory cat, OnChange *proc) : SettingDesc(save, name, flags, cmd, startup), def(def), min(min), max(max), interval(interval), - str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc), many(many), many_cnvt(many_cnvt) {} + str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc) {} virtual ~IntSettingDesc() {} int32 def; ///< default value given when none is present @@ -147,8 +147,6 @@ struct IntSettingDesc : SettingDesc { StringID str_val; ///< (Translated) first string describing the value. SettingCategory cat; ///< assigned categories of the setting OnChange *proc; ///< callback procedure for when the value is changed - const char *many; ///< ONE/MANY_OF_MANY: string of possible values for this type - OnConvert *many_cnvt; ///< callback procedure when loading value mechanism fails void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; @@ -170,6 +168,41 @@ struct BoolSettingDesc : IntSettingDesc { void FormatValue(char *buf, const char *last, const void *object) const override; }; +/** One of many setting. */ +struct OneOfManySettingDesc : IntSettingDesc { + OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, + std::initializer_list many, OnConvert *many_cnvt) : + IntSettingDesc(save, name, flags, cmd, startup, def, 0, max, 0, str, str_help, str_val, cat, proc), many_cnvt(many_cnvt) + { + for (auto one : many) this->many.push_back(one); + } + + virtual ~OneOfManySettingDesc() {} + + std::vector many; ///< possible values for this type + OnConvert *many_cnvt; ///< callback procedure when loading value mechanism fails + + static size_t ParseSingleValue(const char *str, size_t len, const std::vector &many); + char *FormatSingleValue(char *buf, const char *last, uint id) const; + + size_t ParseValue(const char *str) const override; + void FormatValue(char *buf, const char *last, const void *object) const override; +}; + +/** Many of many setting. */ +struct ManyOfManySettingDesc : OneOfManySettingDesc { + ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, + std::initializer_list many, OnConvert *many_cnvt) : + OneOfManySettingDesc(save, name, flags, cmd, startup, def, (1 << many.size()) - 1, str, str_help, + str_val, cat, proc, many, many_cnvt) {} + virtual ~ManyOfManySettingDesc() {} + + size_t ParseValue(const char *str) const override; + void FormatValue(char *buf, const char *last, const void *object) const override; +}; + /** String settings. */ struct StringSettingDesc : SettingDesc { StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 1e60770f21..56ac7d7816 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -12,16 +12,16 @@ uint8 _old_units; ///< Old units from old s /* Most of these strings are used both for gameopt-backward compatibility * and the settings tables. The rest is here for consistency. */ -static const char *_locale_currencies = "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|RON|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom"; -static const char *_locale_units = "imperial|metric|si|gameunits"; -static const char *_town_names = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovak|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan"; -static const char *_climates = "temperate|arctic|tropic|toyland"; -static const char *_autosave_interval = "off|monthly|quarterly|half year|yearly"; -static const char *_roadsides = "left|right"; -static const char *_savegame_date = "long|short|iso"; -static const char *_osk_activation = "disabled|double|single|immediately"; -static const char *_settings_profiles = "easy|medium|hard"; -static const char *_news_display = "off|summarized|full"; +static std::initializer_list _locale_currencies{"GBP", "USD", "EUR", "YEN", "ATS", "BEF", "CHF", "CZK", "DEM", "DKK", "ESP", "FIM", "FRF", "GRD", "HUF", "ISK", "ITL", "NLG", "NOK", "PLN", "RON", "RUR", "SIT", "SEK", "YTL", "SKK", "BRL", "EEK", "custom"}; +static std::initializer_list _locale_units{"imperial", "metric", "si", "gameunits"}; +static std::initializer_list _town_names{"english", "french", "german", "american", "latin", "silly", "swedish", "dutch", "finnish", "polish", "slovak", "norwegian", "hungarian", "austrian", "romanian", "czech", "swiss", "danish", "turkish", "italian", "catalan"}; +static std::initializer_list _climates{"temperate", "arctic", "tropic", "toyland"}; +static std::initializer_list _autosave_interval{"off", "monthly", "quarterly", "half year", "yearly"}; +static std::initializer_list _roadsides{"left", "right"}; +static std::initializer_list _savegame_date{"long", "short", "iso"}; +static std::initializer_list _osk_activation{"disabled", "double", "single", "immediately"}; +static std::initializer_list _settings_profiles{"easy", "medium", "hard"}; +static std::initializer_list _news_display{ "off", "summarized", "full"}; static const SettingTable _gameopt_settings{ /* In version 4 a new difficulty setting has been added to the difficulty settings, diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index a3efbc65e8..017320c863 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -7,7 +7,8 @@ [pre-amble] extern std::string _config_language_file; -static const char *_support8bppmodes = "no|system|hardware"; +static std::initializer_list _support8bppmodes{"no", "system" , "hardware"}; +static std::initializer_list _display_opt_modes{"SHOW_TOWN_NAMES", "SHOW_STATION_NAMES", "SHOW_SIGNS", "FULL_ANIMATION", "", "FULL_DETAIL", "WAYPOINTS", "SHOW_COMPETITOR_SIGNS"}; #ifdef WITH_COCOA extern bool _allow_hidpi_window; @@ -53,7 +54,7 @@ name = ""display_opt"" type = SLE_UINT8 var = _display_opt def = (1 << DO_SHOW_TOWN_NAMES | 1 << DO_SHOW_STATION_NAMES | 1 << DO_SHOW_SIGNS | 1 << DO_FULL_ANIMATION | 1 << DO_FULL_DETAIL | 1 << DO_SHOW_WAYPOINT_NAMES | 1 << DO_SHOW_COMPETITOR_SIGNS) -full = ""SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION||FULL_DETAIL|WAYPOINTS|SHOW_COMPETITOR_SIGNS"" +full = _display_opt_modes [SDTG_BOOL] name = ""fullscreen"" diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index c6788f707e..df10b6deb6 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -71,10 +71,10 @@ static size_t ConvertLandscape(const char *value); NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, SDT_STDSTRING, startup, def, max_length, proc) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full) + NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full) + NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_NULL(length, from, to)\ NSD(Null, SLEG_NULL(length, from, to)) @@ -94,10 +94,10 @@ static size_t ConvertLandscape(const char *value); NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_STDSTRING, startup, def, 0, proc) #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full, load) + NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, load) #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full, nullptr) + NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDT_NULL(length, from, to)\ NSD(Null, SLE_CONDNULL(length, from, to)) From 8ffb4122df903393bceca49a25ac81cc42cca3ff Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 18 May 2021 20:57:44 +0200 Subject: [PATCH 250/800] Codechange: just pass the SettingDesc to SetSettingValue and remove distinction between (non)company --- src/network/network_gui.cpp | 8 +-- src/news_gui.cpp | 3 +- src/script/api/script_gamesettings.cpp | 11 ++-- src/settings.cpp | 82 ++++++++++++-------------- src/settings_gui.cpp | 25 ++------ src/settings_internal.h | 8 +-- 6 files changed, 54 insertions(+), 83 deletions(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index f0c28530a6..e37843db84 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2199,9 +2199,7 @@ public: case WID_CL_SERVER_NAME_EDIT: { if (!_network_server) break; - uint index; - GetSettingFromName("network.server_name", &index); - SetSettingValue(index, StrEmpty(str) ? "Unnamed Server" : str); + SetSettingValue(GetSettingFromName("network.server_name"), StrEmpty(str) ? "Unnamed Server" : str); this->InvalidateData(); break; } @@ -2210,9 +2208,7 @@ public: std::string client_name(str); if (!NetworkValidateClientName(client_name)) break; - uint index; - GetSettingFromName("network.client_name", &index); - SetSettingValue(index, client_name.c_str()); + SetSettingValue(GetSettingFromName("network.client_name"), client_name.c_str()); this->InvalidateData(); break; } diff --git a/src/news_gui.cpp b/src/news_gui.cpp index e3fb600336..58d62dde81 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -253,8 +253,7 @@ static_assert(lengthof(_news_type_data) == NT_END); */ NewsDisplay NewsTypeData::GetDisplay() const { - uint index; - const SettingDesc *sd = GetSettingFromName(this->name, &index); + const SettingDesc *sd = GetSettingFromName(this->name); assert(sd != nullptr); void *ptr = GetVariableAddress(nullptr, &sd->save); return (NewsDisplay)ReadValue(ptr, sd->save.conv); diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 2717d4ddd8..12435d253f 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -17,8 +17,7 @@ /* static */ bool ScriptGameSettings::IsValid(const char *setting) { - uint i; - const SettingDesc *sd = GetSettingFromName(setting, &i); + const SettingDesc *sd = GetSettingFromName(setting); return sd != nullptr && sd->desc.cmd != SDT_STDSTRING; } @@ -26,8 +25,7 @@ { if (!IsValid(setting)) return -1; - uint index; - const SettingDesc *sd = GetSettingFromName(setting, &index); + const SettingDesc *sd = GetSettingFromName(setting); void *ptr = GetVariableAddress(&_settings_game, &sd->save); if (sd->desc.cmd == SDT_BOOLX) return *(bool*)ptr; @@ -39,13 +37,12 @@ { if (!IsValid(setting)) return false; - uint index; - const SettingDesc *sd = GetSettingFromName(setting, &index); + const SettingDesc *sd = GetSettingFromName(setting); if ((sd->save.conv & SLF_NO_NETWORK_SYNC) != 0) return false; if (sd->desc.cmd != SDT_BOOLX && sd->desc.cmd != SDT_NUMX) return false; - return ScriptObject::DoCommand(0, index, value, CMD_CHANGE_SETTING); + return ScriptObject::DoCommand(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); } /* static */ bool ScriptGameSettings::IsDisabledVehicleType(ScriptVehicle::VehicleType vehicle_type) diff --git a/src/settings.cpp b/src/settings.cpp index 6882179eb0..5d4e92b358 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1948,6 +1948,17 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 return CommandCost(); } +/** + * Get the index of the setting with this description. + * @param sd the setting to get the index for. + * @return the index of the setting to be used for CMD_CHANGE_SETTING. + */ +uint GetSettingIndex(const SettingDesc *sd) +{ + assert((sd->desc.flags & SGF_PER_COMPANY) == 0); + return sd - _settings; +} + /** * Top function to save the new value of an element of the Settings struct * @param index offset in the SettingDesc array of the Settings struct which @@ -1955,9 +1966,19 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 * @param value new value of the setting * @param force_newgame force the newgame settings */ -bool SetSettingValue(uint index, int32 value, bool force_newgame) +bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) { - const SettingDesc *sd = &_settings[index]; + if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { + if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { + return DoCommandP(0, sd - _company_settings, value, CMD_CHANGE_COMPANY_SETTING); + } + + void *var = GetVariableAddress(&_settings_client.company, &sd->save); + Write_ValidateSetting(var, sd, value); + if (sd->desc.proc != nullptr) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); + return true; + } + /* If an item is company-based, we do not send it over the network * (if any) to change. Also *hack*hack* we update the _newgame version * of settings because changing a company-based setting in a game also @@ -1988,29 +2009,11 @@ bool SetSettingValue(uint index, int32 value, bool force_newgame) /* send non-company-based settings over the network */ if (!_networking || (_networking && _network_server)) { - return DoCommandP(0, index, value, CMD_CHANGE_SETTING); + return DoCommandP(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); } return false; } -/** - * Top function to save the new value of an element of the Settings struct - * @param index offset in the SettingDesc array of the CompanySettings struct - * which identifies the setting member we want to change - * @param value new value of the setting - */ -void SetCompanySetting(uint index, int32 value) -{ - const SettingDesc *sd = &_company_settings[index]; - if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { - DoCommandP(0, index, value, CMD_CHANGE_COMPANY_SETTING); - } else { - void *var = GetVariableAddress(&_settings_client.company, &sd->save); - Write_ValidateSetting(var, sd, value); - if (sd->desc.proc != nullptr) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); - } -} - /** * Set the company settings for a new company to their default values. */ @@ -2047,23 +2050,20 @@ void SyncCompanySettings() */ uint GetCompanySettingIndex(const char *name) { - uint i; - const SettingDesc *sd = GetSettingFromName(name, &i); - (void)sd; // Unused without asserts + const SettingDesc *sd = GetSettingFromName(name); assert(sd != nullptr && (sd->desc.flags & SGF_PER_COMPANY) != 0); - return i; + return sd - _company_settings; } /** * Set a setting value with a string. - * @param index the settings index. + * @param sd the setting to change. * @param value the value to write * @param force_newgame force the newgame settings * @note Strings WILL NOT be synced over the network */ -bool SetSettingValue(uint index, const char *value, bool force_newgame) +bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame) { - const SettingDesc *sd = &_settings[index]; assert(sd->save.conv & SLF_NO_NETWORK_SYNC); if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && strcmp(value, "(null)") == 0) { @@ -2085,18 +2085,16 @@ bool SetSettingValue(uint index, const char *value, bool force_newgame) * @return Pointer to the setting description of setting \a name if it can be found, * \c nullptr indicates failure to obtain the description */ -const SettingDesc *GetSettingFromName(const char *name, uint *i) +const SettingDesc *GetSettingFromName(const char *name) { - const SettingDesc *sd; - /* First check all full names */ - for (*i = 0, sd = _settings; sd->save.cmd != SL_END; sd++, (*i)++) { + for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (strcmp(sd->desc.name, name) == 0) return sd; } /* Then check the shortcut variant of the name. */ - for (*i = 0, sd = _settings; sd->save.cmd != SL_END; sd++, (*i)++) { + for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; const char *short_name = strchr(sd->desc.name, '.'); if (short_name != nullptr) { @@ -2107,7 +2105,7 @@ const SettingDesc *GetSettingFromName(const char *name, uint *i) if (strncmp(name, "company.", 8) == 0) name += 8; /* And finally the company-based settings */ - for (*i = 0, sd = _company_settings; sd->save.cmd != SL_END; sd++, (*i)++) { + for (const SettingDesc *sd = _company_settings; sd->save.cmd != SL_END; sd++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (strcmp(sd->desc.name, name) == 0) return sd; } @@ -2119,8 +2117,7 @@ const SettingDesc *GetSettingFromName(const char *name, uint *i) * and besides, it is also better to keep stuff like this at the same place */ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) { - uint index; - const SettingDesc *sd = GetSettingFromName(name, &index); + const SettingDesc *sd = GetSettingFromName(name); if (sd == nullptr) { IConsolePrintF(CC_WARNING, "'%s' is an unknown setting.", name); @@ -2129,7 +2126,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) bool success; if (sd->desc.cmd == SDT_STDSTRING) { - success = SetSettingValue(index, value, force_newgame); + success = SetSettingValue(sd, value, force_newgame); } else { uint32 val; extern bool GetArgumentInteger(uint32 *value, const char *arg); @@ -2139,7 +2136,7 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) return; } - success = SetSettingValue(index, val, force_newgame); + success = SetSettingValue(sd, val, force_newgame); } if (!success) { @@ -2153,11 +2150,9 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) void IConsoleSetSetting(const char *name, int value) { - uint index; - const SettingDesc *sd = GetSettingFromName(name, &index); - (void)sd; // Unused without asserts + const SettingDesc *sd = GetSettingFromName(name); assert(sd != nullptr); - SetSettingValue(index, value); + SetSettingValue(sd, value); } /** @@ -2168,8 +2163,7 @@ void IConsoleSetSetting(const char *name, int value) void IConsoleGetSetting(const char *name, bool force_newgame) { char value[20]; - uint index; - const SettingDesc *sd = GetSettingFromName(name, &index); + const SettingDesc *sd = GetSettingFromName(name); const void *ptr; if (sd == nullptr) { diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 664cfbd218..b069d27066 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -826,7 +826,6 @@ protected: struct SettingEntry : BaseSettingEntry { const char *name; ///< Name of the setting const SettingDesc *setting; ///< Setting description of the setting - uint index; ///< Index of the setting in the settings table SettingEntry(const char *name); @@ -1021,7 +1020,6 @@ SettingEntry::SettingEntry(const char *name) { this->name = name; this->setting = nullptr; - this->index = 0; } /** @@ -1031,7 +1029,7 @@ SettingEntry::SettingEntry(const char *name) void SettingEntry::Init(byte level) { BaseSettingEntry::Init(level); - this->setting = GetSettingFromName(this->name, &this->index); + this->setting = GetSettingFromName(this->name); assert(this->setting != nullptr); } @@ -1039,7 +1037,7 @@ void SettingEntry::Init(byte level) void SettingEntry::ResetAll() { int32 default_value = ReadValue(&this->setting->desc.def, this->setting->save.conv); - SetSettingValue(this->index, default_value); + SetSettingValue(this->setting, default_value); } /** @@ -2288,11 +2286,7 @@ struct GameSettingsWindow : Window { } if (value != oldvalue) { - if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { - SetCompanySetting(pe->index, value); - } else { - SetSettingValue(pe->index, value); - } + SetSettingValue(sd, value); this->SetDirty(); } } else { @@ -2340,11 +2334,7 @@ struct GameSettingsWindow : Window { value = (int32)(size_t)sd->desc.def; } - if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { - SetCompanySetting(this->valuewindow_entry->index, value); - } else { - SetSettingValue(this->valuewindow_entry->index, value); - } + SetSettingValue(this->valuewindow_entry->setting, value); this->SetDirty(); } @@ -2380,12 +2370,7 @@ struct GameSettingsWindow : Window { const SettingDesc *sd = this->valuedropdown_entry->setting; assert(sd->desc.flags & SGF_MULTISTRING); - if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { - SetCompanySetting(this->valuedropdown_entry->index, index); - } else { - SetSettingValue(this->valuedropdown_entry->index, index); - } - + SetSettingValue(sd, index); this->SetDirty(); } break; diff --git a/src/settings_internal.h b/src/settings_internal.h index d5f237f3cc..225bb71953 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -123,9 +123,9 @@ struct SettingDesc { * offset in a certain struct */ typedef SettingDesc SettingDescGlobVarList; -const SettingDesc *GetSettingFromName(const char *name, uint *i); -bool SetSettingValue(uint index, int32 value, bool force_newgame = false); -bool SetSettingValue(uint index, const char *value, bool force_newgame = false); -void SetCompanySetting(uint index, int32 value); +const SettingDesc *GetSettingFromName(const char *name); +bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame = false); +bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame = false); +uint GetSettingIndex(const SettingDesc *sd); #endif /* SETTINGS_INTERNAL_H */ From 3bb6ce8827b71ae1dcfde4a7836fb6c636fb5a67 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Tue, 18 May 2021 21:01:42 +0200 Subject: [PATCH 251/800] Codechange: use initializer_lists for the settings tables Not using vectors as those require copying from the initializer list and that makes unique_ptrs to the actual SettingDesc objects later impossible. --- src/saveload/linkgraph_sl.cpp | 4 +- src/settings.cpp | 169 ++++++++++++++++++-------------- src/settings_internal.h | 2 + src/table/company_settings.ini | 8 +- src/table/currency_settings.ini | 6 +- src/table/gameopt_settings.ini | 6 +- src/table/misc_settings.ini | 6 +- src/table/settings.h.preamble | 4 - src/table/settings.ini | 6 +- src/table/win32_settings.ini | 6 +- src/table/window_settings.ini | 7 +- 11 files changed, 107 insertions(+), 117 deletions(-) diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index 3abf986e0f..af28902445 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -74,7 +74,7 @@ const SaveLoad *GetLinkGraphJobDesc() int setting = 0; const SettingDesc *desc = GetSettingDescription(setting); - while (desc->save.cmd != SL_END) { + while (desc != nullptr) { if (desc->name != nullptr && strncmp(desc->name, prefix, prefixlen) == 0) { SaveLoad sl = desc->save; sl.address_proc = proc; @@ -86,7 +86,7 @@ const SaveLoad *GetLinkGraphJobDesc() int i = 0; do { saveloads.push_back(job_desc[i++]); - } while (saveloads[saveloads.size() - 1].cmd != SL_END); + } while (saveloads.back().cmd != SL_END); } return &saveloads[0]; diff --git a/src/settings.cpp b/src/settings.cpp index 2133fd63b4..746e477da9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -87,11 +87,33 @@ typedef std::list ErrorList; static ErrorList _settings_error_list; ///< Errors while loading minimal settings. -typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname, void *object, bool only_startup); +typedef void SettingDescProc(IniFile *ini, const SettingTable &desc, const char *grpname, void *object, bool only_startup); typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList &list); static bool IsSignedVarMemType(VarType vt); +/** + * Get the setting at the given index into the settings table. + * @param index The index to look for. + * @return The setting at the given index, or nullptr when the index is invalid. + */ +const SettingDesc *GetSettingDescription(uint index) +{ + if (index >= _settings.size()) return nullptr; + return &_settings.begin()[index]; +} + +/** + * Get the setting at the given index into the company settings table. + * @param index The index to look for. + * @return The setting at the given index, or nullptr when the index is invalid. + */ +static const SettingDesc *GetCompanySettingDescription(uint index) +{ + if (index >= _company_settings.size()) return nullptr; + return &_company_settings.begin()[index]; +} + /** * Groups in openttd.cfg that are actually lists. */ @@ -529,23 +551,23 @@ static void Write_ValidateStdString(void *ptr, const SettingDesc *sd, const char /** * Load values from a group of an IniFile structure into the internal representation * @param ini pointer to IniFile structure that holds administrative information - * @param sd pointer to SettingDesc structure whose internally pointed variables will + * @param settings_table table with SettingDesc structures whose internally pointed variables will * be given values * @param grpname the group of the IniFile to search in for the new values * @param object pointer to the object been loaded * @param only_startup load only the startup settings set */ -static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object, bool only_startup) +static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup) { IniGroup *group; IniGroup *group_def = ini->GetGroup(grpname); - for (; sd->save.cmd != SL_END; sd++) { - const SettingDescBase *sdb = sd; - const SaveLoad *sld = &sd->save; + for (auto &sd : settings_table) { + const SettingDescBase *sdb = &sd; + const SaveLoad *sld = &sd.save; if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; - if (sd->startup != only_startup) continue; + if (sd.startup != only_startup) continue; /* For settings.xx.yy load the settings from [xx] yy = ? */ std::string s{ sdb->name }; @@ -578,11 +600,11 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp case SDT_NUMX: case SDT_ONEOFMANY: case SDT_MANYOFMANY: - Write_ValidateSetting(ptr, sd, (int32)(size_t)p); + Write_ValidateSetting(ptr, &sd, (int32)(size_t)p); break; case SDT_STDSTRING: - Write_ValidateStdString(ptr, sd, (const char *)p); + Write_ValidateStdString(ptr, &sd, (const char *)p); break; case SDT_INTLIST: { @@ -593,8 +615,8 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp /* Use default */ LoadIntList((const char*)sdb->def, ptr, sld->length, GetVarMemType(sld->conv)); - } else if (sd->proc_cnvt != nullptr) { - sd->proc_cnvt((const char*)p); + } else if (sd.proc_cnvt != nullptr) { + sd.proc_cnvt((const char*)p); } break; } @@ -615,16 +637,16 @@ static void IniLoadSettings(IniFile *ini, const SettingDesc *sd, const char *grp * values are reloaded when saving). If settings indeed have changed, we get * these and save them. */ -static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object, bool) +static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, const char *grpname, void *object, bool) { IniGroup *group_def = nullptr, *group; IniItem *item; char buf[512]; void *ptr; - for (; sd->save.cmd != SL_END; sd++) { - const SettingDescBase *sdb = sd; - const SaveLoad *sld = &sd->save; + for (auto &sd : settings_table) { + const SettingDescBase *sdb = &sd; + const SaveLoad *sld = &sd.save; /* If the setting is not saved to the configuration * file, just continue with the next setting */ @@ -1424,7 +1446,7 @@ static void HandleOldDiffCustom(bool savegame) } for (uint i = 0; i < options_to_load; i++) { - const SettingDesc *sd = &_settings[i]; + const SettingDesc *sd = GetSettingDescription(i); /* Skip deprecated options */ if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; void *var = GetVariableAddress(savegame ? &_settings_game : &_settings_newgame, &sd->save); @@ -1708,9 +1730,9 @@ static void GRFSaveConfig(IniFile *ini, const char *grpname, const GRFConfig *li /* Common handler for saving/loading variables to the configuration file */ static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescProcList *proc_list, bool only_startup = false) { - proc(ini, (const SettingDesc*)_misc_settings, "misc", nullptr, only_startup); + proc(ini, _misc_settings, "misc", nullptr, only_startup); #if defined(_WIN32) && !defined(DEDICATED) - proc(ini, (const SettingDesc*)_win32_settings, "win32", nullptr, only_startup); + proc(ini, _win32_settings, "win32", nullptr, only_startup); #endif /* _WIN32 */ proc(ini, _settings, "patches", &_settings_newgame, only_startup); @@ -1855,12 +1877,6 @@ void DeleteGRFPresetFromConfig(const char *config_name) delete ini; } -const SettingDesc *GetSettingDescription(uint index) -{ - if (index >= lengthof(_settings)) return nullptr; - return &_settings[index]; -} - /** * Network-safe changing of settings (server-only). * @param tile unused @@ -1923,8 +1939,8 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin */ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (p1 >= lengthof(_company_settings)) return CMD_ERROR; - const SettingDesc *sd = &_company_settings[p1]; + const SettingDesc *sd = GetCompanySettingDescription(p1); + if (sd == nullptr) return CMD_ERROR; if (flags & DC_EXEC) { void *var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); @@ -1955,8 +1971,19 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 */ uint GetSettingIndex(const SettingDesc *sd) { - assert((sd->flags & SGF_PER_COMPANY) == 0); - return sd - _settings; + assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) == 0); + return sd - _settings.begin(); +} + +/** + * Get the index of the company setting with this description. + * @param sd the setting to get the index for. + * @return the index of the setting to be used for CMD_CHANGE_COMPANY_SETTING. + */ +static uint GetCompanySettingIndex(const SettingDesc *sd) +{ + assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) != 0); + return sd - _company_settings.begin(); } /** @@ -1970,7 +1997,7 @@ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) { if ((sd->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { - return DoCommandP(0, sd - _company_settings, value, CMD_CHANGE_COMPANY_SETTING); + return DoCommandP(0, GetCompanySettingIndex(sd), value, CMD_CHANGE_COMPANY_SETTING); } void *var = GetVariableAddress(&_settings_client.company, &sd->save); @@ -2020,10 +2047,9 @@ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame) void SetDefaultCompanySettings(CompanyID cid) { Company *c = Company::Get(cid); - const SettingDesc *sd; - for (sd = _company_settings; sd->save.cmd != SL_END; sd++) { - void *var = GetVariableAddress(&c->settings, &sd->save); - Write_ValidateSetting(var, sd, (int32)(size_t)sd->def); + for (auto &sd : _company_settings) { + void *var = GetVariableAddress(&c->settings, &sd.save); + Write_ValidateSetting(var, &sd, (int32)(size_t)sd.def); } } @@ -2032,14 +2058,14 @@ void SetDefaultCompanySettings(CompanyID cid) */ void SyncCompanySettings() { - const SettingDesc *sd; uint i = 0; - for (sd = _company_settings; sd->save.cmd != SL_END; sd++, i++) { - const void *old_var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); - const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save); - uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv); - uint32 new_value = (uint32)ReadValue(new_var, sd->save.conv); + for (auto &sd : _company_settings) { + const void *old_var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd.save); + const void *new_var = GetVariableAddress(&_settings_client.company, &sd.save); + uint32 old_value = (uint32)ReadValue(old_var, sd.save.conv); + uint32 new_value = (uint32)ReadValue(new_var, sd.save.conv); if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company); + i++; } } @@ -2050,9 +2076,7 @@ void SyncCompanySettings() */ uint GetCompanySettingIndex(const char *name) { - const SettingDesc *sd = GetSettingFromName(name); - assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) != 0); - return sd - _company_settings; + return GetCompanySettingIndex(GetSettingFromName(name)); } /** @@ -2088,26 +2112,26 @@ bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgam const SettingDesc *GetSettingFromName(const char *name) { /* First check all full names */ - for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->name, name) == 0) return sd; + for (auto &sd : _settings) { + if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; + if (strcmp(sd.name, name) == 0) return &sd; } /* Then check the shortcut variant of the name. */ - for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - const char *short_name = strchr(sd->name, '.'); + for (auto &sd : _settings) { + if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; + const char *short_name = strchr(sd.name, '.'); if (short_name != nullptr) { short_name++; - if (strcmp(short_name, name) == 0) return sd; + if (strcmp(short_name, name) == 0) return &sd; } } if (strncmp(name, "company.", 8) == 0) name += 8; /* And finally the company-based settings */ - for (const SettingDesc *sd = _company_settings; sd->save.cmd != SL_END; sd++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->name, name) == 0) return sd; + for (auto &sd : _company_settings) { + if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; + if (strcmp(sd.name, name) == 0) return &sd; } return nullptr; @@ -2196,20 +2220,20 @@ void IConsoleListSettings(const char *prefilter) { IConsolePrintF(CC_WARNING, "All settings with their current value:"); - for (const SettingDesc *sd = _settings; sd->save.cmd != SL_END; sd++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (prefilter != nullptr && strstr(sd->name, prefilter) == nullptr) continue; + for (auto &sd : _settings) { + if (!SlIsObjectCurrentlyValid(sd.save.version_from, sd.save.version_to)) continue; + if (prefilter != nullptr && strstr(sd.name, prefilter) == nullptr) continue; char value[80]; - const void *ptr = GetVariableAddress(&GetGameSettings(), &sd->save); + const void *ptr = GetVariableAddress(&GetGameSettings(), &sd.save); - if (sd->cmd == SDT_BOOLX) { + if (sd.cmd == SDT_BOOLX) { seprintf(value, lastof(value), (*(const bool *)ptr != 0) ? "on" : "off"); - } else if (sd->cmd == SDT_STDSTRING) { + } else if (sd.cmd == SDT_STDSTRING) { seprintf(value, lastof(value), "%s", reinterpret_cast(ptr)->c_str()); } else { - seprintf(value, lastof(value), sd->min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd->save.conv)); + seprintf(value, lastof(value), sd.min < 0 ? "%d" : "%u", (int32)ReadValue(ptr, sd.save.conv)); } - IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name, value); + IConsolePrintF(CC_DEFAULT, "%s = %s", sd.name, value); } IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); @@ -2217,41 +2241,40 @@ void IConsoleListSettings(const char *prefilter) /** * Save and load handler for settings - * @param osd SettingDesc struct containing all information + * @param settings SettingDesc struct containing all information * @param object can be either nullptr in which case we load global variables or * a pointer to a struct which is getting saved */ -static void LoadSettings(const SettingDesc *osd, void *object) +static void LoadSettings(const SettingTable &settings, void *object) { - for (; osd->save.cmd != SL_END; osd++) { - const SaveLoad *sld = &osd->save; + for (auto &osd : settings) { + const SaveLoad *sld = &osd.save; void *ptr = GetVariableAddress(object, sld); if (!SlObjectMember(ptr, sld)) continue; - if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, osd, ReadValue(ptr, sld->conv)); + if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, &osd, ReadValue(ptr, sld->conv)); } } /** * Save and load handler for settings - * @param sd SettingDesc struct containing all information + * @param settings SettingDesc struct containing all information * @param object can be either nullptr in which case we load global variables or * a pointer to a struct which is getting saved */ -static void SaveSettings(const SettingDesc *sd, void *object) +static void SaveSettings(const SettingTable &settings, void *object) { /* We need to write the CH_RIFF header, but unfortunately can't call * SlCalcLength() because we have a different format. So do this manually */ - const SettingDesc *i; size_t length = 0; - for (i = sd; i->save.cmd != SL_END; i++) { - length += SlCalcObjMemberLength(object, &i->save); + for (auto &sd : settings) { + length += SlCalcObjMemberLength(object, &sd.save); } SlSetLength(length); - for (i = sd; i->save.cmd != SL_END; i++) { - void *ptr = GetVariableAddress(object, &i->save); - SlObjectMember(ptr, &i->save); + for (auto &sd : settings) { + void *ptr = GetVariableAddress(object, &sd.save); + SlObjectMember(ptr, &sd.save); } } diff --git a/src/settings_internal.h b/src/settings_internal.h index f92480a764..fca85de0c7 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -107,6 +107,8 @@ struct SettingDesc : SettingDescBase { SettingType GetType() const; }; +typedef std::initializer_list SettingTable; + const SettingDesc *GetSettingFromName(const char *name); bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame = false); bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame = false); diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index eea2371fc6..eecebb40e6 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -12,13 +12,12 @@ static bool UpdateIntervalRoadVeh(int32 p1); static bool UpdateIntervalShips(int32 p1); static bool UpdateIntervalAircraft(int32 p1); -static const SettingDesc _company_settings[] = { +static const SettingTable _company_settings{ [post-amble] }; [templates] SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_END = SDT_END() [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -136,8 +135,3 @@ str = STR_CONFIG_SETTING_SERVINT_AIRCRAFT strhelp = STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT strval = STR_CONFIG_SETTING_SERVINT_VALUE proc = UpdateIntervalAircraft - -[SDT_END] - - -}; diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index d2f12473e7..613f9bfa55 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -5,13 +5,12 @@ ; [pre-amble] -static const SettingDesc _currency_settings[] = { +static const SettingTable _currency_settings{ [post-amble] }; [templates] SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_END = SDT_END() [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -67,6 +66,3 @@ base = CurrencySpec var = suffix type = SLE_STRQ def = "" credits"" - -[SDT_END] - diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index b0b1798ab9..39caa45c95 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -23,7 +23,7 @@ static const char *_osk_activation = "disabled|double|single|immediately"; static const char *_settings_profiles = "easy|medium|hard"; static const char *_news_display = "off|summarized|full"; -static const SettingDesc _gameopt_settings[] = { +static const SettingTable _gameopt_settings{ /* In version 4 a new difficulty setting has been added to the difficulty settings, * town attitude towards demolishing. Needs special handling because some dimwit thought * it funny to have the GameDifficulty struct be an array while it is a struct of @@ -43,7 +43,6 @@ SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $ma SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_END = SDT_END() [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -186,6 +185,3 @@ def = 1 max = 1 full = _roadsides cat = SC_BASIC - -[SDT_END] - diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 2613b4dddb..4e1c3482ec 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -16,7 +16,7 @@ extern bool _allow_hidpi_window; #define WITHOUT_COCOA #endif -static const SettingDesc _misc_settings[] = { +static const SettingTable _misc_settings{ [post-amble] }; [templates] @@ -26,7 +26,6 @@ SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_END = SDTG_END() [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -353,6 +352,3 @@ ifdef = WITH_COCOA name = ""allow_hidpi"" var = _allow_hidpi_window def = true - -[SDTG_END] - diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 6410b0360f..f9bb279020 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -83,8 +83,6 @@ static size_t ConvertLandscape(const char *value); #define SDTG_NULL(length, from, to)\ {{"", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false}, SLEG_NULL(length, from, to)} -#define SDTG_END() {{nullptr, nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false}, SLEG_END()} - /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ #define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extra, startup)\ @@ -127,5 +125,3 @@ static size_t ConvertLandscape(const char *value); #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra, startup) -#define SDT_END() {{nullptr, nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, false}, SLE_END()} - diff --git a/src/table/settings.ini b/src/table/settings.ini index eea30e003c..ed07dfb118 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -59,7 +59,7 @@ static bool UpdateClientConfigValues(int32 p1); * assigns its own value. If the setting was company-based, that would mean that * vehicles could decide on different moments that they are heading back to a * service depot, causing desyncs on a massive scale. */ -const SettingDesc _settings[] = { +const SettingTable _settings{ [post-amble] }; [templates] @@ -76,7 +76,6 @@ SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL($length, $from, $to), -SDT_END = SDT_END() [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -4112,6 +4111,3 @@ str = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_HELPTEXT strval = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND cat = SC_BASIC - -[SDT_END] - diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini index 963a11df8c..669474cc74 100644 --- a/src/table/win32_settings.ini +++ b/src/table/win32_settings.ini @@ -9,14 +9,13 @@ #if defined(_WIN32) && !defined(DEDICATED) extern bool _window_maximize; -static const SettingDesc _win32_settings[] = { +static const SettingTable _win32_settings{ [post-amble] }; #endif /* _WIN32 */ [templates] SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_END = SDTG_END() [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -42,6 +41,3 @@ name = ""window_maximize"" var = _window_maximize def = false cat = SC_BASIC - -[SDTG_END] - diff --git a/src/table/window_settings.ini b/src/table/window_settings.ini index fb252076ce..5e11ea002a 100644 --- a/src/table/window_settings.ini +++ b/src/table/window_settings.ini @@ -6,13 +6,12 @@ [pre-amble] -static const SettingDesc _window_settings[] = { +static const SettingTable _window_settings{ [post-amble] }; [templates] SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_END = SDT_END() [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -52,7 +51,3 @@ type = SLE_INT16 def = 0 min = 0 max = 32000 - -[SDT_END] - -}; From 86c9ef81345901afb015930fa0e3a637acbbc709 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 19:27:46 +0200 Subject: [PATCH 252/800] Codechange: remove SettingDescType in lieu of the actual classes --- src/script/api/script_gamesettings.cpp | 5 +- src/settings.cpp | 110 ++++++++++--------------- src/settings_gui.cpp | 87 +++++++++---------- src/settings_internal.h | 71 ++++++++-------- src/table/settings.h.preamble | 24 +++--- 5 files changed, 136 insertions(+), 161 deletions(-) diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index f96048e153..8b0459367e 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -18,7 +18,7 @@ /* static */ bool ScriptGameSettings::IsValid(const char *setting) { const SettingDesc *sd = GetSettingFromName(setting); - return sd != nullptr && sd->cmd != SDT_STDSTRING; + return sd != nullptr && sd->IsIntSetting(); } /* static */ int32 ScriptGameSettings::GetValue(const char *setting) @@ -28,8 +28,6 @@ const SettingDesc *sd = GetSettingFromName(setting); void *ptr = GetVariableAddress(&_settings_game, &sd->save); - if (sd->cmd == SDT_BOOLX) return *(bool*)ptr; - return (int32)ReadValue(ptr, sd->save.conv); } @@ -40,7 +38,6 @@ const SettingDesc *sd = GetSettingFromName(setting); if ((sd->save.conv & SLF_NO_NETWORK_SYNC) != 0) return false; - if (sd->cmd != SDT_BOOLX && sd->cmd != SDT_NUMX) return false; return ScriptObject::DoCommand(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); } diff --git a/src/settings.cpp b/src/settings.cpp index 24950e779e..a86622fa5a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -400,52 +400,49 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const { void *ptr = GetVariableAddress(object, &this->save); - /* We cannot know the maximum value of a bitset variable, so just have faith */ - if (this->cmd != SDT_MANYOFMANY) { - /* We need to take special care of the uint32 type as we receive from the function - * a signed integer. While here also bail out on 64-bit settings as those are not - * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed - * 32-bit variable - * TODO: Support 64-bit settings/variables */ - switch (GetVarMemType(this->save.conv)) { - case SLE_VAR_NULL: return; - case SLE_VAR_BL: - case SLE_VAR_I8: - case SLE_VAR_U8: - case SLE_VAR_I16: - case SLE_VAR_U16: - case SLE_VAR_I32: { - /* Override the minimum value. No value below sdb->min, except special value 0 */ - if (!(this->flags & SGF_0ISDISABLED) || val != 0) { - if (!(this->flags & SGF_MULTISTRING)) { - /* Clamp value-type setting to its valid range */ - val = Clamp(val, this->min, this->max); - } else if (val < this->min || val > (int32)this->max) { - /* Reset invalid discrete setting (where different values change gameplay) to its default value */ - val = this->def; - } + /* We need to take special care of the uint32 type as we receive from the function + * a signed integer. While here also bail out on 64-bit settings as those are not + * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed + * 32-bit variable + * TODO: Support 64-bit settings/variables; requires 64 bit over command protocol! */ + switch (GetVarMemType(this->save.conv)) { + case SLE_VAR_NULL: return; + case SLE_VAR_BL: + case SLE_VAR_I8: + case SLE_VAR_U8: + case SLE_VAR_I16: + case SLE_VAR_U16: + case SLE_VAR_I32: { + /* Override the minimum value. No value below this->min, except special value 0 */ + if (!(this->flags & SGF_0ISDISABLED) || val != 0) { + if (!(this->flags & SGF_MULTISTRING)) { + /* Clamp value-type setting to its valid range */ + val = Clamp(val, this->min, this->max); + } else if (val < this->min || val > (int32)this->max) { + /* Reset invalid discrete setting (where different values change gameplay) to its default value */ + val = this->def; } - break; } - case SLE_VAR_U32: { - /* Override the minimum value. No value below sdb->min, except special value 0 */ - uint32 uval = (uint32)val; - if (!(this->flags & SGF_0ISDISABLED) || uval != 0) { - if (!(this->flags & SGF_MULTISTRING)) { - /* Clamp value-type setting to its valid range */ - uval = ClampU(uval, this->min, this->max); - } else if (uval < (uint)this->min || uval > this->max) { - /* Reset invalid discrete setting to its default value */ - uval = (uint32)this->def; - } - } - WriteValue(ptr, SLE_VAR_U32, (int64)uval); - return; - } - case SLE_VAR_I64: - case SLE_VAR_U64: - default: NOT_REACHED(); + break; } + case SLE_VAR_U32: { + /* Override the minimum value. No value below this->min, except special value 0 */ + uint32 uval = (uint32)val; + if (!(this->flags & SGF_0ISDISABLED) || uval != 0) { + if (!(this->flags & SGF_MULTISTRING)) { + /* Clamp value-type setting to its valid range */ + uval = ClampU(uval, this->min, this->max); + } else if (uval < (uint)this->min || uval > this->max) { + /* Reset invalid discrete setting to its default value */ + uval = (uint32)this->def; + } + } + WriteValue(ptr, SLE_VAR_U32, (int64)uval); + return; + } + case SLE_VAR_I64: + case SLE_VAR_U64: + default: NOT_REACHED(); } WriteValue(ptr, this->save.conv, (int64)val); @@ -755,22 +752,6 @@ SettingType SettingDesc::GetType() const return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; } -/** - * Check whether this setting is an integer type setting. - * @return True when the underlying type is an integer. - */ -bool SettingDesc::IsIntSetting() const { - return this->cmd == SDT_BOOLX || this->cmd == SDT_NUMX || this->cmd == SDT_ONEOFMANY || this->cmd == SDT_MANYOFMANY; -} - -/** - * Check whether this setting is an string type setting. - * @return True when the underlying type is a string. - */ -bool SettingDesc::IsStringSetting() const { - return this->cmd == SDT_STDSTRING; -} - /** * Get the setting description of this setting as an integer setting. * @return The integer setting description. @@ -2109,10 +2090,10 @@ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) return; } - bool success; - if (sd->cmd == SDT_STDSTRING) { + bool success = true; + if (sd->IsStringSetting()) { success = SetSettingValue(sd->AsStringSetting(), value, force_newgame); - } else { + } else if (sd->IsIntSetting()) { uint32 val; extern bool GetArgumentInteger(uint32 *value, const char *arg); success = GetArgumentInteger(&val, value); @@ -2155,9 +2136,8 @@ void IConsoleGetSetting(const char *name, bool force_newgame) const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game; - if (sd->cmd == SDT_STDSTRING) { - const void *ptr = GetVariableAddress(object, &sd->save); - IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, reinterpret_cast(ptr)->c_str()); + if (sd->IsStringSetting()) { + IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, sd->AsStringSetting()->Read(object).c_str()); } else if (sd->IsIntSetting()) { char value[20]; sd->FormatValue(value, lastof(value), object); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 18beb690a8..183b98a1e9 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1167,7 +1167,7 @@ static const void *ResolveVariableAddress(const GameSettings *settings_ptr, cons */ void SettingEntry::SetValueDParams(uint first_param, int32 value) const { - if (this->setting->cmd == SDT_BOOLX) { + if (this->setting->IsBoolSetting()) { SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); } else { if ((this->setting->flags & SGF_MULTISTRING) != 0) { @@ -1207,7 +1207,7 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE); int32 value = (int32)ReadValue(var, sd->save.conv); - if (sd->cmd == SDT_BOOLX) { + if (sd->IsBoolSetting()) { /* Draw checkbox for boolean-value either on/off */ DrawBoolButton(buttons_left, button_y, value != 0, editable); } else if ((sd->flags & SGF_MULTISTRING) != 0) { @@ -2228,52 +2228,47 @@ struct GameSettingsWindow : Window { this->SetDisplayedHelpText(pe); int32 oldvalue = value; - switch (sd->cmd) { - case SDT_BOOLX: value ^= 1; break; - case SDT_ONEOFMANY: - case SDT_NUMX: { - /* Add a dynamic step-size to the scroller. In a maximum of - * 50-steps you should be able to get from min to max, - * unless specified otherwise in the 'interval' variable - * of the current setting. */ - uint32 step = (sd->interval == 0) ? ((sd->max - sd->min) / 50) : sd->interval; - if (step == 0) step = 1; + if (sd->IsBoolSetting()) { + value ^= 1; + } else { + /* Add a dynamic step-size to the scroller. In a maximum of + * 50-steps you should be able to get from min to max, + * unless specified otherwise in the 'interval' variable + * of the current setting. */ + uint32 step = (sd->interval == 0) ? ((sd->max - sd->min) / 50) : sd->interval; + if (step == 0) step = 1; - /* don't allow too fast scrolling */ - if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) { - _left_button_clicked = false; - return; - } - - /* Increase or decrease the value and clamp it to extremes */ - if (x >= SETTING_BUTTON_WIDTH / 2) { - value += step; - if (sd->min < 0) { - assert((int32)sd->max >= 0); - if (value > (int32)sd->max) value = (int32)sd->max; - } else { - if ((uint32)value > sd->max) value = (int32)sd->max; - } - if (value < sd->min) value = sd->min; // skip between "disabled" and minimum - } else { - value -= step; - if (value < sd->min) value = (sd->flags & SGF_0ISDISABLED) ? 0 : sd->min; - } - - /* Set up scroller timeout for numeric values */ - if (value != oldvalue) { - if (this->clicked_entry != nullptr) { // Release previous buttons if any - this->clicked_entry->SetButtons(0); - } - this->clicked_entry = pe; - this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED); - this->SetTimeout(); - _left_button_clicked = false; - } - break; + /* don't allow too fast scrolling */ + if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) { + _left_button_clicked = false; + return; } - default: NOT_REACHED(); + /* Increase or decrease the value and clamp it to extremes */ + if (x >= SETTING_BUTTON_WIDTH / 2) { + value += step; + if (sd->min < 0) { + assert((int32)sd->max >= 0); + if (value > (int32)sd->max) value = (int32)sd->max; + } else { + if ((uint32)value > sd->max) value = (int32)sd->max; + } + if (value < sd->min) value = sd->min; // skip between "disabled" and minimum + } else { + value -= step; + if (value < sd->min) value = (sd->flags & SGF_0ISDISABLED) ? 0 : sd->min; + } + + /* Set up scroller timeout for numeric values */ + if (value != oldvalue) { + if (this->clicked_entry != nullptr) { // Release previous buttons if any + this->clicked_entry->SetButtons(0); + } + this->clicked_entry = pe; + this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED); + this->SetTimeout(); + _left_button_clicked = false; + } } if (value != oldvalue) { @@ -2282,7 +2277,7 @@ struct GameSettingsWindow : Window { } } else { /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */ - if (this->last_clicked == pe && sd->cmd != SDT_BOOLX && !(sd->flags & SGF_MULTISTRING)) { + if (this->last_clicked == pe && !sd->IsBoolSetting() && !(sd->flags & SGF_MULTISTRING)) { int64 value64 = value; /* Show the correct currency-translated value */ if (sd->flags & SGF_CURRENCY) value64 *= _currency->rate; diff --git a/src/settings_internal.h b/src/settings_internal.h index 488b85441d..0f6d0c3ade 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -12,22 +12,6 @@ #include "saveload/saveload.h" -/** - * Convention/Type of settings. This is then further specified if necessary - * with the SLE_ (SLE_VAR/SLE_FILE) enums in saveload.h - * @see VarTypes - * @see SettingDesc - */ -enum SettingDescType : byte { - SDT_NUMX = 0, ///< any number-type - SDT_BOOLX = 1, ///< a boolean number - SDT_ONEOFMANY = 2, ///< bitmasked number where only ONE bit may be set - SDT_MANYOFMANY = 3, ///< bitmasked number where MULTIPLE bits may be set - SDT_INTLIST = 4, ///< list of integers separated by a comma ',' - SDT_STDSTRING = 6, ///< \c std::string - SDT_NULL = 7, ///< an old setting that has been removed but could still be in savegames -}; - enum SettingGuiFlag : uint16 { /* 2 bytes allocated for a maximum of 16 flags. */ SGF_NONE = 0, @@ -85,20 +69,30 @@ typedef size_t OnConvert(const char *value); ///< callback prototype for convers /** Properties of config file settings. */ struct SettingDesc { - SettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup) : - name(name), flags(flags), cmd(cmd), startup(startup), save(save) {} + SettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup) : + name(name), flags(flags), startup(startup), save(save) {} virtual ~SettingDesc() {} const char *name; ///< name of the setting. Used in configuration file and for console SettingGuiFlag flags; ///< handles how a setting would show up in the GUI (text/currency, etc.) - SettingDescType cmd; ///< various flags for the variable bool startup; ///< setting has to be loaded directly at startup? SaveLoad save; ///< Internal structure (going to savegame, parts to config) bool IsEditable(bool do_command = false) const; SettingType GetType() const; - bool IsIntSetting() const; - bool IsStringSetting() const; + + /** + * Check whether this setting is an integer type setting. + * @return True when the underlying type is an integer. + */ + virtual bool IsIntSetting() const { return false; } + + /** + * Check whether this setting is an string type setting. + * @return True when the underlying type is a string. + */ + virtual bool IsStringSetting() const { return false; } + const struct IntSettingDesc *AsIntSetting() const; const struct StringSettingDesc *AsStringSetting() const; @@ -131,10 +125,10 @@ struct SettingDesc { /** Base integer type, including boolean, settings. Only these are shown in the settings UI. */ struct IntSettingDesc : SettingDesc { - IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, + IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc) : - SettingDesc(save, name, flags, cmd, startup), def(def), min(min), max(max), interval(interval), + SettingDesc(save, name, flags, startup), def(def), min(min), max(max), interval(interval), str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc) {} virtual ~IntSettingDesc() {} @@ -148,6 +142,13 @@ struct IntSettingDesc : SettingDesc { SettingCategory cat; ///< assigned categories of the setting OnChange *proc; ///< callback procedure for when the value is changed + /** + * Check whether this setting is a boolean type setting. + * @return True when the underlying type is an integer. + */ + virtual bool IsBoolSetting() const { return false; } + bool IsIntSetting() const override { return true; } + void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; @@ -159,21 +160,22 @@ struct IntSettingDesc : SettingDesc { /** Boolean setting. */ struct BoolSettingDesc : IntSettingDesc { - BoolSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, bool def, + BoolSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, bool def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc) : - IntSettingDesc(save, name, flags, cmd, startup, def, 0, 1, 0, str, str_help, str_val, cat, proc) {} + IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, proc) {} virtual ~BoolSettingDesc() {} + bool IsBoolSetting() const override { return true; } size_t ParseValue(const char *str) const override; void FormatValue(char *buf, const char *last, const void *object) const override; }; /** One of many setting. */ struct OneOfManySettingDesc : IntSettingDesc { - OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, std::initializer_list many, OnConvert *many_cnvt) : - IntSettingDesc(save, name, flags, cmd, startup, def, 0, max, 0, str, str_help, str_val, cat, proc), many_cnvt(many_cnvt) + IntSettingDesc(save, name, flags, startup, def, 0, max, 0, str, str_help, str_val, cat, proc), many_cnvt(many_cnvt) { for (auto one : many) this->many.push_back(one); } @@ -192,10 +194,10 @@ struct OneOfManySettingDesc : IntSettingDesc { /** Many of many setting. */ struct ManyOfManySettingDesc : OneOfManySettingDesc { - ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, std::initializer_list many, OnConvert *many_cnvt) : - OneOfManySettingDesc(save, name, flags, cmd, startup, def, (1 << many.size()) - 1, str, str_help, + OneOfManySettingDesc(save, name, flags, startup, def, (1 << many.size()) - 1, str, str_help, str_val, cat, proc, many, many_cnvt) {} virtual ~ManyOfManySettingDesc() {} @@ -205,15 +207,16 @@ struct ManyOfManySettingDesc : OneOfManySettingDesc { /** String settings. */ struct StringSettingDesc : SettingDesc { - StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, + StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def, uint32 max_length, OnChange proc) : - SettingDesc(save, name, flags, cmd, startup), def(def), max_length(max_length), proc(proc) {} + SettingDesc(save, name, flags, startup), def(def), max_length(max_length), proc(proc) {} virtual ~StringSettingDesc() {} const char *def; ///< default value given when none is present uint32 max_length; ///< maximum length of the string, 0 means no maximum length OnChange *proc; ///< callback procedure for when the value is changed + bool IsStringSetting() const override { return true; } void ChangeValue(const void *object, const char *newval) const; void Write_ValidateSetting(const void *object, const char *str) const; @@ -225,8 +228,8 @@ struct StringSettingDesc : SettingDesc { /** List/array settings. */ struct ListSettingDesc : SettingDesc { - ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def) : - SettingDesc(save, name, flags, cmd, startup), def(def) {} + ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def) : + SettingDesc(save, name, flags, startup), def(def) {} virtual ~ListSettingDesc() {} const char *def; ///< default value given when none is present @@ -239,7 +242,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, "", SGF_NONE, SDT_NULL, false) {} + SettingDesc(save, "", SGF_NONE, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index df10b6deb6..7f9ac2dd59 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -59,22 +59,22 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for global variables */ #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) + NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, SDT_BOOLX, startup, def, str, strhelp, strval, cat, proc) + NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, proc) #define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ - NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, SDT_INTLIST, startup, def) + NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, startup, def) #define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, proc, from, to, cat, extra, startup)\ - NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, SDT_STDSTRING, startup, def, max_length, proc) + NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, startup, def, max_length, proc) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) + NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) + NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_NULL(length, from, to)\ NSD(Null, SLEG_NULL(length, from, to)) @@ -82,22 +82,22 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ #define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_NUMX, startup, def, min, max, interval, str, strhelp, strval, cat, proc) + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, proc) #define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, SDT_BOOLX, startup, def, str, strhelp, strval, cat, proc) + NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, proc) #define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ - NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_INTLIST, startup, def) + NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def) #define SDT_SSTR(base, var, type, flags, guiflags, def, proc, from, to, cat, extra, startup)\ - NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_STDSTRING, startup, def, 0, proc) + NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def, 0, proc) #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ - NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, load) + NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, load) #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) + NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDT_NULL(length, from, to)\ NSD(Null, SLE_CONDNULL(length, from, to)) From ac99a38175c78612d058b40e7e1219d440b3d7ce Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 22 May 2021 08:32:51 +0200 Subject: [PATCH 253/800] Cleanup: remove and/or fix some confusing comments The comments for SettingDescType; it is a byte, so not 4 bytes and since it is not a flag there are about 250 other possibilities left instead of 9. SettingGuiFlag is uint16 so has 2 bytes allocated. SettingDescGlobVarList and related comments imply that global vars cannot be used elsewhere, but they are used for settings just fine. Even then the type is not used anywhere else but the definition of the table. --- src/settings_internal.h | 17 +---------------- src/table/misc_settings.ini | 2 +- src/table/settings.h.preamble | 4 +--- src/table/win32_settings.ini | 2 +- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/settings_internal.h b/src/settings_internal.h index 225bb71953..fc8e0a1e30 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -19,22 +19,16 @@ * @see SettingDescBase */ enum SettingDescType : byte { - /* 4 bytes allocated a maximum of 16 types for GenericType */ - SDT_BEGIN = 0, SDT_NUMX = 0, ///< any number-type SDT_BOOLX = 1, ///< a boolean number SDT_ONEOFMANY = 2, ///< bitmasked number where only ONE bit may be set SDT_MANYOFMANY = 3, ///< bitmasked number where MULTIPLE bits may be set SDT_INTLIST = 4, ///< list of integers separated by a comma ',' SDT_STDSTRING = 6, ///< \c std::string - SDT_END, - /* 9 more possible primitives */ }; - enum SettingGuiFlag : uint16 { - /* 1 byte allocated for a maximum of 8 flags - * Flags directing saving/loading of a variable */ + /* 2 bytes allocated for a maximum of 16 flags. */ SGF_NONE = 0, SGF_0ISDISABLED = 1 << 0, ///< a value of zero means the feature is disabled SGF_DISPLAY_ABS = 1 << 1, ///< display absolute value of the setting @@ -114,15 +108,6 @@ struct SettingDesc { SettingType GetType() const; }; -/* NOTE: The only difference between SettingDesc and SettingDescGlob is - * that one uses global variables as a source and the other offsets - * in a struct which are bound to a certain variable during runtime. - * The only way to differentiate between these two is to check if an object - * has been passed to the function or not. If not, then it is a global variable - * and save->variable has its address, otherwise save->variable only holds the - * offset in a certain struct */ -typedef SettingDesc SettingDescGlobVarList; - const SettingDesc *GetSettingFromName(const char *name); bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame = false); bool SetSettingValue(const SettingDesc *sd, const char *value, bool force_newgame = false); diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 37994644a6..2613b4dddb 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -16,7 +16,7 @@ extern bool _allow_hidpi_window; #define WITHOUT_COCOA #endif -static const SettingDescGlobVarList _misc_settings[] = { +static const SettingDesc _misc_settings[] = { [post-amble] }; [templates] diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 826b272d7a..6410b0360f 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -23,9 +23,7 @@ static size_t ConvertLandscape(const char *value); * The macros can be grouped depending on where the config variable is * stored: * 1. SDTG_something - * These are for global variables, so this is the one you will use - * for a #SettingDescGlobVarList section. Here 'var' refers to a - * global variable. + * These are for global variables. Here 'var' refers to a global variable. * 2. SDTC_something * These are for client-only variables. Here the 'var' refers to an * entry inside _settings_client. diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini index c3cc45014c..963a11df8c 100644 --- a/src/table/win32_settings.ini +++ b/src/table/win32_settings.ini @@ -9,7 +9,7 @@ #if defined(_WIN32) && !defined(DEDICATED) extern bool _window_maximize; -static const SettingDescGlobVarList _win32_settings[] = { +static const SettingDesc _win32_settings[] = { [post-amble] }; #endif /* _WIN32 */ From cf6b91f30f2e923b0084255e4082605803d2fd32 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 10:29:38 +0200 Subject: [PATCH 254/800] Codechange: do not use SettingDescBase directly when not needed --- src/settings.cpp | 12 +++++------ src/settings_gui.cpp | 48 +++++++++++++++++++------------------------- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 746e477da9..15d90f312b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -379,7 +379,7 @@ static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 * @param orig_str input string that will be parsed based on the type of desc * @return return the parsed value of the setting */ -static const void *StringToVal(const SettingDescBase *desc, const char *orig_str) +static const void *StringToVal(const SettingDesc *desc, const char *orig_str) { const char *str = orig_str == nullptr ? "" : orig_str; @@ -456,7 +456,7 @@ static const void *StringToVal(const SettingDescBase *desc, const char *orig_str */ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val) { - const SettingDescBase *sdb = sd; + const SettingDesc *sdb = sd; if (sdb->cmd != SDT_BOOLX && sdb->cmd != SDT_NUMX && @@ -563,8 +563,8 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co IniGroup *group_def = ini->GetGroup(grpname); for (auto &sd : settings_table) { - const SettingDescBase *sdb = &sd; - const SaveLoad *sld = &sd.save; + const SettingDesc *sdb = &sd; + const SaveLoad *sld = &sd.save; if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; if (sd.startup != only_startup) continue; @@ -645,8 +645,8 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void *ptr; for (auto &sd : settings_table) { - const SettingDescBase *sdb = &sd; - const SaveLoad *sld = &sd.save; + const SettingDesc *sdb = &sd; + const SaveLoad *sld = &sd.save; /* If the setting is not saved to the configuration * file, just continue with the next setting */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index edde335601..f4570624d7 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1127,10 +1127,8 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) /* Process the search text filter for this item. */ filter.string.ResetState(); - const SettingDescBase *sdb = sd; - SetDParam(0, STR_EMPTY); - filter.string.AddLine(sdb->str); + filter.string.AddLine(sd->str); filter.string.AddLine(this->GetHelpText()); visible = filter.string.GetState(); @@ -1171,17 +1169,16 @@ static const void *ResolveVariableAddress(const GameSettings *settings_ptr, cons */ void SettingEntry::SetValueDParams(uint first_param, int32 value) const { - const SettingDescBase *sdb = this->setting; - if (sdb->cmd == SDT_BOOLX) { + if (this->setting->cmd == SDT_BOOLX) { SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); } else { - if ((sdb->flags & SGF_MULTISTRING) != 0) { - SetDParam(first_param++, sdb->str_val - sdb->min + value); - } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) { - SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0)); + if ((this->setting->flags & SGF_MULTISTRING) != 0) { + SetDParam(first_param++, this->setting->str_val - this->setting->min + value); + } else if ((this->setting->flags & SGF_DISPLAY_ABS) != 0) { + SetDParam(first_param++, this->setting->str_val + ((value >= 0) ? 1 : 0)); value = abs(value); } else { - SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0)); + SetDParam(first_param++, this->setting->str_val + ((value == 0 && (this->setting->flags & SGF_0ISDISABLED) != 0) ? 1 : 0)); } SetDParam(first_param++, value); } @@ -1198,7 +1195,6 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const { const SettingDesc *sd = this->setting; - const SettingDescBase *sdb = sd; const void *var = ResolveVariableAddress(settings_ptr, sd); int state = this->flags & SEF_BUTTONS_MASK; @@ -1213,19 +1209,19 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE); int32 value = (int32)ReadValue(var, sd->save.conv); - if (sdb->cmd == SDT_BOOLX) { + if (sd->cmd == SDT_BOOLX) { /* Draw checkbox for boolean-value either on/off */ DrawBoolButton(buttons_left, button_y, value != 0, editable); - } else if ((sdb->flags & SGF_MULTISTRING) != 0) { + } else if ((sd->flags & SGF_MULTISTRING) != 0) { /* Draw [v] button for settings of an enum-type */ DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable); } else { /* Draw [<][>] boxes for settings of an integer-type */ DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state, - editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max); + editable && value != (sd->flags & SGF_0ISDISABLED ? 0 : sd->min), editable && (uint32)value != sd->max); } this->SetValueDParams(1, value); - DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE); + DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sd->str, highlight ? TC_WHITE : TC_LIGHT_BLUE); } /* == SettingsContainer methods == */ @@ -2196,7 +2192,6 @@ struct GameSettingsWindow : Window { /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */ if (x < SETTING_BUTTON_WIDTH && (sd->flags & SGF_MULTISTRING)) { - const SettingDescBase *sdb = sd; this->SetDisplayedHelpText(pe); if (this->valuedropdown_entry == pe) { @@ -2224,8 +2219,8 @@ struct GameSettingsWindow : Window { this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED); DropDownList list; - for (int i = sdb->min; i <= (int)sdb->max; i++) { - list.emplace_back(new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false)); + for (int i = sd->min; i <= (int)sd->max; i++) { + list.emplace_back(new DropDownListStringItem(sd->str_val + i - sd->min, i, false)); } ShowDropDownListAt(this, std::move(list), value, -1, wi_rect, COLOUR_ORANGE, true); @@ -2234,10 +2229,9 @@ struct GameSettingsWindow : Window { this->SetDirty(); } else if (x < SETTING_BUTTON_WIDTH) { this->SetDisplayedHelpText(pe); - const SettingDescBase *sdb = sd; int32 oldvalue = value; - switch (sdb->cmd) { + switch (sd->cmd) { case SDT_BOOLX: value ^= 1; break; case SDT_ONEOFMANY: case SDT_NUMX: { @@ -2245,7 +2239,7 @@ struct GameSettingsWindow : Window { * 50-steps you should be able to get from min to max, * unless specified otherwise in the 'interval' variable * of the current setting. */ - uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval; + uint32 step = (sd->interval == 0) ? ((sd->max - sd->min) / 50) : sd->interval; if (step == 0) step = 1; /* don't allow too fast scrolling */ @@ -2257,16 +2251,16 @@ struct GameSettingsWindow : Window { /* Increase or decrease the value and clamp it to extremes */ if (x >= SETTING_BUTTON_WIDTH / 2) { value += step; - if (sdb->min < 0) { - assert((int32)sdb->max >= 0); - if (value > (int32)sdb->max) value = (int32)sdb->max; + if (sd->min < 0) { + assert((int32)sd->max >= 0); + if (value > (int32)sd->max) value = (int32)sd->max; } else { - if ((uint32)value > sdb->max) value = (int32)sdb->max; + if ((uint32)value > sd->max) value = (int32)sd->max; } - if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum + if (value < sd->min) value = sd->min; // skip between "disabled" and minimum } else { value -= step; - if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min; + if (value < sd->min) value = (sd->flags & SGF_0ISDISABLED) ? 0 : sd->min; } /* Set up scroller timeout for numeric values */ From 8372c679e3c16f776ecd0847b60c940ac066ed4c Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 10:42:02 +0200 Subject: [PATCH 255/800] Codechange: add helper functions to read an int setting value --- src/settings.cpp | 44 ++++++++++++++++++++++++++--------------- src/settings_gui.cpp | 29 +++++++++++---------------- src/settings_internal.h | 1 + 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index a86622fa5a..af06d3befc 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -313,13 +313,13 @@ char *OneOfManySettingDesc::FormatSingleValue(char *buf, const char *last, uint void OneOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - uint id = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + uint id = (uint)this->Read(object); this->FormatSingleValue(buf, last, id); } void ManyOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - uint bitmask = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + uint bitmask = (uint)this->Read(object); uint id = 0; bool first = true; FOR_EACH_SET_BIT(id, bitmask) { @@ -448,6 +448,17 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const WriteValue(ptr, this->save.conv, (int64)val); } +/** + * Read the integer from the the actual setting. + * @param object The object the setting is to be saved in. + * @return The value of the saved integer. + */ +int32 IntSettingDesc::Read(const void *object) const +{ + void *ptr = GetVariableAddress(object, &this->save); + return (int32)ReadValue(ptr, this->save.conv); +} + /** * Set the string value of a setting. * @param object The object the setting is to be saved in. @@ -609,20 +620,20 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - uint32 i = (uint32)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + uint32 i = (uint32)this->Read(object); seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); } void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - bool val = ReadValue(GetVariableAddress(object, &this->save), this->save.conv) != 0; + bool val = this->Read(object) != 0; strecpy(buf, val ? "true" : "false", last); } bool IntSettingDesc::IsSameValue(const IniItem *item, void *object) const { - int64 item_value = this->ParseValue(item->value->c_str()); - int64 object_value = ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + int32 item_value = (int32)this->ParseValue(item->value->c_str()); + int32 object_value = this->Read(object); return item_value == object_value; } @@ -1814,18 +1825,16 @@ void DeleteGRFPresetFromConfig(const char *config_name) */ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const { - void *var = GetVariableAddress(object, &this->save); - - int32 oldval = (int32)ReadValue(var, this->save.conv); + int32 oldval = this->Read(object); this->Write_ValidateSetting(object, newval); - newval = (int32)ReadValue(var, this->save.conv); + newval = this->Read(object); if (oldval == newval) return; if (this->proc != nullptr && !this->proc(newval)) { /* The change was not allowed, so revert. */ - WriteValue(var, this->save.conv, (int64)oldval); + WriteValue(GetVariableAddress(object, &this->save), this->save.conv, (int64)oldval); return; } @@ -1989,12 +1998,12 @@ void SetDefaultCompanySettings(CompanyID cid) */ void SyncCompanySettings() { + const void *old_object = &Company::Get(_current_company)->settings; + const void *new_object = &_settings_client.company; uint i = 0; for (auto &sd : _company_settings) { - const void *old_var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); - const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save); - uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv); - uint32 new_value = (uint32)ReadValue(new_var, sd->save.conv); + uint32 old_value = (uint32)sd->AsIntSetting()->Read(new_object); + uint32 new_value = (uint32)sd->AsIntSetting()->Read(old_object); if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company); i++; } @@ -2179,7 +2188,10 @@ static void LoadSettings(const SettingTable &settings, void *object) void *ptr = GetVariableAddress(object, &osd->save); if (!SlObjectMember(ptr, &osd->save)) continue; - if (osd->IsIntSetting()) osd->AsIntSetting()->Write_ValidateSetting(object, ReadValue(ptr, osd->save.conv)); + if (osd->IsIntSetting()) { + const IntSettingDesc *int_setting = osd->AsIntSetting(); + int_setting->Write_ValidateSetting(object, int_setting->Read(object)); + } } } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 183b98a1e9..559c395875 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -74,7 +74,7 @@ static const StringID _font_zoom_dropdown[] = { static Dimension _circle_size; ///< Dimension of the circle +/- icon. This is here as not all users are within the class of the settings window. -static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const IntSettingDesc *sd); +static const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd); /** * Get index of the current screen resolution. @@ -1075,16 +1075,14 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const /* There shall not be any restriction, i.e. all settings shall be visible. */ if (mode == RM_ALL) return true; - GameSettings *settings_ptr = &GetGameSettings(); const IntSettingDesc *sd = this->setting; if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0; if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0; /* Read the current value. */ - const void *var = ResolveVariableAddress(settings_ptr, sd); - int64 current_value = ReadValue(var, sd->save.conv); - + const void *object = ResolveObject(&GetGameSettings(), sd); + int64 current_value = sd->Read(object); int64 filter_value; if (mode == RM_CHANGED_AGAINST_DEFAULT) { @@ -1098,11 +1096,10 @@ bool SettingEntry::IsVisibleByRestrictionMode(RestrictionMode mode) const * its value is used when starting a new game. */ /* Make sure we're not comparing the new game settings against itself. */ - assert(settings_ptr != &_settings_newgame); + assert(&GetGameSettings() != &_settings_newgame); /* Read the new game's value. */ - var = ResolveVariableAddress(&_settings_newgame, sd); - filter_value = ReadValue(var, sd->save.conv); + filter_value = sd->Read(ResolveObject(&_settings_newgame, sd)); } return current_value != filter_value; @@ -1147,17 +1144,15 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) return visible; } -static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const IntSettingDesc *sd) +static const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd) { if ((sd->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { - return GetVariableAddress(&Company::Get(_local_company)->settings, &sd->save); - } else { - return GetVariableAddress(&_settings_client.company, &sd->save); + return &Company::Get(_local_company)->settings; } - } else { - return GetVariableAddress(settings_ptr, &sd->save); + return &_settings_client.company; } + return settings_ptr; } /** @@ -1193,7 +1188,6 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const { const IntSettingDesc *sd = this->setting; - const void *var = ResolveVariableAddress(settings_ptr, sd); int state = this->flags & SEF_BUTTONS_MASK; bool rtl = _current_text_dir == TD_RTL; @@ -1206,7 +1200,7 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, bool editable = sd->IsEditable(); SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE); - int32 value = (int32)ReadValue(var, sd->save.conv); + int32 value = sd->Read(ResolveObject(settings_ptr, sd)); if (sd->IsBoolSetting()) { /* Draw checkbox for boolean-value either on/off */ DrawBoolButton(buttons_left, button_y, value != 0, editable); @@ -2184,8 +2178,7 @@ struct GameSettingsWindow : Window { return; } - const void *var = ResolveVariableAddress(settings_ptr, sd); - int32 value = (int32)ReadValue(var, sd->save.conv); + int32 value = sd->Read(ResolveObject(settings_ptr, sd)); /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */ if (x < SETTING_BUTTON_WIDTH && (sd->flags & SGF_MULTISTRING)) { diff --git a/src/settings_internal.h b/src/settings_internal.h index 0f6d0c3ade..e7dd6e9149 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -156,6 +156,7 @@ struct IntSettingDesc : SettingDesc { void FormatValue(char *buf, const char *last, const void *object) const override; void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; + int32 Read(const void *object) const; }; /** Boolean setting. */ From 76484833643c1aff90d41eb01de70f7e8ba0ceb9 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 27 May 2021 18:56:39 +0200 Subject: [PATCH 256/800] Change: by default, make "unload all" leave stations empty (#9301) --- src/order_gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 8504ee16f1..2b3715ebd6 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -643,8 +643,8 @@ private: DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_UNLOAD | (unload_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); - /* Transfer orders with leave empty as default */ - if (unload_type == OUFB_TRANSFER) { + /* Transfer and unload orders with leave empty as default */ + if (unload_type == OUFB_TRANSFER || unload_type == OUFB_UNLOAD) { DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_LOAD | (OLFB_NO_LOAD << 4), CMD_MODIFY_ORDER); this->SetWidgetDirty(WID_O_FULL_LOAD); } From 7b5c0b4236b5de9aece6540c7fbc256390552cea Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 27 May 2021 19:38:25 +0000 Subject: [PATCH 257/800] Update: Translations from eints chinese (traditional): 9 changes by benny30111 english (us): 3 changes by 2TallTyler --- src/lang/english_US.txt | 4 +++- src/lang/traditional_chinese.txt | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 2b5fd29afd..a76b1d9079 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -3558,7 +3558,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Click to STR_GROUP_DELETE_TOOLTIP :{BLACK}Delete the selected group STR_GROUP_RENAME_TOOLTIP :{BLACK}Rename the selected group STR_GROUP_LIVERY_TOOLTIP :{BLACK}Change livery of the selected group -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Click to protect this group from global autoreplace +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Click to protect this group from global autoreplace. Ctrl+Click to also protect sub-groups. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Delete Group STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Are you sure you want to delete this group and any descendants? @@ -3811,7 +3811,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles STR_REPLACE_ROAD_VEHICLES :Road Vehicles STR_REPLACE_TRAM_VEHICLES :Streetcars +STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing cars (starting at the front), if replacing the engine would make the train longer +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+Click to also apply to sub-groups # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index e70c5beb5a..1441c0f474 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -966,6 +966,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :每 12 個月 STR_GAME_OPTIONS_LANGUAGE :{BLACK}語言 STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}選擇要用的介面語言 +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} (已完成{NUM}%) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}全螢幕 STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}勾選即可在全螢幕下玩 OpenTTD @@ -2007,7 +2008,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}公司 STR_NETWORK_COMPANY_LIST_CLIENT_LIST :用戶端清單 # Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}多人遊戲 +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}伺服器 +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :踢出 STR_NETWORK_SERVER :伺服器 @@ -2337,6 +2341,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}挖掘 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}切換鋪設/移除公路 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}切換鋪設電車軌 STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}轉換或升級路面類型。按 Shift 鍵可切換鋪設和顯示預估成本。 +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}轉換/升級電車軌道類型。按 Shift 鍵可切換建築/顯示預估成本。 STR_ROAD_NAME_ROAD :路面 STR_ROAD_NAME_TRAM :電車軌 @@ -2631,6 +2636,7 @@ STR_FRAMERATE_DATA_POINTS :{BLACK}數據 STR_FRAMERATE_MS_BAD :{RED}{DECIMAL} 毫秒 STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} ############ Leave those lines in this order!! +STR_FRAMERATE_AI :{BLACK} AI {NUM} {STRING} ############ End of leave-in-this-order ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GL_LANDSCAPE :世界刻 @@ -2675,6 +2681,7 @@ STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}市鎮數量: STR_MAPGEN_DATE :{BLACK}日期: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}工業數量: +STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}地形產生器: STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形種類: STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}海平面: @@ -3309,6 +3316,7 @@ STR_BUY_VEHICLE_AIRCRAFT_CAPTION :新購飛機 ############ range for vehicle availability ends STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}費用:{GOLD}{CURRENCY_LONG}{BLACK} 載重:{GOLD}{WEIGHT_SHORT} +STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}費用:{GOLD}{CURRENCY_LONG}{BLACK} (改裝費用:{GOLD}{CURRENCY_LONG}{BLACK}) 載重:{GOLD}{WEIGHT_SHORT} STR_PURCHASE_INFO_SPEED_POWER :{BLACK}速度:{GOLD}{VELOCITY}{BLACK} 功率:{GOLD}{POWER} STR_PURCHASE_INFO_SPEED :{BLACK}速度:{GOLD}{VELOCITY} STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}在海上速度: {GOLD}{VELOCITY} @@ -3340,6 +3348,7 @@ STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}購買 STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}購買飛機 STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購買並改裝車輛 +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購買並改裝飛機 STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}購買選定的列車。按住 Shift 點選則只會顯示預估的購買費用 STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}購買選定的車輛。按住 Shift 點選則只會顯示預估的購買費用 From ce1c60699afc7c7fa857fb118995a255e87c5b91 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 28 May 2021 19:53:19 +0000 Subject: [PATCH 258/800] Update: Translations from eints norwegian (bokmal): 3 changes by Anolitt dutch: 3 changes by Afoklala portuguese (brazilian): 3 changes by Vimerum --- src/lang/brazilian_portuguese.txt | 4 +++- src/lang/dutch.txt | 4 +++- src/lang/norwegian_bokmal.txt | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 386701dc15..4776249796 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -3559,7 +3559,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Clique p STR_GROUP_DELETE_TOOLTIP :{BLACK}Remove o grupo selecionado STR_GROUP_RENAME_TOOLTIP :{BLACK}Renomeia o grupo selecionado STR_GROUP_LIVERY_TOOLTIP :{BLACK}Alterar a pintura do grupo selecionado -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para excluir esse grupo da substituição automática +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para excluir esse grupo da substituição automática global. Ctrl+Clique para também excluir os subgrupos. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Remover grupo STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Tem certeza que quer remover esse grupo e seus descendentes? @@ -3812,7 +3812,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglevs STR_REPLACE_ROAD_VEHICLES :Veículos terrestres STR_REPLACE_TRAM_VEHICLES :Bondes +STR_REPLACE_REMOVE_WAGON :{BLACK}Remoção de vagões ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Faz autosubstituição manter o tamanho do trem removendo vagões (começando pela frente), se ao substituir a locomotiva o trem ficar maior +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+Clique para também aplicar para os subgrupos # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 9798a97823..a156876303 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -3558,7 +3558,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Klik om STR_GROUP_DELETE_TOOLTIP :{BLACK}Verwijder de geselecteerde groep STR_GROUP_RENAME_TOOLTIP :{BLACK}Hiermee hernoem je de geselecteerde groep STR_GROUP_LIVERY_TOOLTIP :{BLACK}Wijzig het uiterlijk van de geselecteerde groep -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klik om deze groep te beschermen tegen globaal automatisch vervangen +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klik om deze groep te beschermen tegen globaal automatisch vervangen. Met Ctrl+klik geldt dit ook voor subgroepen. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Verwijder groep STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Weet je zeker dat je deze groep en de eventuele subgroepen wilt verwijderen? @@ -3811,7 +3811,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Magneetzweefspo STR_REPLACE_ROAD_VEHICLES :Wegvoertuigen STR_REPLACE_TRAM_VEHICLES :Trams +STR_REPLACE_REMOVE_WAGON :{BLACK}Wagons verwijderen ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}De te vervangen trein behoudt zijn lengte door wagons weg te halen (startend aan de voorkant), als het vervangen de trein langer zou maken +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Met Ctrl+klik geldt dit ook voor subgroepen # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 5b675a667d..34a55d0c87 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -3562,7 +3562,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Klikk fo STR_GROUP_DELETE_TOOLTIP :{BLACK}Fjern den valgte gruppen STR_GROUP_RENAME_TOOLTIP :{BLACK}Gi nytt navn på den valgte gruppen STR_GROUP_LIVERY_TOOLTIP :{BLACK}Endre firmafarger for valgt gruppe -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klikk for å beskytte denne gruppen fra global autoerstatning +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klikk for å beskytte denne gruppen fra global autoerstatning. Ctrl+klikk for å også beskytte undergrupper STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Slette gruppe STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Er du sikker på at du vil slette denne gruppen og eventuelle etterkommere? @@ -3815,7 +3815,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Maglev-kjøret STR_REPLACE_ROAD_VEHICLES :Veikjøretøy STR_REPLACE_TRAM_VEHICLES :Trikkekjøretøy +STR_REPLACE_REMOVE_WAGON :{BLACK}Vognfjerning ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}La autoerstatningen beholde lengen på toget ved å fjerne vogner (fra første vogn), hvis utskiftningen gjør toget lengre. +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+klikk for å også gjelde undergrupper # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} From 208952f2ba80faeb2fd16f18193a96bf066a7dae Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 09:44:20 +0200 Subject: [PATCH 259/800] Codechange: split Write_ValidateSetting to get separate functions for making strings valid and writing strings --- src/network/network_gui.cpp | 2 +- src/settings.cpp | 61 ++++++++++++++++++------------------- src/settings_internal.h | 14 ++++++--- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 3c61cf77aa..6df77cd083 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2208,7 +2208,7 @@ public: std::string client_name(str); if (!NetworkValidateClientName(client_name)) break; - SetSettingValue(GetSettingFromName("network.client_name")->AsStringSetting(), client_name.c_str()); + SetSettingValue(GetSettingFromName("network.client_name")->AsStringSetting(), client_name); this->InvalidateData(); break; } diff --git a/src/settings.cpp b/src/settings.cpp index af06d3befc..26460fbb10 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -460,34 +460,31 @@ int32 IntSettingDesc::Read(const void *object) const } /** - * Set the string value of a setting. + * Make the value valid given the limitations of this setting. + * + * In the case of string settings this is ensuring the string contains only accepted + * Utf8 characters and is at most the maximum length defined in this setting. + * @param str The string to make valid. + */ +void StringSettingDesc::MakeValueValid(std::string &str) const +{ + if (this->max_length == 0 || str.size() < this->max_length) return; + + /* In case a maximum length is imposed by the setting, the length + * includes the '\0' termination for network transfer purposes. + * Also ensure the string is valid after chopping of some bytes. */ + std::string stdstr(str, this->max_length - 1); + str.assign(str_validate(stdstr, SVS_NONE)); +} + +/** + * Write a string to the actual setting. * @param object The object the setting is to be saved in. * @param str The string to save. */ -void StringSettingDesc::Write_ValidateSetting(const void *object, const char *str) const +void StringSettingDesc::Write(const void *object, const std::string &str) const { - std::string *dst = reinterpret_cast(GetVariableAddress(object, &this->save)); - - switch (GetVarMemType(this->save.conv)) { - case SLE_VAR_STR: - case SLE_VAR_STRQ: - if (str != nullptr) { - if (this->max_length != 0 && strlen(str) >= this->max_length) { - /* In case a maximum length is imposed by the setting, the length - * includes the '\0' termination for network transfer purposes. - * Also ensure the string is valid after chopping of some bytes. */ - std::string stdstr(str, this->max_length - 1); - dst->assign(str_validate(stdstr, SVS_NONE)); - } else { - dst->assign(str); - } - } else { - dst->clear(); - } - break; - - default: NOT_REACHED(); - } + reinterpret_cast(GetVariableAddress(object, &this->save))->assign(str); } /** @@ -553,8 +550,9 @@ void IntSettingDesc::ParseValue(const IniItem *item, void *object) const void StringSettingDesc::ParseValue(const IniItem *item, void *object) const { - const char *str = (item == nullptr) ? this->def : item->value.has_value() ? item->value->c_str() : nullptr; - this->Write_ValidateSetting(object, str); + std::string str = (item == nullptr) ? this->def : item->value.value_or(""); + this->MakeValueValid(str); + this->Write(object, str); } void ListSettingDesc::ParseValue(const IniItem *item, void *object) const @@ -2026,12 +2024,12 @@ uint GetCompanySettingIndex(const char *name) * @param force_newgame force the newgame settings * @note Strings WILL NOT be synced over the network */ -bool SetSettingValue(const StringSettingDesc *sd, const char *value, bool force_newgame) +bool SetSettingValue(const StringSettingDesc *sd, std::string value, bool force_newgame) { assert(sd->save.conv & SLF_NO_NETWORK_SYNC); - if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && strcmp(value, "(null)") == 0) { - value = nullptr; + if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && value.compare("(null)") == 0) { + value.clear(); } const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game; @@ -2045,9 +2043,10 @@ bool SetSettingValue(const StringSettingDesc *sd, const char *value, bool force_ * @param object The object the setting is in. * @param newval The new value for the setting. */ -void StringSettingDesc::ChangeValue(const void *object, const char *newval) const +void StringSettingDesc::ChangeValue(const void *object, std::string &newval) const { - this->Write_ValidateSetting(object, newval); + this->MakeValueValid(newval); + this->Write(object, newval); if (this->proc != nullptr) this->proc(0); if (_save_config) SaveToConfig(); diff --git a/src/settings_internal.h b/src/settings_internal.h index e7dd6e9149..9e6358a6c6 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -210,21 +210,25 @@ struct ManyOfManySettingDesc : OneOfManySettingDesc { struct StringSettingDesc : SettingDesc { StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def, uint32 max_length, OnChange proc) : - SettingDesc(save, name, flags, startup), def(def), max_length(max_length), proc(proc) {} + SettingDesc(save, name, flags, startup), def(def == nullptr ? "" : def), max_length(max_length), + proc(proc) {} virtual ~StringSettingDesc() {} - const char *def; ///< default value given when none is present + std::string def; ///< default value given when none is present uint32 max_length; ///< maximum length of the string, 0 means no maximum length OnChange *proc; ///< callback procedure for when the value is changed bool IsStringSetting() const override { return true; } - void ChangeValue(const void *object, const char *newval) const; - void Write_ValidateSetting(const void *object, const char *str) const; + void ChangeValue(const void *object, std::string &newval) const; void FormatValue(char *buf, const char *last, const void *object) const override; void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; const std::string &Read(const void *object) const; + +private: + void MakeValueValid(std::string &str) const; + void Write(const void *object, const std::string &str) const; }; /** List/array settings. */ @@ -255,7 +259,7 @@ typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame = false); -bool SetSettingValue(const StringSettingDesc *sd, const char *value, bool force_newgame = false); +bool SetSettingValue(const StringSettingDesc *sd, const std::string value, bool force_newgame = false); uint GetSettingIndex(const SettingDesc *sd); #endif /* SETTINGS_INTERNAL_H */ From ea9715d970911300b17f8a55dd1047f3706d22f4 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 10:42:02 +0200 Subject: [PATCH 260/800] Codechange: split Write_ValidateSetting to get separate functions for making ints valid and writing ints --- src/settings.cpp | 43 +++++++++++++++++++++++++++++++---------- src/settings_internal.h | 6 +++++- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 26460fbb10..bf3360319a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -392,14 +392,28 @@ size_t BoolSettingDesc::ParseValue(const char *str) const } /** - * Set the value of a setting and if needed clamp the value to the preset minimum and maximum. + * Make the value valid and then write it to the setting. + * See #MakeValidValid and #Write for more details. * @param object The object the setting is to be saved in. * @param val Signed version of the new value. */ -void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const +void IntSettingDesc::MakeValueValidAndWrite(const void *object, int32 val) const { - void *ptr = GetVariableAddress(object, &this->save); + this->MakeValueValid(val); + this->Write(object, val); +} +/** + * Make the value valid given the limitations of this setting. + * + * In the case of int settings this is ensuring the value is between the minimum and + * maximum value, with a special case for 0 if SGF_0ISDISABLED is set. + * This is generally done by clamping the value so it is within the allowed value range. + * However, for SGF_MULTISTRING the default is used when the value is not valid. + * @param val The value to make valid. + */ +void IntSettingDesc::MakeValueValid(int32 &val) const +{ /* We need to take special care of the uint32 type as we receive from the function * a signed integer. While here also bail out on 64-bit settings as those are not * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed @@ -437,14 +451,23 @@ void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const uval = (uint32)this->def; } } - WriteValue(ptr, SLE_VAR_U32, (int64)uval); + val = (int32)val; return; } case SLE_VAR_I64: case SLE_VAR_U64: default: NOT_REACHED(); } +} +/** + * Set the value of a setting. + * @param object The object the setting is to be saved in. + * @param val Signed version of the new value. + */ +void IntSettingDesc::Write(const void *object, int32 val) const +{ + void *ptr = GetVariableAddress(object, &this->save); WriteValue(ptr, this->save.conv, (int64)val); } @@ -545,7 +568,7 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::ParseValue(const IniItem *item, void *object) const { size_t val = (item == nullptr) ? this->def : this->ParseValue(item->value.has_value() ? item->value->c_str() : ""); - this->Write_ValidateSetting(object, (int32)val); + this->MakeValueValidAndWrite(object, (int32)val); } void StringSettingDesc::ParseValue(const IniItem *item, void *object) const @@ -1388,7 +1411,7 @@ static void HandleOldDiffCustom(bool savegame) /* Skip deprecated options */ if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; int32 value = (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]); - sd->AsIntSetting()->Write_ValidateSetting(savegame ? &_settings_game : &_settings_newgame, value); + sd->AsIntSetting()->MakeValueValidAndWrite(savegame ? &_settings_game : &_settings_newgame, value); } } @@ -1825,14 +1848,14 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const { int32 oldval = this->Read(object); - this->Write_ValidateSetting(object, newval); + this->MakeValueValidAndWrite(object, newval); newval = this->Read(object); if (oldval == newval) return; if (this->proc != nullptr && !this->proc(newval)) { /* The change was not allowed, so revert. */ - WriteValue(GetVariableAddress(object, &this->save), this->save.conv, (int64)oldval); + this->Write(object, oldval); return; } @@ -1987,7 +2010,7 @@ void SetDefaultCompanySettings(CompanyID cid) Company *c = Company::Get(cid); for (auto &sd : _company_settings) { const IntSettingDesc *int_setting = sd->AsIntSetting(); - int_setting->Write_ValidateSetting(&c->settings, int_setting->def); + int_setting->MakeValueValidAndWrite(&c->settings, int_setting->def); } } @@ -2189,7 +2212,7 @@ static void LoadSettings(const SettingTable &settings, void *object) if (!SlObjectMember(ptr, &osd->save)) continue; if (osd->IsIntSetting()) { const IntSettingDesc *int_setting = osd->AsIntSetting(); - int_setting->Write_ValidateSetting(object, int_setting->Read(object)); + int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); } } } diff --git a/src/settings_internal.h b/src/settings_internal.h index 9e6358a6c6..d13f4c89eb 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -150,13 +150,17 @@ struct IntSettingDesc : SettingDesc { bool IsIntSetting() const override { return true; } void ChangeValue(const void *object, int32 newvalue) const; - void Write_ValidateSetting(const void *object, int32 value) const; + void MakeValueValidAndWrite(const void *object, int32 value) const; virtual size_t ParseValue(const char *str) const; void FormatValue(char *buf, const char *last, const void *object) const override; void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; int32 Read(const void *object) const; + +private: + void MakeValueValid(int32 &value) const; + void Write(const void *object, int32 value) const; }; /** Boolean setting. */ From e2f5d9e561b70aec85d67b4eea822ba49f0c20bf Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 09:44:20 +0200 Subject: [PATCH 261/800] Codechange: use separate pre and post callbacks for string settings --- src/network/network_client.cpp | 17 ++++-------- src/network/network_func.h | 2 +- src/settings.cpp | 41 ++++++++++++--------------- src/settings_internal.h | 26 +++++++++++++---- src/table/currency_settings.ini | 6 ++-- src/table/misc_settings.ini | 14 ++++++---- src/table/settings.h.preamble | 12 ++++---- src/table/settings.ini | 49 +++++++++++++++++---------------- 8 files changed, 89 insertions(+), 78 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 08a35e980b..1a729e34fc 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1344,27 +1344,22 @@ bool NetworkValidateClientName() } /** - * Send the server our name. + * Send the server our name as callback from the setting. + * @param newname The new client name. */ -void NetworkUpdateClientName() +void NetworkUpdateClientName(const std::string &client_name) { NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id); - if (ci == nullptr) return; - /* There is no validation on string settings, it is actually a post change callback. - * This method is called from that post change callback. So, when the client name is - * changed via the console there is no easy way to prevent an invalid name. Though, - * we can prevent it getting sent here. */ - if (!NetworkValidateClientName()) return; /* Don't change the name if it is the same as the old name */ - if (_settings_client.network.client_name.compare(ci->client_name) != 0) { + if (client_name.compare(ci->client_name) != 0) { if (!_network_server) { - MyClient::SendSetName(_settings_client.network.client_name.c_str()); + MyClient::SendSetName(client_name.c_str()); } else { /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ char temporary_name[NETWORK_CLIENT_NAME_LENGTH]; - strecpy(temporary_name, _settings_client.network.client_name.c_str(), lastof(temporary_name)); + strecpy(temporary_name, client_name.c_str(), lastof(temporary_name)); if (NetworkFindName(temporary_name, lastof(temporary_name))) { NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); ci->client_name = temporary_name; diff --git a/src/network/network_func.h b/src/network/network_func.h index 1c5916eda0..fbae8daf76 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -38,7 +38,7 @@ byte NetworkSpectatorCount(); bool NetworkIsValidClientName(const std::string_view client_name); bool NetworkValidateClientName(); bool NetworkValidateClientName(std::string &client_name); -void NetworkUpdateClientName(); +void NetworkUpdateClientName(const std::string &client_name); bool NetworkCompanyHasClients(CompanyID company); std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password); void NetworkReboot(); diff --git a/src/settings.cpp b/src/settings.cpp index bf3360319a..f2980a3632 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1343,37 +1343,28 @@ static bool InvalidateShipPathCache(int32 p1) return true; } -static bool UpdateClientName(int32 p1) +/** + * Replace a passwords that are a literal asterisk with an empty string. + * @param newval The new string value for this password field. + * @return Always true. + */ +static bool ReplaceAsteriskWithEmptyPassword(std::string &newval) { - NetworkUpdateClientName(); - return true; -} - -static bool UpdateServerPassword(int32 p1) -{ - if (_settings_client.network.server_password.compare("*") == 0) { - _settings_client.network.server_password.clear(); - } - - NetworkServerUpdateGameInfo(); - return true; -} - -static bool UpdateRconPassword(int32 p1) -{ - if (_settings_client.network.rcon_password.compare("*") == 0) { - _settings_client.network.rcon_password.clear(); - } - + if (newval.compare("*") == 0) newval.clear(); return true; } static bool UpdateClientConfigValues(int32 p1) +{ + UpdateClientConfigValues(); + return true; +} + +/** Update the game info, and send it to the clients when we are running as a server. */ +static void UpdateClientConfigValues() { NetworkServerUpdateGameInfo(); if (_network_server) NetworkServerSendConfigUpdate(); - - return true; } /* End - Callback Functions */ @@ -2069,8 +2060,10 @@ bool SetSettingValue(const StringSettingDesc *sd, std::string value, bool force_ void StringSettingDesc::ChangeValue(const void *object, std::string &newval) const { this->MakeValueValid(newval); + if (this->pre_check != nullptr && !this->pre_check(newval)) return; + this->Write(object, newval); - if (this->proc != nullptr) this->proc(0); + if (this->post_callback != nullptr) this->post_callback(newval); if (_save_config) SaveToConfig(); } diff --git a/src/settings_internal.h b/src/settings_internal.h index d13f4c89eb..4a483cc0e8 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -212,15 +212,31 @@ struct ManyOfManySettingDesc : OneOfManySettingDesc { /** String settings. */ struct StringSettingDesc : SettingDesc { + /** + * A check to be performed before the setting gets changed. The passed string may be + * changed by the check if that is important, for example to remove unwanted white + * space. The return value denotes whether the value, potentially after the changes, + * is allowed to be used/set in the configuration. + * @param value The prospective new value for the setting. + * @return True when the setting is accepted. + */ + typedef bool PreChangeCheck(std::string &value); + /** + * A callback to denote that a setting has been changed. + * @param The new value for the setting. + */ + typedef void PostChangeCallback(const std::string &value); + StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def, - uint32 max_length, OnChange proc) : + uint32 max_length, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def == nullptr ? "" : def), max_length(max_length), - proc(proc) {} + pre_check(pre_check), post_callback(post_callback) {} virtual ~StringSettingDesc() {} - std::string def; ///< default value given when none is present - uint32 max_length; ///< maximum length of the string, 0 means no maximum length - OnChange *proc; ///< callback procedure for when the value is changed + std::string def; ///< Default value given when none is present + uint32 max_length; ///< Maximum length of the string, 0 means no maximum length + PreChangeCheck *pre_check; ///< Callback to check for the validity of the setting. + PostChangeCallback *post_callback; ///< Callback when the setting has been changed. bool IsStringSetting() const override { return true; } void ChangeValue(const void *object, std::string &newval) const; diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 76eecc1043..0714b1b93d 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -9,8 +9,8 @@ static const SettingTable _currency_settings{ [post-amble] }; [templates] -SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $proc, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -23,6 +23,8 @@ str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 017320c863..952839daa4 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -21,12 +21,12 @@ static const SettingTable _misc_settings{ [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $proc, $from, $to, $cat, $extra, $startup), -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -40,6 +40,8 @@ str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 7f9ac2dd59..f5f7352440 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -67,8 +67,8 @@ static size_t ConvertLandscape(const char *value); #define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, startup, def) -#define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, proc, from, to, cat, extra, startup)\ - NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, startup, def, max_length, proc) +#define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, startup, def, max_length, pre_check, post_callback) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) @@ -90,8 +90,8 @@ static size_t ConvertLandscape(const char *value); #define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def) -#define SDT_SSTR(base, var, type, flags, guiflags, def, proc, from, to, cat, extra, startup)\ - NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def, 0, proc) +#define SDT_SSTR(base, var, type, flags, guiflags, def, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def, 0, pre_check, post_callback) #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, load) @@ -112,8 +112,8 @@ static size_t ConvertLandscape(const char *value); #define SDTC_LIST(var, type, flags, guiflags, def, from, to, cat, extra, startup)\ SDTG_LIST(#var, type, flags, guiflags, _settings_client.var, def, lengthof(_settings_client.var), from, to, cat, extra, startup) -#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, proc, from, to, cat, extra, startup)\ - SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, proc, from, to, cat, extra, startup)\ +#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index 4f105b5f66..1de905c5b4 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -43,9 +43,8 @@ static bool SpriteZoomMinChanged(int32 p1); static bool MaxVehiclesChanged(int32 p1); static bool InvalidateShipPathCache(int32 p1); -static bool UpdateClientName(int32 p1); -static bool UpdateServerPassword(int32 p1); -static bool UpdateRconPassword(int32 p1); +static bool ReplaceAsteriskWithEmptyPassword(std::string &newval); +static void UpdateClientConfigValues(); static bool UpdateClientConfigValues(int32 p1); /* End - Callback Functions for the various settings */ @@ -54,7 +53,7 @@ static bool UpdateClientConfigValues(int32 p1); * These include for example the GUI settings and will not be saved with the * savegame. * It is also a bit tricky since you would think that service_interval - * for example doesn't need to be synched. Every client assigns the + * for example does not need to be synched. Every client assigns the * service_interval value to the v->service_interval, meaning that every client * assigns its own value. If the setting was company-based, that would mean that * vehicles could decide on different moments that they are heading back to a @@ -63,18 +62,18 @@ const SettingTable _settings{ [post-amble] }; [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $proc, $from, $to, $cat, $extra, $startup), -SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $proc, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL($length, $from, $to), [validation] @@ -93,6 +92,8 @@ str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION @@ -2646,7 +2647,7 @@ type = SLE_STRQ from = SLV_118 flags = SLF_NO_NETWORK_SYNC def = nullptr -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_SSTR] @@ -2656,7 +2657,7 @@ type = SLE_STRQ from = SLV_118 flags = SLF_NO_NETWORK_SYNC def = nullptr -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_SSTR] @@ -2666,7 +2667,7 @@ type = SLE_STRQ from = SLV_126 flags = SLF_NO_NETWORK_SYNC def = nullptr -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC @@ -3921,7 +3922,8 @@ type = SLE_STR length = NETWORK_CLIENT_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = nullptr -proc = UpdateClientName +pre_cb = NetworkValidateClientName +post_cb = NetworkUpdateClientName cat = SC_BASIC [SDTC_SSTR] @@ -3931,7 +3933,8 @@ length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr -proc = UpdateServerPassword +pre_cb = ReplaceAsteriskWithEmptyPassword +post_cb = [](auto) { NetworkServerUpdateGameInfo(); } cat = SC_BASIC [SDTC_SSTR] @@ -3941,7 +3944,7 @@ length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr -proc = UpdateRconPassword +pre_cb = ReplaceAsteriskWithEmptyPassword cat = SC_BASIC [SDTC_SSTR] @@ -3967,7 +3970,7 @@ length = NETWORK_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr -proc = UpdateClientConfigValues +post_cb = [](auto) { UpdateClientConfigValues(); } cat = SC_BASIC [SDTC_SSTR] From 08308d808c2ab3a6621762127eed6c46f16286c6 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 11:47:37 +0200 Subject: [PATCH 262/800] Codechange: use separate pre and post callbacks for int settings --- src/elrail.cpp | 5 +- src/elrail_func.h | 2 +- src/newgrf_config.cpp | 6 +- src/newgrf_config.h | 2 +- src/rail_gui.cpp | 7 +- src/rail_gui.h | 2 +- src/settings.cpp | 282 ++++++++------------------------ src/settings_internal.h | 50 ++++-- src/table/company_settings.ini | 30 ++-- src/table/currency_settings.ini | 3 +- src/table/gameopt_settings.ini | 13 +- src/table/misc_settings.ini | 9 +- src/table/settings.h.preamble | 44 ++--- src/table/settings.ini | 219 ++++++++++++------------- src/table/win32_settings.ini | 7 +- src/table/window_settings.ini | 7 +- 16 files changed, 272 insertions(+), 416 deletions(-) diff --git a/src/elrail.cpp b/src/elrail.cpp index 44481dd313..4959bb2cba 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -593,9 +593,9 @@ void DrawRailCatenary(const TileInfo *ti) DrawRailCatenaryRailway(ti); } -bool SettingsDisableElrail(int32 p1) +void SettingsDisableElrail(int32 new_value) { - bool disable = (p1 != 0); + bool disable = (new_value != 0); /* we will now walk through all electric train engines and change their railtypes if it is the wrong one*/ const RailType old_railtype = disable ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; @@ -639,5 +639,4 @@ bool SettingsDisableElrail(int32 p1) * rails. It may have unintended consequences if that function is ever * extended, though. */ ReinitGuiAfterToggleElrail(disable); - return true; } diff --git a/src/elrail_func.h b/src/elrail_func.h index 0438437241..bd301d6bb1 100644 --- a/src/elrail_func.h +++ b/src/elrail_func.h @@ -36,6 +36,6 @@ void DrawRailCatenary(const TileInfo *ti); void DrawRailCatenaryOnTunnel(const TileInfo *ti); void DrawRailCatenaryOnBridge(const TileInfo *ti); -bool SettingsDisableElrail(int32 p1); ///< _settings_game.disable_elrail callback +void SettingsDisableElrail(int32 new_value); ///< _settings_game.disable_elrail callback #endif /* ELRAIL_FUNC_H */ diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index b92b297da0..044d361939 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -282,15 +282,13 @@ void GRFParameterInfo::Finalize() /** * Update the palettes of the graphics from the config file. * Called when changing the default palette in advanced settings. - * @param p1 Unused. - * @return Always true. + * @param new_value Unused. */ -bool UpdateNewGRFConfigPalette(int32 p1) +void UpdateNewGRFConfigPalette(int32 new_value) { for (GRFConfig *c = _grfconfig_newgame; c != nullptr; c = c->next) c->SetSuitablePalette(); for (GRFConfig *c = _grfconfig_static; c != nullptr; c = c->next) c->SetSuitablePalette(); for (GRFConfig *c = _all_grfs; c != nullptr; c = c->next) c->SetSuitablePalette(); - return true; } /** diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 1588f8c3ab..3b3da962ea 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -239,6 +239,6 @@ void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFC GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create); void UpdateNewGRFScanStatus(uint num, const char *name); -bool UpdateNewGRFConfigPalette(int32 p1 = 0); +void UpdateNewGRFConfigPalette(int32 new_value = 0); #endif /* NEWGRF_CONFIG_H */ diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index e7221d01c4..86f7189843 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -2130,10 +2130,9 @@ static void SetDefaultRailGui() /** * Updates the current signal variant used in the signal GUI * to the one adequate to current year. - * @param p needed to be called when a setting changes - * @return success, needed for settings + * @param new_value needed to be called when a setting changes */ -bool ResetSignalVariant(int32 p) +void ResetSignalVariant(int32 new_value) { SignalVariant new_variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); @@ -2145,8 +2144,6 @@ bool ResetSignalVariant(int32 p) } _cur_signal_variant = new_variant; } - - return true; } /** diff --git a/src/rail_gui.h b/src/rail_gui.h index 29a1b9b161..81fb8f6271 100644 --- a/src/rail_gui.h +++ b/src/rail_gui.h @@ -15,7 +15,7 @@ struct Window *ShowBuildRailToolbar(RailType railtype); void ReinitGuiAfterToggleElrail(bool disable); -bool ResetSignalVariant(int32 = 0); +void ResetSignalVariant(int32 = 0); void InitializeRailGUI(); DropDownList GetRailTypeDropDownList(bool for_replacement = false, bool all_option = false); diff --git a/src/settings.cpp b/src/settings.cpp index f2980a3632..0160f8e0e3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -807,99 +807,56 @@ const StringSettingDesc *SettingDesc::AsStringSetting() const /* Begin - Callback Functions for the various settings. */ /** Reposition the main toolbar as the setting changed. */ -static bool v_PositionMainToolbar(int32 p1) +static void v_PositionMainToolbar(int32 new_value) { if (_game_mode != GM_MENU) PositionMainToolbar(nullptr); - return true; } /** Reposition the statusbar as the setting changed. */ -static bool v_PositionStatusbar(int32 p1) +static void v_PositionStatusbar(int32 new_value) { if (_game_mode != GM_MENU) { PositionStatusbar(nullptr); PositionNewsMessage(nullptr); PositionNetworkChatWindow(nullptr); } - return true; -} - -static bool PopulationInLabelActive(int32 p1) -{ - UpdateAllTownVirtCoords(); - return true; -} - -static bool RedrawScreen(int32 p1) -{ - MarkWholeScreenDirty(); - return true; } /** * Redraw the smallmap after a colour scheme change. * @param p1 Callback parameter. - * @return Always true. */ -static bool RedrawSmallmap(int32 p1) +static void RedrawSmallmap(int32 new_value) { BuildLandLegend(); BuildOwnerLegend(); SetWindowClassesDirty(WC_SMALLMAP); - return true; } -static bool InvalidateDetailsWindow(int32 p1) -{ - SetWindowClassesDirty(WC_VEHICLE_DETAILS); - return true; -} - -static bool StationSpreadChanged(int32 p1) +static void StationSpreadChanged(int32 p1) { InvalidateWindowData(WC_SELECT_STATION, 0); InvalidateWindowData(WC_BUILD_STATION, 0); - return true; } -static bool InvalidateBuildIndustryWindow(int32 p1) +static void CloseSignalGUI(int32 new_value) { - InvalidateWindowData(WC_BUILD_INDUSTRY, 0); - return true; -} - -static bool CloseSignalGUI(int32 p1) -{ - if (p1 == 0) { + if (new_value == 0) { DeleteWindowByClass(WC_BUILD_SIGNAL); } - return true; } -static bool InvalidateTownViewWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_TOWN_VIEW, p1); - return true; -} - -static bool DeleteSelectStationWindow(int32 p1) -{ - DeleteWindowById(WC_SELECT_STATION, 0); - return true; -} - -static bool UpdateConsists(int32 p1) +static void UpdateConsists(int32 new_value) { for (Train *t : Train::Iterate()) { /* Update the consist of all trains so the maximum speed is set correctly. */ if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(CCF_TRACK); } InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); - return true; } -/* Check service intervals of vehicles, p1 is value of % or day based servicing */ -static bool CheckInterval(int32 p1) +/* Check service intervals of vehicles, newvalue is value of % or day based servicing */ +static void UpdateServiceInterval(int32 new_value) { bool update_vehicles; VehicleDefaultSettings *vds; @@ -911,7 +868,7 @@ static bool CheckInterval(int32 p1) update_vehicles = true; } - if (p1 != 0) { + if (new_value != 0) { vds->servint_trains = 50; vds->servint_roadveh = 50; vds->servint_aircraft = 50; @@ -928,66 +885,42 @@ static bool CheckInterval(int32 p1) for (Vehicle *v : Vehicle::Iterate()) { if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { v->SetServiceInterval(CompanyServiceInterval(c, v->type)); - v->SetServiceIntervalIsPercent(p1 != 0); + v->SetServiceIntervalIsPercent(new_value != 0); } } } - InvalidateDetailsWindow(0); - - return true; + SetWindowClassesDirty(WC_VEHICLE_DETAILS); } -static bool UpdateInterval(VehicleType type, int32 p1) +static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value) { - bool update_vehicles; VehicleDefaultSettings *vds; if (_game_mode == GM_MENU || !Company::IsValidID(_current_company)) { vds = &_settings_client.company.vehicle; - update_vehicles = false; } else { vds = &Company::Get(_current_company)->settings.vehicle; - update_vehicles = true; } /* Test if the interval is valid */ - uint16 interval = GetServiceIntervalClamped(p1, vds->servint_ispercent); - if (interval != p1) return false; + int32 interval = GetServiceIntervalClamped(new_value, vds->servint_ispercent); + return interval == new_value; +} - if (update_vehicles) { +static void UpdateServiceInterval(VehicleType type, int32 new_value) +{ + if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) { for (Vehicle *v : Vehicle::Iterate()) { if (v->owner == _current_company && v->type == type && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { - v->SetServiceInterval(p1); + v->SetServiceInterval(new_value); } } } - InvalidateDetailsWindow(0); - - return true; + SetWindowClassesDirty(WC_VEHICLE_DETAILS); } -static bool UpdateIntervalTrains(int32 p1) -{ - return UpdateInterval(VEH_TRAIN, p1); -} - -static bool UpdateIntervalRoadVeh(int32 p1) -{ - return UpdateInterval(VEH_ROAD, p1); -} - -static bool UpdateIntervalShips(int32 p1) -{ - return UpdateInterval(VEH_SHIP, p1); -} - -static bool UpdateIntervalAircraft(int32 p1) -{ - return UpdateInterval(VEH_AIRCRAFT, p1); -} - -static bool TrainAccelerationModelChanged(int32 p1) +static void TrainAccelerationModelChanged(int32 new_value) { for (Train *t : Train::Iterate()) { if (t->IsFrontEngine()) { @@ -1000,30 +933,24 @@ static bool TrainAccelerationModelChanged(int32 p1) SetWindowClassesDirty(WC_ENGINE_PREVIEW); InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); SetWindowClassesDirty(WC_VEHICLE_DETAILS); - - return true; } /** * This function updates the train acceleration cache after a steepness change. - * @param p1 Callback parameter. - * @return Always true. + * @param new_value Unused new value of setting. */ -static bool TrainSlopeSteepnessChanged(int32 p1) +static void TrainSlopeSteepnessChanged(int32 new_value) { for (Train *t : Train::Iterate()) { if (t->IsFrontEngine()) t->CargoChanged(); } - - return true; } /** * This function updates realistic acceleration caches when the setting "Road vehicle acceleration model" is set. - * @param p1 Callback parameter - * @return Always true + * @param new_value Unused new value of setting. */ -static bool RoadVehAccelerationModelChanged(int32 p1) +static void RoadVehAccelerationModelChanged(int32 new_value) { if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) { for (RoadVehicle *rv : RoadVehicle::Iterate()) { @@ -1037,48 +964,29 @@ static bool RoadVehAccelerationModelChanged(int32 p1) SetWindowClassesDirty(WC_ENGINE_PREVIEW); InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); SetWindowClassesDirty(WC_VEHICLE_DETAILS); - - return true; } /** * This function updates the road vehicle acceleration cache after a steepness change. - * @param p1 Callback parameter. - * @return Always true. + * @param new_value Unused new value of setting. */ -static bool RoadVehSlopeSteepnessChanged(int32 p1) +static void RoadVehSlopeSteepnessChanged(int32 new_value) { for (RoadVehicle *rv : RoadVehicle::Iterate()) { if (rv->IsFrontEngine()) rv->CargoChanged(); } - - return true; } -static bool DragSignalsDensityChanged(int32) -{ - InvalidateWindowData(WC_BUILD_SIGNAL, 0); - - return true; -} - -static bool TownFoundingChanged(int32 p1) +static void TownFoundingChanged(int32 new_value) { if (_game_mode != GM_EDITOR && _settings_game.economy.found_town == TF_FORBIDDEN) { DeleteWindowById(WC_FOUND_TOWN, 0); - return true; + } else { + InvalidateWindowData(WC_FOUND_TOWN, 0); } - InvalidateWindowData(WC_FOUND_TOWN, 0); - return true; } -static bool InvalidateVehTimetableWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE, VIWD_MODIFY_ORDERS); - return true; -} - -static bool ZoomMinMaxChanged(int32 p1) +static void ZoomMinMaxChanged(int32 new_value) { extern void ConstrainAllViewportsZoom(); ConstrainAllViewportsZoom(); @@ -1089,81 +997,32 @@ static bool ZoomMinMaxChanged(int32 p1) UpdateCursorSize(); LoadStringWidthTable(); } - return true; } -static bool SpriteZoomMinChanged(int32 p1) { +static void SpriteZoomMinChanged(int32 new_value) +{ GfxClearSpriteCache(); /* Force all sprites to redraw at the new chosen zoom level */ MarkWholeScreenDirty(); - return true; } /** * Update any possible saveload window and delete any newgrf dialogue as * its widget parts might change. Reinit all windows as it allows access to the * newgrf debug button. - * @param p1 unused. - * @return Always true. + * @param new_value unused. */ -static bool InvalidateNewGRFChangeWindows(int32 p1) +static void InvalidateNewGRFChangeWindows(int32 new_value) { InvalidateWindowClassesData(WC_SAVELOAD); DeleteWindowByClass(WC_GAME_OPTIONS); ReInitAllWindows(_gui_zoom_cfg); - return true; } -static bool InvalidateCompanyLiveryWindow(int32 p1) +static void InvalidateCompanyLiveryWindow(int32 new_value) { InvalidateWindowClassesData(WC_COMPANY_COLOUR, -1); ResetVehicleColourMap(); - return RedrawScreen(p1); -} - -static bool InvalidateIndustryViewWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_INDUSTRY_VIEW); - return true; -} - -static bool InvalidateAISettingsWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_AI_SETTINGS); - return true; -} - -/** - * Update the town authority window after a town authority setting change. - * @param p1 Unused. - * @return Always true. - */ -static bool RedrawTownAuthority(int32 p1) -{ - SetWindowClassesDirty(WC_TOWN_AUTHORITY); - return true; -} - -/** - * Invalidate the company infrastructure details window after a infrastructure maintenance setting change. - * @param p1 Unused. - * @return Always true. - */ -static bool InvalidateCompanyInfrastructureWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_COMPANY_INFRASTRUCTURE); - return true; -} - -/** - * Invalidate the company details window after the shares setting changed. - * @param p1 Unused. - * @return Always true. - */ -static bool InvalidateCompanyWindow(int32 p1) -{ - InvalidateWindowClassesData(WC_COMPANY); - return true; } /** Checks if any settings are set to incorrect values, and sets them to correct values in that case. */ @@ -1176,7 +1035,7 @@ static void ValidateSettings() } } -static bool DifficultyNoiseChange(int32 i) +static void DifficultyNoiseChange(int32 new_value) { if (_game_mode == GM_NORMAL) { UpdateAirportsNoise(); @@ -1184,11 +1043,9 @@ static bool DifficultyNoiseChange(int32 i) InvalidateWindowClassesData(WC_TOWN_VIEW, 0); } } - - return true; } -static bool MaxNoAIsChange(int32 i) +static void MaxNoAIsChange(int32 new_value) { if (GetGameSettings().difficulty.max_no_competitors != 0 && AI::GetInfoList()->size() == 0 && @@ -1197,15 +1054,14 @@ static bool MaxNoAIsChange(int32 i) } InvalidateWindowClassesData(WC_GAME_OPTIONS, 0); - return true; } /** * Check whether the road side may be changed. - * @param p1 unused + * @param new_value unused * @return true if the road side may be changed. */ -static bool CheckRoadSide(int p1) +static bool CheckRoadSide(int32 &new_value) { extern bool RoadVehiclesAreBuilt(); return _game_mode == GM_MENU || !RoadVehiclesAreBuilt(); @@ -1225,10 +1081,10 @@ static size_t ConvertLandscape(const char *value) return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values); } -static bool CheckFreeformEdges(int32 p1) +static bool CheckFreeformEdges(int32 &new_value) { if (_game_mode == GM_MENU) return true; - if (p1 != 0) { + if (new_value != 0) { for (Ship *s : Ship::Iterate()) { /* Check if there is a ship on the northern border. */ if (TileX(s->tile) == 0 || TileY(s->tile) == 0) { @@ -1243,8 +1099,6 @@ static bool CheckFreeformEdges(int32 p1) return false; } } - for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); - for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); } else { for (uint i = 0; i < MapMaxX(); i++) { if (TileHeight(TileXY(i, 1)) != 0) { @@ -1270,6 +1124,18 @@ static bool CheckFreeformEdges(int32 p1) return false; } } + } + return true; +} + +static void UpdateFreeformEdges(int32 new_value) +{ + if (_game_mode == GM_MENU) return; + + if (new_value != 0) { + for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); + for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); + } else { /* Make tiles at the border water again. */ for (uint i = 0; i < MapMaxX(); i++) { SetTileHeight(TileXY(i, 0), 0); @@ -1281,14 +1147,13 @@ static bool CheckFreeformEdges(int32 p1) } } MarkWholeScreenDirty(); - return true; } /** * Changing the setting "allow multiple NewGRF sets" is not allowed * if there are vehicles. */ -static bool ChangeDynamicEngines(int32 p1) +static bool CheckDynamicEngines(int32 &new_value) { if (_game_mode == GM_MENU) return true; @@ -1300,7 +1165,7 @@ static bool ChangeDynamicEngines(int32 p1) return true; } -static bool ChangeMaxHeightLevel(int32 p1) +static bool CheckMaxHeightLevel(int32 &new_value) { if (_game_mode == GM_NORMAL) return false; if (_game_mode != GM_EDITOR) return true; @@ -1308,39 +1173,33 @@ static bool ChangeMaxHeightLevel(int32 p1) /* Check if at least one mountain on the map is higher than the new value. * If yes, disallow the change. */ for (TileIndex t = 0; t < MapSize(); t++) { - if ((int32)TileHeight(t) > p1) { + if ((int32)TileHeight(t) > new_value) { ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, WL_ERROR); /* Return old, unchanged value */ return false; } } - /* The smallmap uses an index from heightlevels to colours. Trigger rebuilding it. */ - InvalidateWindowClassesData(WC_SMALLMAP, 2); - return true; } -static bool StationCatchmentChanged(int32 p1) +static void StationCatchmentChanged(int32 new_value) { Station::RecomputeCatchmentForAll(); MarkWholeScreenDirty(); - return true; } -static bool MaxVehiclesChanged(int32 p1) +static void MaxVehiclesChanged(int32 new_value) { InvalidateWindowClassesData(WC_BUILD_TOOLBAR); MarkWholeScreenDirty(); - return true; } -static bool InvalidateShipPathCache(int32 p1) +static void InvalidateShipPathCache(int32 new_value) { for (Ship *s : Ship::Iterate()) { s->path.clear(); } - return true; } /** @@ -1354,12 +1213,6 @@ static bool ReplaceAsteriskWithEmptyPassword(std::string &newval) return true; } -static bool UpdateClientConfigValues(int32 p1) -{ - UpdateClientConfigValues(); - return true; -} - /** Update the game info, and send it to the clients when we are running as a server. */ static void UpdateClientConfigValues() { @@ -1838,17 +1691,12 @@ void DeleteGRFPresetFromConfig(const char *config_name) void IntSettingDesc::ChangeValue(const void *object, int32 newval) const { int32 oldval = this->Read(object); - - this->MakeValueValidAndWrite(object, newval); - newval = this->Read(object); - + this->MakeValueValid(newval); + if (this->pre_check != nullptr && !this->pre_check(newval)) return; if (oldval == newval) return; - if (this->proc != nullptr && !this->proc(newval)) { - /* The change was not allowed, so revert. */ - this->Write(object, oldval); - return; - } + this->Write(object, newval); + if (this->post_callback != nullptr) this->post_callback(newval); if (this->flags & SGF_NO_NETWORK) { GamelogStartAction(GLAT_SETTING); diff --git a/src/settings_internal.h b/src/settings_internal.h index 4a483cc0e8..4de0178379 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -64,8 +64,6 @@ enum SettingType { }; struct IniItem; -typedef bool OnChange(int32 var); ///< callback prototype on data modification -typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error /** Properties of config file settings. */ struct SettingDesc { @@ -125,11 +123,27 @@ struct SettingDesc { /** Base integer type, including boolean, settings. Only these are shown in the settings UI. */ struct IntSettingDesc : SettingDesc { + /** + * A check to be performed before the setting gets changed. The passed integer may be + * changed by the check if that is important, for example to remove some unwanted bit. + * The return value denotes whether the value, potentially after the changes, + * is allowed to be used/set in the configuration. + * @param value The prospective new value for the setting. + * @return True when the setting is accepted. + */ + typedef bool PreChangeCheck(int32 &value); + /** + * A callback to denote that a setting has been changed. + * @param The new value for the setting. + */ + typedef void PostChangeCallback(int32 value); + IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, - int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, - SettingCategory cat, OnChange *proc) : + int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, + SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def), min(min), max(max), interval(interval), - str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc) {} + str(str), str_help(str_help), str_val(str_val), cat(cat), pre_check(pre_check), + post_callback(post_callback) {} virtual ~IntSettingDesc() {} int32 def; ///< default value given when none is present @@ -140,7 +154,8 @@ struct IntSettingDesc : SettingDesc { StringID str_help; ///< (Translated) string with help text; gui only. StringID str_val; ///< (Translated) first string describing the value. SettingCategory cat; ///< assigned categories of the setting - OnChange *proc; ///< callback procedure for when the value is changed + PreChangeCheck *pre_check; ///< Callback to check for the validity of the setting. + PostChangeCallback *post_callback; ///< Callback when the setting has been changed. /** * Check whether this setting is a boolean type setting. @@ -166,8 +181,10 @@ private: /** Boolean setting. */ struct BoolSettingDesc : IntSettingDesc { BoolSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, bool def, - StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc) : - IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, proc) {} + StringID str, StringID str_help, StringID str_val, SettingCategory cat, + PreChangeCheck pre_check, PostChangeCallback post_callback) : + IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, + pre_check, post_callback) {} virtual ~BoolSettingDesc() {} bool IsBoolSetting() const override { return true; } @@ -177,10 +194,14 @@ struct BoolSettingDesc : IntSettingDesc { /** One of many setting. */ struct OneOfManySettingDesc : IntSettingDesc { - OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, - int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, - std::initializer_list many, OnConvert *many_cnvt) : - IntSettingDesc(save, name, flags, startup, def, 0, max, 0, str, str_help, str_val, cat, proc), many_cnvt(many_cnvt) + typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error + + OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, + int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, + PreChangeCheck pre_check, PostChangeCallback post_callback, + std::initializer_list many, OnConvert *many_cnvt) : + IntSettingDesc(save, name, flags, startup, def, 0, max, 0, str, str_help, str_val, cat, + pre_check, post_callback), many_cnvt(many_cnvt) { for (auto one : many) this->many.push_back(one); } @@ -200,10 +221,11 @@ struct OneOfManySettingDesc : IntSettingDesc { /** Many of many setting. */ struct ManyOfManySettingDesc : OneOfManySettingDesc { ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, - int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, + int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, + PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : OneOfManySettingDesc(save, name, flags, startup, def, (1 << many.size()) - 1, str, str_help, - str_val, cat, proc, many, many_cnvt) {} + str_val, cat, pre_check, post_callback, many, many_cnvt) {} virtual ~ManyOfManySettingDesc() {} size_t ParseValue(const char *str) const override; diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index eecebb40e6..019c26dd9c 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -5,19 +5,16 @@ ; [pre-amble] -static bool CheckInterval(int32 p1); -static bool InvalidateDetailsWindow(int32 p1); -static bool UpdateIntervalTrains(int32 p1); -static bool UpdateIntervalRoadVeh(int32 p1); -static bool UpdateIntervalShips(int32 p1); -static bool UpdateIntervalAircraft(int32 p1); +static void UpdateServiceInterval(int32 new_value); +static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value); +static void UpdateServiceInterval(VehicleType type, int32 new_value); static const SettingTable _company_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -29,7 +26,8 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION @@ -82,7 +80,7 @@ var = vehicle.servint_ispercent def = false str = STR_CONFIG_SETTING_SERVINT_ISPERCENT strhelp = STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT -proc = CheckInterval +post_cb = UpdateServiceInterval [SDT_VAR] base = CompanySettings @@ -95,7 +93,8 @@ max = 800 str = STR_CONFIG_SETTING_SERVINT_TRAINS strhelp = STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT strval = STR_CONFIG_SETTING_SERVINT_VALUE -proc = UpdateIntervalTrains +pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_TRAIN, new_value); } +post_cb = [](auto new_value) { UpdateServiceInterval(VEH_TRAIN, new_value); } [SDT_VAR] base = CompanySettings @@ -108,7 +107,8 @@ max = 800 str = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES strhelp = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES_HELPTEXT strval = STR_CONFIG_SETTING_SERVINT_VALUE -proc = UpdateIntervalRoadVeh +pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_ROAD, new_value); } +post_cb = [](auto new_value) { UpdateServiceInterval(VEH_ROAD, new_value); } [SDT_VAR] base = CompanySettings @@ -121,7 +121,8 @@ max = 800 str = STR_CONFIG_SETTING_SERVINT_SHIPS strhelp = STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT strval = STR_CONFIG_SETTING_SERVINT_VALUE -proc = UpdateIntervalShips +pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_SHIP, new_value); } +post_cb = [](auto new_value) { UpdateServiceInterval(VEH_SHIP, new_value); } [SDT_VAR] base = CompanySettings @@ -134,4 +135,5 @@ max = 800 str = STR_CONFIG_SETTING_SERVINT_AIRCRAFT strhelp = STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT strval = STR_CONFIG_SETTING_SERVINT_VALUE -proc = UpdateIntervalAircraft +pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_AIRCRAFT, new_value); } +post_cb = [](auto new_value) { UpdateServiceInterval(VEH_AIRCRAFT, new_value); } diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 0714b1b93d..449bbee983 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -9,7 +9,7 @@ static const SettingTable _currency_settings{ [post-amble] }; [templates] -SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] @@ -22,7 +22,6 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr pre_cb = nullptr post_cb = nullptr load = nullptr diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 56ac7d7816..131833a415 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -37,12 +37,12 @@ static const SettingTable _gameopt_settings{ }; [templates] SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL( $length, $from, $to), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -58,7 +58,8 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 952839daa4..1b633a65aa 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -22,11 +22,11 @@ static const SettingTable _misc_settings{ }; [templates] SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -39,7 +39,6 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr pre_cb = nullptr post_cb = nullptr load = nullptr diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index f5f7352440..3c8e6cb721 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -58,11 +58,11 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for global variables */ -#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, proc) +#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) -#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, proc) +#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) #define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, startup, def) @@ -70,22 +70,22 @@ static size_t ConvertLandscape(const char *value); #define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, startup, def, max_length, pre_check, post_callback) -#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) +#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) -#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, proc, full, nullptr) +#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) #define SDTG_NULL(length, from, to)\ NSD(Null, SLEG_NULL(length, from, to)) /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ -#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, proc) +#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) -#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, proc) +#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) #define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def) @@ -93,21 +93,21 @@ static size_t ConvertLandscape(const char *value); #define SDT_SSTR(base, var, type, flags, guiflags, def, pre_check, post_callback, from, to, cat, extra, startup)\ NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def, 0, pre_check, post_callback) -#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ - NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, max, str, strhelp, strval, cat, proc, full, load) +#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, load, cat, extra, startup)\ + NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, load) -#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, proc, full, nullptr) +#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, pre_check, post_callback, strhelp, strval, from, to, cat, extra, startup)\ + NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) #define SDT_NULL(length, from, to)\ NSD(Null, SLE_CONDNULL(length, from, to)) -#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_VAR(#var, type, flags, guiflags, _settings_client.var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_VAR(#var, type, flags, guiflags, _settings_client.var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) -#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_BOOL(#var, flags, guiflags, _settings_client.var, def, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_BOOL(#var, flags, guiflags, _settings_client.var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) #define SDTC_LIST(var, type, flags, guiflags, def, from, to, cat, extra, startup)\ SDTG_LIST(#var, type, flags, guiflags, _settings_client.var, def, lengthof(_settings_client.var), from, to, cat, extra, startup) @@ -115,5 +115,5 @@ static size_t ConvertLandscape(const char *value); #define SDTC_SSTR(var, type, flags, guiflags, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ -#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup) +#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) diff --git a/src/table/settings.ini b/src/table/settings.ini index 1de905c5b4..2b6187087f 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -6,46 +6,34 @@ [pre-amble] /* Begin - Callback Functions for the various settings */ -static bool v_PositionMainToolbar(int32 p1); -static bool v_PositionStatusbar(int32 p1); -static bool PopulationInLabelActive(int32 p1); -static bool RedrawScreen(int32 p1); -static bool RedrawSmallmap(int32 p1); -static bool StationSpreadChanged(int32 p1); -static bool InvalidateBuildIndustryWindow(int32 p1); -static bool CloseSignalGUI(int32 p1); -static bool InvalidateTownViewWindow(int32 p1); -static bool DeleteSelectStationWindow(int32 p1); -static bool UpdateConsists(int32 p1); -static bool TrainAccelerationModelChanged(int32 p1); -static bool RoadVehAccelerationModelChanged(int32 p1); -static bool TrainSlopeSteepnessChanged(int32 p1); -static bool RoadVehSlopeSteepnessChanged(int32 p1); -static bool DragSignalsDensityChanged(int32); -static bool TownFoundingChanged(int32 p1); -static bool DifficultyNoiseChange(int32 i); -static bool MaxNoAIsChange(int32 i); -static bool CheckRoadSide(int p1); -static bool ChangeMaxHeightLevel(int32 p1); -static bool CheckFreeformEdges(int32 p1); -static bool ChangeDynamicEngines(int32 p1); -static bool StationCatchmentChanged(int32 p1); -static bool InvalidateVehTimetableWindow(int32 p1); -static bool InvalidateCompanyLiveryWindow(int32 p1); -static bool InvalidateNewGRFChangeWindows(int32 p1); -static bool InvalidateIndustryViewWindow(int32 p1); -static bool InvalidateAISettingsWindow(int32 p1); -static bool RedrawTownAuthority(int32 p1); -static bool InvalidateCompanyInfrastructureWindow(int32 p1); -static bool InvalidateCompanyWindow(int32 p1); -static bool ZoomMinMaxChanged(int32 p1); -static bool SpriteZoomMinChanged(int32 p1); -static bool MaxVehiclesChanged(int32 p1); -static bool InvalidateShipPathCache(int32 p1); +static void v_PositionMainToolbar(int32 new_value); +static void v_PositionStatusbar(int32 new_value); +static void RedrawSmallmap(int32 new_value); +static void StationSpreadChanged(int32 new_value); +static void CloseSignalGUI(int32 new_value); +static void UpdateConsists(int32 new_value); +static void TrainAccelerationModelChanged(int32 new_value); +static void RoadVehAccelerationModelChanged(int32 new_value); +static void TrainSlopeSteepnessChanged(int32 new_value); +static void RoadVehSlopeSteepnessChanged(int32 new_value); +static void TownFoundingChanged(int32 new_value); +static void DifficultyNoiseChange(int32 new_value); +static void MaxNoAIsChange(int32 new_value); +static bool CheckRoadSide(int32 &new_value); +static bool CheckMaxHeightLevel(int32 &new_value); +static bool CheckFreeformEdges(int32 &new_value); +static void UpdateFreeformEdges(int32 new_value); +static bool CheckDynamicEngines(int32 &new_value); +static void StationCatchmentChanged(int32 new_value); +static void InvalidateCompanyLiveryWindow(int32 new_value); +static void InvalidateNewGRFChangeWindows(int32 new_value); +static void ZoomMinMaxChanged(int32 new_value); +static void SpriteZoomMinChanged(int32 new_value); +static void MaxVehiclesChanged(int32 new_value); +static void InvalidateShipPathCache(int32 new_value); static bool ReplaceAsteriskWithEmptyPassword(std::string &newval); static void UpdateClientConfigValues(); -static bool UpdateClientConfigValues(int32 p1); /* End - Callback Functions for the various settings */ @@ -62,18 +50,18 @@ const SettingTable _settings{ [post-amble] }; [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup), +SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL($length, $from, $to), [validation] @@ -91,7 +79,6 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr pre_cb = nullptr post_cb = nullptr load = nullptr @@ -114,7 +101,7 @@ def = 0 min = 0 max = MAX_COMPANIES - 1 interval = 1 -proc = MaxNoAIsChange +post_cb = MaxNoAIsChange cat = SC_BASIC [SDT_NULL] @@ -324,7 +311,7 @@ interval = 1 str = STR_CONFIG_SETTING_CITY_APPROVAL strhelp = STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT strval = STR_CITY_APPROVAL_PERMISSIVE -proc = DifficultyNoiseChange +post_cb = DifficultyNoiseChange [SDTG_VAR] name = ""diff_level"" @@ -384,7 +371,7 @@ full = _roadsides str = STR_CONFIG_SETTING_ROAD_SIDE strhelp = STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT strval = STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT -proc = CheckRoadSide +pre_cb = CheckRoadSide cat = SC_BASIC ; Construction @@ -402,7 +389,8 @@ interval = 1 str = STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT strhelp = STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT strval = STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE -proc = ChangeMaxHeightLevel +pre_cb = CheckMaxHeightLevel +post_cb = [](auto) { InvalidateWindowClassesData(WC_SMALLMAP, 2); } cat = SC_ADVANCED [SDT_VAR] @@ -578,7 +566,7 @@ max = 2 str = STR_CONFIG_SETTING_SIGNALSIDE strhelp = STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT strval = STR_CONFIG_SETTING_SIGNALSIDE_LEFT -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_BOOL] @@ -602,7 +590,7 @@ interval = 1 str = STR_CONFIG_SETTING_TOWN_LAYOUT strhelp = STR_CONFIG_SETTING_TOWN_LAYOUT_HELPTEXT strval = STR_CONFIG_SETTING_TOWN_LAYOUT_DEFAULT -proc = TownFoundingChanged +post_cb = TownFoundingChanged [SDT_BOOL] base = GameSettings @@ -626,7 +614,7 @@ interval = 1 str = STR_CONFIG_SETTING_TOWN_FOUNDING strhelp = STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT strval = STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN -proc = TownFoundingChanged +post_cb = TownFoundingChanged cat = SC_BASIC [SDT_BOOL] @@ -822,7 +810,7 @@ interval = 1 str = STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL strhelp = STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT strval = STR_CONFIG_SETTING_ORIGINAL -proc = TrainAccelerationModelChanged +post_cb = TrainAccelerationModelChanged [SDT_VAR] base = GameSettings @@ -837,7 +825,7 @@ interval = 1 str = STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL strhelp = STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT strval = STR_CONFIG_SETTING_ORIGINAL -proc = RoadVehAccelerationModelChanged +post_cb = RoadVehAccelerationModelChanged [SDT_VAR] base = GameSettings @@ -851,7 +839,7 @@ interval = 1 str = STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS strhelp = STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT strval = STR_CONFIG_SETTING_PERCENTAGE -proc = TrainSlopeSteepnessChanged +post_cb = TrainSlopeSteepnessChanged cat = SC_EXPERT [SDT_VAR] @@ -866,7 +854,7 @@ interval = 1 str = STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS strhelp = STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS_HELPTEXT strval = STR_CONFIG_SETTING_PERCENTAGE -proc = RoadVehSlopeSteepnessChanged +post_cb = RoadVehSlopeSteepnessChanged cat = SC_EXPERT [SDT_BOOL] @@ -875,7 +863,7 @@ var = pf.forbid_90_deg def = false str = STR_CONFIG_SETTING_FORBID_90_DEG strhelp = STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT -proc = InvalidateShipPathCache +post_cb = InvalidateShipPathCache cat = SC_EXPERT [SDT_VAR] @@ -998,7 +986,7 @@ interval = 1 str = STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS strhelp = STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_HELPTEXT strval = STR_CONFIG_SETTING_PATHFINDER_NPF -proc = InvalidateShipPathCache +post_cb = InvalidateShipPathCache cat = SC_EXPERT [SDT_BOOL] @@ -1019,7 +1007,7 @@ max = 5000 str = STR_CONFIG_SETTING_MAX_TRAINS strhelp = STR_CONFIG_SETTING_MAX_TRAINS_HELPTEXT strval = STR_JUST_COMMA -proc = MaxVehiclesChanged +post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] @@ -1032,7 +1020,7 @@ max = 5000 str = STR_CONFIG_SETTING_MAX_ROAD_VEHICLES strhelp = STR_CONFIG_SETTING_MAX_ROAD_VEHICLES_HELPTEXT strval = STR_JUST_COMMA -proc = MaxVehiclesChanged +post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] @@ -1045,7 +1033,7 @@ max = 5000 str = STR_CONFIG_SETTING_MAX_AIRCRAFT strhelp = STR_CONFIG_SETTING_MAX_AIRCRAFT_HELPTEXT strval = STR_JUST_COMMA -proc = MaxVehiclesChanged +post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] @@ -1058,7 +1046,7 @@ max = 5000 str = STR_CONFIG_SETTING_MAX_SHIPS strhelp = STR_CONFIG_SETTING_MAX_SHIPS_HELPTEXT strval = STR_JUST_COMMA -proc = MaxVehiclesChanged +post_cb = MaxVehiclesChanged cat = SC_BASIC [SDTG_BOOL] @@ -1122,7 +1110,7 @@ guiflags = SGF_NO_NETWORK def = true str = STR_CONFIG_SETTING_WAGONSPEEDLIMITS strhelp = STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT -proc = UpdateConsists +post_cb = UpdateConsists [SDT_BOOL] base = GameSettings @@ -1132,7 +1120,7 @@ guiflags = SGF_NO_NETWORK def = false str = STR_CONFIG_SETTING_DISABLE_ELRAILS strhelp = STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT -proc = SettingsDisableElrail +post_cb = SettingsDisableElrail cat = SC_EXPERT [SDT_VAR] @@ -1148,7 +1136,7 @@ interval = 1 str = STR_CONFIG_SETTING_FREIGHT_TRAINS strhelp = STR_CONFIG_SETTING_FREIGHT_TRAINS_HELPTEXT strval = STR_JUST_COMMA -proc = UpdateConsists +post_cb = UpdateConsists ; order.timetabling [SDT_NULL] @@ -1175,7 +1163,7 @@ var = vehicle.dynamic_engines from = SLV_95 guiflags = SGF_NO_NETWORK def = true -proc = ChangeDynamicEngines +pre_cb = CheckDynamicEngines cat = SC_EXPERT [SDT_VAR] @@ -1238,7 +1226,7 @@ max = 64 str = STR_CONFIG_SETTING_STATION_SPREAD strhelp = STR_CONFIG_SETTING_STATION_SPREAD_HELPTEXT strval = STR_CONFIG_SETTING_TILE_LENGTH -proc = StationSpreadChanged +post_cb = StationSpreadChanged cat = SC_BASIC [SDT_BOOL] @@ -1255,7 +1243,7 @@ var = station.modified_catchment def = true str = STR_CONFIG_SETTING_CATCHMENT strhelp = STR_CONFIG_SETTING_CATCHMENT_HELPTEXT -proc = StationCatchmentChanged +post_cb = StationCatchmentChanged cat = SC_EXPERT [SDT_BOOL] @@ -1265,7 +1253,7 @@ def = true from = SLV_SERVE_NEUTRAL_INDUSTRIES str = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES strhelp = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT -proc = StationCatchmentChanged +post_cb = StationCatchmentChanged [SDT_BOOL] base = GameSettings @@ -1308,7 +1296,7 @@ guiflags = SGF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NOISE_LEVEL strhelp = STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT -proc = InvalidateTownViewWindow +post_cb = [](auto new_value) { InvalidateWindowClassesData(WC_TOWN_VIEW, new_value); } [SDT_BOOL] base = GameSettings @@ -1317,7 +1305,7 @@ from = SLV_106 def = true str = STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS strhelp = STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS_HELPTEXT -proc = DeleteSelectStationWindow +post_cb = [](auto) { DeleteWindowById(WC_SELECT_STATION, 0); } ## [SDT_BOOL] @@ -1340,7 +1328,7 @@ max = 2 str = STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD strhelp = STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT strval = STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE -proc = InvalidateBuildIndustryWindow +post_cb = [](auto) { InvalidateWindowData(WC_BUILD_INDUSTRY, 0); } cat = SC_BASIC [SDT_VAR] @@ -1373,7 +1361,7 @@ var = economy.bribe def = true str = STR_CONFIG_SETTING_BRIBE strhelp = STR_CONFIG_SETTING_BRIBE_HELPTEXT -proc = RedrawTownAuthority +post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] @@ -1383,7 +1371,7 @@ from = SLV_79 def = true str = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE strhelp = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT -proc = RedrawTownAuthority +post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] @@ -1393,7 +1381,7 @@ from = SLV_165 def = true str = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS strhelp = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT -proc = RedrawTownAuthority +post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] @@ -1403,7 +1391,7 @@ from = SLV_160 def = true str = STR_CONFIG_SETTING_ALLOW_FUND_ROAD strhelp = STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT -proc = RedrawTownAuthority +post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] @@ -1505,7 +1493,7 @@ max = ET_END - 1 str = STR_CONFIG_SETTING_ECONOMY_TYPE strhelp = STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT strval = STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL -proc = InvalidateIndustryViewWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_INDUSTRY_VIEW); } cat = SC_BASIC [SDT_BOOL] @@ -1514,7 +1502,7 @@ var = economy.allow_shares def = false str = STR_CONFIG_SETTING_ALLOW_SHARES strhelp = STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT -proc = InvalidateCompanyWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY); } [SDT_VAR] base = GameSettings @@ -1758,7 +1746,7 @@ from = SLV_166 def = false str = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE strhelp = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT -proc = InvalidateCompanyInfrastructureWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY_INFRASTRUCTURE); } cat = SC_BASIC ## @@ -2427,7 +2415,8 @@ base = GameSettings var = construction.freeform_edges from = SLV_111 def = true -proc = CheckFreeformEdges +pre_cb = CheckFreeformEdges +post_cb = UpdateFreeformEdges cat = SC_EXPERT [SDT_VAR] @@ -2528,7 +2517,7 @@ flags = SLF_NO_NETWORK_SYNC def = 0 max = CURRENCY_END - 1 full = _locale_currencies -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDTG_OMANY] @@ -2541,7 +2530,7 @@ flags = SLF_NOT_IN_CONFIG def = 1 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_OMANY] @@ -2554,7 +2543,7 @@ guiflags = SGF_MULTISTRING def = 1 max = 3 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT @@ -2570,7 +2559,7 @@ guiflags = SGF_MULTISTRING def = 1 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT @@ -2586,7 +2575,7 @@ guiflags = SGF_MULTISTRING def = 1 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_HELPTEXT @@ -2602,7 +2591,7 @@ guiflags = SGF_MULTISTRING def = 1 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_HELPTEXT @@ -2618,7 +2607,7 @@ guiflags = SGF_MULTISTRING def = 2 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_HELPTEXT @@ -2634,7 +2623,7 @@ guiflags = SGF_MULTISTRING def = 1 max = 2 full = _locale_units -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC str = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT @@ -2811,7 +2800,7 @@ max = 2 str = STR_CONFIG_SETTING_TOOLBAR_POS strhelp = STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT strval = STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT -proc = v_PositionMainToolbar +post_cb = v_PositionMainToolbar cat = SC_BASIC [SDTC_VAR] @@ -2825,7 +2814,7 @@ max = 2 str = STR_CONFIG_SETTING_STATUSBAR_POS strhelp = STR_CONFIG_SETTING_STATUSBAR_POS_HELPTEXT strval = STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT -proc = v_PositionStatusbar +post_cb = v_PositionStatusbar cat = SC_BASIC [SDTC_VAR] @@ -2866,7 +2855,7 @@ max = ZOOM_LVL_OUT_4X str = STR_CONFIG_SETTING_ZOOM_MIN strhelp = STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT strval = STR_CONFIG_SETTING_ZOOM_LVL_MIN -proc = ZoomMinMaxChanged +post_cb = ZoomMinMaxChanged startup = true [SDTC_VAR] @@ -2880,7 +2869,7 @@ max = ZOOM_LVL_MAX str = STR_CONFIG_SETTING_ZOOM_MAX strhelp = STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT strval = STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X -proc = ZoomMinMaxChanged +post_cb = ZoomMinMaxChanged startup = true [SDTC_VAR] @@ -2894,7 +2883,7 @@ max = ZOOM_LVL_OUT_4X str = STR_CONFIG_SETTING_SPRITE_ZOOM_MIN strhelp = STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT strval = STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_MIN -proc = SpriteZoomMinChanged +post_cb = SpriteZoomMinChanged [SDTC_BOOL] var = gui.population_in_label @@ -2902,7 +2891,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_POPULATION_IN_LABEL strhelp = STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT -proc = PopulationInLabelActive +post_cb = [](auto) { UpdateAllTownVirtCoords(); } [SDTC_BOOL] var = gui.link_terraform_toolbar @@ -2922,7 +2911,7 @@ max = 2 str = STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR strhelp = STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT strval = STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN -proc = RedrawSmallmap +post_cb = RedrawSmallmap [SDTC_VAR] var = gui.liveries @@ -2935,7 +2924,7 @@ max = 2 str = STR_CONFIG_SETTING_LIVERIES strhelp = STR_CONFIG_SETTING_LIVERIES_HELPTEXT strval = STR_CONFIG_SETTING_LIVERIES_NONE -proc = InvalidateCompanyLiveryWindow +post_cb = InvalidateCompanyLiveryWindow [SDTC_VAR] var = gui.starting_colour @@ -3017,7 +3006,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_TIMETABLE_IN_TICKS strhelp = STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT -proc = InvalidateVehTimetableWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE, VIWD_MODIFY_ORDERS); } cat = SC_EXPERT [SDTC_BOOL] @@ -3026,7 +3015,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE strhelp = STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT -proc = InvalidateVehTimetableWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE, VIWD_MODIFY_ORDERS); } [SDTC_BOOL] var = gui.quick_goto @@ -3047,7 +3036,7 @@ max = 2 str = STR_CONFIG_SETTING_LOADING_INDICATORS strhelp = STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT strval = STR_CONFIG_SETTING_COMPANIES_OFF -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDTC_VAR] @@ -3069,7 +3058,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI strhelp = STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI_HELPTEXT -proc = CloseSignalGUI +post_cb = CloseSignalGUI cat = SC_EXPERT [SDTC_VAR] @@ -3095,7 +3084,7 @@ max = 20 str = STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY strhelp = STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT strval = STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE -proc = DragSignalsDensityChanged +post_cb = [](auto) { InvalidateWindowData(WC_BUILD_SIGNAL, 0); } cat = SC_BASIC [SDTC_BOOL] @@ -3117,7 +3106,7 @@ interval = 1 str = STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE strhelp = STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE_HELPTEXT strval = STR_JUST_INT -proc = ResetSignalVariant +post_cb = ResetSignalVariant [SDTC_BOOL] var = gui.vehicle_income_warn @@ -3213,7 +3202,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION strhelp = STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDTC_VAR] @@ -3286,7 +3275,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_EXPENSES_LAYOUT strhelp = STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } [SDTC_VAR] var = gui.station_gui_group_order @@ -3334,7 +3323,7 @@ max = 5 str = STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS strhelp = STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT strval = STR_JUST_COMMA -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } [SDTC_BOOL] var = gui.show_newgrf_name @@ -3342,7 +3331,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_SHOW_NEWGRF_NAME strhelp = STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT -proc = RedrawScreen +post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_ADVANCED ; For the dedicated build we'll enable dates in logs by default. @@ -3379,21 +3368,21 @@ cat = SC_EXPERT var = gui.newgrf_developer_tools flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false -proc = InvalidateNewGRFChangeWindows +post_cb = InvalidateNewGRFChangeWindows cat = SC_EXPERT [SDTC_BOOL] var = gui.ai_developer_tools flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false -proc = InvalidateAISettingsWindow +post_cb = [](auto) { InvalidateWindowClassesData(WC_AI_SETTINGS); } cat = SC_EXPERT [SDTC_BOOL] var = gui.scenario_developer flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false -proc = InvalidateNewGRFChangeWindows +post_cb = InvalidateNewGRFChangeWindows [SDTC_BOOL] var = gui.newgrf_show_old_versions @@ -3409,7 +3398,7 @@ guiflags = SGF_MULTISTRING def = 1 min = 0 max = 1 -proc = UpdateNewGRFConfigPalette +post_cb = UpdateNewGRFConfigPalette cat = SC_EXPERT [SDTC_VAR] @@ -4029,7 +4018,7 @@ guiflags = SGF_NETWORK_ONLY def = 15 min = 1 max = MAX_COMPANIES -proc = UpdateClientConfigValues +post_cb = [](auto) { UpdateClientConfigValues(); } cat = SC_BASIC [SDTC_VAR] @@ -4040,7 +4029,7 @@ guiflags = SGF_NETWORK_ONLY def = 25 min = 2 max = MAX_CLIENTS -proc = UpdateClientConfigValues +post_cb = [](auto) { UpdateClientConfigValues(); } cat = SC_BASIC [SDTC_VAR] @@ -4051,7 +4040,7 @@ guiflags = SGF_NETWORK_ONLY def = 15 min = 0 max = MAX_CLIENTS -proc = UpdateClientConfigValues +post_cb = [](auto) { UpdateClientConfigValues(); } cat = SC_BASIC [SDTC_VAR] diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini index 669474cc74..6b7d5276d8 100644 --- a/src/table/win32_settings.ini +++ b/src/table/win32_settings.ini @@ -14,8 +14,8 @@ static const SettingTable _win32_settings{ }; #endif /* _WIN32 */ [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -27,7 +27,8 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION diff --git a/src/table/window_settings.ini b/src/table/window_settings.ini index 5e11ea002a..5334b0fc1d 100644 --- a/src/table/window_settings.ini +++ b/src/table/window_settings.ini @@ -10,8 +10,8 @@ static const SettingTable _window_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); @@ -24,7 +24,8 @@ interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strval = STR_NULL -proc = nullptr +pre_cb = nullptr +post_cb = nullptr load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION From 4144e949edf3b14c2d478aa0fcba1996942a03fa Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 24 May 2021 12:13:54 +0200 Subject: [PATCH 263/800] Fix: [Network] Prevent an empty server name to be set anywhere --- src/lang/english.txt | 1 + src/network/network.cpp | 25 +++++++++++++++++++++---- src/network/network_func.h | 1 + src/network/network_gui.cpp | 21 ++++++++++++--------- src/table/settings.ini | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index db74c230bd..4a92eba893 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Could no STR_NETWORK_ERROR_TIMEOUT :{WHITE}Connection #{NUM} timed out 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_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 diff --git a/src/network/network.cpp b/src/network/network.cpp index 53ef645d7b..94a5539f0e 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -835,10 +835,6 @@ void NetworkClientJoinGame() static void NetworkInitGameInfo() { - if (_settings_client.network.server_name.empty()) { - _settings_client.network.server_name = "Unnamed Server"; - } - FillStaticNetworkServerGameInfo(); /* The server is a client too */ _network_game_info.clients_on = _network_dedicated ? 0 : 1; @@ -851,6 +847,25 @@ static void NetworkInitGameInfo() ci->client_name = _settings_client.network.client_name; } +/** + * 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. + * + * @param server_name The server name to validate. It will be trimmed of leading + * and trailing spaces. + * @return True iff the server name is valid. + */ +bool NetworkValidateServerName(std::string &server_name) +{ + StrTrimInPlace(server_name); + if (!server_name.empty()) return true; + + ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_NAME, 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. @@ -860,12 +875,14 @@ static void NetworkInitGameInfo() static void CheckClientAndServerName() { static const std::string fallback_client_name = "Unnamed Client"; + StrTrimInPlace(_settings_client.network.client_name); if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) { DEBUG(net, 1, "No \"client_name\" has been set, using \"%s\" instead. Please set this now using the \"name \" command", fallback_client_name.c_str()); _settings_client.network.client_name = fallback_client_name; } static const std::string fallback_server_name = "Unnamed Server"; + StrTrimInPlace(_settings_client.network.server_name); if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) { DEBUG(net, 1, "No \"server_name\" has been set, using \"%s\" instead. Please set this now using the \"server_name \" command", fallback_server_name.c_str()); _settings_client.network.server_name = fallback_server_name; diff --git a/src/network/network_func.h b/src/network/network_func.h index fbae8daf76..d30616fd0a 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -38,6 +38,7 @@ byte NetworkSpectatorCount(); bool NetworkIsValidClientName(const std::string_view client_name); bool NetworkValidateClientName(); bool NetworkValidateClientName(std::string &client_name); +bool NetworkValidateServerName(std::string &server_name); void NetworkUpdateClientName(const std::string &client_name); bool NetworkCompanyHasClients(CompanyID company); std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 6df77cd083..d06ff27be4 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1095,6 +1095,7 @@ struct NetworkStartServerWindow : public Window { break; case WID_NSS_GENERATE_GAME: // Start game + if (!CheckServerName()) return; _is_network_server = true; if (_ctrl_pressed) { StartNewGameWithoutGUI(GENERATE_NEW_SEED); @@ -1104,16 +1105,19 @@ struct NetworkStartServerWindow : public Window { break; case WID_NSS_LOAD_GAME: + if (!CheckServerName()) return; _is_network_server = true; ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break; case WID_NSS_PLAY_SCENARIO: + if (!CheckServerName()) return; _is_network_server = true; ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD); break; case WID_NSS_PLAY_HEIGHTMAP: + if (!CheckServerName()) return; _is_network_server = true; ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD); break; @@ -1133,11 +1137,13 @@ struct NetworkStartServerWindow : public Window { this->SetDirty(); } - void OnEditboxChanged(int wid) override + bool CheckServerName() { - if (wid == WID_NSS_GAMENAME) { - _settings_client.network.server_name = this->name_editbox.text.buf; - } + std::string str = this->name_editbox.text.buf; + if (!NetworkValidateServerName(str)) return false; + + SetSettingValue(GetSettingFromName("network.server_name")->AsStringSetting(), str); + return true; } void OnTimeout() override @@ -2199,16 +2205,13 @@ public: case WID_CL_SERVER_NAME_EDIT: { if (!_network_server) break; - SetSettingValue(GetSettingFromName("network.server_name")->AsStringSetting(), StrEmpty(str) ? "Unnamed Server" : str); + SetSettingValue(GetSettingFromName("network.server_name")->AsStringSetting(), str); this->InvalidateData(); break; } case WID_CL_CLIENT_NAME_EDIT: { - std::string client_name(str); - if (!NetworkValidateClientName(client_name)) break; - - SetSettingValue(GetSettingFromName("network.client_name")->AsStringSetting(), client_name); + SetSettingValue(GetSettingFromName("network.client_name")->AsStringSetting(), str); this->InvalidateData(); break; } diff --git a/src/table/settings.ini b/src/table/settings.ini index 2b6187087f..6a2cb5b14a 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3959,6 +3959,7 @@ length = NETWORK_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY def = nullptr +pre_cb = NetworkValidateServerName post_cb = [](auto) { UpdateClientConfigValues(); } cat = SC_BASIC From 4c0e083128a4e9c3eefefaab70648057bd1d9fb2 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 09:12:11 +0200 Subject: [PATCH 264/800] Cleanup: set the base in the setting templates, instead of defining the base for every setting This has the added benefit of not getting mistaken that multiple bases can be used for the same SettingTable --- src/table/company_settings.ini | 15 +- src/table/currency_settings.ini | 11 +- src/table/gameopt_settings.ini | 23 ++- src/table/settings.ini | 243 ++------------------------------ src/table/window_settings.ini | 7 +- 5 files changed, 33 insertions(+), 266 deletions(-) diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index 019c26dd9c..bb104adebf 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -13,11 +13,11 @@ static const SettingTable _company_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(CompanySettings, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(CompanySettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] -SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CompanySettings.$var exceeds storage size"); [defaults] flags = 0 @@ -38,7 +38,6 @@ startup = false [SDT_BOOL] -base = CompanySettings var = engine_renew def = true str = STR_CONFIG_SETTING_AUTORENEW_VEHICLE @@ -46,7 +45,6 @@ strhelp = STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT cat = SC_BASIC [SDT_VAR] -base = CompanySettings var = engine_renew_months type = SLE_INT16 guiflags = SGF_PER_COMPANY | SGF_DISPLAY_ABS @@ -58,7 +56,6 @@ strhelp = STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT strval = STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE [SDT_VAR] -base = CompanySettings var = engine_renew_money type = SLE_UINT guiflags = SGF_PER_COMPANY | SGF_CURRENCY @@ -70,12 +67,10 @@ strhelp = STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT strval = STR_JUST_CURRENCY_LONG [SDT_BOOL] -base = CompanySettings var = renew_keep_length def = false [SDT_BOOL] -base = CompanySettings var = vehicle.servint_ispercent def = false str = STR_CONFIG_SETTING_SERVINT_ISPERCENT @@ -83,7 +78,6 @@ strhelp = STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT post_cb = UpdateServiceInterval [SDT_VAR] -base = CompanySettings var = vehicle.servint_trains type = SLE_UINT16 guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED @@ -97,7 +91,6 @@ pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_TRAIN, new_v post_cb = [](auto new_value) { UpdateServiceInterval(VEH_TRAIN, new_value); } [SDT_VAR] -base = CompanySettings var = vehicle.servint_roadveh type = SLE_UINT16 guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED @@ -111,7 +104,6 @@ pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_ROAD, new_va post_cb = [](auto new_value) { UpdateServiceInterval(VEH_ROAD, new_value); } [SDT_VAR] -base = CompanySettings var = vehicle.servint_ships type = SLE_UINT16 guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED @@ -125,7 +117,6 @@ pre_cb = [](auto new_value) { return CanUpdateServiceInterval(VEH_SHIP, new_va post_cb = [](auto new_value) { UpdateServiceInterval(VEH_SHIP, new_value); } [SDT_VAR] -base = CompanySettings var = vehicle.servint_aircraft type = SLE_UINT16 guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 449bbee983..ce0213758d 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -9,11 +9,11 @@ static const SettingTable _currency_settings{ [post-amble] }; [templates] -SDT_VAR = SDT_VAR ($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR (CurrencySpec, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR(CurrencySpec, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] -SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CurrencySpec.$var exceeds storage size"); [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -34,7 +34,6 @@ startup = false [SDT_VAR] -base = CurrencySpec var = rate type = SLE_UINT16 def = 1 @@ -42,14 +41,12 @@ min = 0 max = UINT16_MAX [SDT_SSTR] -base = CurrencySpec var = separator type = SLE_STRQ def = ""."" cat = SC_BASIC [SDT_VAR] -base = CurrencySpec var = to_euro type = SLE_INT32 def = 0 @@ -57,13 +54,11 @@ min = MIN_YEAR max = MAX_YEAR [SDT_SSTR] -base = CurrencySpec var = prefix type = SLE_STRQ def = nullptr [SDT_SSTR] -base = CurrencySpec var = suffix type = SLE_STRQ def = "" credits"" diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 131833a415..b3b7ec6510 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -36,20 +36,20 @@ static const SettingTable _gameopt_settings{ [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_NULL = SDT_NULL( $length, $from, $to), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_NULL = SDT_NULL( $length, $from, $to), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); -SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); -SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); [defaults] flags = 0 @@ -104,7 +104,6 @@ max = SP_CUSTOM cat = SC_BASIC [SDT_OMANY] -base = GameSettings var = locale.currency type = SLE_UINT8 flags = SLF_NO_NETWORK_SYNC @@ -126,7 +125,6 @@ cat = SC_BASIC # There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow # these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. [SDT_OMANY] -base = GameSettings var = game_creation.town_name type = SLE_UINT8 def = 0 @@ -135,7 +133,6 @@ full = _town_names cat = SC_BASIC [SDT_OMANY] -base = GameSettings var = game_creation.landscape type = SLE_UINT8 def = 0 @@ -145,7 +142,6 @@ load = ConvertLandscape cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.snow_line_height type = SLE_UINT8 def = DEF_SNOWLINE_HEIGHT * TILE_HEIGHT @@ -174,7 +170,6 @@ full = _autosave_interval cat = SC_BASIC [SDT_OMANY] -base = GameSettings var = vehicle.road_side type = SLE_UINT8 def = 1 diff --git a/src/table/settings.ini b/src/table/settings.ini index 6a2cb5b14a..3c22ec4c18 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -50,27 +50,27 @@ const SettingTable _settings{ [post-amble] }; [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR($base, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_NULL = SDT_NULL($length, $from, $to), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(GameSettings, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR(GameSettings, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_NULL = SDT_NULL( $length, $from, $to), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTC_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); -SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); -SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); [defaults] flags = 0 @@ -93,7 +93,6 @@ startup = false ; Saved settings variables. ; Do not ADD or REMOVE something in this "difficulty.XXX" table or before it. It breaks savegame compatibility. [SDT_VAR] -base = GameSettings var = difficulty.max_no_competitors type = SLE_UINT8 from = SLV_97 @@ -110,7 +109,6 @@ from = SLV_97 to = SLV_110 [SDT_VAR] -base = GameSettings var = difficulty.number_towns type = SLE_UINT8 from = SLV_97 @@ -123,7 +121,6 @@ strval = STR_NUM_VERY_LOW cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.industry_density type = SLE_UINT8 from = SLV_97 @@ -138,7 +135,6 @@ strval = STR_FUNDING_ONLY cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.max_loan type = SLE_UINT32 from = SLV_97 @@ -153,7 +149,6 @@ strval = STR_JUST_CURRENCY_LONG cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.initial_interest type = SLE_UINT8 from = SLV_97 @@ -167,7 +162,6 @@ strhelp = STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT strval = STR_CONFIG_SETTING_PERCENTAGE [SDT_VAR] -base = GameSettings var = difficulty.vehicle_costs type = SLE_UINT8 from = SLV_97 @@ -182,7 +176,6 @@ strval = STR_SEA_LEVEL_LOW cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.competitor_speed type = SLE_UINT8 from = SLV_97 @@ -202,7 +195,6 @@ from = SLV_97 to = SLV_110 [SDT_VAR] -base = GameSettings var = difficulty.vehicle_breakdowns type = SLE_UINT8 from = SLV_97 @@ -217,7 +209,6 @@ strval = STR_DISASTER_NONE cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.subsidy_multiplier type = SLE_UINT8 from = SLV_97 @@ -231,7 +222,6 @@ strhelp = STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT strval = STR_SUBSIDY_X1_5 [SDT_VAR] -base = GameSettings var = difficulty.construction_cost type = SLE_UINT8 from = SLV_97 @@ -246,7 +236,6 @@ strval = STR_SEA_LEVEL_LOW cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.terrain_type type = SLE_UINT8 from = SLV_97 @@ -261,7 +250,6 @@ strval = STR_TERRAIN_TYPE_VERY_FLAT cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.quantity_sea_lakes type = SLE_UINT8 from = SLV_97 @@ -274,7 +262,6 @@ strval = STR_SEA_LEVEL_VERY_LOW cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = difficulty.economy from = SLV_97 def = false @@ -282,7 +269,6 @@ str = STR_CONFIG_SETTING_RECESSIONS strhelp = STR_CONFIG_SETTING_RECESSIONS_HELPTEXT [SDT_BOOL] -base = GameSettings var = difficulty.line_reverse_mode from = SLV_97 def = false @@ -290,7 +276,6 @@ str = STR_CONFIG_SETTING_TRAIN_REVERSING strhelp = STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT [SDT_BOOL] -base = GameSettings var = difficulty.disasters from = SLV_97 def = false @@ -299,7 +284,6 @@ strhelp = STR_CONFIG_SETTING_DISASTERS_HELPTEXT cat = SC_BASIC [SDT_VAR] -base = GameSettings var = difficulty.town_council_tolerance type = SLE_UINT8 from = SLV_97 @@ -328,7 +312,6 @@ cat = SC_BASIC ; There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow ; these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. [SDT_OMANY] -base = GameSettings var = game_creation.town_name type = SLE_UINT8 from = SLV_97 @@ -339,7 +322,6 @@ full = _town_names cat = SC_BASIC [SDT_OMANY] -base = GameSettings var = game_creation.landscape type = SLE_UINT8 from = SLV_97 @@ -360,7 +342,6 @@ from = SLV_97 to = SLV_164 [SDT_OMANY] -base = GameSettings var = vehicle.road_side type = SLE_UINT8 from = SLV_97 @@ -377,7 +358,6 @@ cat = SC_BASIC ; Construction [SDT_VAR] -base = GameSettings var = construction.map_height_limit type = SLE_UINT8 from = SLV_194 @@ -394,7 +374,6 @@ post_cb = [](auto) { InvalidateWindowClassesData(WC_SMALLMAP, 2); } cat = SC_ADVANCED [SDT_VAR] -base = GameSettings var = game_creation.heightmap_height type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP @@ -405,14 +384,12 @@ max = MAX_MAP_HEIGHT_LIMIT interval = 1 [SDT_BOOL] -base = GameSettings var = construction.build_on_slopes guiflags = SGF_NO_NETWORK def = true cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.command_pause_level type = SLE_UINT8 from = SLV_154 @@ -426,7 +403,6 @@ strhelp = STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT strval = STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS [SDT_VAR] -base = GameSettings var = construction.terraform_per_64k_frames type = SLE_UINT32 from = SLV_156 @@ -437,7 +413,6 @@ interval = 1 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.terraform_frame_burst type = SLE_UINT16 from = SLV_156 @@ -448,7 +423,6 @@ interval = 1 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.clear_per_64k_frames type = SLE_UINT32 from = SLV_156 @@ -459,7 +433,6 @@ interval = 1 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.clear_frame_burst type = SLE_UINT16 from = SLV_156 @@ -470,7 +443,6 @@ interval = 1 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.tree_per_64k_frames type = SLE_UINT32 from = SLV_175 @@ -481,7 +453,6 @@ interval = 1 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.tree_frame_burst type = SLE_UINT16 from = SLV_175 @@ -492,7 +463,6 @@ interval = 1 cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = construction.autoslope from = SLV_75 def = true @@ -501,14 +471,12 @@ strhelp = STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = construction.extra_dynamite def = true str = STR_CONFIG_SETTING_EXTRADYNAMITE strhelp = STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT [SDT_VAR] -base = GameSettings var = construction.max_bridge_length type = SLE_UINT16 from = SLV_159 @@ -522,7 +490,6 @@ strhelp = STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH_HELPTEXT strval = STR_CONFIG_SETTING_TILE_LENGTH [SDT_VAR] -base = GameSettings var = construction.max_bridge_height type = SLE_UINT8 from = SLV_194 @@ -537,7 +504,6 @@ strval = STR_JUST_COMMA cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = construction.max_tunnel_length type = SLE_UINT16 from = SLV_159 @@ -556,7 +522,6 @@ length = 1 to = SLV_159 [SDT_VAR] -base = GameSettings var = construction.train_signal_side type = SLE_UINT8 guiflags = SGF_MULTISTRING | SGF_NO_NETWORK @@ -570,7 +535,6 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = station.never_expire_airports guiflags = SGF_NO_NETWORK def = false @@ -578,7 +542,6 @@ str = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT [SDT_VAR] -base = GameSettings var = economy.town_layout type = SLE_UINT8 from = SLV_59 @@ -593,7 +556,6 @@ strval = STR_CONFIG_SETTING_TOWN_LAYOUT_DEFAULT post_cb = TownFoundingChanged [SDT_BOOL] -base = GameSettings var = economy.allow_town_roads from = SLV_113 guiflags = SGF_NO_NETWORK @@ -602,7 +564,6 @@ str = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT [SDT_VAR] -base = GameSettings var = economy.found_town type = SLE_UINT8 from = SLV_128 @@ -618,7 +579,6 @@ post_cb = TownFoundingChanged cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.allow_town_level_crossings from = SLV_143 guiflags = SGF_NO_NETWORK @@ -627,7 +587,6 @@ str = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT [SDT_VAR] -base = GameSettings var = economy.town_cargogen_mode type = SLE_UINT8 from = SLV_TOWN_CARGOGEN @@ -644,7 +603,6 @@ cat = SC_ADVANCED ; link graph [SDT_VAR] -base = GameSettings var = linkgraph.recalc_interval type = SLE_UINT16 from = SLV_183 @@ -658,7 +616,6 @@ strhelp = STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT extra = offsetof(LinkGraphSettings, recalc_interval) [SDT_VAR] -base = GameSettings var = linkgraph.recalc_time type = SLE_UINT16 from = SLV_183 @@ -673,7 +630,6 @@ extra = offsetof(LinkGraphSettings, recalc_time) [SDT_VAR] -base = GameSettings var = linkgraph.distribution_pax type = SLE_UINT8 from = SLV_183 @@ -689,7 +645,6 @@ extra = offsetof(LinkGraphSettings, distribution_pax) [SDT_VAR] -base = GameSettings var = linkgraph.distribution_mail type = SLE_UINT8 from = SLV_183 @@ -705,7 +660,6 @@ extra = offsetof(LinkGraphSettings, distribution_mail) [SDT_VAR] -base = GameSettings var = linkgraph.distribution_armoured type = SLE_UINT8 from = SLV_183 @@ -721,7 +675,6 @@ extra = offsetof(LinkGraphSettings, distribution_armoured) [SDT_VAR] -base = GameSettings var = linkgraph.distribution_default type = SLE_UINT8 from = SLV_183 @@ -737,7 +690,6 @@ extra = offsetof(LinkGraphSettings, distribution_default) [SDT_VAR] -base = GameSettings var = linkgraph.accuracy type = SLE_UINT8 from = SLV_183 @@ -752,7 +704,6 @@ extra = offsetof(LinkGraphSettings, accuracy) [SDT_VAR] -base = GameSettings var = linkgraph.demand_distance type = SLE_UINT8 from = SLV_183 @@ -767,7 +718,6 @@ extra = offsetof(LinkGraphSettings, demand_distance) [SDT_VAR] -base = GameSettings var = linkgraph.demand_size type = SLE_UINT8 from = SLV_183 @@ -782,7 +732,6 @@ extra = offsetof(LinkGraphSettings, demand_size) [SDT_VAR] -base = GameSettings var = linkgraph.short_path_saturation type = SLE_UINT8 from = SLV_183 @@ -799,7 +748,6 @@ extra = offsetof(LinkGraphSettings, short_path_saturation) ; Vehicles [SDT_VAR] -base = GameSettings var = vehicle.train_acceleration_model type = SLE_UINT8 guiflags = SGF_MULTISTRING @@ -813,7 +761,6 @@ strval = STR_CONFIG_SETTING_ORIGINAL post_cb = TrainAccelerationModelChanged [SDT_VAR] -base = GameSettings var = vehicle.roadveh_acceleration_model type = SLE_UINT8 from = SLV_139 @@ -828,7 +775,6 @@ strval = STR_CONFIG_SETTING_ORIGINAL post_cb = RoadVehAccelerationModelChanged [SDT_VAR] -base = GameSettings var = vehicle.train_slope_steepness type = SLE_UINT8 from = SLV_133 @@ -843,7 +789,6 @@ post_cb = TrainSlopeSteepnessChanged cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = vehicle.roadveh_slope_steepness type = SLE_UINT8 from = SLV_139 @@ -858,7 +803,6 @@ post_cb = RoadVehSlopeSteepnessChanged cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.forbid_90_deg def = false str = STR_CONFIG_SETTING_FORBID_90_DEG @@ -867,7 +811,6 @@ post_cb = InvalidateShipPathCache cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = vehicle.max_train_length type = SLE_UINT8 from = SLV_159 @@ -886,7 +829,6 @@ length = 1 to = SLV_159 [SDT_VAR] -base = GameSettings var = vehicle.smoke_amount type = SLE_UINT8 from = SLV_145 @@ -906,20 +848,17 @@ to = SLV_159 ; path finder [SDT_BOOL] -base = GameSettings var = pf.roadveh_queue def = true cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.new_pathfinding_all to = SLV_87 def = false cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.yapf.ship_use_yapf from = SLV_28 to = SLV_87 @@ -927,7 +866,6 @@ def = false cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.yapf.road_use_yapf from = SLV_28 to = SLV_87 @@ -935,7 +873,6 @@ def = true cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.yapf.rail_use_yapf from = SLV_28 to = SLV_87 @@ -944,7 +881,6 @@ cat = SC_EXPERT ## [SDT_VAR] -base = GameSettings var = pf.pathfinder_for_trains type = SLE_UINT8 from = SLV_87 @@ -959,7 +895,6 @@ strval = STR_CONFIG_SETTING_PATHFINDER_NPF cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.pathfinder_for_roadvehs type = SLE_UINT8 from = SLV_87 @@ -974,7 +909,6 @@ strval = STR_CONFIG_SETTING_PATHFINDER_NPF cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.pathfinder_for_ships type = SLE_UINT8 from = SLV_87 @@ -990,7 +924,6 @@ post_cb = InvalidateShipPathCache cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = vehicle.never_expire_vehicles guiflags = SGF_NO_NETWORK def = false @@ -998,7 +931,6 @@ str = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT [SDT_VAR] -base = GameSettings var = vehicle.max_trains type = SLE_UINT16 def = 500 @@ -1011,7 +943,6 @@ post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] -base = GameSettings var = vehicle.max_roadveh type = SLE_UINT16 def = 500 @@ -1024,7 +955,6 @@ post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] -base = GameSettings var = vehicle.max_aircraft type = SLE_UINT16 def = 200 @@ -1037,7 +967,6 @@ post_cb = MaxVehiclesChanged cat = SC_BASIC [SDT_VAR] -base = GameSettings var = vehicle.max_ships type = SLE_UINT16 def = 300 @@ -1097,14 +1026,12 @@ max = 800 to = SLV_120 [SDT_BOOL] -base = GameSettings var = order.no_servicing_if_no_breakdowns def = true str = STR_CONFIG_SETTING_NOSERVICE strhelp = STR_CONFIG_SETTING_NOSERVICE_HELPTEXT [SDT_BOOL] -base = GameSettings var = vehicle.wagon_speed_limits guiflags = SGF_NO_NETWORK def = true @@ -1113,7 +1040,6 @@ strhelp = STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT post_cb = UpdateConsists [SDT_BOOL] -base = GameSettings var = vehicle.disable_elrails from = SLV_38 guiflags = SGF_NO_NETWORK @@ -1124,7 +1050,6 @@ post_cb = SettingsDisableElrail cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = vehicle.freight_trains type = SLE_UINT8 from = SLV_39 @@ -1145,7 +1070,6 @@ from = SLV_67 to = SLV_159 [SDT_VAR] -base = GameSettings var = vehicle.plane_speed type = SLE_UINT8 from = SLV_90 @@ -1158,7 +1082,6 @@ strhelp = STR_CONFIG_SETTING_PLANE_SPEED_HELPTEXT strval = STR_CONFIG_SETTING_PLANE_SPEED_VALUE [SDT_BOOL] -base = GameSettings var = vehicle.dynamic_engines from = SLV_95 guiflags = SGF_NO_NETWORK @@ -1167,7 +1090,6 @@ pre_cb = CheckDynamicEngines cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = vehicle.plane_crashes type = SLE_UINT8 from = SLV_138 @@ -1193,14 +1115,12 @@ to = SLV_93 def = true [SDT_BOOL] -base = GameSettings var = order.improved_load guiflags = SGF_NO_NETWORK def = true cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = order.selectgoods def = true cat = SC_EXPERT @@ -1217,7 +1137,6 @@ length = 1 to = SLV_159 [SDT_VAR] -base = GameSettings var = station.station_spread type = SLE_UINT8 def = 12 @@ -1230,7 +1149,6 @@ post_cb = StationSpreadChanged cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = order.serviceathelipad def = true str = STR_CONFIG_SETTING_SERVICEATHELIPAD @@ -1238,7 +1156,6 @@ strhelp = STR_CONFIG_SETTING_SERVICEATHELIPAD_HELPTEXT cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = station.modified_catchment def = true str = STR_CONFIG_SETTING_CATCHMENT @@ -1247,7 +1164,6 @@ post_cb = StationCatchmentChanged cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = station.serve_neutral_industries def = true from = SLV_SERVE_NEUTRAL_INDUSTRIES @@ -1256,7 +1172,6 @@ strhelp = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT post_cb = StationCatchmentChanged [SDT_BOOL] -base = GameSettings var = order.gradual_loading from = SLV_40 guiflags = SGF_NO_NETWORK @@ -1264,7 +1179,6 @@ def = true cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = construction.road_stop_on_town_road from = SLV_47 def = true @@ -1273,7 +1187,6 @@ strhelp = STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = construction.road_stop_on_competitor_road from = SLV_114 def = true @@ -1282,14 +1195,12 @@ strhelp = STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = station.adjacent_stations from = SLV_62 def = true cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = economy.station_noise_level from = SLV_96 guiflags = SGF_NO_NETWORK @@ -1299,7 +1210,6 @@ strhelp = STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT post_cb = [](auto new_value) { InvalidateWindowClassesData(WC_TOWN_VIEW, new_value); } [SDT_BOOL] -base = GameSettings var = station.distant_join_stations from = SLV_106 def = true @@ -1309,7 +1219,6 @@ post_cb = [](auto) { DeleteWindowById(WC_SELECT_STATION, 0); } ## [SDT_BOOL] -base = GameSettings var = economy.inflation guiflags = SGF_NO_NETWORK def = false @@ -1318,7 +1227,6 @@ strhelp = STR_CONFIG_SETTING_INFLATION_HELPTEXT cat = SC_BASIC [SDT_VAR] -base = GameSettings var = construction.raw_industry_construction type = SLE_UINT8 guiflags = SGF_MULTISTRING @@ -1332,7 +1240,6 @@ post_cb = [](auto) { InvalidateWindowData(WC_BUILD_INDUSTRY, 0); } cat = SC_BASIC [SDT_VAR] -base = GameSettings var = construction.industry_platform type = SLE_UINT8 from = SLV_148 @@ -1345,7 +1252,6 @@ strval = STR_CONFIG_SETTING_TILE_LENGTH cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = economy.multiple_industry_per_town def = false str = STR_CONFIG_SETTING_MULTIPINDTOWN @@ -1356,7 +1262,6 @@ length = 1 to = SLV_141 [SDT_BOOL] -base = GameSettings var = economy.bribe def = true str = STR_CONFIG_SETTING_BRIBE @@ -1365,7 +1270,6 @@ post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.exclusive_rights from = SLV_79 def = true @@ -1375,7 +1279,6 @@ post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.fund_buildings from = SLV_165 def = true @@ -1385,7 +1288,6 @@ post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.fund_roads from = SLV_160 def = true @@ -1395,7 +1297,6 @@ post_cb = [](auto) { SetWindowClassesDirty(WC_TOWN_AUTHORITY); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.give_money from = SLV_79 def = true @@ -1404,7 +1305,6 @@ strhelp = STR_CONFIG_SETTING_ALLOW_GIVE_MONEY_HELPTEXT cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.snow_line_height type = SLE_UINT8 guiflags = SGF_SCENEDIT_ONLY @@ -1418,7 +1318,6 @@ strval = STR_JUST_COMMA cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.snow_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP @@ -1433,7 +1332,6 @@ strval = STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.desert_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP @@ -1452,7 +1350,6 @@ length = 4 to = SLV_144 [SDT_VAR] -base = GameSettings var = game_creation.starting_year type = SLE_INT32 def = DEF_START_YEAR @@ -1468,7 +1365,6 @@ length = 4 to = SLV_105 [SDT_VAR] -base = GameSettings var = game_creation.ending_year type = SLE_INT32 from = SLV_ENDING_YEAR @@ -1483,7 +1379,6 @@ strval = STR_CONFIG_SETTING_ENDING_YEAR_VALUE cat = SC_ADVANCED [SDT_VAR] -base = GameSettings var = economy.type type = SLE_UINT8 guiflags = SGF_MULTISTRING @@ -1497,7 +1392,6 @@ post_cb = [](auto) { InvalidateWindowClassesData(WC_INDUSTRY_VIEW); } cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = economy.allow_shares def = false str = STR_CONFIG_SETTING_ALLOW_SHARES @@ -1505,7 +1399,6 @@ strhelp = STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY); } [SDT_VAR] -base = GameSettings var = economy.min_years_for_shares type = SLE_UINT8 from = SLV_TRADING_AGE @@ -1519,7 +1412,6 @@ strval = STR_JUST_INT cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.feeder_payment_share type = SLE_UINT8 from = SLV_134 @@ -1532,7 +1424,6 @@ strval = STR_CONFIG_SETTING_PERCENTAGE cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.town_growth_rate type = SLE_UINT8 from = SLV_54 @@ -1545,7 +1436,6 @@ strhelp = STR_CONFIG_SETTING_TOWN_GROWTH_HELPTEXT strval = STR_CONFIG_SETTING_TOWN_GROWTH_NONE [SDT_VAR] -base = GameSettings var = economy.larger_towns type = SLE_UINT8 from = SLV_54 @@ -1559,7 +1449,6 @@ strhelp = STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT strval = STR_CONFIG_SETTING_LARGER_TOWNS_VALUE [SDT_VAR] -base = GameSettings var = economy.initial_city_size type = SLE_UINT8 from = SLV_56 @@ -1572,7 +1461,6 @@ strhelp = STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT strval = STR_JUST_COMMA [SDT_BOOL] -base = GameSettings var = economy.mod_road_rebuild from = SLV_77 def = true @@ -1584,7 +1472,6 @@ length = 1 to = SLV_107 [SDT_OMANY] -base = GameSettings var = script.settings_profile type = SLE_UINT8 from = SLV_178 @@ -1599,7 +1486,6 @@ strval = STR_CONFIG_SETTING_AI_PROFILE_EASY cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = ai.ai_in_multiplayer def = true str = STR_CONFIG_SETTING_AI_IN_MULTIPLAYER @@ -1607,35 +1493,30 @@ strhelp = STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = ai.ai_disable_veh_train def = false str = STR_CONFIG_SETTING_AI_BUILDS_TRAINS strhelp = STR_CONFIG_SETTING_AI_BUILDS_TRAINS_HELPTEXT [SDT_BOOL] -base = GameSettings var = ai.ai_disable_veh_roadveh def = false str = STR_CONFIG_SETTING_AI_BUILDS_ROAD_VEHICLES strhelp = STR_CONFIG_SETTING_AI_BUILDS_ROAD_VEHICLES_HELPTEXT [SDT_BOOL] -base = GameSettings var = ai.ai_disable_veh_aircraft def = false str = STR_CONFIG_SETTING_AI_BUILDS_AIRCRAFT strhelp = STR_CONFIG_SETTING_AI_BUILDS_AIRCRAFT_HELPTEXT [SDT_BOOL] -base = GameSettings var = ai.ai_disable_veh_ship def = false str = STR_CONFIG_SETTING_AI_BUILDS_SHIPS strhelp = STR_CONFIG_SETTING_AI_BUILDS_SHIPS_HELPTEXT [SDT_VAR] -base = GameSettings var = script.script_max_opcode_till_suspend type = SLE_UINT32 from = SLV_107 @@ -1650,7 +1531,6 @@ strval = STR_JUST_COMMA cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = script.script_max_memory_megabytes type = SLE_UINT32 from = SLV_SCRIPT_MEMLIMIT @@ -1666,7 +1546,6 @@ cat = SC_EXPERT ## [SDT_VAR] -base = GameSettings var = vehicle.extend_vehicle_life type = SLE_UINT8 def = 0 @@ -1675,7 +1554,6 @@ max = 100 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.dist_local_authority type = SLE_UINT8 def = 20 @@ -1684,7 +1562,6 @@ max = 60 cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.reverse_at_signals from = SLV_159 def = false @@ -1692,7 +1569,6 @@ str = STR_CONFIG_SETTING_REVERSE_AT_SIGNALS strhelp = STR_CONFIG_SETTING_REVERSE_AT_SIGNALS_HELPTEXT [SDT_VAR] -base = GameSettings var = pf.wait_oneway_signal type = SLE_UINT8 def = 15 @@ -1701,7 +1577,6 @@ max = 255 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.wait_twoway_signal type = SLE_UINT8 def = 41 @@ -1710,7 +1585,6 @@ max = 255 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.town_noise_population[0] type = SLE_UINT16 from = SLV_96 @@ -1720,7 +1594,6 @@ max = 65535 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.town_noise_population[1] type = SLE_UINT16 from = SLV_96 @@ -1730,7 +1603,6 @@ max = 65535 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = economy.town_noise_population[2] type = SLE_UINT16 from = SLV_96 @@ -1740,7 +1612,6 @@ max = 65535 cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = economy.infrastructure_maintenance from = SLV_166 def = false @@ -1751,7 +1622,6 @@ cat = SC_BASIC ## [SDT_VAR] -base = GameSettings var = pf.wait_for_pbs_path type = SLE_UINT8 from = SLV_100 @@ -1761,14 +1631,12 @@ max = 255 cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.reserve_paths from = SLV_100 def = false cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.path_backoff_interval type = SLE_UINT8 from = SLV_100 @@ -1785,7 +1653,6 @@ to = SLV_REMOVE_OPF ## [SDT_VAR] -base = GameSettings var = pf.npf.npf_max_search_nodes type = SLE_UINT def = 10000 @@ -1794,7 +1661,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_firstred_penalty type = SLE_UINT def = 10 * NPF_TILE_LENGTH @@ -1803,7 +1669,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_firstred_exit_penalty type = SLE_UINT def = 100 * NPF_TILE_LENGTH @@ -1812,7 +1677,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_lastred_penalty type = SLE_UINT def = 10 * NPF_TILE_LENGTH @@ -1821,7 +1685,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_station_penalty type = SLE_UINT def = 1 * NPF_TILE_LENGTH @@ -1830,7 +1693,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_slope_penalty type = SLE_UINT def = 1 * NPF_TILE_LENGTH @@ -1839,7 +1701,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_curve_penalty type = SLE_UINT def = 1 * NPF_TILE_LENGTH @@ -1848,7 +1709,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_depot_reverse_penalty type = SLE_UINT def = 50 * NPF_TILE_LENGTH @@ -1857,7 +1717,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_pbs_cross_penalty type = SLE_UINT from = SLV_100 @@ -1867,7 +1726,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_rail_pbs_signal_back_penalty type = SLE_UINT from = SLV_100 @@ -1877,7 +1735,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_buoy_penalty type = SLE_UINT def = 2 * NPF_TILE_LENGTH @@ -1886,7 +1743,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_water_curve_penalty type = SLE_UINT def = 1 * NPF_TILE_LENGTH @@ -1895,7 +1751,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_road_curve_penalty type = SLE_UINT def = 1 * NPF_TILE_LENGTH @@ -1904,7 +1759,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_crossing_penalty type = SLE_UINT def = 3 * NPF_TILE_LENGTH @@ -1913,7 +1767,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_road_drive_through_penalty type = SLE_UINT from = SLV_47 @@ -1923,7 +1776,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_road_dt_occupied_penalty type = SLE_UINT from = SLV_130 @@ -1933,7 +1785,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.npf_road_bay_occupied_penalty type = SLE_UINT from = SLV_130 @@ -1943,7 +1794,6 @@ max = 100000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.npf.maximum_go_to_depot_penalty type = SLE_UINT from = SLV_131 @@ -1954,14 +1804,12 @@ cat = SC_EXPERT ## [SDT_BOOL] -base = GameSettings var = pf.yapf.disable_node_optimization from = SLV_28 def = false cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.max_search_nodes type = SLE_UINT from = SLV_28 @@ -1971,14 +1819,12 @@ max = 1000000 cat = SC_EXPERT [SDT_BOOL] -base = GameSettings var = pf.yapf.rail_firstred_twoway_eol from = SLV_28 def = false cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_firstred_penalty type = SLE_UINT from = SLV_28 @@ -1988,7 +1834,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_firstred_exit_penalty type = SLE_UINT from = SLV_28 @@ -1998,7 +1843,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_lastred_penalty type = SLE_UINT from = SLV_28 @@ -2008,7 +1852,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_lastred_exit_penalty type = SLE_UINT from = SLV_28 @@ -2018,7 +1861,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_station_penalty type = SLE_UINT from = SLV_28 @@ -2028,7 +1870,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_slope_penalty type = SLE_UINT from = SLV_28 @@ -2038,7 +1879,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_curve45_penalty type = SLE_UINT from = SLV_28 @@ -2048,7 +1888,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_curve90_penalty type = SLE_UINT from = SLV_28 @@ -2058,7 +1897,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_depot_reverse_penalty type = SLE_UINT from = SLV_28 @@ -2068,7 +1906,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_crossing_penalty type = SLE_UINT from = SLV_28 @@ -2078,7 +1915,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_look_ahead_max_signals type = SLE_UINT from = SLV_28 @@ -2088,7 +1924,6 @@ max = 100 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_look_ahead_signal_p0 type = SLE_INT from = SLV_28 @@ -2098,7 +1933,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_look_ahead_signal_p1 type = SLE_INT from = SLV_28 @@ -2108,7 +1942,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_look_ahead_signal_p2 type = SLE_INT from = SLV_28 @@ -2118,7 +1951,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_pbs_cross_penalty type = SLE_UINT from = SLV_100 @@ -2128,7 +1960,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_pbs_station_penalty type = SLE_UINT from = SLV_100 @@ -2138,7 +1969,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_pbs_signal_back_penalty type = SLE_UINT from = SLV_100 @@ -2148,7 +1978,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_doubleslip_penalty type = SLE_UINT from = SLV_100 @@ -2158,7 +1987,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_longer_platform_penalty type = SLE_UINT from = SLV_33 @@ -2168,7 +1996,6 @@ max = 20000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_longer_platform_per_tile_penalty type = SLE_UINT from = SLV_33 @@ -2178,7 +2005,6 @@ max = 20000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_shorter_platform_penalty type = SLE_UINT from = SLV_33 @@ -2188,7 +2014,6 @@ max = 20000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.rail_shorter_platform_per_tile_penalty type = SLE_UINT from = SLV_33 @@ -2198,7 +2023,6 @@ max = 20000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_slope_penalty type = SLE_UINT from = SLV_33 @@ -2208,7 +2032,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_curve_penalty type = SLE_UINT from = SLV_33 @@ -2218,7 +2041,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_crossing_penalty type = SLE_UINT from = SLV_33 @@ -2228,7 +2050,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_stop_penalty type = SLE_UINT from = SLV_47 @@ -2238,7 +2059,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_stop_occupied_penalty type = SLE_UINT from = SLV_130 @@ -2248,7 +2068,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.road_stop_bay_occupied_penalty type = SLE_UINT from = SLV_130 @@ -2258,7 +2077,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.maximum_go_to_depot_penalty type = SLE_UINT from = SLV_131 @@ -2268,7 +2086,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.ship_curve45_penalty type = SLE_UINT from = SLV_SHIP_CURVE_PENALTY @@ -2278,7 +2095,6 @@ max = 1000000 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = pf.yapf.ship_curve90_penalty type = SLE_UINT from = SLV_SHIP_CURVE_PENALTY @@ -2289,7 +2105,6 @@ cat = SC_EXPERT ## [SDT_VAR] -base = GameSettings var = game_creation.land_generator type = SLE_UINT8 from = SLV_30 @@ -2302,7 +2117,6 @@ strhelp = STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT strval = STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL [SDT_VAR] -base = GameSettings var = game_creation.oil_refinery_limit type = SLE_UINT8 from = SLV_30 @@ -2314,7 +2128,6 @@ strval = STR_CONFIG_SETTING_TILE_LENGTH strhelp = STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT [SDT_VAR] -base = GameSettings var = game_creation.tgen_smoothness type = SLE_UINT8 from = SLV_30 @@ -2328,7 +2141,6 @@ strval = STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.variety type = SLE_UINT8 from = SLV_197 @@ -2341,7 +2153,6 @@ strhelp = STR_CONFIG_SETTING_VARIETY_HELPTEXT strval = STR_VARIETY_NONE [SDT_VAR] -base = GameSettings var = game_creation.generation_seed type = SLE_UINT32 from = SLV_30 @@ -2351,7 +2162,6 @@ max = UINT32_MAX cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = game_creation.tree_placer type = SLE_UINT8 from = SLV_30 @@ -2365,7 +2175,6 @@ strval = STR_CONFIG_SETTING_TREE_PLACER_NONE cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.heightmap_rotation type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2378,7 +2187,6 @@ strval = STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.se_flat_world_height type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2391,7 +2199,6 @@ cat = SC_BASIC ## [SDT_VAR] -base = GameSettings var = game_creation.map_x type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2401,7 +2208,6 @@ max = MAX_MAP_SIZE_BITS cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.map_y type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2411,7 +2217,6 @@ max = MAX_MAP_SIZE_BITS cat = SC_BASIC [SDT_BOOL] -base = GameSettings var = construction.freeform_edges from = SLV_111 def = true @@ -2420,7 +2225,6 @@ post_cb = UpdateFreeformEdges cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = game_creation.water_borders type = SLE_UINT8 from = SLV_111 @@ -2429,7 +2233,6 @@ min = 0 max = 16 [SDT_VAR] -base = GameSettings var = game_creation.custom_town_number type = SLE_UINT16 from = SLV_115 @@ -2439,7 +2242,6 @@ max = 5000 cat = SC_BASIC [SDT_VAR] -base = GameSettings var = construction.extra_tree_placement type = SLE_UINT8 from = SLV_132 @@ -2453,7 +2255,6 @@ strval = STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.custom_terrain_type type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP @@ -2464,7 +2265,6 @@ max = MAX_MAP_HEIGHT_LIMIT interval = 1 [SDT_VAR] -base = GameSettings var = game_creation.custom_sea_level type = SLE_UINT8 from = SLV_149 @@ -2474,7 +2274,6 @@ max = CUSTOM_SEA_LEVEL_MAX_PERCENTAGE cat = SC_BASIC [SDT_VAR] -base = GameSettings var = game_creation.min_river_length type = SLE_UINT8 from = SLV_163 @@ -2484,7 +2283,6 @@ max = 255 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = game_creation.river_route_random type = SLE_UINT8 from = SLV_163 @@ -2494,7 +2292,6 @@ max = 255 cat = SC_EXPERT [SDT_VAR] -base = GameSettings var = game_creation.amount_of_rivers type = SLE_UINT8 from = SLV_163 @@ -2509,7 +2306,6 @@ strval = STR_RIVERS_NONE ; locale [SDT_OMANY] -base = GameSettings var = locale.currency type = SLE_UINT8 from = SLV_97 @@ -2534,7 +2330,6 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_OMANY] -base = GameSettings var = locale.units_velocity type = SLE_UINT8 from = SLV_184 @@ -2550,7 +2345,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL [SDT_OMANY] -base = GameSettings var = locale.units_power type = SLE_UINT8 from = SLV_184 @@ -2566,7 +2360,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_IMPERIAL [SDT_OMANY] -base = GameSettings var = locale.units_weight type = SLE_UINT8 from = SLV_184 @@ -2582,7 +2375,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_IMPERIAL [SDT_OMANY] -base = GameSettings var = locale.units_volume type = SLE_UINT8 from = SLV_184 @@ -2598,7 +2390,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_IMPERIAL [SDT_OMANY] -base = GameSettings var = locale.units_force type = SLE_UINT8 from = SLV_184 @@ -2614,7 +2405,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_IMPERIAL [SDT_OMANY] -base = GameSettings var = locale.units_height type = SLE_UINT8 from = SLV_184 @@ -2630,7 +2420,6 @@ strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL [SDT_SSTR] -base = GameSettings var = locale.digit_group_separator type = SLE_STRQ from = SLV_118 @@ -2640,7 +2429,6 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_SSTR] -base = GameSettings var = locale.digit_group_separator_currency type = SLE_STRQ from = SLV_118 @@ -2650,7 +2438,6 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC [SDT_SSTR] -base = GameSettings var = locale.digit_decimal_separator type = SLE_STRQ from = SLV_126 diff --git a/src/table/window_settings.ini b/src/table/window_settings.ini index 5334b0fc1d..560a197ab6 100644 --- a/src/table/window_settings.ini +++ b/src/table/window_settings.ini @@ -10,14 +10,13 @@ static const SettingTable _window_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(WindowDesc, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(WindowDesc, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] -SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for WindowDesc.$var exceeds storage size"); [defaults] -base = WindowDesc flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NONE interval = 0 From 4d74e519074bec9a07c2997715ab635ac0e8f084 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 11:21:30 +0200 Subject: [PATCH 265/800] Fix #9281: acquire a company uses special bookkeeping to make you rich (#9300) When you buy-out a company, you got your shares back. This is based on company-value, which includes values for the vehicles etc. In other words, you not only got the vehicles, but you also got paid to get them back. Additionally, you also got the loan of the company, but not the money for the loan (as that is subtracted from the company-value). Solve this by changing the rules of a buy-out: don't sell your shares, get the loan AND the balance and get the infrastructure. --- src/economy.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/economy.cpp b/src/economy.cpp index 09adf81b99..cde08f76a0 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -324,8 +324,11 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) Backup cur_company2(_current_company, FILE_LINE); const Company *c = Company::Get(old_owner); for (i = 0; i < 4; i++) { - cur_company2.Change(c->share_owners[i]); - if (_current_company != INVALID_OWNER) { + if (c->bankrupt_value == 0 && c->share_owners[i] == new_owner) { + /* You are the one buying the company; so don't sell the shares back to you. */ + Company::Get(new_owner)->share_owners[i] = COMPANY_SPECTATOR; + } else if (c->share_owners[i] != INVALID_OWNER) { + cur_company2.Change(c->share_owners[i]); /* Sell the shares */ CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC | DC_BANKRUPT, CMD_SELL_SHARE_IN_COMPANY); /* Because we are in a DoCommand, we can't just execute another one and @@ -1986,6 +1989,9 @@ static void DoAcquireCompany(Company *c) if (c->bankrupt_value == 0) { Company *owner = Company::Get(_current_company); + + /* Get both the balance and the loan of the company you just bought. */ + SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -c->money)); owner->current_loan += c->current_loan; } From ca9a7df7522a614b839a83e1ba9b6a7b08642b8a Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 11:21:38 +0200 Subject: [PATCH 266/800] Codechange: rename str_validate to StrMakeValid(InPlace) (#9304) This to be more explicit the function changes the value, and not returns yes/no. --- src/console.cpp | 2 +- src/fios.cpp | 6 ++-- src/highscore.cpp | 2 +- src/ini_load.cpp | 6 ++-- src/misc_gui.cpp | 2 +- src/network/core/packet.cpp | 4 +-- src/newgrf.cpp | 2 +- src/os/os2/os2.cpp | 2 +- src/os/unix/unix.cpp | 2 +- src/os/windows/win32.cpp | 2 +- src/saveload/oldloader.cpp | 2 +- src/saveload/saveload.cpp | 4 +-- src/script/api/script_object.cpp | 4 +-- src/script/api/script_text.cpp | 4 +-- src/script/script_info.cpp | 10 +++--- src/script/squirrel.cpp | 2 +- src/script/squirrel_helper.hpp | 2 +- src/settings.cpp | 2 +- src/string.cpp | 53 ++++++++++++++++---------------- src/string_func.h | 6 ++-- src/textfile_gui.cpp | 4 +-- src/video/dedicated_v.cpp | 2 +- 22 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/console.cpp b/src/console.cpp index fbd34c1977..f1fe46094c 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -111,7 +111,7 @@ void IConsolePrint(TextColour colour_code, const char *string) * characters and (when applicable) assign it to the console buffer */ str = stredup(string); str_strip_colours(str); - str_validate(str, str + strlen(str)); + StrMakeValidInPlace(str); if (_network_dedicated) { NetworkAdminConsole("console", str); diff --git a/src/fios.cpp b/src/fios.cpp index c56e505fa0..c59bcfb210 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -342,7 +342,7 @@ bool FiosFileScanner::AddFile(const std::string &filename, size_t basepath_lengt t = filename.c_str() + (ps == std::string::npos ? 0 : ps + 1); } strecpy(fios->title, t, lastof(fios->title)); - str_validate(fios->title, lastof(fios->title)); + StrMakeValidInPlace(fios->title, lastof(fios->title)); return true; } @@ -394,7 +394,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c std::string dirname = std::string(d_name) + PATHSEP; SetDParamStr(0, dirname); GetString(fios->title, STR_SAVELOAD_DIRECTORY, lastof(fios->title)); - str_validate(fios->title, lastof(fios->title)); + StrMakeValidInPlace(fios->title, lastof(fios->title)); } } closedir(dir); @@ -446,7 +446,7 @@ static void GetFileTitle(const std::string &file, char *title, const char *last, size_t read = fread(title, 1, last - title, f); assert(title + read <= last); title[read] = '\0'; - str_validate(title, last); + StrMakeValidInPlace(title, last); FioFCloseFile(f); } diff --git a/src/highscore.cpp b/src/highscore.cpp index 4c5b6b1aa2..d40f2419de 100644 --- a/src/highscore.cpp +++ b/src/highscore.cpp @@ -170,7 +170,7 @@ void LoadFromHighScore() i = SP_SAVED_HIGHSCORE_END; break; } - str_validate(hs->company, lastof(hs->company), SVS_NONE); + StrMakeValidInPlace(hs->company, lastof(hs->company), SVS_NONE); hs->title = EndGameGetPerformanceTitleFromValue(hs->score); } } diff --git a/src/ini_load.cpp b/src/ini_load.cpp index 33bb46b12a..308f822be8 100644 --- a/src/ini_load.cpp +++ b/src/ini_load.cpp @@ -22,7 +22,7 @@ */ IniItem::IniItem(IniGroup *parent, const std::string &name) : next(nullptr) { - this->name = str_validate(name); + this->name = StrMakeValid(name); *parent->last_item = this; parent->last_item = &this->next; @@ -50,7 +50,7 @@ void IniItem::SetValue(const std::string_view value) */ IniGroup::IniGroup(IniLoadFile *parent, const std::string &name) : next(nullptr), type(IGT_VARIABLES), item(nullptr) { - this->name = str_validate(name); + this->name = StrMakeValid(name); this->last_item = &this->item; *parent->last_group = this; @@ -288,7 +288,7 @@ void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir) if (!quoted && e == t) { item->value.reset(); } else { - item->value = str_validate(std::string(t)); + item->value = StrMakeValid(std::string(t)); } } else { /* it's an orphan item */ diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 3094d0eade..f7061d328d 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -997,7 +997,7 @@ struct QueryStringWindow : public Window { char *last_of = &this->editbox.text.buf[this->editbox.text.max_bytes - 1]; GetString(this->editbox.text.buf, str, last_of); - str_validate(this->editbox.text.buf, last_of, SVS_NONE); + StrMakeValidInPlace(this->editbox.text.buf, last_of, SVS_NONE); /* Make sure the name isn't too long for the text buffer in the number of * characters (not bytes). max_chars also counts the '\0' characters. */ diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 738afec4e6..c27a37d461 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -394,7 +394,7 @@ void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings set assert(pos <= std::numeric_limits::max()); this->pos = static_cast(pos); - str_validate(bufp, last, settings); + StrMakeValidInPlace(bufp, last, settings); } /** @@ -423,7 +423,7 @@ std::string Packet::Recv_string(size_t length, StringValidationSettings settings while (this->Recv_uint8() != '\0') {} } - return str_validate(str, settings); + return StrMakeValid(str, settings); } /** diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 29125f158e..318c5e8ea8 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2598,7 +2598,7 @@ static std::string ReadDWordAsString(ByteReader *reader) char output[5]; for (int i = 0; i < 4; i++) output[i] = reader->ReadByte(); output[4] = '\0'; - str_validate(output, lastof(output)); + StrMakeValidInPlace(output, lastof(output)); return std::string(output); } diff --git a/src/os/os2/os2.cpp b/src/os/os2/os2.cpp index 009a3e0ede..d3de2631bc 100644 --- a/src/os/os2/os2.cpp +++ b/src/os/os2/os2.cpp @@ -174,7 +174,7 @@ int CDECL main(int argc, char *argv[]) SetRandomSeed(time(nullptr)); /* Make sure our arguments contain only valid UTF-8 characters. */ - for (int i = 0; i < argc; i++) ValidateString(argv[i]); + for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]); return openttd_main(argc, argv); } diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 57edf1d38e..8bb947e857 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -243,7 +243,7 @@ void CocoaReleaseAutoreleasePool(); int CDECL main(int argc, char *argv[]) { /* Make sure our arguments contain only valid UTF-8 characters. */ - for (int i = 0; i < argc; i++) ValidateString(argv[i]); + for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]); #ifdef WITH_COCOA CocoaSetupAutoreleasePool(); diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index eee81be402..3ed0cdb2a7 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -429,7 +429,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi argc = ParseCommandLine(cmdline, argv, lengthof(argv)); /* Make sure our arguments contain only valid UTF-8 characters. */ - for (int i = 0; i < argc; i++) ValidateString(argv[i]); + for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]); openttd_main(argc, argv); diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp index 6bc07ad27a..74a1466da6 100644 --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -234,7 +234,7 @@ static inline bool CheckOldSavegameType(FILE *f, char *temp, const char *last, u bool ret = VerifyOldNameChecksum(temp, len); temp[len - 2] = '\0'; // name is null-terminated in savegame, but it's better to be sure - str_validate(temp, last); + StrMakeValidInPlace(temp, last); return ret; } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 442ab9135c..9a9ed7cc5c 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -972,7 +972,7 @@ static void SlString(void *ptr, size_t length, VarType conv) if ((conv & SLF_ALLOW_NEWLINE) != 0) { settings = settings | SVS_ALLOW_NEWLINE; } - str_validate((char *)ptr, (char *)ptr + len, settings); + StrMakeValidInPlace((char *)ptr, (char *)ptr + len, settings); break; } case SLA_PTRS: break; @@ -1016,7 +1016,7 @@ static void SlStdString(void *ptr, VarType conv) if ((conv & SLF_ALLOW_NEWLINE) != 0) { settings = settings | SVS_ALLOW_NEWLINE; } - str_validate(buf, buf + len, settings); + StrMakeValidInPlace(buf, buf + len, settings); // Store sanitized string. str->assign(buf); diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index 85a85cca1b..1f72eaa227 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -283,7 +283,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() { char buffer[64]; ::GetString(buffer, string, lastof(buffer)); - ::str_validate(buffer, lastof(buffer), SVS_NONE); + ::StrMakeValidInPlace(buffer, lastof(buffer), SVS_NONE); return ::stredup(buffer); } @@ -312,7 +312,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() if (!StrEmpty(text) && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) { /* The string must be valid, i.e. not contain special codes. Since some * can be made with GSText, make sure the control codes are removed. */ - ::str_validate(const_cast(text), text + strlen(text), SVS_NONE); + ::StrMakeValidInPlace(text, SVS_NONE); } /* Set the default callback to return a true/false result of the DoCommand */ diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index 36f9417930..dd32d0d421 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -82,7 +82,7 @@ SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm) sq_getstring(vm, -1, &value); this->params[parameter] = stredup(value); - ValidateString(this->params[parameter]); + StrMakeValidInPlace(this->params[parameter]); break; } @@ -157,7 +157,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm) if (sq_gettype(vm, 2) == OT_STRING) { const SQChar *key_string; sq_getstring(vm, 2, &key_string); - ValidateString(key_string); + StrMakeValidInPlace(key_string); if (strncmp(key_string, "param_", 6) != 0 || strlen(key_string) > 8) return SQ_ERROR; k = atoi(key_string + 6); diff --git a/src/script/script_info.cpp b/src/script/script_info.cpp index d02bbe324e..17b0e19697 100644 --- a/src/script/script_info.cpp +++ b/src/script/script_info.cpp @@ -122,14 +122,14 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm) while (SQ_SUCCEEDED(sq_next(vm, -2))) { const SQChar *key; if (SQ_FAILED(sq_getstring(vm, -2, &key))) return SQ_ERROR; - ValidateString(key); + StrMakeValidInPlace(key); if (strcmp(key, "name") == 0) { const SQChar *sqvalue; if (SQ_FAILED(sq_getstring(vm, -1, &sqvalue))) return SQ_ERROR; char *name = stredup(sqvalue); char *s; - ValidateString(name); + StrMakeValidInPlace(name); /* Don't allow '=' and ',' in configure setting names, as we need those * 2 chars to nicely store the settings as a string. */ @@ -141,7 +141,7 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm) const SQChar *sqdescription; if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR; config.description = stredup(sqdescription); - ValidateString(config.description); + StrMakeValidInPlace(config.description); items |= 0x002; } else if (strcmp(key, "min_value") == 0) { SQInteger res; @@ -226,7 +226,7 @@ SQInteger ScriptInfo::AddLabels(HSQUIRRELVM vm) { const SQChar *setting_name; if (SQ_FAILED(sq_getstring(vm, -2, &setting_name))) return SQ_ERROR; - ValidateString(setting_name); + StrMakeValidInPlace(setting_name); ScriptConfigItem *config = nullptr; for (auto &item : this->config_list) { @@ -253,7 +253,7 @@ SQInteger ScriptInfo::AddLabels(HSQUIRRELVM vm) /* Because squirrel doesn't support identifiers starting with a digit, * we skip the first character. */ int key = atoi(key_string + 1); - ValidateString(label); + StrMakeValidInPlace(label); /* !Contains() prevents stredup from leaking. */ if (!config->labels->Contains(key)) config->labels->Insert(key, stredup(label)); diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index 77f84a6416..89d86180d2 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -448,7 +448,7 @@ bool Squirrel::CallStringMethodStrdup(HSQOBJECT instance, const char *method_nam if (!this->CallMethod(instance, method_name, &ret, suspend)) return false; if (ret._type != OT_STRING) return false; *res = stredup(ObjectToString(&ret)); - ValidateString(*res); + StrMakeValidInPlace(*res); return true; } diff --git a/src/script/squirrel_helper.hpp b/src/script/squirrel_helper.hpp index 3c6bed6c2c..ff25a5d58a 100644 --- a/src/script/squirrel_helper.hpp +++ b/src/script/squirrel_helper.hpp @@ -116,7 +116,7 @@ namespace SQConvert { char *tmp_str = stredup(tmp); sq_poptop(vm); ptr->push_back((void *)tmp_str); - str_validate(tmp_str, tmp_str + strlen(tmp_str)); + StrMakeValidInPlace(tmp_str); return tmp_str; } diff --git a/src/settings.cpp b/src/settings.cpp index 0160f8e0e3..c36f0855f7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -497,7 +497,7 @@ void StringSettingDesc::MakeValueValid(std::string &str) const * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ std::string stdstr(str, this->max_length - 1); - str.assign(str_validate(stdstr, SVS_NONE)); + str.assign(StrMakeValid(stdstr, SVS_NONE)); } /** diff --git a/src/string.cpp b/src/string.cpp index a76006fe81..930d0dba12 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -186,7 +186,7 @@ void str_fix_scc_encoded(char *str, const char *last) template -static void str_validate(T &dst, const char *str, const char *last, StringValidationSettings settings) +static void StrMakeValidInPlace(T &dst, const char *str, const char *last, StringValidationSettings settings) { /* Assume the ABSOLUTE WORST to be in str as it comes from the outside. */ @@ -246,49 +246,50 @@ static void str_validate(T &dst, const char *str, const char *last, StringValida } /** - * Scans the string for valid characters and if it finds invalid ones, - * replaces them with a question mark '?' (if not ignored) - * @param str the string to validate - * @param last the last valid character of str - * @param settings the settings for the string validation. + * Scans the string for invalid characters and replaces then with a + * question mark '?' (if not ignored). + * @param str The string to validate. + * @param last The last valid character of str. + * @param settings The settings for the string validation. */ -void str_validate(char *str, const char *last, StringValidationSettings settings) +void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings) { char *dst = str; - str_validate(dst, str, last, settings); + StrMakeValidInPlace(dst, str, last, settings); *dst = '\0'; } /** - * Scans the string for valid characters and if it finds invalid ones, - * replaces them with a question mark '?' (if not ignored) - * @param str the string to validate - * @param settings the settings for the string validation. + * Scans the string for invalid characters and replaces then with a + * question mark '?' (if not ignored). + * Only use this function when you are sure the string ends with a '\0'; + * otherwise use StrMakeValidInPlace(str, last, settings) variant. + * @param str The string (of which you are sure ends with '\0') to validate. */ -std::string str_validate(const std::string &str, StringValidationSettings settings) +void StrMakeValidInPlace(const char *str, StringValidationSettings settings) +{ + /* We know it is '\0' terminated. */ + StrMakeValidInPlace(const_cast(str), str + strlen(str), settings); +} + +/** + * Scans the string for invalid characters and replaces then with a + * question mark '?' (if not ignored). + * @param str The string to validate. + * @param settings The settings for the string validation. + */ +std::string StrMakeValid(const std::string &str, StringValidationSettings settings) { auto buf = str.data(); auto last = buf + str.size(); std::ostringstream dst; std::ostreambuf_iterator dst_iter(dst); - str_validate(dst_iter, buf, last, settings); + StrMakeValidInPlace(dst_iter, buf, last, settings); return dst.str(); } -/** - * Scans the string for valid characters and if it finds invalid ones, - * replaces them with a question mark '?'. - * @param str the string to validate - */ -void ValidateString(const char *str) -{ - /* We know it is '\0' terminated. */ - str_validate(const_cast(str), str + strlen(str) + 1); -} - - /** * Checks whether the given string is valid, i.e. contains only * valid (printable) characters and is properly terminated. diff --git a/src/string_func.h b/src/string_func.h index 7ff84d43ee..be409072ef 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -39,9 +39,9 @@ int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); -void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2); -[[nodiscard]] std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); -void ValidateString(const char *str); +void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2); +[[nodiscard]] std::string StrMakeValid(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +void StrMakeValidInPlace(const char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2); void str_strip_colours(char *str); diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index d6c37a4580..e9223af70a 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -375,7 +375,7 @@ static void Xunzip(byte **bufp, size_t *sizep) this->text = ReallocT(this->text, filesize + 1); this->text[filesize] = '\0'; - /* Replace tabs and line feeds with a space since str_validate removes those. */ + /* Replace tabs and line feeds with a space since StrMakeValidInPlace removes those. */ for (char *p = this->text; *p != '\0'; p++) { if (*p == '\t' || *p == '\r') *p = ' '; } @@ -384,7 +384,7 @@ static void Xunzip(byte **bufp, size_t *sizep) char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0); /* Make sure the string is a valid UTF-8 sequence. */ - str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); + StrMakeValidInPlace(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); /* Split the string on newlines. */ int row = 0; diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index 6f631e2278..445ff19e41 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -229,7 +229,7 @@ static void DedicatedHandleKeyInput() break; } } - str_validate(input_line, lastof(input_line)); + StrMakeValidInPlace(input_line, lastof(input_line)); IConsoleCmdExec(input_line); // execute command } From e58046c9477d52470ebb50e2dbd1ccc1af9dae25 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 10:58:07 +0200 Subject: [PATCH 267/800] Codechange: move all settings.ini files to table/settings --- src/table/CMakeLists.txt | 48 +------------------ src/table/settings/CMakeLists.txt | 47 ++++++++++++++++++ src/table/{ => settings}/company_settings.ini | 0 .../{ => settings}/currency_settings.ini | 0 src/table/{ => settings}/gameopt_settings.ini | 0 src/table/{ => settings}/misc_settings.ini | 0 src/table/{ => settings}/settings.ini | 0 src/table/{ => settings}/win32_settings.ini | 0 src/table/{ => settings}/window_settings.ini | 0 9 files changed, 48 insertions(+), 47 deletions(-) create mode 100644 src/table/settings/CMakeLists.txt rename src/table/{ => settings}/company_settings.ini (100%) rename src/table/{ => settings}/currency_settings.ini (100%) rename src/table/{ => settings}/gameopt_settings.ini (100%) rename src/table/{ => settings}/misc_settings.ini (100%) rename src/table/{ => settings}/settings.ini (100%) rename src/table/{ => settings}/win32_settings.ini (100%) rename src/table/{ => settings}/window_settings.ini (100%) diff --git a/src/table/CMakeLists.txt b/src/table/CMakeLists.txt index bb2311cf1e..c4043681b7 100644 --- a/src/table/CMakeLists.txt +++ b/src/table/CMakeLists.txt @@ -1,50 +1,4 @@ -set(GENERATED_BINARY_DIR ${CMAKE_BINARY_DIR}/generated) -set(TABLE_BINARY_DIR ${GENERATED_BINARY_DIR}/table) - -set(TABLE_INI_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/company_settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/currency_settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/gameopt_settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/misc_settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/win32_settings.ini - ${CMAKE_CURRENT_SOURCE_DIR}/window_settings.ini -) - -if (HOST_BINARY_DIR) - include(${HOST_BINARY_DIR}/settingsgen.cmake) -endif() - -# Generate a command and target to create the settings table -add_custom_command_timestamp(OUTPUT ${TABLE_BINARY_DIR}/settings.h - COMMAND ${CMAKE_COMMAND} -E make_directory ${TABLE_BINARY_DIR} - COMMAND settingsgen - -o ${TABLE_BINARY_DIR}/settings.h - -b ${CMAKE_SOURCE_DIR}/src/table/settings.h.preamble - -a ${CMAKE_SOURCE_DIR}/src/table/settings.h.postamble - ${TABLE_INI_SOURCE_FILES} - DEPENDS settingsgen ${TABLE_INI_SOURCE_FILES} - ${CMAKE_SOURCE_DIR}/src/table/settings.h.preamble - ${CMAKE_SOURCE_DIR}/src/table/settings.h.postamble - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating table/settings.h" -) -add_custom_target_timestamp(table_settings - DEPENDS - ${TABLE_BINARY_DIR}/settings.h -) - -add_library(settings - INTERFACE -) -target_include_directories(settings - INTERFACE - ${GENERATED_BINARY_DIR} -) -add_dependencies(settings - table_settings -) -add_library(openttd::settings ALIAS settings) +add_subdirectory(settings) add_files( airport_defaults.h diff --git a/src/table/settings/CMakeLists.txt b/src/table/settings/CMakeLists.txt new file mode 100644 index 0000000000..b1503145fd --- /dev/null +++ b/src/table/settings/CMakeLists.txt @@ -0,0 +1,47 @@ +set(GENERATED_BINARY_DIR ${CMAKE_BINARY_DIR}/generated) +set(TABLE_BINARY_DIR ${GENERATED_BINARY_DIR}/table) + +set(TABLE_INI_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/company_settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/currency_settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/gameopt_settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/misc_settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/win32_settings.ini + ${CMAKE_CURRENT_SOURCE_DIR}/window_settings.ini +) + +if (HOST_BINARY_DIR) + include(${HOST_BINARY_DIR}/settingsgen.cmake) +endif() + +# Generate a command and target to create the settings table +add_custom_command_timestamp(OUTPUT ${TABLE_BINARY_DIR}/settings.h + COMMAND ${CMAKE_COMMAND} -E make_directory ${TABLE_BINARY_DIR} + COMMAND settingsgen + -o ${TABLE_BINARY_DIR}/settings.h + -b ${CMAKE_SOURCE_DIR}/src/table/settings.h.preamble + -a ${CMAKE_SOURCE_DIR}/src/table/settings.h.postamble + ${TABLE_INI_SOURCE_FILES} + DEPENDS settingsgen ${TABLE_INI_SOURCE_FILES} + ${CMAKE_SOURCE_DIR}/src/table/settings.h.preamble + ${CMAKE_SOURCE_DIR}/src/table/settings.h.postamble + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating table/settings.h" +) +add_custom_target_timestamp(table_settings + DEPENDS + ${TABLE_BINARY_DIR}/settings.h +) + +add_library(settings + INTERFACE +) +target_include_directories(settings + INTERFACE + ${GENERATED_BINARY_DIR} +) +add_dependencies(settings + table_settings +) +add_library(openttd::settings ALIAS settings) diff --git a/src/table/company_settings.ini b/src/table/settings/company_settings.ini similarity index 100% rename from src/table/company_settings.ini rename to src/table/settings/company_settings.ini diff --git a/src/table/currency_settings.ini b/src/table/settings/currency_settings.ini similarity index 100% rename from src/table/currency_settings.ini rename to src/table/settings/currency_settings.ini diff --git a/src/table/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini similarity index 100% rename from src/table/gameopt_settings.ini rename to src/table/settings/gameopt_settings.ini diff --git a/src/table/misc_settings.ini b/src/table/settings/misc_settings.ini similarity index 100% rename from src/table/misc_settings.ini rename to src/table/settings/misc_settings.ini diff --git a/src/table/settings.ini b/src/table/settings/settings.ini similarity index 100% rename from src/table/settings.ini rename to src/table/settings/settings.ini diff --git a/src/table/win32_settings.ini b/src/table/settings/win32_settings.ini similarity index 100% rename from src/table/win32_settings.ini rename to src/table/settings/win32_settings.ini diff --git a/src/table/window_settings.ini b/src/table/settings/window_settings.ini similarity index 100% rename from src/table/window_settings.ini rename to src/table/settings/window_settings.ini From b0f44d7eb1cfac13a5ede8b7154664f5fb455775 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 11:08:58 +0200 Subject: [PATCH 268/800] Doc: describe what each settings-file is about --- src/table/settings/company_settings.ini | 3 +++ src/table/settings/currency_settings.ini | 2 ++ src/table/settings/gameopt_settings.ini | 9 +++++++++ src/table/settings/misc_settings.ini | 3 +++ src/table/settings/settings.ini | 3 +++ src/table/settings/win32_settings.ini | 3 +++ src/table/settings/window_settings.ini | 3 +++ 7 files changed, 26 insertions(+) diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index bb104adebf..5767100651 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -4,6 +4,9 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; These are settings that are company-wide. Meaning that if 1 player in a +; company changes them, it changes for all players. + [pre-amble] static void UpdateServiceInterval(int32 new_value); static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value); diff --git a/src/table/settings/currency_settings.ini b/src/table/settings/currency_settings.ini index ce0213758d..a10583150e 100644 --- a/src/table/settings/currency_settings.ini +++ b/src/table/settings/currency_settings.ini @@ -4,6 +4,8 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; Settings for the in-game custom currency. + [pre-amble] static const SettingTable _currency_settings{ [post-amble] diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index b3b7ec6510..849c731b67 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -4,6 +4,15 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; Settings that used to be saved in the savegame under the OPTS chunk and +; under "gameopts" in the configuration file, but no longer are. Most of these +; are now moved to other places. +; +; For backwards compatability, this file dictates how both were saved. When +; a configuration files contains these entries, they are read once, and removed +; from the configuration file afterwards. Those that are still supported will +; be saved in their new place. + [pre-amble] static const uint GAME_DIFFICULTY_NUM = 18; static uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 1b633a65aa..bafdf2369b 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -4,6 +4,9 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; Various of settings that are stored in global variables. They are all +; located under "misc" in the configuration files. + [pre-amble] extern std::string _config_language_file; diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 3c22ec4c18..51481e1c73 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -4,6 +4,9 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; Settings as stored in the main configuration file ("openttd.cfg") and in the +; savegame PATS chunk (if not flagged not to). + [pre-amble] /* Begin - Callback Functions for the various settings */ static void v_PositionMainToolbar(int32 new_value); diff --git a/src/table/settings/win32_settings.ini b/src/table/settings/win32_settings.ini index 6b7d5276d8..7a3fb9a5c6 100644 --- a/src/table/settings/win32_settings.ini +++ b/src/table/settings/win32_settings.ini @@ -4,6 +4,9 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; Windows specific settings that are stored in global variables. They are all +; located under "win32" in the configuration files. + [pre-amble] /* win32_v.cpp only settings */ #if defined(_WIN32) && !defined(DEDICATED) diff --git a/src/table/settings/window_settings.ini b/src/table/settings/window_settings.ini index 560a197ab6..17596a4d58 100644 --- a/src/table/settings/window_settings.ini +++ b/src/table/settings/window_settings.ini @@ -4,6 +4,9 @@ ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . ; +; The windows configuration file ("windows.cfg") defines various of properties +; of all windows. + [pre-amble] static const SettingTable _window_settings{ From 665e3c1f45a6ae44d4a25534b1d67816f2d1962b Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 15:13:11 +0200 Subject: [PATCH 269/800] Fix: ScriptObject::DoCommand could modify "text" while defined "const" This could have unwanted side-effects, as it could change the source for ever and ever. --- src/script/api/script_object.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index 1f72eaa227..d61a76d9f8 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -309,10 +309,11 @@ ScriptObject::ActiveInstance::~ActiveInstance() return false; } - if (!StrEmpty(text) && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) { + std::string command_text = text == nullptr ? std::string{} : text; + if (!command_text.empty() && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) { /* The string must be valid, i.e. not contain special codes. Since some * can be made with GSText, make sure the control codes are removed. */ - ::StrMakeValidInPlace(text, SVS_NONE); + command_text = ::StrMakeValid(command_text, SVS_NONE); } /* Set the default callback to return a true/false result of the DoCommand */ @@ -328,7 +329,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() if (!estimate_only && _networking && !_generating_world) SetLastCommand(tile, p1, p2, cmd); /* Try to perform the command. */ - CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, text, false, estimate_only); + CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, command_text.c_str(), false, estimate_only); /* We failed; set the error and bail out */ if (res.Failed()) { From 7713c3e3ccdb8dea2924cc11a7108f227e374232 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 15:18:51 +0200 Subject: [PATCH 270/800] Codechange: move casting a "const char *" to "char *" to the caller It is not nice to have your definition say you won't change a value while in fact the whole reason for your existance is to change it. --- src/script/api/script_text.cpp | 2 +- src/script/script_info.cpp | 8 ++++---- src/script/squirrel.cpp | 2 +- src/string.cpp | 4 ++-- src/string_func.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index dd32d0d421..eeb7b22212 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -157,7 +157,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm) if (sq_gettype(vm, 2) == OT_STRING) { const SQChar *key_string; sq_getstring(vm, 2, &key_string); - StrMakeValidInPlace(key_string); + StrMakeValidInPlace(const_cast(key_string)); if (strncmp(key_string, "param_", 6) != 0 || strlen(key_string) > 8) return SQ_ERROR; k = atoi(key_string + 6); diff --git a/src/script/script_info.cpp b/src/script/script_info.cpp index 17b0e19697..d381ae9c2c 100644 --- a/src/script/script_info.cpp +++ b/src/script/script_info.cpp @@ -122,7 +122,7 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm) while (SQ_SUCCEEDED(sq_next(vm, -2))) { const SQChar *key; if (SQ_FAILED(sq_getstring(vm, -2, &key))) return SQ_ERROR; - StrMakeValidInPlace(key); + StrMakeValidInPlace(const_cast(key)); if (strcmp(key, "name") == 0) { const SQChar *sqvalue; @@ -141,7 +141,7 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm) const SQChar *sqdescription; if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR; config.description = stredup(sqdescription); - StrMakeValidInPlace(config.description); + StrMakeValidInPlace(const_cast(config.description)); items |= 0x002; } else if (strcmp(key, "min_value") == 0) { SQInteger res; @@ -226,7 +226,7 @@ SQInteger ScriptInfo::AddLabels(HSQUIRRELVM vm) { const SQChar *setting_name; if (SQ_FAILED(sq_getstring(vm, -2, &setting_name))) return SQ_ERROR; - StrMakeValidInPlace(setting_name); + StrMakeValidInPlace(const_cast(setting_name)); ScriptConfigItem *config = nullptr; for (auto &item : this->config_list) { @@ -253,7 +253,7 @@ SQInteger ScriptInfo::AddLabels(HSQUIRRELVM vm) /* Because squirrel doesn't support identifiers starting with a digit, * we skip the first character. */ int key = atoi(key_string + 1); - StrMakeValidInPlace(label); + StrMakeValidInPlace(const_cast(label)); /* !Contains() prevents stredup from leaking. */ if (!config->labels->Contains(key)) config->labels->Insert(key, stredup(label)); diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index 89d86180d2..aa698af83a 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -448,7 +448,7 @@ bool Squirrel::CallStringMethodStrdup(HSQOBJECT instance, const char *method_nam if (!this->CallMethod(instance, method_name, &ret, suspend)) return false; if (ret._type != OT_STRING) return false; *res = stredup(ObjectToString(&ret)); - StrMakeValidInPlace(*res); + StrMakeValidInPlace(const_cast(*res)); return true; } diff --git a/src/string.cpp b/src/string.cpp index 930d0dba12..1cf61e8b46 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -266,10 +266,10 @@ void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings s * otherwise use StrMakeValidInPlace(str, last, settings) variant. * @param str The string (of which you are sure ends with '\0') to validate. */ -void StrMakeValidInPlace(const char *str, StringValidationSettings settings) +void StrMakeValidInPlace(char *str, StringValidationSettings settings) { /* We know it is '\0' terminated. */ - StrMakeValidInPlace(const_cast(str), str + strlen(str), settings); + StrMakeValidInPlace(str, str + strlen(str), settings); } /** diff --git a/src/string_func.h b/src/string_func.h index be409072ef..0988f01b33 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -41,7 +41,7 @@ char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2); [[nodiscard]] std::string StrMakeValid(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); -void StrMakeValidInPlace(const char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2); void str_strip_colours(char *str); From 0125ba82e8b94461894a9628dea6552c0bbfa38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0efl?= Date: Mon, 17 May 2021 22:32:30 +0200 Subject: [PATCH 271/800] Fix: Do not send vehicles towards incomplete PF nodes YAPF could end up in a situation where it sets the best intermediate node to a node whose construction is never finalized (i.e. it is never added to the open list). The content of the node would be overwritten in the next round, potentially sending the vehicle to an unwanted location. --- src/pathfinder/yapf/yapf_base.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pathfinder/yapf/yapf_base.hpp b/src/pathfinder/yapf/yapf_base.hpp index 41c38ab34d..c548cfd97f 100644 --- a/src/pathfinder/yapf/yapf_base.hpp +++ b/src/pathfinder/yapf/yapf_base.hpp @@ -252,9 +252,9 @@ public: return; } - if (m_max_search_nodes > 0 && (m_pBestIntermediateNode == nullptr || (m_pBestIntermediateNode->GetCostEstimate() - m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost()))) { - m_pBestIntermediateNode = &n; - } + /* The new node can be set as the best intermediate node only once we're + * certain it will be finalized by being inserted into the open list. */ + bool set_intermediate = m_max_search_nodes > 0 && (m_pBestIntermediateNode == nullptr || (m_pBestIntermediateNode->GetCostEstimate() - m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost())); /* check new node against open list */ Node *openNode = m_nodes.FindOpenNode(n.GetKey()); @@ -267,6 +267,7 @@ public: *openNode = n; /* add the updated old node back to open list */ m_nodes.InsertOpenNode(*openNode); + if (set_intermediate) m_pBestIntermediateNode = openNode; } return; } @@ -292,6 +293,7 @@ public: /* the new node is really new * add it to the open list */ m_nodes.InsertOpenNode(n); + if (set_intermediate) m_pBestIntermediateNode = &n; } const VehicleType * GetVehicle() const From b4aedef848822649d3f7a045504eb2a9870b4b7e Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 16:02:53 +0200 Subject: [PATCH 272/800] Codechange: add std::string variant of Utf8StringLength --- src/string.cpp | 10 ++++++++++ src/string_func.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/string.cpp b/src/string.cpp index 1cf61e8b46..e9a619c400 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -395,6 +395,16 @@ size_t Utf8StringLength(const char *s) return len; } +/** + * Get the length of an UTF-8 encoded string in number of characters + * and thus not the number of bytes that the encoded string contains. + * @param s The string to get the length for. + * @return The length of the string in characters. + */ +size_t Utf8StringLength(const std::string &str) +{ + return Utf8StringLength(str.c_str()); +} /** * Convert a given ASCII string to lowercase. diff --git a/src/string_func.h b/src/string_func.h index 0988f01b33..2e258fbd20 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -166,6 +166,7 @@ static inline const char *Utf8PrevChar(const char *s) } size_t Utf8StringLength(const char *s); +size_t Utf8StringLength(const std::string &str); /** * Is the given character a lead surrogate code point? From 661728558e9ce2eb8cfdb6afd7182b85e1f19a67 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 16:07:42 +0200 Subject: [PATCH 273/800] Codechange: let IsUnique.* functions accept std::string --- src/company_cmd.cpp | 4 ++-- src/depot_cmd.cpp | 2 +- src/engine.cpp | 2 +- src/station_cmd.cpp | 2 +- src/town_cmd.cpp | 2 +- src/vehicle_cmd.cpp | 2 +- src/waypoint_cmd.cpp | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 85809544d4..5a2b9ba1db 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -1049,7 +1049,7 @@ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param name Name to search. * @return \c true if the name us unique (that is, not in use), else \c false. */ -static bool IsUniqueCompanyName(const char *name) +static bool IsUniqueCompanyName(const std::string &name) { for (const Company *c : Company::Iterate()) { if (!c->name.empty() && c->name == name) return false; @@ -1095,7 +1095,7 @@ CommandCost CmdRenameCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param name Name to search. * @return \c true if the name us unique (that is, not in use), else \c false. */ -static bool IsUniquePresidentName(const char *name) +static bool IsUniquePresidentName(const std::string &name) { for (const Company *c : Company::Iterate()) { if (!c->president_name.empty() && c->president_name == name) return false; diff --git a/src/depot_cmd.cpp b/src/depot_cmd.cpp index 9379afb82f..7296780727 100644 --- a/src/depot_cmd.cpp +++ b/src/depot_cmd.cpp @@ -26,7 +26,7 @@ * @param name The name to check. * @return True if there is no depot with the given name. */ -static bool IsUniqueDepotName(const char *name) +static bool IsUniqueDepotName(const std::string &name) { for (const Depot *d : Depot::Iterate()) { if (!d->name.empty() && d->name == name) return false; diff --git a/src/engine.cpp b/src/engine.cpp index 41cd9dba80..e60cd7f4d5 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1061,7 +1061,7 @@ void EnginesMonthlyLoop() * @param name New name of an engine. * @return \c false if the name is being used already, else \c true. */ -static bool IsUniqueEngineName(const char *name) +static bool IsUniqueEngineName(const std::string &name) { for (const Engine *e : Engine::Iterate()) { if (!e->name.empty() && e->name == name) return false; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index d9529da11d..887c347d48 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3915,7 +3915,7 @@ static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceT return amount; } -static bool IsUniqueStationName(const char *name) +static bool IsUniqueStationName(const std::string &name) { for (const Station *st : Station::Iterate()) { if (!st->name.empty() && st->name == name) return false; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 177b507e42..f70776c575 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1907,7 +1907,7 @@ static CommandCost TownCanBePlacedHere(TileIndex tile) * @param name name to check * @return is this name unique? */ -static bool IsUniqueTownName(const char *name) +static bool IsUniqueTownName(const std::string &name) { for (const Town *t : Town::Iterate()) { if (!t->name.empty() && t->name == name) return false; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 9da6b89cee..f55e66ace8 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -748,7 +748,7 @@ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 * @param name Name to test. * @return True ifffffff the name is unique. */ -static bool IsUniqueVehicleName(const char *name) +static bool IsUniqueVehicleName(const std::string &name) { for (const Vehicle *v : Vehicle::Iterate()) { if (!v->name.empty() && v->name == name) return false; diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index e8e9e69455..b41e80f974 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -395,7 +395,7 @@ CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags) * @param name The name to check. * @return True iff the name is unique. */ -static bool IsUniqueWaypointName(const char *name) +static bool IsUniqueWaypointName(const std::string &name) { for (const Waypoint *wp : Waypoint::Iterate()) { if (!wp->name.empty() && wp->name == name) return false; From 2e136285e1dfb4435c11769bf7cabb1ec2057e08 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 16:09:25 +0200 Subject: [PATCH 274/800] Codechange: move from C-string to std::string for DoCommand --- src/autoreplace_cmd.cpp | 4 ++-- src/build_vehicle_gui.cpp | 2 +- src/command.cpp | 10 +++++----- src/command_func.h | 8 ++++---- src/command_type.h | 2 +- src/company_cmd.cpp | 21 +++++++++----------- src/depot_cmd.cpp | 4 ++-- src/economy.cpp | 6 +++--- src/engine.cpp | 10 +++++----- src/goal.cpp | 30 ++++++++++++++-------------- src/group_cmd.cpp | 20 +++++++++---------- src/industry_cmd.cpp | 6 +++--- src/landscape.cpp | 4 ++-- src/misc_cmd.cpp | 10 +++++----- src/network/network_command.cpp | 4 ++-- src/news_gui.cpp | 6 +++--- src/object_cmd.cpp | 4 ++-- src/order_backup.cpp | 2 +- src/order_cmd.cpp | 14 ++++++------- src/rail_cmd.cpp | 24 +++++++++++----------- src/road_cmd.cpp | 10 +++++----- src/roadveh_cmd.cpp | 2 +- src/script/api/script_object.cpp | 2 +- src/settings.cpp | 4 ++-- src/signs_cmd.cpp | 10 +++++----- src/station_cmd.cpp | 20 +++++++++---------- src/story.cpp | 34 ++++++++++++++++---------------- src/subsidy.cpp | 2 +- src/terraform_cmd.cpp | 4 ++-- src/timetable_cmd.cpp | 8 ++++---- src/town_cmd.cpp | 26 ++++++++++++------------ src/train_cmd.cpp | 6 +++--- src/tree_cmd.cpp | 2 +- src/tunnelbridge_cmd.cpp | 4 ++-- src/vehicle_cmd.cpp | 28 +++++++++++++------------- src/viewport.cpp | 2 +- src/water_cmd.cpp | 6 +++--- src/waypoint_cmd.cpp | 8 ++++---- 38 files changed, 183 insertions(+), 186 deletions(-) diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index d5f031aa65..de5617a4d9 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -715,7 +715,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(p1); if (v == nullptr) return CMD_ERROR; @@ -808,7 +808,7 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Company *c = Company::GetIfValid(_current_company); if (c == nullptr) return CMD_ERROR; diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 8ac0494558..fb22e7380b 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1230,7 +1230,7 @@ struct BuildVehicleWindow : Window { if (!this->listview_mode) { /* Query for cost and refitted capacity */ - CommandCost ret = DoCommand(this->window_number, this->sel_engine | (cargo << 24), 0, DC_QUERY_COST, GetCmdBuildVeh(this->vehicle_type), nullptr); + CommandCost ret = DoCommand(this->window_number, this->sel_engine | (cargo << 24), 0, DC_QUERY_COST, GetCmdBuildVeh(this->vehicle_type)); if (ret.Succeeded()) { this->te.cost = ret.GetCost() - e->GetCost(); this->te.capacity = _returned_refit_capacity; diff --git a/src/command.cpp b/src/command.cpp index dd6ce1cbf5..39065aa49d 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -465,7 +465,7 @@ CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags) * @see CommandProc * @return the cost */ -CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text) +CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const std::string &text) { CommandCost res; @@ -558,7 +558,7 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd) * @param my_cmd indicator if the command is from a company or server (to display error messages for a user) * @return \c true if the command succeeded, else \c false. */ -bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd) +bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, bool my_cmd) { /* Cost estimation is generally only done when the * local user presses shift while doing something. @@ -631,7 +631,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac * @param estimate_only whether to give only the estimate or also execute the command * @return the command cost of this function. */ -CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only) +CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, bool my_cmd, bool estimate_only) { /* Prevent recursion; it gives a mess over the network */ assert(_docommand_recursive == 0); @@ -696,7 +696,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, if (!_networking || _generating_world || (cmd & CMD_NETWORK_COMMAND) != 0) { /* Log the failed command as well. Just to be able to be find * causes of desyncs due to bad command test implementations. */ - DEBUG(desync, 1, "cmdf: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, GetCommandName(cmd)); + DEBUG(desync, 1, "cmdf: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text.c_str(), GetCommandName(cmd)); } cur_company.Restore(); return_dcpi(res); @@ -716,7 +716,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, * reset the storages as we've not executed the command. */ return_dcpi(CommandCost()); } - DEBUG(desync, 1, "cmd: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, GetCommandName(cmd)); + DEBUG(desync, 1, "cmd: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text.c_str(), GetCommandName(cmd)); /* Actually try and execute the command. If no cost-type is given * use the construction one */ diff --git a/src/command_func.h b/src/command_func.h index aa14600591..426283bd3a 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -32,15 +32,15 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID); */ #define return_cmd_error(errcode) return CommandCost(errcode); -CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = nullptr); +CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const std::string &text = {}); CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags); -bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr, const char *text = nullptr, bool my_cmd = true); +bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr, const std::string &text = {}, bool my_cmd = true); bool DoCommandP(const CommandContainer *container, bool my_cmd = true); -CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only); +CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, bool my_cmd, bool estimate_only); -void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company); +void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, CompanyID company); extern Money _additional_cash_required; diff --git a/src/command_type.h b/src/command_type.h index 732932b7a8..a8e16e6d7b 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -443,7 +443,7 @@ enum CommandPauseLevel { * @param text Additional text * @return The CommandCost of the command, which can be succeeded or failed. */ -typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); +typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text); /** * Define a command with the flags which belongs to it. diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 5a2b9ba1db..f00db97c55 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -807,7 +807,7 @@ void CompanyAdminRemove(CompanyID company_id, CompanyRemoveReason reason) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0); CompanyID company_id = (CompanyID)GB(p1, 16, 8); @@ -932,7 +932,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetCompanyManagerFace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetCompanyManagerFace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyManagerFace cmf = (CompanyManagerFace)p2; @@ -956,7 +956,7 @@ CommandCost CmdSetCompanyManagerFace(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Colours colour = Extract(p2); LiveryScheme scheme = Extract(p1); @@ -1067,9 +1067,9 @@ static bool IsUniqueCompanyName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_COMPANY_NAME_CHARS) return CMD_ERROR; @@ -1113,9 +1113,9 @@ static bool IsUniquePresidentName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return CMD_ERROR; @@ -1131,10 +1131,7 @@ CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, u c->president_name = text; if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) { - char buf[80]; - - seprintf(buf, lastof(buf), "%s Transport", text); - DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY, buf); + DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY, text + " Transport"); } } @@ -1201,7 +1198,7 @@ uint32 CompanyInfrastructure::GetTramTotal() const * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdGiveMoney(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdGiveMoney(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!_settings_game.economy.give_money) return CMD_ERROR; diff --git a/src/depot_cmd.cpp b/src/depot_cmd.cpp index 7296780727..6f5ddda27e 100644 --- a/src/depot_cmd.cpp +++ b/src/depot_cmd.cpp @@ -44,7 +44,7 @@ static bool IsUniqueDepotName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Depot *d = Depot::GetIfValid(p1); if (d == nullptr) return CMD_ERROR; @@ -52,7 +52,7 @@ CommandCost CmdRenameDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 CommandCost ret = CheckTileOwnership(d->xy); if (ret.Failed()) return ret; - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_DEPOT_NAME_CHARS) return CMD_ERROR; diff --git a/src/economy.cpp b/src/economy.cpp index cde08f76a0..16a6072284 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -2017,7 +2017,7 @@ extern int GetAmountOwnedBy(const Company *c, Owner owner); * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost cost(EXPENSES_OTHER); CompanyID target_company = (CompanyID)p1; @@ -2069,7 +2069,7 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyID target_company = (CompanyID)p1; Company *c = Company::GetIfValid(target_company); @@ -2110,7 +2110,7 @@ CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyID target_company = (CompanyID)p1; Company *c = Company::GetIfValid(target_company); diff --git a/src/engine.cpp b/src/engine.cpp index e60cd7f4d5..5e002a3c20 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -882,7 +882,7 @@ void ClearEnginesHiddenFlagOfCompany(CompanyID cid) * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdSetVehicleVisibility(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetVehicleVisibility(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Engine *e = Engine::GetIfValid(GB(p2, 0, 31)); if (e == nullptr || _current_company >= MAX_COMPANIES) return CMD_ERROR; @@ -906,7 +906,7 @@ CommandCost CmdSetVehicleVisibility(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdWantEnginePreview(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdWantEnginePreview(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Engine *e = Engine::GetIfValid(p1); if (e == nullptr || !(e->flags & ENGINE_EXCLUSIVE_PREVIEW) || e->preview_company != _current_company) return CMD_ERROR; @@ -927,7 +927,7 @@ CommandCost CmdWantEnginePreview(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdEngineCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdEngineCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; EngineID engine_id = (EngineID)p1; @@ -1079,12 +1079,12 @@ static bool IsUniqueEngineName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameEngine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameEngine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Engine *e = Engine::GetIfValid(p1); if (e == nullptr) return CMD_ERROR; - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_ENGINE_NAME_CHARS) return CMD_ERROR; diff --git a/src/goal.cpp b/src/goal.cpp index 63fdd45895..fe36f286ed 100644 --- a/src/goal.cpp +++ b/src/goal.cpp @@ -43,7 +43,7 @@ INSTANTIATE_POOL_METHODS(Goal) * @param text Text of the goal. * @return the cost of this operation or an error */ -CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!Goal::CanAllocateItem()) return CMD_ERROR; @@ -51,7 +51,7 @@ CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 CompanyID company = (CompanyID)GB(p1, 8, 8); if (_current_company != OWNER_DEITY) return CMD_ERROR; - if (StrEmpty(text)) return CMD_ERROR; + if (text.empty()) return CMD_ERROR; if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR; switch (type) { @@ -90,7 +90,7 @@ CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 g->type = type; g->dst = p2; g->company = company; - g->text = stredup(text); + g->text = stredup(text.c_str()); g->progress = nullptr; g->completed = false; @@ -116,7 +116,7 @@ CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text unused. * @return the cost of this operation or an error */ -CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; if (!Goal::IsValidID(p1)) return CMD_ERROR; @@ -146,16 +146,16 @@ CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text Text of the goal. * @return the cost of this operation or an error */ -CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; if (!Goal::IsValidID(p1)) return CMD_ERROR; - if (StrEmpty(text)) return CMD_ERROR; + if (text.empty()) return CMD_ERROR; if (flags & DC_EXEC) { Goal *g = Goal::Get(p1); free(g->text); - g->text = stredup(text); + g->text = stredup(text.c_str()); if (g->company == INVALID_COMPANY) { InvalidateWindowClassesData(WC_GOALS_LIST); @@ -176,7 +176,7 @@ CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param text Progress text of the goal. * @return the cost of this operation or an error */ -CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; if (!Goal::IsValidID(p1)) return CMD_ERROR; @@ -184,10 +184,10 @@ CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (flags & DC_EXEC) { Goal *g = Goal::Get(p1); free(g->progress); - if (StrEmpty(text)) { + if (text.empty()) { g->progress = nullptr; } else { - g->progress = stredup(text); + g->progress = stredup(text.c_str()); } if (g->company == INVALID_COMPANY) { @@ -209,7 +209,7 @@ CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; if (!Goal::IsValidID(p1)) return CMD_ERROR; @@ -242,7 +242,7 @@ CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text Text of the question. * @return the cost of this operation or an error */ -CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { uint16 uniqueid = (uint16)GB(p1, 0, 16); CompanyID company = (CompanyID)GB(p1, 16, 8); @@ -254,7 +254,7 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint bool is_client = HasBit(p2, 31); if (_current_company != OWNER_DEITY) return CMD_ERROR; - if (StrEmpty(text)) return CMD_ERROR; + if (text.empty()) return CMD_ERROR; if (is_client) { /* Only check during pre-flight; the client might have left between * testing and executing. In that case it is fine to just ignore the @@ -274,7 +274,7 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost(); if (company != INVALID_COMPANY && company != _local_company) return CommandCost(); } - ShowGoalQuestion(uniqueid, type, button_mask, text); + ShowGoalQuestion(uniqueid, type, button_mask, text.c_str()); } return CommandCost(); @@ -289,7 +289,7 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * @param text Text of the question. * @return the cost of this operation or an error */ -CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (p1 > UINT16_MAX) return CMD_ERROR; if (p2 >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR; diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index bbef35ae23..bee5b03f29 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -300,7 +300,7 @@ Group::Group(Owner owner) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleType vt = Extract(p1); if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR; @@ -350,7 +350,7 @@ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Group *g = Group::GetIfValid(p1); if (g == nullptr || g->owner != _current_company) return CMD_ERROR; @@ -404,14 +404,14 @@ CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Group *g = Group::GetIfValid(GB(p1, 0, 16)); if (g == nullptr || g->owner != _current_company) return CMD_ERROR; if (!HasBit(p1, 16)) { /* Rename group */ - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR; @@ -508,7 +508,7 @@ static void AddVehicleToGroup(Vehicle *v, GroupID new_g) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(GB(p2, 0, 20)); GroupID new_g = p1; @@ -524,7 +524,7 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (new_g == NEW_GROUP) { /* Create new group. */ - CommandCost ret = CmdCreateGroup(0, flags, v->type, INVALID_GROUP, nullptr); + CommandCost ret = CmdCreateGroup(0, flags, v->type, INVALID_GROUP, {}); if (ret.Failed()) return ret; new_g = _new_group_id; @@ -565,7 +565,7 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleType type = Extract(p2); GroupID id_g = p1; @@ -602,7 +602,7 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { GroupID old_g = p1; Group *g = Group::GetIfValid(old_g); @@ -636,7 +636,7 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3 * - p2 bit 8 Set secondary instead of primary colour * - p2 bit 16-23 Colour. */ -CommandCost CmdSetGroupLivery(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetGroupLivery(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Group *g = Group::GetIfValid(p1); bool primary = !HasBit(p2, 8); @@ -697,7 +697,7 @@ static void SetGroupFlag(Group *g, GroupFlags flag, bool set, bool children) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetGroupFlag(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetGroupFlag(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Group *g = Group::GetIfValid(GB(p1, 0, 16)); if (g == nullptr || g->owner != _current_company) return CMD_ERROR; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 5bd2a3dc27..c6ae129c37 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1982,7 +1982,7 @@ static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, Do * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { IndustryType it = GB(p1, 0, 8); if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR; @@ -2074,7 +2074,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text - Additional industry text (only used with set text action) * @return Empty cost or an error. */ -CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; @@ -2112,7 +2112,7 @@ CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint case IndustryAction::SetText: { ind->text.clear(); - if (!StrEmpty(text)) ind->text = text; + if (!text.empty()) ind->text = text; InvalidateWindowData(WC_INDUSTRY_VIEW, ind->index); break; } diff --git a/src/landscape.cpp b/src/landscape.cpp index 6ea3af75b6..f13d1835f7 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -690,7 +690,7 @@ void ClearSnowLine() * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost cost(EXPENSES_CONSTRUCTION); bool do_clear = false; @@ -740,7 +740,7 @@ CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, ui * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (p1 >= MapSize()) return CMD_ERROR; diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index f9a102d1a1..e60717cf89 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -42,7 +42,7 @@ static_assert((LOAN_INTERVAL & 3) == 0); * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdIncreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdIncreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Company *c = Company::Get(_current_company); @@ -90,7 +90,7 @@ CommandCost CmdIncreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDecreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDecreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Company *c = Company::Get(_current_company); @@ -150,7 +150,7 @@ static void AskUnsafeUnpauseCallback(Window *w, bool confirmed) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdPause(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdPause(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { switch (p1) { case PM_PAUSED_SAVELOAD: @@ -202,7 +202,7 @@ CommandCost CmdPause(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { return CommandCost(EXPENSES_OTHER, -(int32)p1); } @@ -217,7 +217,7 @@ CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text unused * @return zero cost or an error */ -CommandCost CmdChangeBankBalance(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdChangeBankBalance(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { int32 delta = (int32)p1; CompanyID company = (CompanyID) GB(p2, 0, 8); diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index c9b21204a1..d41c89272e 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -133,7 +133,7 @@ static CommandQueue _local_execution_queue; * @param text The text to pass * @param company The company that wants to send the command */ -void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company) +void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, CompanyID company) { assert((cmd & CMD_FLAGS_MASK) == 0); @@ -145,7 +145,7 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman c.cmd = cmd; c.callback = callback; - strecpy(c.text, (text != nullptr) ? text : "", lastof(c.text)); + strecpy(c.text, text.c_str(), lastof(c.text)); if (_network_server) { /* If we are the server, we queue the command in our 'special' queue. diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 58d62dde81..8dc66c8467 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -840,7 +840,7 @@ void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceTy * @param text The text of the news message. * @return the cost of this operation or an error */ -CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; @@ -850,7 +850,7 @@ CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, ui if (company != INVALID_OWNER && !Company::IsValidID(company)) return CMD_ERROR; if (type >= NT_END) return CMD_ERROR; - if (StrEmpty(text)) return CMD_ERROR; + if (text.empty()) return CMD_ERROR; switch (reftype1) { case NR_NONE: break; @@ -884,7 +884,7 @@ CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, ui if (company != INVALID_OWNER && company != _local_company) return CommandCost(); if (flags & DC_EXEC) { - char *news = stredup(text); + char *news = stredup(text.c_str()); SetDParamStr(0, news); AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, p2, NR_NONE, UINT32_MAX, news); } diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index c11409d4ba..556e5af5c3 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -199,7 +199,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags); * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost cost(EXPENSES_PROPERTY); @@ -769,7 +769,7 @@ void GenerateObjects() default: uint8 view = RandomRange(spec->views); - if (CmdBuildObject(RandomTile(), DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, i, view, nullptr).Succeeded()) amount--; + if (CmdBuildObject(RandomTile(), DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, i, view, {}).Succeeded()) amount--; break; } } diff --git a/src/order_backup.cpp b/src/order_backup.cpp index 000df56540..f1263809b6 100644 --- a/src/order_backup.cpp +++ b/src/order_backup.cpp @@ -147,7 +147,7 @@ void OrderBackup::DoRestore(Vehicle *v) * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* No need to check anything. If the tile or user don't exist we just ignore it. */ if (flags & DC_EXEC) OrderBackup::ResetOfUser(tile == 0 ? INVALID_TILE : tile, p2); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 70fce860be..1023bc12a1 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -735,7 +735,7 @@ uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); VehicleOrderID sel_ord = GB(p1, 20, 8); @@ -1010,7 +1010,7 @@ static CommandCost DecloneOrder(Vehicle *dst, DoCommandFlag flags) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh_id = GB(p1, 0, 20); VehicleOrderID sel_ord = GB(p2, 0, 8); @@ -1115,7 +1115,7 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh_id = GB(p1, 0, 20); VehicleOrderID sel_ord = GB(p2, 0, 8); @@ -1156,7 +1156,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @note The target order will move one place down in the orderlist * if you move the order upwards else it'll move it one place down */ -CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); VehicleOrderID moving_order = GB(p2, 0, 16); @@ -1259,7 +1259,7 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleOrderID sel_ord = GB(p1, 20, 8); VehicleID veh = GB(p1, 0, 20); @@ -1528,7 +1528,7 @@ static bool CheckAircraftOrderDistance(const Aircraft *v_new, const Vehicle *v_o * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh_src = GB(p2, 0, 20); VehicleID veh_dst = GB(p1, 0, 20); @@ -1675,7 +1675,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); VehicleOrderID order_number = GB(p2, 16, 8); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 72ae0724c8..2526fe401c 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -434,7 +434,7 @@ static inline bool ValParamTrackOrientation(Track track) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { RailType railtype = Extract(p1); Track track = Extract(p2); @@ -622,7 +622,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); @@ -884,7 +884,7 @@ static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileInd * @param text unused * @return the cost of this operation or an error */ -static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost total_cost(EXPENSES_CONSTRUCTION); Track track = Extract(p2); @@ -945,7 +945,7 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint3 * @return the cost of this operation or an error * @see CmdRailTrackHelper */ -CommandCost CmdBuildRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { return CmdRailTrackHelper(tile, flags, p1, ClrBit(p2, 9), text); } @@ -964,7 +964,7 @@ CommandCost CmdBuildRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1 * @return the cost of this operation or an error * @see CmdRailTrackHelper */ -CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { return CmdRailTrackHelper(tile, flags, p1, SetBit(p2, 9), text); } @@ -981,7 +981,7 @@ CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p * @todo When checking for the tile slope, * distinguish between "Flat land required" and "land sloped in wrong direction" */ -CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* check railtype and valid direction for depot (0 through 3), 4 in total */ RailType railtype = Extract(p1); @@ -1055,7 +1055,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @return the cost of this operation or an error * @todo p2 should be replaced by two bits for "along" and "against" the track. */ -CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Track track = Extract(p1); bool ctrl_pressed = HasBit(p1, 3); // was the CTRL button pressed @@ -1281,7 +1281,7 @@ static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal * @param text unused * @return the cost of this operation or an error */ -static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost total_cost(EXPENSES_CONSTRUCTION); TileIndex start_tile = tile; @@ -1451,7 +1451,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin * @return the cost of this operation or an error * @see CmdSignalTrackHelper */ -CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { return CmdSignalTrackHelper(tile, flags, p1, p2, text); } @@ -1468,7 +1468,7 @@ CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Track track = Extract(p1); @@ -1543,7 +1543,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1 * @return the cost of this operation or an error * @see CmdSignalTrackHelper */ -CommandCost CmdRemoveSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5), text); // bit 5 is remove bit } @@ -1571,7 +1571,7 @@ static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { RailType totype = Extract(p2); TileIndex area_start = p1; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 82e944f6e6..70a014434e 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -610,7 +610,7 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyID company = _current_company; CommandCost cost(EXPENSES_CONSTRUCTION); @@ -981,7 +981,7 @@ static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { DisallowedRoadDirections drd = DRD_NORTHBOUND; @@ -1086,7 +1086,7 @@ CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost cost(EXPENSES_CONSTRUCTION); @@ -1163,7 +1163,7 @@ CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 * @todo When checking for the tile slope, * distinguish between "Flat land required" and "land sloped in wrong direction" */ -CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { DiagDirection dir = Extract(p1); @@ -2350,7 +2350,7 @@ static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, R * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { RoadType to_type = Extract(p2); diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index d44a37c872..86c2de78eb 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -366,7 +366,7 @@ bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destinati * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { RoadVehicle *v = RoadVehicle::GetIfValid(p1); if (v == nullptr) return CMD_ERROR; diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index d61a76d9f8..208e0d8e8c 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -329,7 +329,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() if (!estimate_only && _networking && !_generating_world) SetLastCommand(tile, p1, p2, cmd); /* Try to perform the command. */ - CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, command_text.c_str(), false, estimate_only); + CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, command_text, false, estimate_only); /* We failed; set the error and bail out */ if (res.Failed()) { diff --git a/src/settings.cpp b/src/settings.cpp index c36f0855f7..158c15fc3d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1720,7 +1720,7 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const * @return the cost of this operation or an error * @see _settings */ -CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { const SettingDesc *sd = GetSettingDescription(p1); @@ -1747,7 +1747,7 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { const SettingDesc *sd = GetCompanySettingDescription(p1); if (sd == nullptr) return CMD_ERROR; diff --git a/src/signs_cmd.cpp b/src/signs_cmd.cpp index 6ffb6cda1f..0dd821157e 100644 --- a/src/signs_cmd.cpp +++ b/src/signs_cmd.cpp @@ -36,13 +36,13 @@ SignID _new_sign_id; * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* Try to locate a new sign */ if (!Sign::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_SIGNS); /* Check sign text length if any */ - if (!StrEmpty(text) && Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR; + if (Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR; /* When we execute, really make the sign */ if (flags & DC_EXEC) { @@ -53,7 +53,7 @@ CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 si->x = x; si->y = y; si->z = GetSlopePixelZ(x, y); - if (!StrEmpty(text)) { + if (!text.empty()) { si->name = text; } si->UpdateVirtCoord(); @@ -75,14 +75,14 @@ CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Sign *si = Sign::GetIfValid(p1); if (si == nullptr) return CMD_ERROR; if (si->owner == OWNER_DEITY && _current_company != OWNER_DEITY && _game_mode != GM_EDITOR) return CMD_ERROR; /* Rename the signs when empty, otherwise remove it */ - if (!StrEmpty(text)) { + if (!text.empty()) { if (Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR; if (flags & DC_EXEC) { diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 887c347d48..3e40ba3fce 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1250,7 +1250,7 @@ static void RestoreTrainReservation(Train *v) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* Unpack parameters */ RailType rt = Extract(p1); @@ -1659,7 +1659,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { TileIndex end = p1 == 0 ? start : p1; if (start >= MapSize() || end >= MapSize()) return CMD_ERROR; @@ -1693,7 +1693,7 @@ CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint3 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { TileIndex end = p1 == 0 ? start : p1; if (start >= MapSize() || end >= MapSize()) return CMD_ERROR; @@ -1832,7 +1832,7 @@ static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID statio * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { bool type = HasBit(p2, 0); bool is_drive_through = HasBit(p2, 1); @@ -2082,7 +2082,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags) * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { uint8 width = (uint8)GB(p1, 0, 8); uint8 height = (uint8)GB(p1, 8, 8); @@ -2241,7 +2241,7 @@ void UpdateAirportsNoise() * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { StationID station_to_join = GB(p2, 16, 16); bool reuse = (station_to_join != NEW_STATION); @@ -2458,7 +2458,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!Station::IsValidID(p1)) return CMD_ERROR; Station *st = Station::Get(p1); @@ -2513,7 +2513,7 @@ static const byte _dock_h_chk[4] = { 1, 2, 1, 2 }; * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { StationID station_to_join = GB(p2, 16, 16); bool reuse = (station_to_join != NEW_STATION); @@ -3933,7 +3933,7 @@ static bool IsUniqueStationName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Station *st = Station::GetIfValid(p1); if (st == nullptr) return CMD_ERROR; @@ -3941,7 +3941,7 @@ CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uin CommandCost ret = CheckOwnership(st->owner); if (ret.Failed()) return ret; - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_STATION_NAME_CHARS) return CMD_ERROR; diff --git a/src/story.cpp b/src/story.cpp index e60c60a9fa..641ed7fbf5 100644 --- a/src/story.cpp +++ b/src/story.cpp @@ -204,7 +204,7 @@ bool StoryPageButtonData::ValidateVehicleType() const * @param text Title of the story page. Null is allowed in which case a generic page title is provided by OpenTTD. * @return the cost of this operation or an error */ -CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!StoryPage::CanAllocateItem()) return CMD_ERROR; @@ -223,10 +223,10 @@ CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, u s->sort_value = _story_page_next_sort_value; s->date = _date; s->company = company; - if (StrEmpty(text)) { + if (text.empty()) { s->title = nullptr; } else { - s->title = stredup(text); + s->title = stredup(text.c_str()); } InvalidateWindowClassesData(WC_STORY_BOOK, -1); @@ -250,7 +250,7 @@ CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text Text content in case it is a text or location page element * @return the cost of this operation or an error */ -CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!StoryPageElement::CanAllocateItem()) return CMD_ERROR; @@ -266,7 +266,7 @@ CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 if (_current_company != OWNER_DEITY) return CMD_ERROR; if (!StoryPage::IsValidID(page_id)) return CMD_ERROR; - if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR; + if (!VerifyElementContentParameters(page_id, type, tile, p2, text.c_str())) return CMD_ERROR; if (flags & DC_EXEC) { if (_story_page_element_pool.items == 0) { @@ -278,7 +278,7 @@ CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 pe->sort_value = _story_page_element_next_sort_value; pe->type = type; pe->page = page_id; - UpdateElement(*pe, tile, p2, text); + UpdateElement(*pe, tile, p2, text.c_str()); InvalidateWindowClassesData(WC_STORY_BOOK, page_id); @@ -300,7 +300,7 @@ CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 * @param text Text content in case it is a text or location page element * @return the cost of this operation or an error */ -CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16); @@ -311,10 +311,10 @@ CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 StoryPageID page_id = pe->page; StoryPageElementType type = pe->type; - if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR; + if (!VerifyElementContentParameters(page_id, type, tile, p2, text.c_str())) return CMD_ERROR; if (flags & DC_EXEC) { - UpdateElement(*pe, tile, p2, text); + UpdateElement(*pe, tile, p2, text.c_str()); InvalidateWindowClassesData(WC_STORY_BOOK, pe->page); } @@ -330,7 +330,7 @@ CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 * @param text title text of the story page. * @return the cost of this operation or an error */ -CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; StoryPageID page_id = (StoryPageID)GB(p1, 0, 16); @@ -339,10 +339,10 @@ CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, if (flags & DC_EXEC) { StoryPage *p = StoryPage::Get(page_id); free(p->title); - if (StrEmpty(text)) { + if (text.empty()) { p->title = nullptr; } else { - p->title = stredup(text); + p->title = stredup(text.c_str()); } InvalidateWindowClassesData(WC_STORY_BOOK, page_id); @@ -360,7 +360,7 @@ CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; StoryPageID page_id = (StoryPageID)GB(p1, 0, 16); @@ -387,7 +387,7 @@ CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; StoryPageID page_id = (StoryPageID)GB(p1, 0, 16); @@ -409,7 +409,7 @@ CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text unused. * @return the cost of this operation or an error */ -CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; StoryPageID page_id = (StoryPageID)p1; @@ -442,7 +442,7 @@ CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text unused. * @return the cost of this operation or an error */ -CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; StoryPageElementID page_element_id = (StoryPageElementID)p1; @@ -469,7 +469,7 @@ CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 * @param text Unused. * @return The cost of the operation, or an error. */ -CommandCost CmdStoryPageButton(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdStoryPageButton(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16); diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 4cf42eb5c9..14679e4dc0 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -240,7 +240,7 @@ void CreateSubsidy(CargoID cid, SourceType src_type, SourceID src, SourceType ds * @param text unused. * @return the cost of this operation or an error */ -CommandCost CmdCreateSubsidy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCreateSubsidy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (!Subsidy::CanAllocateItem()) return CMD_ERROR; diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index a23e02ab91..f23ba78c64 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -184,7 +184,7 @@ static CommandCost TerraformTileHeight(TerraformerState *ts, TileIndex tile, int * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { _terraform_err_tile = INVALID_TILE; @@ -341,7 +341,7 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (p1 >= MapSize()) return CMD_ERROR; diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 76f8d3d2fd..b8f3adc699 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -97,7 +97,7 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); @@ -191,7 +191,7 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); @@ -258,7 +258,7 @@ static bool VehicleTimetableSorter(Vehicle * const &a, Vehicle * const &b) * @param text Not used. * @return The error or cost of the operation. */ -CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { bool timetable_all = HasBit(p1, 20); Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20)); @@ -323,7 +323,7 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID veh = GB(p1, 0, 20); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index f70776c575..ee1ac343e4 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1928,7 +1928,7 @@ static bool IsUniqueTownName(const std::string &name) * @param text Custom name for the town. If empty, the town name parts will be used. * @return the cost of this operation or an error */ -CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { TownSize size = Extract(p1); bool city = HasBit(p1, 2); @@ -1953,7 +1953,7 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 return CMD_ERROR; } - if (StrEmpty(text)) { + if (text.empty()) { /* If supplied name is empty, townnameparts has to generate unique automatic name */ if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE); } else { @@ -2003,7 +2003,7 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 UpdateNearestTownForRoadTiles(false); old_generating_world.Restore(); - if (t != nullptr && !StrEmpty(text)) { + if (t != nullptr && !text.empty()) { t->name = text; t->UpdateVirtCoord(); } @@ -2743,12 +2743,12 @@ void ClearTownHouse(Town *t, TileIndex tile) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Town *t = Town::GetIfValid(p1); if (t == nullptr) return CMD_ERROR; - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_TOWN_NAME_CHARS) return CMD_ERROR; @@ -2796,7 +2796,7 @@ const CargoSpec *FindFirstCargoWithTownEffect(TownEffect effect) * @param text Unused. * @return Empty cost or an error. */ -CommandCost CmdTownCargoGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTownCargoGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; @@ -2829,7 +2829,7 @@ CommandCost CmdTownCargoGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text The new text (empty to remove the text). * @return Empty cost or an error. */ -CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; Town *t = Town::GetIfValid(p1); @@ -2837,7 +2837,7 @@ CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (flags & DC_EXEC) { t->text.clear(); - if (!StrEmpty(text)) t->text = text; + if (!text.empty()) t->text = text; InvalidateWindowData(WC_TOWN_VIEW, p1); } @@ -2853,7 +2853,7 @@ CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param text Unused. * @return Empty cost or an error. */ -CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; if (GB(p2, 16, 16) != 0) return CMD_ERROR; @@ -2893,7 +2893,7 @@ CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, ui * @param text Unused. * @return Empty cost or an error. */ -CommandCost CmdTownRating(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdTownRating(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; @@ -2922,7 +2922,7 @@ CommandCost CmdTownRating(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text Unused. * @return Empty cost or an error. */ -CommandCost CmdExpandTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdExpandTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY) return CMD_ERROR; Town *t = Town::GetIfValid(p1); @@ -2962,7 +2962,7 @@ CommandCost CmdExpandTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param text Unused. * @return Empty cost or an error. */ -CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_game_mode != GM_EDITOR && !_generating_world) return CMD_ERROR; Town *t = Town::GetIfValid(p1); @@ -3351,7 +3351,7 @@ uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDoTownAction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDoTownAction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Town *t = Town::GetIfValid(p1); if (t == nullptr || p2 >= lengthof(_town_action_proc)) return CMD_ERROR; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 0a3a5db9ef..77ffa01614 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1160,7 +1160,7 @@ static void NormaliseTrainHead(Train *head) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleID s = GB(p1, 0, 20); VehicleID d = GB(p2, 0, 20); @@ -1898,7 +1898,7 @@ void ReverseTrainDirection(Train *v) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Train *v = Train::GetIfValid(p1); if (v == nullptr) return CMD_ERROR; @@ -1971,7 +1971,7 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Train *t = Train::GetIfValid(p1); if (t == nullptr) return CMD_ERROR; diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index baf149f5f1..0ee91b4cd9 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -378,7 +378,7 @@ void GenerateTrees() * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { StringID msg = INVALID_STRING_ID; CommandCost cost(EXPENSES_OTHER); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index dd8d731ee9..05ad1025e8 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -257,7 +257,7 @@ static Money TunnelBridgeClearCost(TileIndex tile, Price base_price) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyID company = _current_company; @@ -630,7 +630,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CompanyID company = _current_company; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index f55e66ace8..84d339b279 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -72,7 +72,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin CommandCost CmdBuildShip (TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v); CommandCost CmdBuildAircraft (TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v); -CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); +CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text); /** * Build a vehicle. @@ -86,7 +86,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* Elementary check for valid location. */ if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; @@ -154,7 +154,7 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (refitting) { /* Refit only one vehicle. If we purchased an engine, it may have gained free wagons. */ - value.AddCost(CmdRefitVehicle(tile, flags, v->index, cargo | (1 << 16), nullptr)); + value.AddCost(CmdRefitVehicle(tile, flags, v->index, cargo | (1 << 16), {})); } else { /* Fill in non-refitted capacities */ _returned_refit_capacity = e->GetDisplayDefaultCapacity(&_returned_mail_refit_capacity); @@ -206,7 +206,7 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *v, uint16 data, uint3 * @param text unused. * @return the cost of this operation or an error. */ -CommandCost CmdSellVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSellVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20)); if (v == nullptr) return CMD_ERROR; @@ -468,7 +468,7 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(p1); if (v == nullptr) return CMD_ERROR; @@ -556,7 +556,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* Disable the effect of p2 bit 0, when DC_AUTOREPLACE is not set */ if ((flags & DC_AUTOREPLACE) == 0) SetBit(p2, 0); @@ -640,7 +640,7 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleList list; bool do_start = HasBit(p1, 0); @@ -680,7 +680,7 @@ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleList list; @@ -718,7 +718,7 @@ CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); @@ -822,7 +822,7 @@ static void CloneVehicleName(const Vehicle *src, Vehicle *dst) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { CommandCost total_cost(EXPENSES_NEW_VEHICLES); @@ -1044,7 +1044,7 @@ static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, bool service, con * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (p1 & DEPOT_MASS_SEND) { /* Mass goto depot requested */ @@ -1069,7 +1069,7 @@ CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1 * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(p1); if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; @@ -1077,7 +1077,7 @@ CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uin CommandCost ret = CheckOwnership(v->owner); if (ret.Failed()) return ret; - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_VEHICLE_NAME_CHARS) return CMD_ERROR; @@ -1110,7 +1110,7 @@ CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdChangeServiceInt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdChangeServiceInt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Vehicle *v = Vehicle::GetIfValid(p1); if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; diff --git a/src/viewport.cpp b/src/viewport.cpp index 7217cbc451..d3488317e3 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -3472,7 +3472,7 @@ void InitializeSpriteSorter() * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdScrollViewport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdScrollViewport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; ViewportScrollTarget target = (ViewportScrollTarget)p1; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index dfbed60127..dbb4999a7c 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -98,7 +98,7 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Axis axis = Extract(p1); @@ -417,7 +417,7 @@ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); @@ -443,7 +443,7 @@ bool RiverModifyDesertZone(TileIndex tile, void *) * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { WaterClass wc = Extract(p2); if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR; diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index b41e80f974..632d697429 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -174,7 +174,7 @@ extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { /* Unpack parameters */ Axis axis = Extract(p1); @@ -302,7 +302,7 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (tile == 0 || !HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE); if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); @@ -413,7 +413,7 @@ static bool IsUniqueWaypointName(const std::string &name) * @param text the new name or an empty string when resetting to the default * @return the cost of this operation or an error */ -CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { Waypoint *wp = Waypoint::GetIfValid(p1); if (wp == nullptr) return CMD_ERROR; @@ -423,7 +423,7 @@ CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, ui if (ret.Failed()) return ret; } - bool reset = StrEmpty(text); + bool reset = text.empty(); if (!reset) { if (Utf8StringLength(text) >= MAX_LENGTH_STATION_NAME_CHARS) return CMD_ERROR; From ef991b1772f5f8b4874f76ea715a9a95811ad979 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 16:16:51 +0200 Subject: [PATCH 275/800] Codechange: [Network] Use std::string in CommandPacket --- src/command_type.h | 2 +- src/network/network.cpp | 11 ++++++----- src/network/network_client.cpp | 2 +- src/network/network_command.cpp | 13 ++++++------- src/network/network_gui.cpp | 2 +- src/network/network_server.cpp | 2 +- src/settings.cpp | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/command_type.h b/src/command_type.h index a8e16e6d7b..61154ea04b 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -482,7 +482,7 @@ struct CommandContainer { uint32 p2; ///< parameter p2. uint32 cmd; ///< command being executed. CommandCallback *callback; ///< any callback function executed upon successful completion of the command. - char text[32 * MAX_CHAR_LENGTH]; ///< possible text sent for name changes etc, in bytes including '\0'. + std::string text; ///< possible text sent for name changes etc. }; #endif /* COMMAND_TYPE_H */ diff --git a/src/network/network.cpp b/src/network/network.cpp index 94a5539f0e..2bc3589449 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1071,7 +1071,7 @@ void NetworkGameLoop() if (_date == next_date && _date_fract == next_date_fract) { if (cp != nullptr) { NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text, cp->company); - DEBUG(desync, 0, "Injecting: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text, GetCommandName(cp->cmd)); + DEBUG(desync, 0, "Injecting: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text.c_str(), GetCommandName(cp->cmd)); free(cp); cp = nullptr; } @@ -1107,10 +1107,11 @@ void NetworkGameLoop() ) { p += 5; if (*p == ' ') p++; - cp = CallocT(1); + cp = new CommandPacket(); int company; - static_assert(sizeof(cp->text) == 128); - int ret = sscanf(p, "%x; %x; %x; %x; %x; %x; %x; \"%127[^\"]\"", &next_date, &next_date_fract, &company, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, cp->text); + char buffer[128]; + int ret = sscanf(p, "%x; %x; %x; %x; %x; %x; %x; \"%127[^\"]\"", &next_date, &next_date_fract, &company, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, buffer); + cp->text = buffer; /* There are 8 pieces of data to read, however the last is a * string that might or might not exist. Ignore it if that * string misses because in 99% of the time it's not used. */ @@ -1121,7 +1122,7 @@ void NetworkGameLoop() int ret = sscanf(p + 6, "%x; %x", &next_date, &next_date_fract); assert(ret == 2); DEBUG(desync, 0, "Injecting pause for join at %08x:%02x; please join when paused", next_date, next_date_fract); - cp = CallocT(1); + cp = new CommandPacket(); cp->company = COMPANY_SPECTATOR; cp->cmd = CMD_PAUSE; cp->p1 = PM_PAUSED_NORMAL; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1a729e34fc..44359941a8 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -944,7 +944,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet * the server will give us a client-id and let us in */ _network_join_status = NETWORK_JOIN_STATUS_REGISTERING; ShowJoinStatusWindow(); - NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company); + NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, {}, _local_company); } } else { /* take control over an existing company */ diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index d41c89272e..d43e971ff9 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -56,7 +56,7 @@ static CommandCallback * const _callback_table[] = { */ void CommandQueue::Append(CommandPacket *p) { - CommandPacket *add = MallocT(1); + CommandPacket *add = new CommandPacket(); *add = *p; add->next = nullptr; if (this->first == nullptr) { @@ -113,7 +113,7 @@ void CommandQueue::Free() { CommandPacket *cp; while ((cp = this->Pop()) != nullptr) { - free(cp); + delete cp; } assert(this->count == 0); } @@ -144,8 +144,7 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman c.p2 = p2; c.cmd = cmd; c.callback = callback; - - strecpy(c.text, text.c_str(), lastof(c.text)); + c.text = text; if (_network_server) { /* If we are the server, we queue the command in our 'special' queue. @@ -212,7 +211,7 @@ void NetworkExecuteLocalCommandQueue() DoCommandP(cp, cp->my_cmd); queue.Pop(); - free(cp); + delete cp; } /* Local company may have changed, so we should not restore the old value */ @@ -271,7 +270,7 @@ static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owne while (--to_go >= 0 && (cp = queue->Pop(true)) != nullptr) { DistributeCommandPacket(*cp, owner); NetworkAdminCmdLogging(owner, cp); - free(cp); + delete cp; } } @@ -304,7 +303,7 @@ const char *NetworkGameSocketHandler::ReceiveCommand(Packet *p, CommandPacket *c cp->p1 = p->Recv_uint32(); cp->p2 = p->Recv_uint32(); cp->tile = p->Recv_uint32(); - p->Recv_string(cp->text, lengthof(cp->text), (!_network_server && GetCommandFlags(cp->cmd) & CMD_STR_CTRL) != 0 ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK); + cp->text = p->Recv_string(NETWORK_COMPANY_NAME_LENGTH, (!_network_server && GetCommandFlags(cp->cmd) & CMD_STR_CTRL) != 0 ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK); byte callback = p->Recv_uint8(); if (callback >= lengthof(_callback_table)) return "invalid callback"; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index d06ff27be4..322e128cfb 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1825,7 +1825,7 @@ private: if (_network_server) { DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL); } else { - NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company); + NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, {}, _local_company); } } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 3a9128427e..fe585c03ce 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -2182,7 +2182,7 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */ ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); - NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name.c_str(), c->index); + NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index); } /* Announce new company on network. */ diff --git a/src/settings.cpp b/src/settings.cpp index 158c15fc3d..11dff7143a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1864,7 +1864,7 @@ void SyncCompanySettings() for (auto &sd : _company_settings) { uint32 old_value = (uint32)sd->AsIntSetting()->Read(new_object); uint32 new_value = (uint32)sd->AsIntSetting()->Read(old_object); - if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company); + if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, {}, _local_company); i++; } } From 994bf19aef3dde6c9482434bdc51688f76a937ea Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 15 May 2021 23:12:25 +0200 Subject: [PATCH 276/800] Fix f6d5c01: Delay deletion when closing windows --- src/ai/ai_gui.cpp | 17 +++--- src/airport_gui.cpp | 6 +- src/bootstrap_gui.cpp | 13 ++-- src/bridge_gui.cpp | 4 +- src/company_gui.cpp | 4 +- src/console_gui.cpp | 3 +- src/date_gui.cpp | 2 +- src/depot_gui.cpp | 3 +- src/dock_gui.cpp | 6 +- src/engine_gui.cpp | 4 +- src/error_gui.cpp | 35 ++++++----- src/fios_gui.cpp | 11 ++-- src/goal_gui.cpp | 6 +- src/highscore_gui.cpp | 11 ++-- src/misc_gui.cpp | 30 ++++----- src/network/network_chat_gui.cpp | 7 ++- src/network/network_content_gui.cpp | 18 +++--- src/network/network_content_gui.h | 6 +- src/network/network_gui.cpp | 2 +- src/newgrf_gui.cpp | 13 ++-- src/news_gui.cpp | 4 +- src/osk_gui.cpp | 6 +- src/rail_gui.cpp | 9 ++- src/road_gui.cpp | 6 +- src/settings_gui.cpp | 3 +- src/signs_gui.cpp | 4 +- src/smallmap_gui.cpp | 5 ++ src/smallmap_gui.h | 1 + src/station_gui.cpp | 8 ++- src/town_gui.cpp | 3 +- src/vehicle_gui.cpp | 7 ++- src/waypoint_gui.cpp | 3 +- src/widgets/dropdown.cpp | 30 ++++----- src/window.cpp | 95 ++++++++++++++++++----------- src/window_gui.h | 12 +++- 35 files changed, 231 insertions(+), 166 deletions(-) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index 49e37621e5..1817148f44 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -196,7 +196,7 @@ struct AIListWindow : public Window { this->SetDirty(); if (click_count > 1) { this->ChangeAI(); - delete this; + this->Close(); } } break; @@ -204,12 +204,12 @@ struct AIListWindow : public Window { case WID_AIL_ACCEPT: { this->ChangeAI(); - delete this; + this->Close(); break; } case WID_AIL_CANCEL: - delete this; + this->Close(); break; } } @@ -227,7 +227,7 @@ struct AIListWindow : public Window { void OnInvalidateData(int data = 0, bool gui_scope = true) override { if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) { - delete this; + this->Close(); return; } @@ -518,7 +518,7 @@ struct AISettingsWindow : public Window { } case WID_AIS_ACCEPT: - delete this; + this->Close(); break; case WID_AIS_RESET: @@ -655,7 +655,7 @@ struct ScriptTextfileWindow : public TextfileWindow { { const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot); if (textfile == nullptr) { - delete this; + this->Close(); } else { this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); } @@ -744,10 +744,11 @@ struct AIConfigWindow : public Window { this->OnInvalidateData(0); } - ~AIConfigWindow() + void Close() override { DeleteWindowByClass(WC_AI_LIST); DeleteWindowByClass(WC_AI_SETTINGS); + this->Window::Close(); } void SetStringParameters(int widget) const override @@ -929,7 +930,7 @@ struct AIConfigWindow : public Window { break; case WID_AIC_CLOSE: - delete this; + this->Close(); break; case WID_AIC_CONTENT_DOWNLOAD: diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 7eb8c6dce7..1941a86025 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -76,10 +76,11 @@ struct BuildAirToolbarWindow : Window { this->last_user_action = WIDGET_LIST_END; } - ~BuildAirToolbarWindow() + void Close() override { if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -276,9 +277,10 @@ public: if (selectFirstAirport) this->SelectFirstAvailableAirport(true); } - virtual ~BuildAirportWindow() + void Close() override { DeleteWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void SetStringParameters(int widget) const override diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index 7495e08ba5..d8e4aedec9 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -91,9 +91,10 @@ public: this->InitNested(1); } - ~BootstrapErrorWindow() + void Close() override { _exit_game = true; + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -144,12 +145,13 @@ public: { } - ~BootstrapContentDownloadStatusWindow() + void Close() override { /* If we are not set to exit the game, it means the bootstrap failed. */ if (!_exit_game) { new BootstrapErrorWindow(); } + this->BaseNetworkContentDownloadStatusWindow::Close(); } void OnDownloadComplete(ContentID cid) override @@ -162,7 +164,7 @@ public: /* _exit_game is used to break out of the outer video driver's MainLoop. */ _exit_game = true; - delete this; + this->Close(); } }; @@ -201,9 +203,10 @@ public: } /** Stop listening to the content client events. */ - ~BootstrapAskForDownloadWindow() + void Close() override { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -264,7 +267,7 @@ public: /* And once the meta data is received, start downloading it. */ _network_content_client.Select(ci->id); new BootstrapContentDownloadStatusWindow(); - delete this; + this->Close(); } }; diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 07858e7afb..4a9a56b790 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -249,7 +249,7 @@ public: if (i < 9 && i < this->bridges->size()) { /* Build the requested bridge */ this->BuildBridge(i); - delete this; + this->Close(); return ES_HANDLED; } return ES_NOT_HANDLED; @@ -263,7 +263,7 @@ public: uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BBS_BRIDGE_LIST); if (i < this->bridges->size()) { this->BuildBridge(i); - delete this; + this->Close(); } break; } diff --git a/src/company_gui.cpp b/src/company_gui.cpp index a23bda7bd7..fe8c2326c2 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1586,7 +1586,7 @@ public: /* Cancel button */ case WID_SCMF_CANCEL: - delete this; + this->Close(); break; /* Load button */ @@ -2767,7 +2767,7 @@ struct BuyCompanyWindow : Window { { switch (widget) { case WID_BC_NO: - delete this; + this->Close(); break; case WID_BC_YES: diff --git a/src/console_gui.cpp b/src/console_gui.cpp index 7310738667..e5d80fcba1 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -185,10 +185,11 @@ struct IConsoleWindow : Window ResizeWindow(this, _screen.width, _screen.height / 3); } - ~IConsoleWindow() + void Close() override { _iconsole_mode = ICONSOLE_CLOSED; VideoDriver::GetInstance()->EditBoxLostFocus(); + this->Window::Close(); } /** diff --git a/src/date_gui.cpp b/src/date_gui.cpp index 8feb3f8adf..77b9a7c4ca 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -147,7 +147,7 @@ struct SetDateWindow : Window { case WID_SD_SET_DATE: if (this->callback != nullptr) this->callback(this, ConvertYMDToDate(this->date.year, this->date.month, this->date.day)); - delete this; + this->Close(); break; } } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 0756eae2ca..80774e900e 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -291,11 +291,12 @@ struct DepotWindow : Window { OrderBackup::Reset(); } - ~DepotWindow() + void Close() override { DeleteWindowById(WC_BUILD_VEHICLE, this->window_number); DeleteWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false); OrderBackup::Reset(this->window_number); + this->Window::Close(); } /** diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 850b9d3f30..483a71d6b6 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -101,10 +101,11 @@ struct BuildDocksToolbarWindow : Window { if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); } - ~BuildDocksToolbarWindow() + void Close() override { if (_game_mode == GM_NORMAL && this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -416,9 +417,10 @@ public: this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); } - virtual ~BuildDocksStationWindow() + void Close() override { DeleteWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void OnPaint() override diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 77ce954130..bc0143be17 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -128,7 +128,7 @@ struct EnginePreviewWindow : Window { DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW); FALLTHROUGH; case WID_EP_NO: - if (!_shift_pressed) delete this; + if (!_shift_pressed) this->Close(); break; } } @@ -138,7 +138,7 @@ struct EnginePreviewWindow : Window { if (!gui_scope) return; EngineID engine = this->window_number; - if (Engine::Get(engine)->preview_company != _local_company) delete this; + if (Engine::Get(engine)->preview_company != _local_company) this->Close(); } }; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 7b7413228c..70b403a683 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -250,7 +250,7 @@ public: void OnInvalidateData(int data = 0, bool gui_scope = true) override { /* If company gets shut down, while displaying an error about it, remove the error message. */ - if (this->face != INVALID_COMPANY && !Company::IsValidID(this->face)) delete this; + if (this->face != INVALID_COMPANY && !Company::IsValidID(this->face)) this->Close(); } void SetStringParameters(int widget) const override @@ -298,20 +298,21 @@ public: void OnMouseLoop() override { /* Disallow closing the window too easily, if timeout is disabled */ - if (_right_button_down && !this->display_timer.HasElapsed()) delete this; + if (_right_button_down && !this->display_timer.HasElapsed()) this->Close(); } void OnRealtimeTick(uint delta_ms) override { if (this->display_timer.CountElapsed(delta_ms) == 0) return; - delete this; + this->Close(); } - ~ErrmsgWindow() + void Close() override { SetRedErrorSquare(INVALID_TILE); if (_window_system_initialized) ShowFirstError(); + this->Window::Close(); } /** @@ -354,7 +355,7 @@ void UnshowCriticalError() if (_window_system_initialized && w != nullptr) { if (w->IsCritical()) _error_list.push_front(*w); _window_system_initialized = false; - delete w; + w->Close(); } } @@ -403,18 +404,20 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel data.CopyOutDParams(); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); - if (w != nullptr && w->IsCritical()) { - /* A critical error is currently shown. */ - if (wl == WL_CRITICAL) { - /* Push another critical error in the queue of errors, - * but do not put other errors in the queue. */ - _error_list.push_back(data); + if (w != nullptr) { + if (w->IsCritical()) { + /* A critical error is currently shown. */ + if (wl == WL_CRITICAL) { + /* Push another critical error in the queue of errors, + * but do not put other errors in the queue. */ + _error_list.push_back(data); + } + return; } - } else { - /* Nothing or a non-critical error was shown. */ - delete w; - new ErrmsgWindow(data); + /* A non-critical error was shown. */ + w->Close(); } + new ErrmsgWindow(data); } @@ -425,7 +428,7 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel bool HideActiveErrorMessage() { ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); if (w == nullptr) return false; - delete w; + w->Close(); return true; } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 40a082d64f..c04092f6bd 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -398,12 +398,13 @@ public: } } - virtual ~SaveLoadWindow() + void Close() override { /* pause is only used in single-player, non-editor mode, non menu mode */ if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) { DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); } + this->Window::Close(); } void DrawWidget(const Rect &r, int widget) const override @@ -617,12 +618,12 @@ public: _file_to_saveload.SetTitle(this->selected->title); if (this->abstract_filetype == FT_HEIGHTMAP) { - delete this; + this->Close(); ShowHeightmapLoad(); } else if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) { _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME; ClearErrorMessages(); - delete this; + this->Close(); } break; } @@ -688,7 +689,7 @@ public: _file_to_saveload.SetName(name); _file_to_saveload.SetTitle(file->title); - delete this; + this->Close(); ShowHeightmapLoad(); } } @@ -749,7 +750,7 @@ public: EventState OnKeyPress(WChar key, uint16 keycode) override { if (keycode == WKC_ESC) { - delete this; + this->Close(); return ES_HANDLED; } diff --git a/src/goal_gui.cpp b/src/goal_gui.cpp index 9fdca309bc..922f5f5d5b 100644 --- a/src/goal_gui.cpp +++ b/src/goal_gui.cpp @@ -384,17 +384,17 @@ struct GoalQuestionWindow : public Window { switch (widget) { case WID_GQ_BUTTON_1: DoCommandP(0, this->window_number, this->button[0], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; case WID_GQ_BUTTON_2: DoCommandP(0, this->window_number, this->button[1], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; case WID_GQ_BUTTON_3: DoCommandP(0, this->window_number, this->button[2], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; } } diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index 356235fa03..e36935c1e8 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -64,7 +64,7 @@ struct EndGameHighScoreBaseWindow : Window { void OnClick(Point pt, int widget, int click_count) override { - delete this; + this->Close(); } EventState OnKeyPress(WChar key, uint16 keycode) override @@ -79,7 +79,7 @@ struct EndGameHighScoreBaseWindow : Window { case WKC_RETURN: case WKC_ESC: case WKC_SPACE: - delete this; + this->Close(); return ES_HANDLED; default: @@ -122,10 +122,11 @@ struct EndGameWindow : EndGameHighScoreBaseWindow { MarkWholeScreenDirty(); } - ~EndGameWindow() + void Close() override { if (!_networking) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause ShowHighscoreTable(this->window_number, this->rank); + this->EndGameHighScoreBaseWindow::Close(); } void OnPaint() override @@ -169,11 +170,13 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow { this->rank = ranking; } - ~HighScoreWindow() + void Close() override { if (_game_mode != GM_MENU) ShowVitalWindows(); if (!_networking && !this->game_paused_by_player) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause + + this->EndGameHighScoreBaseWindow::Close(); } void OnPaint() override diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index f7061d328d..59b0282d54 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -759,20 +759,20 @@ struct TooltipsWindow : public Window { /* Always close tooltips when the cursor is not in our window. */ if (!_cursor.in_window) { - delete this; + this->Close(); return; } /* We can show tooltips while dragging tools. These are shown as long as * we are dragging the tool. Normal tooltips work with hover or rmb. */ switch (this->close_cond) { - case TCC_RIGHT_CLICK: if (!_right_button_down) delete this; break; - case TCC_HOVER: if (!_mouse_hovering) delete this; break; + case TCC_RIGHT_CLICK: if (!_right_button_down) this->Close(); break; + case TCC_HOVER: if (!_mouse_hovering) this->Close(); break; case TCC_NONE: break; case TCC_EXIT_VIEWPORT: { Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); - if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) delete this; + if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) this->Close(); break; } } @@ -1090,18 +1090,19 @@ struct QueryStringWindow : public Window FALLTHROUGH; case WID_QS_CANCEL: - delete this; + this->Close(); break; } } - ~QueryStringWindow() + void Close() override { if (!this->editbox.handled && this->parent != nullptr) { Window *parent = this->parent; - this->parent = nullptr; // so parent doesn't try to delete us again + this->parent = nullptr; // so parent doesn't try to close us again parent->OnQueryTextFinished(nullptr); } + this->Window::Close(); } }; @@ -1167,9 +1168,10 @@ struct QueryWindow : public Window { this->InitNested(WN_CONFIRM_POPUP_QUERY); } - ~QueryWindow() + void Close() override { if (this->proc != nullptr) this->proc(this->parent, false); + this->Window::Close(); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -1222,7 +1224,7 @@ struct QueryWindow : public Window { Window *parent = this->parent; /* Prevent the destructor calling the callback function */ this->proc = nullptr; - delete this; + this->Close(); if (proc != nullptr) { proc(parent, true); proc = nullptr; @@ -1230,7 +1232,7 @@ struct QueryWindow : public Window { break; } case WID_Q_NO: - delete this; + this->Close(); break; } } @@ -1248,7 +1250,7 @@ struct QueryWindow : public Window { FALLTHROUGH; case WKC_ESC: - delete this; + this->Close(); return ES_HANDLED; } return ES_NOT_HANDLED; @@ -1289,13 +1291,13 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback { if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0); - for (const Window *w : Window::Iterate()) { + for (Window *w : Window::Iterate()) { if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue; - const QueryWindow *qw = (const QueryWindow *)w; + QueryWindow *qw = dynamic_cast(w); if (qw->parent != parent || qw->proc != callback) continue; - delete qw; + qw->Close(); break; } diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 068a5314ee..53546aa873 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -307,9 +307,10 @@ struct NetworkChatWindow : public Window { PositionNetworkChatWindow(this); } - ~NetworkChatWindow() + void Close() override { InvalidateWindowData(WC_NEWS_WINDOW, 0, 0); + this->Window::Close(); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -470,7 +471,7 @@ struct NetworkChatWindow : public Window { FALLTHROUGH; case WID_NC_CLOSE: /* Cancel */ - delete this; + this->Close(); break; } } @@ -497,7 +498,7 @@ struct NetworkChatWindow : public Window { */ void OnInvalidateData(int data = 0, bool gui_scope = true) override { - if (data == this->dest) delete this; + if (data == this->dest) this->Close(); } }; diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index dd9590e99c..8c75cb572a 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -109,9 +109,10 @@ BaseNetworkContentDownloadStatusWindow::BaseNetworkContentDownloadStatusWindow(W this->InitNested(WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); } -BaseNetworkContentDownloadStatusWindow::~BaseNetworkContentDownloadStatusWindow() +void BaseNetworkContentDownloadStatusWindow::Close() { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widget) const @@ -171,8 +172,7 @@ public: this->parent = FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); } - /** Free whatever we've allocated */ - ~NetworkContentDownloadStatusWindow() + void Close() override { TarScanner::Mode mode = TarScanner::NONE; for (auto ctype : this->receivedTypes) { @@ -254,6 +254,8 @@ public: /* Always invalidate the download window; tell it we are going to be gone */ InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST, 2); + + this->BaseNetworkContentDownloadStatusWindow::Close(); } void OnClick(Point pt, int widget, int click_count) override @@ -261,7 +263,7 @@ public: if (widget == WID_NCDS_CANCELOK) { if (this->downloaded_bytes != this->total_bytes) { _network_content_client.CloseConnection(); - delete this; + this->Close(); } else { /* If downloading succeeded, close the online content window. This will close * the current window as well. */ @@ -549,10 +551,10 @@ public: this->InvalidateData(); } - /** Free everything we allocated */ - ~NetworkContentListWindow() + void Close() override { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -837,7 +839,7 @@ public: break; case WID_NCL_CANCEL: - delete this; + this->Close(); break; case WID_NCL_OPEN_URL: @@ -941,7 +943,7 @@ public: { if (!success) { ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR); - delete this; + this->Close(); return; } diff --git a/src/network/network_content_gui.h b/src/network/network_content_gui.h index 4853101bbf..dd9d9cfdf4 100644 --- a/src/network/network_content_gui.h +++ b/src/network/network_content_gui.h @@ -32,11 +32,7 @@ public: */ BaseNetworkContentDownloadStatusWindow(WindowDesc *desc); - /** - * Free everything associated with this window. - */ - ~BaseNetworkContentDownloadStatusWindow(); - + void Close() override; void DrawWidget(const Rect &r, int widget) const override; void OnDownloadProgress(const ContentInfo *ci, int bytes) override; }; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 322e128cfb..7f179a05ff 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2597,7 +2597,7 @@ struct NetworkCompanyPasswordWindow : public Window { FALLTHROUGH; case WID_NCP_CANCEL: - delete this; + this->Close(); break; case WID_NCP_SAVE_AS_DEFAULT_PASSWORD: diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 9e86a575f0..a9b43ea9d3 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -424,7 +424,7 @@ struct NewGRFParametersWindow : public Window { break; case WID_NP_ACCEPT: - delete this; + this->Close(); break; } } @@ -662,7 +662,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->OnInvalidateData(GOID_NEWGRF_CURRENT_LOADED); } - ~NewGRFWindow() + void Close() override { DeleteWindowByClass(WC_GRF_PARAMETERS); DeleteWindowByClass(WC_TEXTFILE); @@ -674,6 +674,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { ReloadNewGRFData(); } + this->Window::Close(); + } + + ~NewGRFWindow() + { /* Remove the temporary copy of grf-list used in window */ ClearGRFConfigList(&this->actives); } @@ -2121,13 +2126,13 @@ struct SavePresetWindow : public Window { } case WID_SVP_CANCEL: - delete this; + this->Close(); break; case WID_SVP_SAVE: { Window *w = FindWindowById(WC_GAME_OPTIONS, WN_GAME_OPTIONS_NEWGRF_STATE); if (w != nullptr && !StrEmpty(this->presetname_editbox.text.buf)) w->OnQueryTextFinished(this->presetname_editbox.text.buf); - delete this; + this->Close(); break; } } diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 8dc66c8467..513624b3ec 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -479,7 +479,7 @@ struct NewsWindow : Window { switch (widget) { case WID_N_CLOSEBOX: NewsWindow::duration = 0; - delete this; + this->Close(); _forced_news = nullptr; break; @@ -1028,7 +1028,7 @@ static void ShowNewsMessage(const NewsItem *ni) bool HideActiveNewsMessage() { NewsWindow *w = (NewsWindow*)FindWindowById(WC_NEWS_WINDOW, 0); if (w == nullptr) return false; - delete w; + w->Close(); return true; } diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 92b15eaba4..6fb1ee5a07 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -170,7 +170,7 @@ struct OskWindow : public Window { return; } } - delete this; + this->Close(); break; case WID_OSK_CANCEL: @@ -182,7 +182,7 @@ struct OskWindow : public Window { qs->text.Assign(this->orig_str_buf); qs->text.MovePos(WKC_END); this->OnEditboxChanged(WID_OSK_TEXT); - delete this; + this->Close(); } break; } @@ -205,7 +205,7 @@ struct OskWindow : public Window { void OnFocusLost() override { VideoDriver::GetInstance()->EditBoxLostFocus(); - delete this; + this->Close(); } }; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 86f7189843..bb5244ae74 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -434,10 +434,11 @@ struct BuildRailToolbarWindow : Window { if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); } - ~BuildRailToolbarWindow() + void Close() override { if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -1028,9 +1029,10 @@ public: this->InvalidateData(); } - virtual ~BuildRailStationWindow() + void Close() override { DeleteWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } /** Sort station classes by StationClassID. */ @@ -1695,9 +1697,10 @@ public: this->OnInvalidateData(); } - ~BuildSignalWindow() + void Close() override { _convert_signal_button = false; + this->PickerWindowBase::Close(); } void OnInit() override diff --git a/src/road_gui.cpp b/src/road_gui.cpp index ae84404a2a..c12e94c164 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -289,10 +289,11 @@ struct BuildRoadToolbarWindow : Window { if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); } - ~BuildRoadToolbarWindow() + void Close() override { if (_game_mode == GM_NORMAL && (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION))) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -1095,9 +1096,10 @@ struct BuildRoadStationWindow : public PickerWindowBase { this->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION; } - virtual ~BuildRoadStationWindow() + void Close() override { DeleteWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void OnPaint() override diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 559c395875..6fae298bc1 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -172,11 +172,12 @@ struct GameOptionsWindow : Window { this->OnInvalidateData(0); } - ~GameOptionsWindow() + void Close() override { DeleteWindowById(WC_CUSTOM_CURRENCY, 0); DeleteWindowByClass(WC_TEXTFILE); if (this->reload) _switch_mode = SM_MENU; + this->Window::Close(); } /** diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index 93c4dd4312..d7d93c905a 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -527,7 +527,7 @@ struct SignWindow : Window, SignList { FALLTHROUGH; case WID_QES_CANCEL: - delete this; + this->Close(); break; } } @@ -592,5 +592,5 @@ void DeleteRenameSignWindow(SignID sign) { SignWindow *w = dynamic_cast(FindWindowById(WC_QUERY_STRING, WN_QUERY_STRING_SIGN)); - if (w != nullptr && w->cur_sign == sign) delete w; + if (w != nullptr && w->cur_sign == sign) w->Close(); } diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index bc0a7b447d..7827620af5 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1095,7 +1095,12 @@ SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(des SmallMapWindow::~SmallMapWindow() { delete this->overlay; +} + +/* virtual */ void SmallMapWindow::Close() +{ this->BreakIndustryChainLink(); + this->Window::Close(); } /** diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index e2fa9074d7..a5552333cd 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -178,6 +178,7 @@ public: void SmallMapCenterOnCurrentPos(); Point GetStationMiddle(const Station *st) const; + void Close() override; void SetStringParameters(int widget) const override; void OnInit() override; void OnPaint() override; diff --git a/src/station_gui.cpp b/src/station_gui.cpp index ab0eb5d1a5..7fb1b66a42 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1334,7 +1334,7 @@ struct StationViewWindow : public Window { this->owner = Station::Get(window_number)->owner; } - ~StationViewWindow() + void Close() override { DeleteWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false); DeleteWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->window_number).Pack(), false); @@ -1342,6 +1342,7 @@ struct StationViewWindow : public Window { DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false); SetViewportCatchmentStation(Station::Get(this->window_number), false); + this->Window::Close(); } /** @@ -2285,11 +2286,12 @@ struct SelectStationWindow : Window { _thd.freeze = true; } - ~SelectStationWindow() + void Close() override { if (_settings_client.gui.station_show_coverage) SetViewportCatchmentStation(nullptr, true); _thd.freeze = false; + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -2424,7 +2426,7 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta) Window *selection_window = FindWindowById(WC_SELECT_STATION, 0); if (selection_window != nullptr) { /* Abort current distant-join and start new one */ - delete selection_window; + selection_window->Close(); UpdateTileSelection(); } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index bd5893561b..021590cb9f 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -336,9 +336,10 @@ public: this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server); } - ~TownViewWindow() + void Close() override { SetViewportCatchmentTown(Town::Get(this->window_number), false); + this->Window::Close(); } void SetStringParameters(int widget) const override diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 0066644919..28155f7240 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1033,9 +1033,9 @@ struct RefitWindow : public Window { if (this->order == INVALID_VEH_ORDER_ID) { bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX; - if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) delete this; + if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) this->Close(); } else { - if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) delete this; + if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) this->Close(); } } break; @@ -2718,12 +2718,13 @@ public: this->UpdateButtonStatus(); } - ~VehicleViewWindow() + void Close() override { DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number, false); DeleteWindowById(WC_VEHICLE_REFIT, this->window_number, false); DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number, false); DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index 40c3401b0c..946d123c56 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -74,9 +74,10 @@ public: this->OnInvalidateData(0); } - ~WaypointWindow() + void Close() override { DeleteWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false); + this->Window::Close(); } void SetStringParameters(int widget) const override diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index e838d72315..77b54d5646 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -184,12 +184,11 @@ struct DropdownWindow : Window { this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); } - ~DropdownWindow() + void Close() override { - /* Make the dropdown "invisible", so it doesn't affect new window placement. + /* Finish closing the dropdown, so it doesn't affect new window placement. * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - *this->z_position = nullptr; - this->SetDirty(); + this->Window::Close(); Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); if (w2 != nullptr) { @@ -200,7 +199,7 @@ struct DropdownWindow : Window { } } - virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) + Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override { return this->position; } @@ -237,7 +236,7 @@ struct DropdownWindow : Window { return false; } - virtual void DrawWidget(const Rect &r, int widget) const + void DrawWidget(const Rect &r, int widget) const override { if (widget != WID_DM_ITEMS) return; @@ -265,7 +264,7 @@ struct DropdownWindow : Window { } } - virtual void OnClick(Point pt, int widget, int click_count) + void OnClick(Point pt, int widget, int click_count) override { if (widget != WID_DM_ITEMS) return; int item; @@ -276,7 +275,7 @@ struct DropdownWindow : Window { } } - virtual void OnRealtimeTick(uint delta_ms) + void OnRealtimeTick(uint delta_ms) override { if (!this->scrolling_timer.Elapsed(delta_ms)) return; this->scrolling_timer.SetInterval(MILLISECONDS_PER_TICK); @@ -293,22 +292,19 @@ struct DropdownWindow : Window { } } - virtual void OnMouseLoop() + void OnMouseLoop() override { Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); if (w2 == nullptr) { - delete this; + this->Close(); return; } if (this->click_delay != 0 && --this->click_delay == 0) { - /* Make the dropdown "invisible", so it doesn't affect new window placement. + /* Close the dropdown, so it doesn't affect new window placement. * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - *this->z_position = nullptr; - this->SetDirty(); - + this->Close(); w2->OnDropdownSelect(this->parent_button, this->selected_index); - delete this; return; } @@ -318,7 +314,7 @@ struct DropdownWindow : Window { if (!_left_button_clicked) { this->drag_mode = false; if (!this->GetDropDownItem(item)) { - if (this->instant_close) delete this; + if (this->instant_close) this->Close(); return; } this->click_delay = 2; @@ -509,7 +505,7 @@ int HideDropDownMenu(Window *pw) if (pw->window_class == dw->parent_wnd_class && pw->window_number == dw->parent_wnd_num) { int parent_button = dw->parent_button; - delete dw; + dw->Close(); return parent_button; } } diff --git a/src/window.cpp b/src/window.cpp index 036b17bcca..aae3efffb7 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -56,6 +56,21 @@ static Window *_last_scroll_window = nullptr; ///< Window of the last scroll eve /** List of windows opened at the screen sorted from the front to back. */ WindowList _z_windows; +/** List of closed windows to delete. */ +/* static */ std::vector Window::closed_windows; + +/** + * Delete all closed windows. + */ +/* static */ void Window::DeleteClosedWindows() +{ + for (Window *w : Window::closed_windows) delete w; + Window::closed_windows.clear(); + + /* Remove dead entries from the window list */ + _z_windows.remove(nullptr); +} + /** If false, highlight is white, otherwise the by the widget defined colour. */ bool _window_highlight_colour = false; @@ -705,7 +720,7 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) } case WWT_CLOSEBOX: // 'X' - delete w; + w->Close(); return; case WWT_CAPTION: // 'Title bar' @@ -793,7 +808,7 @@ static void DispatchRightClickEvent(Window *w, int x, int y) /* Right-click close is enabled and there is a closebox */ if (_settings_client.gui.right_mouse_wnd_close && w->nested_root->GetWidgetOfType(WWT_CLOSEBOX)) { - delete w; + w->Close(); } else if (_settings_client.gui.hover_delay_ms == 0 && !w->OnTooltip(pt, wid->index, TCC_RIGHT_CLICK) && wid->tool_tip != 0) { GuiShowTooltips(w, wid->tool_tip, 0, nullptr, TCC_RIGHT_CLICK); } @@ -1068,16 +1083,21 @@ void Window::DeleteChildWindows(WindowClass wc) const { Window *child = FindChildWindow(this, wc); while (child != nullptr) { - delete child; + child->Close(); child = FindChildWindow(this, wc); } } /** - * Remove window and all its child windows from the window stack. + * Hide the window and all its child windows, and mark them for a later deletion. */ -Window::~Window() +void Window::Close() { + /* Don't close twice. */ + if (*this->z_position == nullptr) return; + + *this->z_position = nullptr; + if (_thd.window_class == this->window_class && _thd.window_number == this->window_number) { ResetObjectToPlace(); @@ -1094,21 +1114,29 @@ Window::~Window() /* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */ if (_focused_window == this) { - /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ - this->Window::OnFocusLost(); + this->OnFocusLost(); _focused_window = nullptr; } this->DeleteChildWindows(); - if (this->viewport != nullptr) DeleteWindowViewport(this); - this->SetDirty(); + Window::closed_windows.push_back(this); +} + +/** + * Remove window and all its child windows from the window stack. + */ +Window::~Window() +{ + /* Make sure the window is closed, deletion is allowed only in Window::DeleteClosedWindows(). */ + assert(*this->z_position == nullptr); + + if (this->viewport != nullptr) DeleteWindowViewport(this); + free(this->nested_array); // Contents is released through deletion of #nested_root. delete this->nested_root; - - *this->z_position = nullptr; } /** @@ -1151,7 +1179,7 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) { Window *w = FindWindowById(cls, number); if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) { - delete w; + w->Close(); } } @@ -1164,7 +1192,7 @@ void DeleteWindowByClass(WindowClass cls) /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { if (w->window_class == cls) { - delete w; + w->Close(); } } } @@ -1180,7 +1208,7 @@ void DeleteCompanyWindows(CompanyID id) /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { if (w->owner == id) { - delete w; + w->Close(); } } @@ -1818,9 +1846,11 @@ void UnInitWindowSystem() { UnshowCriticalError(); - for (Window *w : Window::Iterate()) delete w; + for (Window *w : Window::Iterate()) w->Close(); - _z_windows.clear(); + Window::DeleteClosedWindows(); + + assert(_z_windows.empty()); } /** @@ -2968,7 +2998,7 @@ static void CheckSoftLimit() if (deletable_count <= _settings_client.gui.window_soft_limit) break; assert(last_deletable != nullptr); - delete last_deletable; + last_deletable->Close(); } } @@ -2983,14 +3013,8 @@ void InputLoop() CheckSoftLimit(); - /* Remove dead entries from the window list */ - for (auto it = _z_windows.begin(); it != _z_windows.end(); ) { - if (*it == nullptr) { - it = _z_windows.erase(it); - } else { - ++it; - } - } + /* Process scheduled window deletion. */ + Window::DeleteClosedWindows(); if (_input_events_this_tick != 0) { /* The input loop is called only once per GameLoop() - so we can clear the counter here */ @@ -3237,7 +3261,7 @@ void CallWindowGameTickEvent() void DeleteNonVitalWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::Iterate()) { + for (Window *w : Window::Iterate()) { if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_SELECT_GAME && w->window_class != WC_MAIN_TOOLBAR && @@ -3245,7 +3269,7 @@ void DeleteNonVitalWindows() w->window_class != WC_TOOLTIPS && (w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned' - delete w; + w->Close(); } } } @@ -3263,9 +3287,9 @@ void DeleteAllNonVitalWindows() DeleteNonVitalWindows(); /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::Iterate()) { + for (Window *w : Window::Iterate()) { if (w->flags & WF_STICKY) { - delete w; + w->Close(); } } } @@ -3288,9 +3312,9 @@ void DeleteAllMessages() void DeleteConstructionWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::Iterate()) { + for (Window *w : Window::Iterate()) { if (w->window_desc->flags & WDF_CONSTRUCTION) { - delete w; + w->Close(); } } @@ -3483,12 +3507,11 @@ void RelocateAllWindows(int neww, int newh) } /** - * Destructor of the base class PickerWindowBase - * Main utility is to stop the base Window destructor from triggering - * a free while the child will already be free, in this case by the ResetObjectToPlace(). + * Hide the window and all its child windows, and mark them for a later deletion. + * Always call ResetObjectToPlace() when closing a PickerWindow. */ -PickerWindowBase::~PickerWindowBase() +void PickerWindowBase::Close() { - *this->z_position = nullptr; // stop the ancestor from freeing the already (to be) child ResetObjectToPlace(); + this->Window::Close(); } diff --git a/src/window_gui.h b/src/window_gui.h index 1195c6c491..c84ad333b8 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -277,6 +277,9 @@ enum TooltipCloseCondition { * Data structure for an opened window */ struct Window : ZeroedMemoryAllocator { +private: + static std::vector closed_windows; + protected: void InitializeData(WindowNumber window_number); void InitializePositionSize(int x, int y, int min_width, int min_height); @@ -284,11 +287,12 @@ protected: std::vector scheduled_invalidation_data; ///< Data of scheduled OnInvalidateData() calls. + /* Protected to prevent deletion anywhere outside Window::DeleteClosedWindows(). */ + virtual ~Window(); + public: Window(WindowDesc *desc); - virtual ~Window(); - /** * Helper allocation function to disallow something. * Don't allow arrays; arrays of Windows are pointless as you need @@ -506,6 +510,8 @@ public: static int SortButtonWidth(); void DeleteChildWindows(WindowClass wc = WC_INVALID) const; + virtual void Close(); + static void DeleteClosedWindows(); void SetDirty() const; void ReInit(int rx = 0, int ry = 0); @@ -916,7 +922,7 @@ public: this->parent = parent; } - virtual ~PickerWindowBase(); + void Close() override; }; Window *BringWindowToFrontById(WindowClass cls, WindowNumber number); From 5799402f7a4872d03809838dd7fa01db42bbd282 Mon Sep 17 00:00:00 2001 From: glx22 Date: Mon, 17 May 2021 15:46:38 +0200 Subject: [PATCH 277/800] Codechange: Rename window related DeleteXXX to match new behaviour --- src/ai/ai_core.cpp | 2 +- src/ai/ai_gui.cpp | 22 +++++----- src/airport_gui.cpp | 12 +++--- src/autoreplace_gui.cpp | 2 +- src/bridge_gui.cpp | 2 +- src/build_vehicle_gui.cpp | 2 +- src/cheat_gui.cpp | 2 +- src/company_cmd.cpp | 8 ++-- src/company_gui.h | 2 +- src/console_gui.cpp | 2 +- src/date_gui.cpp | 2 +- src/depot.cpp | 4 +- src/depot_gui.cpp | 4 +- src/dock_gui.cpp | 18 ++++----- src/economy.cpp | 2 +- src/engine.cpp | 6 +-- src/fios_gui.cpp | 2 +- src/genworld.cpp | 4 +- src/genworld_gui.cpp | 6 +-- src/goal.cpp | 4 +- src/group_cmd.cpp | 2 +- src/group_gui.cpp | 2 +- src/highscore_gui.cpp | 4 +- src/industry_cmd.cpp | 2 +- src/main_gui.cpp | 4 +- src/misc_gui.cpp | 10 ++--- src/network/network.cpp | 4 +- src/network/network_chat_gui.cpp | 2 +- src/network/network_client.cpp | 10 ++--- src/network/network_content.cpp | 4 +- src/network/network_content_gui.cpp | 6 +-- src/network/network_gui.cpp | 18 ++++----- src/newgrf_config.cpp | 2 +- src/newgrf_debug_gui.cpp | 2 +- src/newgrf_gui.cpp | 62 ++++++++++++++--------------- src/news_gui.cpp | 8 ++-- src/openttd.cpp | 4 +- src/order_gui.cpp | 12 +++--- src/osk_gui.cpp | 2 +- src/rail_gui.cpp | 32 +++++++-------- src/road_gui.cpp | 28 ++++++------- src/screenshot_gui.cpp | 2 +- src/script/api/script_window.cpp | 4 +- src/settings.cpp | 6 +-- src/settings_gui.cpp | 14 +++---- src/signs_gui.cpp | 2 +- src/station.cpp | 10 ++--- src/station_cmd.cpp | 2 +- src/station_gui.cpp | 10 ++--- src/table/settings/settings.ini | 2 +- src/terraform_gui.cpp | 2 +- src/timetable_gui.cpp | 10 ++--- src/town_cmd.cpp | 2 +- src/train_cmd.cpp | 10 ++--- src/vehicle.cpp | 12 +++--- src/vehicle_gui.cpp | 14 +++---- src/viewport.cpp | 2 +- src/waypoint.cpp | 2 +- src/waypoint_gui.cpp | 2 +- src/widgets/dropdown.cpp | 2 +- src/window.cpp | 56 +++++++++++++------------- src/window_func.h | 10 ++--- src/window_gui.h | 2 +- 63 files changed, 253 insertions(+), 253 deletions(-) diff --git a/src/ai/ai_core.cpp b/src/ai/ai_core.cpp index 95c971af8e..d48ce05bfe 100644 --- a/src/ai/ai_core.cpp +++ b/src/ai/ai_core.cpp @@ -114,7 +114,7 @@ cur_company.Restore(); InvalidateWindowData(WC_AI_DEBUG, 0, -1); - DeleteWindowById(WC_AI_SETTINGS, company); + CloseWindowById(WC_AI_SETTINGS, company); } /* static */ void AI::Pause(CompanyID company) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index 1817148f44..c7ae4740e2 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -182,7 +182,7 @@ struct AIListWindow : public Window { } InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI); InvalidateWindowClassesData(WC_AI_SETTINGS); - DeleteWindowByClass(WC_QUERY_STRING); + CloseWindowByClass(WC_QUERY_STRING); InvalidateWindowClassesData(WC_TEXTFILE); } @@ -276,7 +276,7 @@ static WindowDesc _ai_list_desc( */ static void ShowAIListWindow(CompanyID slot) { - DeleteWindowByClass(WC_AI_LIST); + CloseWindowByClass(WC_AI_LIST); new AIListWindow(&_ai_list_desc, slot); } @@ -444,7 +444,7 @@ struct AISettingsWindow : public Window { if (!this->IsEditableItem(config_item)) return; if (this->clicked_row != num) { - DeleteChildWindows(WC_QUERY_STRING); + this->CloseChildWindows(WC_QUERY_STRING); HideDropDownMenu(this); this->clicked_row = num; this->clicked_dropdown = false; @@ -584,7 +584,7 @@ struct AISettingsWindow : public Window { { this->RebuildVisibleSettings(); HideDropDownMenu(this); - DeleteChildWindows(WC_QUERY_STRING); + this->CloseChildWindows(WC_QUERY_STRING); } private: @@ -628,8 +628,8 @@ static WindowDesc _ai_settings_desc( */ static void ShowAISettingsWindow(CompanyID slot) { - DeleteWindowByClass(WC_AI_LIST); - DeleteWindowByClass(WC_AI_SETTINGS); + CloseWindowByClass(WC_AI_LIST); + CloseWindowByClass(WC_AI_SETTINGS); new AISettingsWindow(&_ai_settings_desc, slot); } @@ -669,7 +669,7 @@ struct ScriptTextfileWindow : public TextfileWindow { */ void ShowScriptTextfileWindow(TextfileType file_type, CompanyID slot) { - DeleteWindowById(WC_TEXTFILE, file_type); + CloseWindowById(WC_TEXTFILE, file_type); new ScriptTextfileWindow(file_type, slot); } @@ -746,8 +746,8 @@ struct AIConfigWindow : public Window { void Close() override { - DeleteWindowByClass(WC_AI_LIST); - DeleteWindowByClass(WC_AI_SETTINGS); + CloseWindowByClass(WC_AI_LIST); + CloseWindowByClass(WC_AI_SETTINGS); this->Window::Close(); } @@ -972,7 +972,7 @@ struct AIConfigWindow : public Window { /** Open the AI config window. */ void ShowAIConfigWindow() { - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); new AIConfigWindow(); } @@ -1264,7 +1264,7 @@ struct AIDebugWindow : public Window { this->highlight_row = -1; // The highlight of one AI make little sense for another AI. /* Close AI settings window to prevent confusion */ - DeleteWindowByClass(WC_AI_SETTINGS); + CloseWindowByClass(WC_AI_SETTINGS); this->InvalidateData(-1); diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 1941a86025..cfe0ca4cb3 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -79,7 +79,7 @@ struct BuildAirToolbarWindow : Window { void Close() override { if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); - if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); this->Window::Close(); } @@ -97,7 +97,7 @@ struct BuildAirToolbarWindow : Window { WID_AT_AIRPORT, WIDGET_LIST_END); if (!can_build) { - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR); + CloseWindowById(WC_BUILD_STATION, TRANSPORT_AIR); /* Show in the tooltip why this button is disabled. */ this->GetWidget(WID_AT_AIRPORT)->SetToolTip(STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE); @@ -159,8 +159,8 @@ struct BuildAirToolbarWindow : Window { this->RaiseButtons(); - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_BUILD_STATION, TRANSPORT_AIR); + CloseWindowById(WC_SELECT_STATION, 0); } static HotkeyList hotkeys; @@ -218,7 +218,7 @@ Window *ShowBuildAirToolbar() { if (!Company::IsValidID(_local_company)) return nullptr; - DeleteWindowByClass(WC_BUILD_TOOLBAR); + CloseWindowByClass(WC_BUILD_TOOLBAR); return AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR); } @@ -279,7 +279,7 @@ public: void Close() override { - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); this->PickerWindowBase::Close(); } diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index a4d7bcb7d4..a7bd071db1 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -864,7 +864,7 @@ static WindowDesc _replace_vehicle_desc( */ void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype) { - DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype); + CloseWindowById(WC_REPLACE_VEHICLE, vehicletype); WindowDesc *desc; switch (vehicletype) { case VEH_TRAIN: desc = &_replace_rail_vehicle_desc; break; diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 4a9a56b790..74c7234d57 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -360,7 +360,7 @@ static WindowDesc _build_bridge_desc( */ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type) { - DeleteWindowByClass(WC_BUILD_BRIDGE); + CloseWindowByClass(WC_BUILD_BRIDGE); /* Data type for the bridge. * Bit 16,15 = transport type, diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index fb22e7380b..bdd32dc22a 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1686,7 +1686,7 @@ void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) assert(IsCompanyBuildableVehicleType(type)); - DeleteWindowById(WC_BUILD_VEHICLE, num); + CloseWindowById(WC_BUILD_VEHICLE, num); new BuildVehicleWindow(&_build_vehicle_desc, tile, type); } diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 497276ad66..4821edbcc9 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -415,6 +415,6 @@ static WindowDesc _cheats_desc( /** Open cheat window. */ void ShowCheatWindow() { - DeleteWindowById(WC_CHEATS, 0); + CloseWindowById(WC_CHEATS, 0); new CheatWindow(&_cheats_desc); } diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index f00db97c55..e58d29b2b5 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -76,7 +76,7 @@ Company::~Company() { if (CleaningPool()) return; - DeleteCompanyWindows(this->index); + CloseCompanyWindows(this->index); } /** @@ -115,7 +115,7 @@ void SetLocalCompany(CompanyID new_company) _current_company = _local_company = new_company; /* Delete any construction windows... */ - if (switching_company) DeleteConstructionWindows(); + if (switching_company) CloseConstructionWindows(); /* ... and redraw the whole screen. */ MarkWholeScreenDirty(); @@ -824,7 +824,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); /* Delete multiplayer progress bar */ - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); Company *c = DoStartupNewCompany(false); @@ -887,7 +887,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (!(flags & DC_EXEC)) return CommandCost(); /* Delete any open window of the company */ - DeleteCompanyWindows(c->index); + CloseCompanyWindows(c->index); CompanyNewsInformation *cni = MallocT(1); cni->FillData(c); diff --git a/src/company_gui.h b/src/company_gui.h index d5c69f6964..f6149b05fb 100644 --- a/src/company_gui.h +++ b/src/company_gui.h @@ -23,7 +23,7 @@ void ShowCompanyFinances(CompanyID company); void ShowCompany(CompanyID company); void InvalidateCompanyWindows(const Company *c); -void DeleteCompanyWindows(CompanyID company); +void CloseCompanyWindows(CompanyID company); void DirtyCompanyInfrastructureWindows(CompanyID company); #endif /* COMPANY_GUI_H */ diff --git a/src/console_gui.cpp b/src/console_gui.cpp index e5d80fcba1..b9062088e8 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -443,7 +443,7 @@ void IConsoleSwitch() break; case ICONSOLE_OPENED: case ICONSOLE_FULL: - DeleteWindowById(WC_CONSOLE, 0); + CloseWindowById(WC_CONSOLE, 0); break; } diff --git a/src/date_gui.cpp b/src/date_gui.cpp index 77b9a7c4ca..9327287201 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -212,6 +212,6 @@ static WindowDesc _set_date_desc( */ void ShowSetDateWindow(Window *parent, int window_number, Date initial_date, Year min_year, Year max_year, SetDateCallback *callback) { - DeleteWindowByClass(WC_SET_DATE); + CloseWindowByClass(WC_SET_DATE); new SetDateWindow(&_set_date_desc, window_number, parent, initial_date, min_year, max_year, callback); } diff --git a/src/depot.cpp b/src/depot.cpp index 05e2af3d4a..13317e8a35 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -41,9 +41,9 @@ Depot::~Depot() RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->index); /* Delete the depot-window */ - DeleteWindowById(WC_VEHICLE_DEPOT, this->xy); + CloseWindowById(WC_VEHICLE_DEPOT, this->xy); /* Delete the depot list */ VehicleType vt = GetDepotVehicleType(this->xy); - DeleteWindowById(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_DEPOT_LIST, vt, GetTileOwner(this->xy), this->index).Pack()); + CloseWindowById(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_DEPOT_LIST, vt, GetTileOwner(this->xy), this->index).Pack()); } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 80774e900e..151eb928d8 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -293,8 +293,8 @@ struct DepotWindow : Window { void Close() override { - DeleteWindowById(WC_BUILD_VEHICLE, this->window_number); - DeleteWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false); + CloseWindowById(WC_BUILD_VEHICLE, this->window_number); + CloseWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false); OrderBackup::Reset(this->window_number); this->Window::Close(); } diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 483a71d6b6..77ebe1be78 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -104,7 +104,7 @@ struct BuildDocksToolbarWindow : Window { void Close() override { if (_game_mode == GM_NORMAL && this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true); - if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); this->Window::Close(); } @@ -124,8 +124,8 @@ struct BuildDocksToolbarWindow : Window { WID_DT_BUOY, WIDGET_LIST_END); if (!can_build) { - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_WATER); - DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_WATER); + CloseWindowById(WC_BUILD_STATION, TRANSPORT_WATER); + CloseWindowById(WC_BUILD_DEPOT, TRANSPORT_WATER); } if (_game_mode != GM_EDITOR) { @@ -262,10 +262,10 @@ struct BuildDocksToolbarWindow : Window { this->RaiseButtons(); - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_WATER); - DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_WATER); - DeleteWindowById(WC_SELECT_STATION, 0); - DeleteWindowByClass(WC_BUILD_BRIDGE); + CloseWindowById(WC_BUILD_STATION, TRANSPORT_WATER); + CloseWindowById(WC_BUILD_DEPOT, TRANSPORT_WATER); + CloseWindowById(WC_SELECT_STATION, 0); + CloseWindowByClass(WC_BUILD_BRIDGE); } void OnPlacePresize(Point pt, TileIndex tile_from) override @@ -359,7 +359,7 @@ Window *ShowBuildDocksToolbar() { if (!Company::IsValidID(_local_company)) return nullptr; - DeleteWindowByClass(WC_BUILD_TOOLBAR); + CloseWindowByClass(WC_BUILD_TOOLBAR); return AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER); } @@ -419,7 +419,7 @@ public: void Close() override { - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); this->PickerWindowBase::Close(); } diff --git a/src/economy.cpp b/src/economy.cpp index 16a6072284..efea96806f 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1997,7 +1997,7 @@ static void DoAcquireCompany(Company *c) if (c->is_ai) AI::Stop(c->index); - DeleteCompanyWindows(ci); + CloseCompanyWindows(ci); InvalidateWindowClassesData(WC_TRAINS_LIST, 0); InvalidateWindowClassesData(WC_SHIPS_LIST, 0); InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); diff --git a/src/engine.cpp b/src/engine.cpp index 5e002a3c20..114cc1db6a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -528,7 +528,7 @@ bool EngineOverrideManager::ResetToCurrentNewGRFConfig() */ void SetupEngines() { - DeleteWindowByClass(WC_ENGINE_PREVIEW); + CloseWindowByClass(WC_ENGINE_PREVIEW); _engine_pool.CleanPool(); assert(_engine_mngr.size() >= _engine_mngr.NUM_DEFAULT_ENGINES); @@ -837,7 +837,7 @@ void EnginesDailyLoop() if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) { if (e->preview_company != INVALID_COMPANY) { if (!--e->preview_wait) { - DeleteWindowById(WC_ENGINE_PREVIEW, i); + CloseWindowById(WC_ENGINE_PREVIEW, i); e->preview_company = INVALID_COMPANY; } } else if (CountBits(e->preview_asked) < MAX_COMPANIES) { @@ -1015,7 +1015,7 @@ static void NewVehicleAvailable(Engine *e) if (e->type == VEH_AIRCRAFT) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_AIR); /* Close pending preview windows */ - DeleteWindowById(WC_ENGINE_PREVIEW, index); + CloseWindowById(WC_ENGINE_PREVIEW, index); } /** Monthly update of the availability, reliability, and preview offers of the engines. */ diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index c04092f6bd..2d33875f67 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -920,7 +920,7 @@ static WindowDesc _save_dialog_desc( */ void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop) { - DeleteWindowById(WC_SAVELOAD, 0); + CloseWindowById(WC_SAVELOAD, 0); WindowDesc *sld; if (fop == SLO_SAVE) { diff --git a/src/genworld.cpp b/src/genworld.cpp index dc722ac000..5ed83d5aa1 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -76,7 +76,7 @@ static void CleanupGeneration() _gw.proc = nullptr; _gw.abortp = nullptr; - DeleteWindowByClass(WC_MODAL_PROGRESS); + CloseWindowByClass(WC_MODAL_PROGRESS); ShowFirstError(); MarkWholeScreenDirty(); } @@ -314,7 +314,7 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0); UnshowCriticalError(); - DeleteAllNonVitalWindows(); + CloseAllNonVitalWindows(); HideVitalWindows(); ShowGenerateWorldProgress(); diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 69ae9576ae..ab5a781ef0 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -285,7 +285,7 @@ static const NWidgetPart _nested_heightmap_load_widgets[] = { static void StartGeneratingLandscape(GenerateLandscapeWindowMode mode) { - DeleteAllNonVitalWindows(); + CloseAllNonVitalWindows(); ClearErrorMessages(); /* Copy all XXX_newgame to XXX when coming from outside the editor */ @@ -974,7 +974,7 @@ static void _ShowGenerateLandscape(GenerateLandscapeWindowMode mode) uint x = 0; uint y = 0; - DeleteWindowByClass(WC_GENERATE_LANDSCAPE); + CloseWindowByClass(WC_GENERATE_LANDSCAPE); /* Generate a new seed when opening the window */ _settings_newgame.game_creation.generation_seed = InteractiveRandom(); @@ -1267,7 +1267,7 @@ static WindowDesc _create_scenario_desc( /** Show the window to create a scenario. */ void ShowCreateScenario() { - DeleteWindowByClass(WC_GENERATE_LANDSCAPE); + CloseWindowByClass(WC_GENERATE_LANDSCAPE); new CreateScenarioWindow(&_create_scenario_desc, GLWM_SCENARIO); } diff --git a/src/goal.cpp b/src/goal.cpp index fe36f286ed..c611650597 100644 --- a/src/goal.cpp +++ b/src/goal.cpp @@ -296,13 +296,13 @@ CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1 if (_current_company == OWNER_DEITY) { /* It has been requested to close this specific question on all clients */ - if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1); + if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, p1); return CommandCost(); } if (_networking && _local_company == _current_company) { /* Somebody in the same company answered the question. Close the window */ - if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1); + if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, p1); if (!_network_server) return CommandCost(); } diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index bee5b03f29..50b361d007 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -382,7 +382,7 @@ CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 VehicleType vt = g->vehicle_type; /* Delete the Replace Vehicle Windows */ - DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type); + CloseWindowById(WC_REPLACE_VEHICLE, g->vehicle_type); delete g; InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack()); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 1a6deae2cb..89a89983d6 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -449,7 +449,7 @@ public: /* Process ID-invalidation in command-scope as well */ if (this->group_rename != INVALID_GROUP && !Group::IsValidID(this->group_rename)) { - DeleteWindowByClass(WC_QUERY_STRING); + CloseWindowByClass(WC_QUERY_STRING); this->group_rename = INVALID_GROUP; } diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index e36935c1e8..768b9c9c17 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -232,7 +232,7 @@ static WindowDesc _endgame_desc( */ void ShowHighscoreTable(int difficulty, int8 ranking) { - DeleteWindowByClass(WC_HIGHSCORE); + CloseWindowByClass(WC_HIGHSCORE); new HighScoreWindow(&_highscore_desc, difficulty, ranking); } @@ -246,6 +246,6 @@ void ShowEndGameChart() if (_network_dedicated || (!_networking && !Company::IsValidID(_local_company))) return; HideVitalWindows(); - DeleteWindowByClass(WC_ENDSCREEN); + CloseWindowByClass(WC_ENDSCREEN); new EndGameWindow(&_endgame_desc); } diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index c6ae129c37..d88f7b692f 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -190,7 +190,7 @@ Industry::~Industry() DecIndustryTypeCount(this->type); DeleteIndustryNews(this->index); - DeleteWindowById(WC_INDUSTRY_VIEW, this->index); + CloseWindowById(WC_INDUSTRY_VIEW, this->index); DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index); DeleteSubsidyWith(ST_INDUSTRY, this->index); diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 1e8cfcbfac..559040f378 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -303,8 +303,8 @@ struct MainWindow : Window } case GHK_RESET_OBJECT_TO_PLACE: ResetObjectToPlace(); break; - case GHK_DELETE_WINDOWS: DeleteNonVitalWindows(); break; - case GHK_DELETE_NONVITAL_WINDOWS: DeleteAllNonVitalWindows(); break; + case GHK_DELETE_WINDOWS: CloseNonVitalWindows(); break; + case GHK_DELETE_NONVITAL_WINDOWS: CloseAllNonVitalWindows(); break; case GHK_DELETE_ALL_MESSAGES: DeleteAllMessages(); break; case GHK_REFRESH_SCREEN: MarkWholeScreenDirty(); break; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 59b0282d54..6ba65c703e 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -399,7 +399,7 @@ public: */ void ShowLandInfo(TileIndex tile) { - DeleteWindowById(WC_LAND_INFO, 0); + CloseWindowById(WC_LAND_INFO, 0); new LandInfoWindow(tile); } @@ -564,7 +564,7 @@ struct AboutWindow : public Window { void ShowAboutWindow() { - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); new AboutWindow(); } @@ -789,7 +789,7 @@ struct TooltipsWindow : public Window */ void GuiShowTooltips(Window *parent, StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_tooltip) { - DeleteWindowById(WC_TOOLTIPS, 0); + CloseWindowById(WC_TOOLTIPS, 0); if (str == STR_NULL || !_cursor.in_window) return; @@ -1142,7 +1142,7 @@ void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *paren { assert(parent != nullptr); - DeleteWindowByClass(WC_QUERY_STRING); + CloseWindowByClass(WC_QUERY_STRING); new QueryStringWindow(str, caption, ((flags & QSF_LEN_IN_CHARS) ? MAX_CHAR_LENGTH : 1) * maxsize, maxsize, &_query_string_desc, parent, afilter, flags); } @@ -1219,7 +1219,7 @@ struct QueryWindow : public Window { switch (widget) { case WID_Q_YES: { /* in the Generate New World window, clicking 'Yes' causes - * DeleteNonVitalWindows() to be called - we shouldn't be in a window then */ + * CloseNonVitalWindows() to be called - we shouldn't be in a window then */ QueryCallbackProc *proc = this->proc; Window *parent = this->parent; /* Prevent the destructor calling the callback function */ diff --git a/src/network/network.cpp b/src/network/network.cpp index 2bc3589449..d89789cf94 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -668,7 +668,7 @@ public: void OnFailure() override { - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); ShowErrorMessage(STR_NETWORK_ERROR_NOCONNECTION, INVALID_STRING_ID, WL_ERROR); } @@ -988,7 +988,7 @@ void NetworkDisconnect(bool blocking, bool close_admins) if (_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(blocking); - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); NetworkClose(close_admins); diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 53546aa873..b42f0c5627 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -533,6 +533,6 @@ static WindowDesc _chat_window_desc( */ void ShowNetworkChatQueryWindow(DestType type, int dest) { - DeleteWindowByClass(WC_SEND_NETWORK_MSG); + CloseWindowByClass(WC_SEND_NETWORK_MSG); new NetworkChatWindow(&_chat_window_desc, type, dest); } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 44359941a8..161bbf4122 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -204,7 +204,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) this->CloseConnection(res); _networking = false; - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); return; } @@ -560,7 +560,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) { /* We try to join a server which is full */ ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL); - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); return NETWORK_RECV_STATUS_SERVER_FULL; } @@ -569,7 +569,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet * { /* We try to join a server where we are banned */ ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL); - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); return NETWORK_RECV_STATUS_SERVER_BANNED; } @@ -754,7 +754,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p /* Perform an emergency save if we had already entered the game */ if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); return NETWORK_RECV_STATUS_SERVER_ERROR; } @@ -924,7 +924,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet this->last_packet = std::chrono::steady_clock::now(); if (!load_success) { - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL); return NETWORK_RECV_STATUS_SAVEGAME; } diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index e09b05ec76..f78a839b81 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -495,7 +495,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) /* We have a file opened, thus are downloading internal content */ size_t toRead = p->RemainingBytesToTransfer(); if (toRead != 0 && (size_t)p->TransferOut(TransferOutFWrite, this->curFile) != toRead) { - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); this->CloseConnection(); fclose(this->curFile); @@ -529,7 +529,7 @@ bool ClientNetworkContentSocketHandler::BeforeDownload() std::string filename = GetFullFilename(this->curInfo, true); if (filename.empty() || (this->curFile = fopen(filename.c_str(), "wb")) == nullptr) { /* Unless that fails of course... */ - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); return false; } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 8c75cb572a..a74d902a3c 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -74,7 +74,7 @@ struct ContentTextfileWindow : public TextfileWindow { void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci) { - DeleteWindowById(WC_TEXTFILE, file_type); + CloseWindowById(WC_TEXTFILE, file_type); new ContentTextfileWindow(file_type, ci); } @@ -267,7 +267,7 @@ public: } else { /* If downloading succeeded, close the online content window. This will close * the current window as well. */ - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); } } } @@ -1130,7 +1130,7 @@ void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentT _network_content_client.RequestContentList(cv, true); } - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); new NetworkContentListWindow(&_network_content_list_desc, cv != nullptr, types); #else ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, WL_ERROR); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 7f179a05ff..bd91cc25ad 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -677,7 +677,7 @@ public: { switch (widget) { case WID_NG_CANCEL: // Cancel button - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); break; case WID_NG_NAME: // Sort by name @@ -966,8 +966,8 @@ static WindowDesc _network_game_window_desc( void ShowNetworkGameWindow() { static bool first = true; - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); /* Only show once */ if (first) { @@ -1265,8 +1265,8 @@ static void ShowNetworkStartServerWindow() { if (!NetworkValidateClientName()) return; - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); new NetworkStartServerWindow(&_network_start_server_window_desc); } @@ -1559,8 +1559,8 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) { if (!NetworkValidateClientName()) return; - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); - DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); + CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); _settings_client.network.last_joined = ngl->connection_string; @@ -2519,7 +2519,7 @@ static WindowDesc _network_join_status_window_desc( void ShowJoinStatusWindow() { - DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); + CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); new NetworkJoinStatusWindow(&_network_join_status_window_desc); } @@ -2642,7 +2642,7 @@ static WindowDesc _network_company_password_window_desc( void ShowNetworkCompanyPasswordWindow(Window *parent) { - DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0); + CloseWindowById(WC_COMPANY_PASSWORD_WINDOW, 0); new NetworkCompanyPasswordWindow(&_network_company_password_window_desc, parent); } diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 044d361939..4e37be54f0 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -706,7 +706,7 @@ void DoScanNewGRFFiles(NewGRFScanCallback *callback) InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_NEWGRF_STATE, GOID_NEWGRF_RESCANNED, true); if (!_exit_game && callback != nullptr) callback->OnNewGRFsScanned(); - DeleteWindowByClass(WC_MODAL_PROGRESS); + CloseWindowByClass(WC_MODAL_PROGRESS); SetModalProgress(false); MarkWholeScreenDirty(); } diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 0d9fae8a48..9453f5de91 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -736,7 +736,7 @@ void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index) if (feature == GSF_INVALID) return; WindowNumber wno = GetInspectWindowNumber(feature, index); - DeleteWindowById(WC_NEWGRF_INSPECT, wno); + CloseWindowById(WC_NEWGRF_INSPECT, wno); /* Reinitialise the land information window to remove the "debug" sprite if needed. * Note: Since we might be called from a command here, it is important to not execute diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index a9b43ea9d3..f017cbf7f9 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -341,7 +341,7 @@ struct NewGRFParametersWindow : public Window { uint num = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NP_BACKGROUND); if (num >= this->vscroll->GetCount()) break; if (this->clicked_row != num) { - DeleteChildWindows(WC_QUERY_STRING); + this->CloseChildWindows(WC_QUERY_STRING); HideDropDownMenu(this); this->clicked_row = num; this->clicked_dropdown = false; @@ -481,7 +481,7 @@ struct NewGRFParametersWindow : public Window { this->vscroll->SetCount(this->action14present ? this->grf_config->num_valid_params : this->grf_config->num_params); if (this->clicked_row != UINT_MAX && this->clicked_row >= this->vscroll->GetCount()) { this->clicked_row = UINT_MAX; - DeleteChildWindows(WC_QUERY_STRING); + this->CloseChildWindows(WC_QUERY_STRING); } } @@ -538,7 +538,7 @@ static WindowDesc _newgrf_parameters_desc( static void OpenGRFParameterWindow(GRFConfig *c, bool editable) { - DeleteWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_GRF_PARAMETERS); new NewGRFParametersWindow(&_newgrf_parameters_desc, c, editable); } @@ -563,7 +563,7 @@ struct NewGRFTextfileWindow : public TextfileWindow { void ShowNewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) { - DeleteWindowById(WC_TEXTFILE, file_type); + CloseWindowById(WC_TEXTFILE, file_type); new NewGRFTextfileWindow(file_type, c); } @@ -664,9 +664,9 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { void Close() override { - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); - DeleteWindowByClass(WC_SAVE_PRESET); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_SAVE_PRESET); if (this->editable && this->modified && !this->execute && !_exit_game) { CopyGRFConfigList(this->orig_list, this->actives, true); @@ -715,8 +715,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { d->next = (*c)->next; d->CopyParams(**c); if (this->active_sel == *c) { - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); this->active_sel = nullptr; } delete *c; @@ -938,7 +938,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i], i, false)); } - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window ShowDropDownList(this, std::move(list), this->preset, WID_NS_PRESET_LIST); break; } @@ -962,7 +962,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->grf_presets = GetGRFPresetList(); this->preset = -1; this->InvalidateData(); - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window break; case WID_NS_MOVE_UP: { // Move GRF up @@ -1012,8 +1012,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { for (c = this->actives; c != nullptr && i > 0; c = c->next, i--) {} if (this->active_sel != c) { - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); } this->active_sel = c; this->avail_sel = nullptr; @@ -1030,8 +1030,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { case WID_NS_REMOVE: { // Remove GRF if (this->active_sel == nullptr || !this->editable) break; - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); /* Choose the next GRF file to be the selected file. */ GRFConfig *newsel = this->active_sel->next; @@ -1071,9 +1071,9 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { uint i = this->vscroll2->GetScrolledRowFromWidget(pt.y, this, WID_NS_AVAIL_LIST); this->active_sel = nullptr; - DeleteWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_GRF_PARAMETERS); if (i < this->avails.size()) { - if (this->avail_sel != this->avails[i]) DeleteWindowByClass(WC_TEXTFILE); + if (this->avail_sel != this->avails[i]) CloseWindowByClass(WC_TEXTFILE); this->avail_sel = this->avails[i]; this->avail_pos = i; } @@ -1107,7 +1107,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { ReloadNewGRFData(); this->InvalidateData(GOID_NEWGRF_CHANGES_APPLIED); } - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window break; case WID_NS_VIEW_PARAMETERS: @@ -1132,7 +1132,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { if (!_network_available) { ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); } else { - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window ShowMissingContentWindow(this->actives); } @@ -1147,11 +1147,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { void OnNewGRFsScanned() override { - if (this->active_sel == nullptr) DeleteWindowByClass(WC_TEXTFILE); + if (this->active_sel == nullptr) CloseWindowByClass(WC_TEXTFILE); this->avail_sel = nullptr; this->avail_pos = -1; this->avails.ForceRebuild(); - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window } void OnDropdownSelect(int widget, int index) override @@ -1167,8 +1167,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->avails.ForceRebuild(); ResetObjectToPlace(); - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); this->active_sel = nullptr; this->InvalidateData(GOID_NEWGRF_CHANGES_MADE); } @@ -1331,8 +1331,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { if (this->avail_pos >= 0) { this->active_sel = nullptr; - DeleteWindowByClass(WC_GRF_PARAMETERS); - if (this->avail_sel != this->avails[this->avail_pos]) DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + if (this->avail_sel != this->avails[this->avail_pos]) CloseWindowByClass(WC_TEXTFILE); this->avail_sel = this->avails[this->avail_pos]; this->vscroll2->ScrollTowards(this->avail_pos); this->InvalidateData(0); @@ -1497,7 +1497,7 @@ private: { if (this->avail_sel == nullptr || !this->editable || HasBit(this->avail_sel->flags, GCF_INVALID)) return false; - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_TEXTFILE); uint count = 0; GRFConfig **entry = nullptr; @@ -1955,8 +1955,8 @@ static WindowDesc _newgrf_desc( static void NewGRFConfirmationCallback(Window *w, bool confirmed) { if (confirmed) { - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowByClass(WC_GRF_PARAMETERS); + CloseWindowByClass(WC_TEXTFILE); NewGRFWindow *nw = dynamic_cast(w); GamelogStartAction(GLAT_GRF); @@ -1978,7 +1978,7 @@ static void NewGRFConfirmationCallback(Window *w, bool confirmed) w->InvalidateData(); ReInitAllWindows(false); - DeleteWindowByClass(WC_BUILD_OBJECT); + CloseWindowByClass(WC_BUILD_OBJECT); } } @@ -1994,7 +1994,7 @@ static void NewGRFConfirmationCallback(Window *w, bool confirmed) */ void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config) { - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); new NewGRFWindow(&_newgrf_desc, editable, show_params, exec_changes, config); } @@ -2150,7 +2150,7 @@ struct SavePresetWindow : public Window { */ static void ShowSavePresetWindow(const char *initial_text) { - DeleteWindowByClass(WC_SAVE_PRESET); + CloseWindowByClass(WC_SAVE_PRESET); new SavePresetWindow(initial_text); } diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 513624b3ec..a8d7c4398d 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -699,7 +699,7 @@ static void MoveToNextNewsItem() * there is no status bar but possible news. */ if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return; - DeleteWindowById(WC_NEWS_WINDOW, 0); // close the newspapers window if shown + CloseWindowById(WC_NEWS_WINDOW, 0); // close the newspapers window if shown _forced_news = nullptr; /* if we're not at the last item, then move on */ @@ -1010,13 +1010,13 @@ static void ShowNewsMessage(const NewsItem *ni) assert(_total_news != 0); /* Delete the news window */ - DeleteWindowById(WC_NEWS_WINDOW, 0); + CloseWindowById(WC_NEWS_WINDOW, 0); /* setup forced news item */ _forced_news = ni; if (_forced_news != nullptr) { - DeleteWindowById(WC_NEWS_WINDOW, 0); + CloseWindowById(WC_NEWS_WINDOW, 0); ShowNewspaper(ni); } } @@ -1251,6 +1251,6 @@ static WindowDesc _message_history_desc( /** Display window with news messages history */ void ShowMessageHistory() { - DeleteWindowById(WC_MESSAGE_HISTORY, 0); + CloseWindowById(WC_MESSAGE_HISTORY, 0); new MessageHistoryWindow(&_message_history_desc); } diff --git a/src/openttd.cpp b/src/openttd.cpp index 5a4e73593b..f39b87c87e 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1086,13 +1086,13 @@ void SwitchToMode(SwitchMode new_mode) SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); } else { - DeleteWindowById(WC_SAVELOAD, 0); + CloseWindowById(WC_SAVELOAD, 0); } break; case SM_SAVE_HEIGHTMAP: // Save heightmap. MakeHeightmapScreenshot(_file_to_saveload.name.c_str()); - DeleteWindowById(WC_SAVELOAD, 0); + CloseWindowById(WC_SAVELOAD, 0); break; case SM_GENRANDLAND: // Generate random land within scenario editor diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 2b3715ebd6..3205be166f 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -843,7 +843,7 @@ public: /* Removed / replaced all orders (after deleting / sharing) */ if (this->selected_order == -1) break; - this->DeleteChildWindows(); + this->CloseChildWindows(); HideDropDownMenu(this); this->selected_order = -1; break; @@ -875,7 +875,7 @@ public: /* Now we are modifying the selected order */ if (to == INVALID_VEH_ORDER_ID) { /* Deleting selected order */ - this->DeleteChildWindows(); + this->CloseChildWindows(); HideDropDownMenu(this); this->selected_order = -1; break; @@ -1174,7 +1174,7 @@ public: } /* This order won't be selected any more, close all child windows and dropdowns */ - this->DeleteChildWindows(); + this->CloseChildWindows(); HideDropDownMenu(this); if (sel == INVALID_VEH_ORDER_ID || this->vehicle->owner != _local_company) { @@ -1700,12 +1700,12 @@ static WindowDesc _other_orders_desc( void ShowOrdersWindow(const Vehicle *v) { - DeleteWindowById(WC_VEHICLE_DETAILS, v->index, false); - DeleteWindowById(WC_VEHICLE_TIMETABLE, v->index, false); + CloseWindowById(WC_VEHICLE_DETAILS, v->index, false); + CloseWindowById(WC_VEHICLE_TIMETABLE, v->index, false); if (BringWindowToFrontById(WC_VEHICLE_ORDERS, v->index) != nullptr) return; /* Using a different WindowDescs for _local_company causes problems. - * Due to this we have to close order windows in ChangeWindowOwner/DeleteCompanyWindows, + * Due to this we have to close order windows in ChangeWindowOwner/CloseCompanyWindows, * because we cannot change switch the WindowDescs and keeping the old WindowDesc results * in crashed due to missing widges. * TODO Rewrite the order GUI to not use different WindowDescs. diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 6fb1ee5a07..630cd18f2d 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -407,7 +407,7 @@ void GetKeyboardLayout() */ void ShowOnScreenKeyboard(Window *parent, int button) { - DeleteWindowById(WC_OSK, 0); + CloseWindowById(WC_OSK, 0); GetKeyboardLayout(); new OskWindow(&_osk_desc, parent, button); diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index bb5244ae74..871938d206 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -291,7 +291,7 @@ void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uin */ static void ToggleRailButton_Remove(Window *w) { - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); w->ToggleWidgetLoweredState(WID_RAT_REMOVE); w->SetWidgetDirty(WID_RAT_REMOVE); _remove_button_clicked = w->IsWidgetLowered(WID_RAT_REMOVE); @@ -437,7 +437,7 @@ struct BuildRailToolbarWindow : Window { void Close() override { if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); - if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); this->Window::Close(); } @@ -743,12 +743,12 @@ struct BuildRailToolbarWindow : Window { this->DisableWidget(WID_RAT_REMOVE); this->SetWidgetDirty(WID_RAT_REMOVE); - DeleteWindowById(WC_BUILD_SIGNAL, TRANSPORT_RAIL); - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_RAIL); - DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_RAIL); - DeleteWindowById(WC_BUILD_WAYPOINT, TRANSPORT_RAIL); - DeleteWindowById(WC_SELECT_STATION, 0); - DeleteWindowByClass(WC_BUILD_BRIDGE); + CloseWindowById(WC_BUILD_SIGNAL, TRANSPORT_RAIL); + CloseWindowById(WC_BUILD_STATION, TRANSPORT_RAIL); + CloseWindowById(WC_BUILD_DEPOT, TRANSPORT_RAIL); + CloseWindowById(WC_BUILD_WAYPOINT, TRANSPORT_RAIL); + CloseWindowById(WC_SELECT_STATION, 0); + CloseWindowByClass(WC_BUILD_BRIDGE); } void OnPlacePresize(Point pt, TileIndex tile) override @@ -865,7 +865,7 @@ Window *ShowBuildRailToolbar(RailType railtype) if (!Company::IsValidID(_local_company)) return nullptr; if (!ValParamRailtype(railtype)) return nullptr; - DeleteWindowByClass(WC_BUILD_TOOLBAR); + CloseWindowByClass(WC_BUILD_TOOLBAR); _cur_railtype = railtype; _remove_button_clicked = false; return new BuildRailToolbarWindow(&_build_rail_desc, railtype); @@ -1031,7 +1031,7 @@ public: void Close() override { - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); this->PickerWindowBase::Close(); } @@ -1347,7 +1347,7 @@ public: this->LowerWidget(_railstation.orientation + WID_BRAS_PLATFORM_DIR_X); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; case WID_BRAS_PLATFORM_NUM_1: @@ -1381,7 +1381,7 @@ public: this->LowerWidget(_settings_client.gui.station_platlength + WID_BRAS_PLATFORM_LEN_BEGIN); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; } @@ -1416,7 +1416,7 @@ public: this->LowerWidget(_settings_client.gui.station_platlength + WID_BRAS_PLATFORM_LEN_BEGIN); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; } @@ -1450,7 +1450,7 @@ public: this->SetWidgetLoweredState(_settings_client.gui.station_platlength + WID_BRAS_PLATFORM_LEN_BEGIN, !_settings_client.gui.station_dragdrop); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; } @@ -1483,7 +1483,7 @@ public: } if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; } @@ -1502,7 +1502,7 @@ public: if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; } } diff --git a/src/road_gui.cpp b/src/road_gui.cpp index c12e94c164..f6ddbae41f 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -292,7 +292,7 @@ struct BuildRoadToolbarWindow : Window { void Close() override { if (_game_mode == GM_NORMAL && (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION))) SetViewportCatchmentStation(nullptr, true); - if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); + if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); this->Window::Close(); } @@ -313,9 +313,9 @@ struct BuildRoadToolbarWindow : Window { WID_ROT_TRUCK_STATION, WIDGET_LIST_END); if (!can_build) { - DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD); - DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD); - DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD); + CloseWindowById(WC_BUS_STATION, TRANSPORT_ROAD); + CloseWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD); + CloseWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD); } if (_game_mode != GM_EDITOR) { @@ -499,7 +499,7 @@ struct BuildRoadToolbarWindow : Window { case WID_ROT_REMOVE: if (this->IsWidgetDisabled(WID_ROT_REMOVE)) return; - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); ToggleRoadButton_Remove(this); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); break; @@ -592,11 +592,11 @@ struct BuildRoadToolbarWindow : Window { this->SetWidgetDirty(WID_ROT_ONE_WAY); } - DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD); - DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD); - DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD); - DeleteWindowById(WC_SELECT_STATION, 0); - DeleteWindowByClass(WC_BUILD_BRIDGE); + CloseWindowById(WC_BUS_STATION, TRANSPORT_ROAD); + CloseWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD); + CloseWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD); + CloseWindowById(WC_SELECT_STATION, 0); + CloseWindowByClass(WC_BUILD_BRIDGE); } void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) override @@ -891,7 +891,7 @@ Window *ShowBuildRoadToolbar(RoadType roadtype) if (!Company::IsValidID(_local_company)) return nullptr; if (!ValParamRoadType(roadtype)) return nullptr; - DeleteWindowByClass(WC_BUILD_TOOLBAR); + CloseWindowByClass(WC_BUILD_TOOLBAR); _cur_roadtype = roadtype; return AllocateWindowDescFront(RoadTypeIsRoad(_cur_roadtype) ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD); @@ -975,7 +975,7 @@ static WindowDesc _build_tramway_scen_desc( */ Window *ShowBuildRoadScenToolbar(RoadType roadtype) { - DeleteWindowById(WC_SCEN_BUILD_TOOLBAR, TRANSPORT_ROAD); + CloseWindowById(WC_SCEN_BUILD_TOOLBAR, TRANSPORT_ROAD); _cur_roadtype = roadtype; return AllocateWindowDescFront(RoadTypeIsRoad(_cur_roadtype) ? &_build_road_scen_desc : &_build_tramway_scen_desc, TRANSPORT_ROAD); @@ -1098,7 +1098,7 @@ struct BuildRoadStationWindow : public PickerWindowBase { void Close() override { - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); this->PickerWindowBase::Close(); } @@ -1159,7 +1159,7 @@ struct BuildRoadStationWindow : public PickerWindowBase { this->LowerWidget(_road_station_picker_orientation + WID_BROS_STATION_NE); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); this->SetDirty(); - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); break; case WID_BROS_LT_OFF: diff --git a/src/screenshot_gui.cpp b/src/screenshot_gui.cpp index c0e65f13d0..e9b989e517 100644 --- a/src/screenshot_gui.cpp +++ b/src/screenshot_gui.cpp @@ -69,6 +69,6 @@ static WindowDesc _screenshot_window_desc( void ShowScreenshotWindow() { - DeleteWindowById(WC_SCREENSHOT, 0); + CloseWindowById(WC_SCREENSHOT, 0); new ScreenshotWindow(&_screenshot_window_desc); } diff --git a/src/script/api/script_window.cpp b/src/script/api/script_window.cpp index f54b4fd601..7969380cb3 100644 --- a/src/script/api/script_window.cpp +++ b/src/script/api/script_window.cpp @@ -20,11 +20,11 @@ if (ScriptGame::IsMultiplayer()) return; if (number == NUMBER_ALL) { - DeleteWindowByClass((::WindowClass)window); + CloseWindowByClass((::WindowClass)window); return; } - DeleteWindowById((::WindowClass)window, number); + CloseWindowById((::WindowClass)window, number); } /* static */ bool ScriptWindow::IsOpen(WindowClass window, uint32 number) diff --git a/src/settings.cpp b/src/settings.cpp index 11dff7143a..c26b3bb47c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -842,7 +842,7 @@ static void StationSpreadChanged(int32 p1) static void CloseSignalGUI(int32 new_value) { if (new_value == 0) { - DeleteWindowByClass(WC_BUILD_SIGNAL); + CloseWindowByClass(WC_BUILD_SIGNAL); } } @@ -980,7 +980,7 @@ static void RoadVehSlopeSteepnessChanged(int32 new_value) static void TownFoundingChanged(int32 new_value) { if (_game_mode != GM_EDITOR && _settings_game.economy.found_town == TF_FORBIDDEN) { - DeleteWindowById(WC_FOUND_TOWN, 0); + CloseWindowById(WC_FOUND_TOWN, 0); } else { InvalidateWindowData(WC_FOUND_TOWN, 0); } @@ -1015,7 +1015,7 @@ static void SpriteZoomMinChanged(int32 new_value) static void InvalidateNewGRFChangeWindows(int32 new_value) { InvalidateWindowClassesData(WC_SAVELOAD); - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); ReInitAllWindows(_gui_zoom_cfg); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 6fae298bc1..f038617d13 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -137,7 +137,7 @@ struct BaseSetTextfileWindow : public TextfileWindow { template void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) { - DeleteWindowById(WC_TEXTFILE, file_type); + CloseWindowById(WC_TEXTFILE, file_type); new BaseSetTextfileWindow(file_type, baseset, content_type); } @@ -174,8 +174,8 @@ struct GameOptionsWindow : Window { void Close() override { - DeleteWindowById(WC_CUSTOM_CURRENCY, 0); - DeleteWindowByClass(WC_TEXTFILE); + CloseWindowById(WC_CUSTOM_CURRENCY, 0); + CloseWindowByClass(WC_TEXTFILE); if (this->reload) _switch_mode = SM_MENU; this->Window::Close(); } @@ -532,7 +532,7 @@ struct GameOptionsWindow : Window { case WID_GO_LANG_DROPDOWN: // Change interface language ReadLanguagePack(&_languages[index]); - DeleteWindowByClass(WC_QUERY_STRING); + CloseWindowByClass(WC_QUERY_STRING); CheckForMissingGlyphs(); ClearAllCachedNames(); UpdateAllVirtCoords(); @@ -744,7 +744,7 @@ static WindowDesc _game_options_desc( /** Open the game options window. */ void ShowGameOptions() { - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); new GameOptionsWindow(&_game_options_desc); } @@ -2479,7 +2479,7 @@ static WindowDesc _settings_selection_desc( /** Open advanced settings window. */ void ShowGameSettings() { - DeleteWindowByClass(WC_GAME_OPTIONS); + CloseWindowByClass(WC_GAME_OPTIONS); new GameSettingsWindow(&_settings_selection_desc); } @@ -2771,6 +2771,6 @@ static WindowDesc _cust_currency_desc( /** Open custom currency window. */ static void ShowCustCurrency() { - DeleteWindowById(WC_CUSTOM_CURRENCY, 0); + CloseWindowById(WC_CUSTOM_CURRENCY, 0); new CustomCurrencyWindow(&_cust_currency_desc); } diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index d7d93c905a..27c618087c 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -579,7 +579,7 @@ void HandleClickOnSign(const Sign *si) void ShowRenameSignWindow(const Sign *si) { /* Delete all other edit windows */ - DeleteWindowByClass(WC_QUERY_STRING); + CloseWindowByClass(WC_QUERY_STRING); new SignWindow(&_query_sign_edit_desc, si); } diff --git a/src/station.cpp b/src/station.cpp index 8926773122..877f53d4e0 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -55,10 +55,10 @@ BaseStation::~BaseStation() if (CleaningPool()) return; - DeleteWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->index).Pack()); - DeleteWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->index).Pack()); - DeleteWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).Pack()); - DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).Pack()); + CloseWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->index).Pack()); + CloseWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->index).Pack()); + CloseWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).Pack()); + CloseWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).Pack()); this->sign.MarkDirty(); } @@ -143,7 +143,7 @@ Station::~Station() InvalidateWindowData(WC_STATION_LIST, this->owner, 0); } - DeleteWindowById(WC_STATION_VIEW, index); + CloseWindowById(WC_STATION_VIEW, index); /* Now delete all orders that go to the station */ RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 3e40ba3fce..52c7bc7561 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2396,7 +2396,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) for (uint i = 0; i < st->airport.GetNumHangars(); ++i) { TileIndex tile_cur = st->airport.GetHangarTile(i); OrderBackup::Reset(tile_cur, false); - DeleteWindowById(WC_VEHICLE_DEPOT, tile_cur); + CloseWindowById(WC_VEHICLE_DEPOT, tile_cur); } const AirportSpec *as = st->airport.GetSpec(); diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 7fb1b66a42..ffd4f14a7a 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1336,10 +1336,10 @@ struct StationViewWindow : public Window { void Close() override { - DeleteWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false); - DeleteWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->window_number).Pack(), false); - DeleteWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->window_number).Pack(), false); - DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false); + CloseWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false); + CloseWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->window_number).Pack(), false); + CloseWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->window_number).Pack(), false); + CloseWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false); SetViewportCatchmentStation(Station::Get(this->window_number), false); this->Window::Close(); @@ -2353,7 +2353,7 @@ struct SelectStationWindow : Window { DoCommandP(&this->select_station_cmd); /* Close Window; this might cause double frees! */ - DeleteWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_STATION, 0); } void OnRealtimeTick(uint delta_ms) override diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 51481e1c73..afa6db52f4 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -1218,7 +1218,7 @@ from = SLV_106 def = true str = STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS strhelp = STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS_HELPTEXT -post_cb = [](auto) { DeleteWindowById(WC_SELECT_STATION, 0); } +post_cb = [](auto) { CloseWindowById(WC_SELECT_STATION, 0); } ## [SDT_BOOL] diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 0e1896a440..6094c710fd 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -364,7 +364,7 @@ Window *ShowTerraformToolbar(Window *link) } /* Delete the terraform toolbar to place it again. */ - DeleteWindowById(WC_SCEN_LAND_GEN, 0, true); + CloseWindowById(WC_SCEN_LAND_GEN, 0, true); w = AllocateWindowDescFront(&_terraform_desc, 0); /* Align the terraform toolbar under the main toolbar. */ w->top -= w->height; diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index fa0e4d114f..4853181b31 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -237,7 +237,7 @@ struct TimetableWindow : Window { /* Removed / replaced all orders (after deleting / sharing) */ if (this->sel_index == -1) break; - this->DeleteChildWindows(); + this->CloseChildWindows(); this->sel_index = -1; break; @@ -276,7 +276,7 @@ struct TimetableWindow : Window { /* Now we are modifying the selected order */ if (to == INVALID_VEH_ORDER_ID) { /* Deleting selected order */ - this->DeleteChildWindows(); + this->CloseChildWindows(); this->sel_index = -1; break; } else { @@ -523,7 +523,7 @@ struct TimetableWindow : Window { case WID_VT_TIMETABLE_PANEL: { // Main panel. int selected = GetOrderFromTimetableWndPt(pt.y, v); - this->DeleteChildWindows(); + this->CloseChildWindows(); this->sel_index = (selected == INVALID_ORDER || selected == this->sel_index) ? -1 : selected; break; } @@ -707,7 +707,7 @@ static WindowDesc _timetable_desc( */ void ShowTimetableWindow(const Vehicle *v) { - DeleteWindowById(WC_VEHICLE_DETAILS, v->index, false); - DeleteWindowById(WC_VEHICLE_ORDERS, v->index, false); + CloseWindowById(WC_VEHICLE_DETAILS, v->index, false); + CloseWindowById(WC_VEHICLE_ORDERS, v->index, false); AllocateWindowDescFront(&_timetable_desc, v->index); } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index ee1ac343e4..627d133b5d 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -104,7 +104,7 @@ Town::~Town() /* Delete town authority window * and remove from list of sorted towns */ - DeleteWindowById(WC_TOWN_VIEW, this->index); + CloseWindowById(WC_TOWN_VIEW, this->index); /* Check no industry is related to us. */ #ifdef WITH_ASSERT diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 77ffa01614..47895122be 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1293,11 +1293,11 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ if (src == original_src_head && src->IsEngine() && !src->IsFrontEngine()) { /* Cases #2 and #3: the front engine gets trashed. */ - DeleteWindowById(WC_VEHICLE_VIEW, src->index); - DeleteWindowById(WC_VEHICLE_ORDERS, src->index); - DeleteWindowById(WC_VEHICLE_REFIT, src->index); - DeleteWindowById(WC_VEHICLE_DETAILS, src->index); - DeleteWindowById(WC_VEHICLE_TIMETABLE, src->index); + CloseWindowById(WC_VEHICLE_VIEW, src->index); + CloseWindowById(WC_VEHICLE_ORDERS, src->index); + CloseWindowById(WC_VEHICLE_REFIT, src->index); + CloseWindowById(WC_VEHICLE_DETAILS, src->index); + CloseWindowById(WC_VEHICLE_TIMETABLE, src->index); DeleteNewGRFInspectWindow(GSF_TRAINS, src->index); SetWindowDirty(WC_COMPANY, _current_company); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 90accdd80e..3c3125606d 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -843,11 +843,11 @@ void Vehicle::PreDestructor() } if (this->IsPrimaryVehicle()) { - DeleteWindowById(WC_VEHICLE_VIEW, this->index); - DeleteWindowById(WC_VEHICLE_ORDERS, this->index); - DeleteWindowById(WC_VEHICLE_REFIT, this->index); - DeleteWindowById(WC_VEHICLE_DETAILS, this->index); - DeleteWindowById(WC_VEHICLE_TIMETABLE, this->index); + CloseWindowById(WC_VEHICLE_VIEW, this->index); + CloseWindowById(WC_VEHICLE_ORDERS, this->index); + CloseWindowById(WC_VEHICLE_REFIT, this->index); + CloseWindowById(WC_VEHICLE_DETAILS, this->index); + CloseWindowById(WC_VEHICLE_TIMETABLE, this->index); SetWindowDirty(WC_COMPANY, this->owner); OrderBackup::ClearVehicle(this); } @@ -2795,7 +2795,7 @@ void Vehicle::RemoveFromShared() if (this->orders.list->GetNumVehicles() == 1) { /* When there is only one vehicle, remove the shared order list window. */ - DeleteWindowById(GetWindowClassForVehicleType(this->type), vli.Pack()); + CloseWindowById(GetWindowClassForVehicleType(this->type), vli.Pack()); InvalidateVehicleOrder(this->FirstShared(), VIWD_MODIFY_ORDERS); } else if (were_first) { /* If we were the first one, update to the new first one. diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 28155f7240..65e7931327 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1118,7 +1118,7 @@ static WindowDesc _vehicle_refit_desc( */ void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit) { - DeleteWindowById(WC_VEHICLE_REFIT, v->index); + CloseWindowById(WC_VEHICLE_REFIT, v->index); RefitWindow *w = new RefitWindow(&_vehicle_refit_desc, v, order, auto_refit); w->parent = parent; } @@ -2462,8 +2462,8 @@ static WindowDesc _nontrain_vehicle_details_desc( /** Shows the vehicle details window of the given vehicle. */ static void ShowVehicleDetailsWindow(const Vehicle *v) { - DeleteWindowById(WC_VEHICLE_ORDERS, v->index, false); - DeleteWindowById(WC_VEHICLE_TIMETABLE, v->index, false); + CloseWindowById(WC_VEHICLE_ORDERS, v->index, false); + CloseWindowById(WC_VEHICLE_TIMETABLE, v->index, false); AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_train_vehicle_details_desc : &_nontrain_vehicle_details_desc, v->index); } @@ -2720,10 +2720,10 @@ public: void Close() override { - DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number, false); - DeleteWindowById(WC_VEHICLE_REFIT, this->window_number, false); - DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number, false); - DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false); + CloseWindowById(WC_VEHICLE_ORDERS, this->window_number, false); + CloseWindowById(WC_VEHICLE_REFIT, this->window_number, false); + CloseWindowById(WC_VEHICLE_DETAILS, this->window_number, false); + CloseWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false); this->Window::Close(); } diff --git a/src/viewport.cpp b/src/viewport.cpp index d3488317e3..f9310dac8e 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2647,7 +2647,7 @@ static inline void ShowMeasurementTooltips(StringID str, uint paramcount, const static void HideMeasurementTooltips() { - DeleteWindowById(WC_TOOLTIPS, 0); + CloseWindowById(WC_TOOLTIPS, 0); } /** highlighting tiles while only going over them with the mouse */ diff --git a/src/waypoint.cpp b/src/waypoint.cpp index f602eee6d0..db1b36b1ec 100644 --- a/src/waypoint.cpp +++ b/src/waypoint.cpp @@ -51,7 +51,7 @@ void Waypoint::GetTileArea(TileArea *ta, StationType type) const Waypoint::~Waypoint() { if (CleaningPool()) return; - DeleteWindowById(WC_WAYPOINT_VIEW, this->index); + CloseWindowById(WC_WAYPOINT_VIEW, this->index); RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index); if (this->sign.kdtree_valid) _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeWaypoint(this->index)); } diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index 946d123c56..4dd2397b78 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -76,7 +76,7 @@ public: void Close() override { - DeleteWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false); + CloseWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false); this->Window::Close(); } diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 77b54d5646..f104be68c8 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -355,7 +355,7 @@ struct DropdownWindow : Window { */ void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width, bool instant_close) { - DeleteWindowById(WC_DROPDOWN_MENU, 0); + CloseWindowById(WC_DROPDOWN_MENU, 0); /* The preferred position is just below the dropdown calling widget */ int top = w->top + wi_rect.bottom + 1; diff --git a/src/window.cpp b/src/window.cpp index aae3efffb7..aead815ec5 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1076,10 +1076,10 @@ static Window *FindChildWindow(const Window *w, WindowClass wc) } /** - * Delete all children a window might have in a head-recursive manner + * Close all children a window might have in a head-recursive manner * @param wc Window class of the window to remove; #WC_INVALID if class does not matter */ -void Window::DeleteChildWindows(WindowClass wc) const +void Window::CloseChildWindows(WindowClass wc) const { Window *child = FindChildWindow(this, wc); while (child != nullptr) { @@ -1118,7 +1118,7 @@ void Window::Close() _focused_window = nullptr; } - this->DeleteChildWindows(); + this->CloseChildWindows(); this->SetDirty(); @@ -1170,12 +1170,12 @@ Window *FindWindowByClass(WindowClass cls) } /** - * Delete a window by its class and window number (if it is open). + * Close a window by its class and window number (if it is open). * @param cls Window class * @param number Number of the window within the window class - * @param force force deletion; if false don't delete when stickied + * @param force force closing; if false don't close when stickied */ -void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) +void CloseWindowById(WindowClass cls, WindowNumber number, bool force) { Window *w = FindWindowById(cls, number); if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) { @@ -1184,10 +1184,10 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) } /** - * Delete all windows of a given class + * Close all windows of a given class * @param cls Window class of windows to delete */ -void DeleteWindowByClass(WindowClass cls) +void CloseWindowByClass(WindowClass cls) { /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { @@ -1198,12 +1198,12 @@ void DeleteWindowByClass(WindowClass cls) } /** - * Delete all windows of a company. We identify windows of a company + * Close all windows of a company. We identify windows of a company * by looking at the caption colour. If it is equal to the company ID - * then we say the window belongs to the company and should be deleted + * then we say the window belongs to the company and should be closed * @param id company identifier */ -void DeleteCompanyWindows(CompanyID id) +void CloseCompanyWindows(CompanyID id) { /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { @@ -1213,7 +1213,7 @@ void DeleteCompanyWindows(CompanyID id) } /* Also delete the company specific windows that don't have a company-colour. */ - DeleteWindowById(WC_BUY_COMPANY, id); + CloseWindowById(WC_BUY_COMPANY, id); } /** @@ -2307,7 +2307,7 @@ static void StartWindowDrag(Window *w) _drag_delta.y = w->top - _cursor.pos.y; BringWindowToFront(w); - DeleteWindowById(WC_DROPDOWN_MENU, 0); + CloseWindowById(WC_DROPDOWN_MENU, 0); } /** @@ -2325,7 +2325,7 @@ static void StartWindowSizing(Window *w, bool to_left) _drag_delta.y = _cursor.pos.y; BringWindowToFront(w); - DeleteWindowById(WC_DROPDOWN_MENU, 0); + CloseWindowById(WC_DROPDOWN_MENU, 0); } /** @@ -3253,12 +3253,12 @@ void CallWindowGameTickEvent() } /** - * Try to delete a non-vital window. + * Try to close a non-vital window. * Non-vital windows are windows other than the game selection, main toolbar, * status bar, toolbar menu, and tooltip windows. Stickied windows are also * considered vital. */ -void DeleteNonVitalWindows() +void CloseNonVitalWindows() { /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { @@ -3281,12 +3281,12 @@ void DeleteNonVitalWindows() * then, does a little hacked loop of closing all stickied windows. Note * that standard windows (status bar, etc.) are not stickied, so these aren't affected */ -void DeleteAllNonVitalWindows() +void CloseAllNonVitalWindows() { - /* Delete every window except for stickied ones, then sticky ones as well */ - DeleteNonVitalWindows(); + /* Close every window except for stickied ones, then sticky ones as well */ + CloseNonVitalWindows(); - /* Note: the container remains stable, even when deleting windows. */ + /* Note: the container remains stable, even when closing windows. */ for (Window *w : Window::Iterate()) { if (w->flags & WF_STICKY) { w->Close(); @@ -3295,21 +3295,21 @@ void DeleteAllNonVitalWindows() } /** - * Delete all messages and their corresponding window (if any). + * Delete all messages and close their corresponding window (if any). */ void DeleteAllMessages() { InitNewsItemStructs(); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); // invalidate the statusbar InvalidateWindowData(WC_MESSAGE_HISTORY, 0); // invalidate the message history - DeleteWindowById(WC_NEWS_WINDOW, 0); // close newspaper or general message window if shown + CloseWindowById(WC_NEWS_WINDOW, 0); // close newspaper or general message window if shown } /** - * Delete all windows that are used for construction of vehicle etc. + * Close all windows that are used for construction of vehicle etc. * Once done with that invalidate the others to ensure they get refreshed too. */ -void DeleteConstructionWindows() +void CloseConstructionWindows() { /* Note: the container remains stable, even when deleting windows. */ for (Window *w : Window::Iterate()) { @@ -3321,11 +3321,11 @@ void DeleteConstructionWindows() for (const Window *w : Window::Iterate()) w->SetDirty(); } -/** Delete all always on-top windows to get an empty screen */ +/** Close all always on-top windows to get an empty screen */ void HideVitalWindows() { - DeleteWindowById(WC_MAIN_TOOLBAR, 0); - DeleteWindowById(WC_STATUS_BAR, 0); + CloseWindowById(WC_MAIN_TOOLBAR, 0); + CloseWindowById(WC_STATUS_BAR, 0); } /** Re-initialize all windows. */ @@ -3443,7 +3443,7 @@ void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index) */ void RelocateAllWindows(int neww, int newh) { - DeleteWindowById(WC_DROPDOWN_MENU, 0); + CloseWindowById(WC_DROPDOWN_MENU, 0); for (Window *w : Window::Iterate()) { int left, top; diff --git a/src/window_func.h b/src/window_func.h index fba00944a5..d68b7ba1c1 100644 --- a/src/window_func.h +++ b/src/window_func.h @@ -36,10 +36,10 @@ void InputLoop(); void InvalidateWindowData(WindowClass cls, WindowNumber number, int data = 0, bool gui_scope = false); void InvalidateWindowClassesData(WindowClass cls, int data = 0, bool gui_scope = false); -void DeleteNonVitalWindows(); -void DeleteAllNonVitalWindows(); +void CloseNonVitalWindows(); +void CloseAllNonVitalWindows(); void DeleteAllMessages(); -void DeleteConstructionWindows(); +void CloseConstructionWindows(); void HideVitalWindows(); void ShowVitalWindows(); @@ -53,8 +53,8 @@ void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_inde void SetWindowDirty(WindowClass cls, WindowNumber number); void SetWindowClassesDirty(WindowClass cls); -void DeleteWindowById(WindowClass cls, WindowNumber number, bool force = true); -void DeleteWindowByClass(WindowClass cls); +void CloseWindowById(WindowClass cls, WindowNumber number, bool force = true); +void CloseWindowByClass(WindowClass cls); bool EditBoxInGlobalFocus(); bool FocusedWindowIsConsole(); diff --git a/src/window_gui.h b/src/window_gui.h index c84ad333b8..58d14a54e7 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -509,7 +509,7 @@ public: void DrawSortButtonState(int widget, SortButtonState state) const; static int SortButtonWidth(); - void DeleteChildWindows(WindowClass wc = WC_INVALID) const; + void CloseChildWindows(WindowClass wc = WC_INVALID) const; virtual void Close(); static void DeleteClosedWindows(); From d70fb74ac669bdb64b5f594894629ec91801fd76 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 29 May 2021 23:27:01 +0200 Subject: [PATCH 278/800] Codechange: use setting name instead of index for CmdChange(Company)Setting (#9306) This is mostly done as there are now constraints on settings.ini you might not expected. For example, conditional settings always have to come last, as otherwise they would influence the index. --- src/autoreplace_gui.cpp | 2 +- src/script/api/script_company.cpp | 6 +- src/script/api/script_gamesettings.cpp | 2 +- src/script/api/script_group.cpp | 2 +- src/settings.cpp | 172 ++++++++++--------------- src/settings_func.h | 1 - src/settings_internal.h | 1 - src/table/settings/settings.ini | 36 +++--- 8 files changed, 87 insertions(+), 135 deletions(-) diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index a7bd071db1..9f2deaf10a 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -544,7 +544,7 @@ public: DoCommandP(0, this->sel_group | (GroupFlags::GF_REPLACE_WAGON_REMOVAL << 16), (HasBit(g->flags, GroupFlags::GF_REPLACE_WAGON_REMOVAL) ? 0 : 1) | (_ctrl_pressed << 1), CMD_SET_GROUP_FLAG); } else { // toggle renew_keep_length - DoCommandP(0, GetCompanySettingIndex("company.renew_keep_length"), Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1, CMD_CHANGE_COMPANY_SETTING); + DoCommandP(0, 0, Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1, CMD_CHANGE_COMPANY_SETTING, nullptr, "company.renew_keep_length"); } break; } diff --git a/src/script/api/script_company.cpp b/src/script/api/script_company.cpp index 20f1b3f7a1..9f5722c100 100644 --- a/src/script/api/script_company.cpp +++ b/src/script/api/script_company.cpp @@ -260,7 +260,7 @@ /* static */ bool ScriptCompany::SetAutoRenewStatus(bool autorenew) { - return ScriptObject::DoCommand(0, ::GetCompanySettingIndex("company.engine_renew"), autorenew ? 1 : 0, CMD_CHANGE_COMPANY_SETTING); + return ScriptObject::DoCommand(0, 0, autorenew ? 1 : 0, CMD_CHANGE_COMPANY_SETTING, "company.engine_renew"); } /* static */ bool ScriptCompany::GetAutoRenewStatus(CompanyID company) @@ -273,7 +273,7 @@ /* static */ bool ScriptCompany::SetAutoRenewMonths(int16 months) { - return ScriptObject::DoCommand(0, ::GetCompanySettingIndex("company.engine_renew_months"), months, CMD_CHANGE_COMPANY_SETTING); + return ScriptObject::DoCommand(0, 0, months, CMD_CHANGE_COMPANY_SETTING, "company.engine_renew_months"); } /* static */ int16 ScriptCompany::GetAutoRenewMonths(CompanyID company) @@ -288,7 +288,7 @@ { EnforcePrecondition(false, money >= 0); EnforcePrecondition(false, (int64)money <= UINT32_MAX); - return ScriptObject::DoCommand(0, ::GetCompanySettingIndex("company.engine_renew_money"), money, CMD_CHANGE_COMPANY_SETTING); + return ScriptObject::DoCommand(0, 0, money, CMD_CHANGE_COMPANY_SETTING, "company.engine_renew_money"); } /* static */ Money ScriptCompany::GetAutoRenewMoney(CompanyID company) diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 8b0459367e..0ade2d7cc6 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -39,7 +39,7 @@ if ((sd->save.conv & SLF_NO_NETWORK_SYNC) != 0) return false; - return ScriptObject::DoCommand(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING); + return ScriptObject::DoCommand(0, 0, value, CMD_CHANGE_SETTING, sd->name); } /* static */ bool ScriptGameSettings::IsDisabledVehicleType(ScriptVehicle::VehicleType vehicle_type) diff --git a/src/script/api/script_group.cpp b/src/script/api/script_group.cpp index 9cf6c7c957..0295c67aa7 100644 --- a/src/script/api/script_group.cpp +++ b/src/script/api/script_group.cpp @@ -118,7 +118,7 @@ { if (HasWagonRemoval() == enable_removal) return true; - return ScriptObject::DoCommand(0, ::GetCompanySettingIndex("company.renew_keep_length"), enable_removal ? 1 : 0, CMD_CHANGE_COMPANY_SETTING); + return ScriptObject::DoCommand(0, 0, enable_removal ? 1 : 0, CMD_CHANGE_COMPANY_SETTING, "company.renew_keep_length"); } /* static */ bool ScriptGroup::HasWagonRemoval() diff --git a/src/settings.cpp b/src/settings.cpp index c26b3bb47c..56c02e5e19 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -103,17 +103,6 @@ const SettingDesc *GetSettingDescription(uint index) return _settings.begin()[index].get(); } -/** - * Get the setting at the given index into the company settings table. - * @param index The index to look for. - * @return The setting at the given index, or nullptr when the index is invalid. - */ -static const SettingDesc *GetCompanySettingDescription(uint index) -{ - if (index >= _company_settings.size()) return nullptr; - return _company_settings.begin()[index].get(); -} - /** * Groups in openttd.cfg that are actually lists. */ @@ -1709,20 +1698,75 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const if (_save_config) SaveToConfig(); } +/** + * Given a name of setting, return a setting description from the table. + * @param name Name of the setting to return a setting description of. + * @param settings Table to look in for the setting. + * @return Pointer to the setting description of setting \a name if it can be found, + * \c nullptr indicates failure to obtain the description. + */ +static const SettingDesc *GetSettingFromName(const char *name, const SettingTable &settings) +{ + /* First check all full names */ + for (auto &sd : settings) { + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (strcmp(sd->name, name) == 0) return sd.get(); + } + + /* Then check the shortcut variant of the name. */ + for (auto &sd : settings) { + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + const char *short_name = strchr(sd->name, '.'); + if (short_name != nullptr) { + short_name++; + if (strcmp(short_name, name) == 0) return sd.get(); + } + } + + return nullptr; +} + +/** + * Given a name of setting, return a company setting description of it. + * @param name Name of the company setting to return a setting description of. + * @return Pointer to the setting description of setting \a name if it can be found, + * \c nullptr indicates failure to obtain the description. + */ +static const SettingDesc *GetCompanySettingFromName(const char *name) +{ + if (strncmp(name, "company.", 8) == 0) name += 8; + return GetSettingFromName(name, _company_settings); +} + +/** + * Given a name of any setting, return any setting description of it. + * @param name Name of the setting to return a setting description of. + * @return Pointer to the setting description of setting \a name if it can be found, + * \c nullptr indicates failure to obtain the description. + */ +const SettingDesc *GetSettingFromName(const char *name) +{ + auto sd = GetSettingFromName(name, _settings); + if (sd != nullptr) return sd; + + return GetCompanySettingFromName(name); +} + /** * Network-safe changing of settings (server-only). * @param tile unused * @param flags operation to perform - * @param p1 the index of the setting in the SettingDesc array which identifies it + * @param p1 unused * @param p2 the new value for the setting * The new value is properly clamped to its minimum/maximum when setting - * @param text unused + * @param text the name of the setting to change * @return the cost of this operation or an error * @see _settings */ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { - const SettingDesc *sd = GetSettingDescription(p1); + if (text.empty()) return CMD_ERROR; + const SettingDesc *sd = GetSettingFromName(text.c_str()); if (sd == nullptr) return CMD_ERROR; if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR; @@ -1741,15 +1785,17 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin * Change one of the per-company settings. * @param tile unused * @param flags operation to perform - * @param p1 the index of the setting in the _company_settings array which identifies it + * @param p1 unused * @param p2 the new value for the setting * The new value is properly clamped to its minimum/maximum when setting - * @param text unused + * @param text the name of the company setting to change * @return the cost of this operation or an error */ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { - const SettingDesc *sd = GetCompanySettingDescription(p1); + if (text.empty()) return CMD_ERROR; + const SettingDesc *sd = GetCompanySettingFromName(text.c_str()); + if (sd == nullptr) return CMD_ERROR; if (!sd->IsIntSetting()) return CMD_ERROR; @@ -1760,44 +1806,6 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 return CommandCost(); } -/** - * Get the index of the given setting in the setting table. - * @param settings The settings to look through. - * @param setting The setting to look for. - * @return The index, or UINT32_MAX when it has not been found. - */ -static uint GetSettingIndex(const SettingTable &settings, const SettingDesc *setting) -{ - uint index = 0; - for (auto &sd : settings) { - if (sd.get() == setting) return index; - index++; - } - return UINT32_MAX; -} - -/** - * Get the index of the setting with this description. - * @param sd the setting to get the index for. - * @return the index of the setting to be used for CMD_CHANGE_SETTING. - */ -uint GetSettingIndex(const SettingDesc *sd) -{ - assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) == 0); - return GetSettingIndex(_settings, sd); -} - -/** - * Get the index of the company setting with this description. - * @param sd the setting to get the index for. - * @return the index of the setting to be used for CMD_CHANGE_COMPANY_SETTING. - */ -static uint GetCompanySettingIndex(const SettingDesc *sd) -{ - assert(sd != nullptr && (sd->flags & SGF_PER_COMPANY) != 0); - return GetSettingIndex(_company_settings, sd); -} - /** * Top function to save the new value of an element of the Settings struct * @param index offset in the SettingDesc array of the Settings struct which @@ -1810,7 +1818,7 @@ bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) const IntSettingDesc *setting = sd->AsIntSetting(); if ((setting->flags & SGF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { - return DoCommandP(0, GetCompanySettingIndex(setting), value, CMD_CHANGE_COMPANY_SETTING); + return DoCommandP(0, 0, value, CMD_CHANGE_COMPANY_SETTING, nullptr, setting->name); } setting->ChangeValue(&_settings_client.company, value); @@ -1836,7 +1844,7 @@ bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) /* send non-company-based settings over the network */ if (!_networking || (_networking && _network_server)) { - return DoCommandP(0, GetSettingIndex(setting), value, CMD_CHANGE_SETTING); + return DoCommandP(0, 0, value, CMD_CHANGE_SETTING, nullptr, setting->name); } return false; } @@ -1860,25 +1868,13 @@ void SyncCompanySettings() { const void *old_object = &Company::Get(_current_company)->settings; const void *new_object = &_settings_client.company; - uint i = 0; for (auto &sd : _company_settings) { uint32 old_value = (uint32)sd->AsIntSetting()->Read(new_object); uint32 new_value = (uint32)sd->AsIntSetting()->Read(old_object); - if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, {}, _local_company); - i++; + if (old_value != new_value) NetworkSendCommand(0, 0, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, sd->name, _local_company); } } -/** - * Get the index in the _company_settings array of a setting - * @param name The name of the setting - * @return The index in the _company_settings array - */ -uint GetCompanySettingIndex(const char *name) -{ - return GetCompanySettingIndex(GetSettingFromName(name)); -} - /** * Set a setting value with a string. * @param sd the setting to change. @@ -1916,47 +1912,11 @@ void StringSettingDesc::ChangeValue(const void *object, std::string &newval) con if (_save_config) SaveToConfig(); } -/** - * Given a name of setting, return a setting description of it. - * @param name Name of the setting to return a setting description of - * @param i Pointer to an integer that will contain the index of the setting after the call, if it is successful. - * @return Pointer to the setting description of setting \a name if it can be found, - * \c nullptr indicates failure to obtain the description - */ -const SettingDesc *GetSettingFromName(const char *name) -{ - /* First check all full names */ - for (auto &sd : _settings) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->name, name) == 0) return sd.get(); - } - - /* Then check the shortcut variant of the name. */ - for (auto &sd : _settings) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - const char *short_name = strchr(sd->name, '.'); - if (short_name != nullptr) { - short_name++; - if (strcmp(short_name, name) == 0) return sd.get(); - } - } - - if (strncmp(name, "company.", 8) == 0) name += 8; - /* And finally the company-based settings */ - for (auto &sd : _company_settings) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->name, name) == 0) return sd.get(); - } - - return nullptr; -} - /* Those 2 functions need to be here, else we have to make some stuff non-static * and besides, it is also better to keep stuff like this at the same place */ void IConsoleSetSetting(const char *name, const char *value, bool force_newgame) { const SettingDesc *sd = GetSettingFromName(name); - if (sd == nullptr) { IConsolePrintF(CC_WARNING, "'%s' is an unknown setting.", name); return; diff --git a/src/settings_func.h b/src/settings_func.h index 4a55821cf6..d1ecdbac1d 100644 --- a/src/settings_func.h +++ b/src/settings_func.h @@ -32,7 +32,6 @@ struct GRFConfig *LoadGRFPresetFromConfig(const char *config_name); void SaveGRFPresetToConfig(const char *config_name, struct GRFConfig *config); void DeleteGRFPresetFromConfig(const char *config_name); -uint GetCompanySettingIndex(const char *name); void SetDefaultCompanySettings(CompanyID cid); void SyncCompanySettings(); diff --git a/src/settings_internal.h b/src/settings_internal.h index 4de0178379..ba5331288c 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -302,6 +302,5 @@ typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame = false); bool SetSettingValue(const StringSettingDesc *sd, const std::string value, bool force_newgame = false); -uint GetSettingIndex(const SettingDesc *sd); #endif /* SETTINGS_INTERNAL_H */ diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index afa6db52f4..4f9ea607ab 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -2533,6 +2533,21 @@ str = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT cat = SC_BASIC +; We might need to emulate a right mouse button on mac +[SDTC_VAR] +ifdef = __APPLE__ +var = gui.right_mouse_btn_emulation +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = 0 +min = 0 +max = 2 +str = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU +strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_HELPTEXT +strval = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND +cat = SC_BASIC + [SDTC_BOOL] var = gui.measure_tooltip flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -3873,24 +3888,3 @@ var = network.no_http_content_downloads flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false cat = SC_EXPERT - -; Since the network code (CmdChangeSetting and friends) use the index in this array to decide -; which setting the server is talking about all conditional compilation of this array must be at the -; end. This isn't really the best solution, the settings the server can tell the client about should -; either use a separate array or some other form of identifier. - -; -; We might need to emulate a right mouse button on mac -[SDTC_VAR] -ifdef = __APPLE__ -var = gui.right_mouse_btn_emulation -type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING -def = 0 -min = 0 -max = 2 -str = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU -strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_HELPTEXT -strval = STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND -cat = SC_BASIC From 8b9f1147dfec4efe3451dd3e111276a1dab3bb99 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 19:29:14 +0200 Subject: [PATCH 279/800] Codechange: [Network] Let server changing a client name use std::string --- src/console_cmds.cpp | 2 +- src/network/network_func.h | 2 +- src/network/network_server.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 39a52f0b5e..e86e2a0d99 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -724,7 +724,7 @@ DEF_CONSOLE_CMD(ConClientNickChange) return true; } - if (!NetworkServerChangeClientName(client_id, client_name.c_str())) { + if (!NetworkServerChangeClientName(client_id, client_name)) { IConsoleError("Cannot give a client a duplicate name"); } diff --git a/src/network/network_func.h b/src/network/network_func.h index d30616fd0a..a50166e2ae 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -73,7 +73,7 @@ void NetworkServerUpdateGameInfo(); void NetworkServerShowStatusToConsole(); bool NetworkServerStart(); void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci); -bool NetworkServerChangeClientName(ClientID client_id, const char *new_name); +bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name); void NetworkServerDoMove(ClientID client_id, CompanyID company_id); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index fe585c03ce..b770dbda3e 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1719,7 +1719,7 @@ bool NetworkFindName(char *new_name, const char *last) * @param new_name the new name for the client * @return true iff the name was changed */ -bool NetworkServerChangeClientName(ClientID client_id, const char *new_name) +bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name) { /* Check if the name's already in use */ for (NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { From f0e1cd01298237dc32413fb0c19e145c45baa2e8 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 19:33:42 +0200 Subject: [PATCH 280/800] Codechange: [Network] Let server rcon result use std::string --- src/network/network_func.h | 2 +- src/network/network_server.cpp | 12 +++++------- src/network/network_server.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/network/network_func.h b/src/network/network_func.h index a50166e2ae..6a21eb80ac 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -77,7 +77,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_na void NetworkServerDoMove(ClientID client_id, CompanyID company_id); -void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string); +void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string); void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, ClientID from_id, int64 data = 0, bool from_admin = false); void NetworkServerKickClient(ClientID client_id, const char *reason); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index b770dbda3e..d15263e531 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -785,7 +785,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGame() * @param colour The colour of the result. * @param command The command that was executed. */ -NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16 colour, const char *command) +NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16 colour, const std::string &command) { Packet *p = new Packet(PACKET_SERVER_RCON); @@ -1424,22 +1424,20 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p) { if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - char command[NETWORK_RCONCOMMAND_LENGTH]; - if (_settings_client.network.rcon_password.empty()) return NETWORK_RECV_STATUS_OKAY; std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH); - p->Recv_string(command, sizeof(command)); + std::string command = p->Recv_string(NETWORK_RCONCOMMAND_LENGTH); if (_settings_client.network.rcon_password.compare(password) != 0) { DEBUG(net, 1, "[rcon] Wrong password from client-id %d", this->client_id); return NETWORK_RECV_STATUS_OKAY; } - DEBUG(net, 3, "[rcon] Client-id %d executed: %s", this->client_id, command); + DEBUG(net, 3, "[rcon] Client-id %d executed: %s", this->client_id, command.c_str()); _redirect_console_to_client = this->client_id; - IConsoleCmdExec(command); + IConsoleCmdExec(command.c_str()); _redirect_console_to_client = INVALID_CLIENT_ID; return NETWORK_RECV_STATUS_OKAY; } @@ -2046,7 +2044,7 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id) * @param colour_code The colour of the text. * @param string The actual reply. */ -void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string) +void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string) { NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string); } diff --git a/src/network/network_server.h b/src/network/network_server.h index 98b2f9b6eb..850b560079 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -89,7 +89,7 @@ public: NetworkRecvStatus SendQuit(ClientID client_id); NetworkRecvStatus SendShutdown(); NetworkRecvStatus SendNewGame(); - NetworkRecvStatus SendRConResult(uint16 colour, const char *command); + NetworkRecvStatus SendRConResult(uint16 colour, const std::string &command); NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id); NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci); From fd95736bac4ef79ba36cff18d09c039a1c713f80 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 19:47:58 +0200 Subject: [PATCH 281/800] Codechange: [Network] Use std::string for server side logic of kicking and banning clients --- src/console_cmds.cpp | 6 +++--- src/network/network_func.h | 6 +++--- src/network/network_gui.cpp | 4 ++-- src/network/network_server.cpp | 14 +++++++------- src/network/network_server.h | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index e86e2a0d99..3c5ca5d24b 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -473,7 +473,7 @@ DEF_CONSOLE_CMD(ConClearBuffer) * Network Core Console Commands **********************************/ -static bool ConKickOrBan(const char *argv, bool ban, const char *reason) +static bool ConKickOrBan(const char *argv, bool ban, const std::string &reason) { uint n; @@ -527,7 +527,7 @@ DEF_CONSOLE_CMD(ConKick) if (argc != 2 && argc != 3) return false; /* No reason supplied for kicking */ - if (argc == 2) return ConKickOrBan(argv[1], false, nullptr); + if (argc == 2) return ConKickOrBan(argv[1], false, {}); /* Reason for kicking supplied */ size_t kick_message_length = strlen(argv[2]); @@ -551,7 +551,7 @@ DEF_CONSOLE_CMD(ConBan) if (argc != 2 && argc != 3) return false; /* No reason supplied for kicking */ - if (argc == 2) return ConKickOrBan(argv[1], true, nullptr); + if (argc == 2) return ConKickOrBan(argv[1], true, {}); /* Reason for kicking supplied */ size_t kick_message_length = strlen(argv[2]); diff --git a/src/network/network_func.h b/src/network/network_func.h index 6a21eb80ac..22ed04c32e 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -80,9 +80,9 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id); void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string); void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &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); -uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason); +void NetworkServerKickClient(ClientID client_id, const std::string &reason); +uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const std::string &reason); +uint NetworkServerKickOrBanIP(const std::string &ip, bool ban, const std::string &reason); void NetworkInitChatMessage(); void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index bd91cc25ad..9048ad8549 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1661,7 +1661,7 @@ enum DropDownAdmin { */ static void AdminClientKickCallback(Window *w, bool confirmed) { - if (confirmed) NetworkServerKickClient(_admin_client_id, nullptr); + if (confirmed) NetworkServerKickClient(_admin_client_id, {}); } /** @@ -1671,7 +1671,7 @@ static void AdminClientKickCallback(Window *w, bool confirmed) */ static void AdminClientBanCallback(Window *w, bool confirmed) { - if (confirmed) NetworkServerKickOrBanIP(_admin_client_id, true, nullptr); + if (confirmed) NetworkServerKickOrBanIP(_admin_client_id, true, {}); } /** diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index d15263e531..b981b11a00 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -429,12 +429,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() * @param error The error to disconnect for. * @param reason In case of kicking a client, specifies the reason for kicking the client. */ -NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error, const char *reason) +NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error, const std::string &reason) { Packet *p = new Packet(PACKET_SERVER_ERROR); p->Send_uint8(error); - if (reason != nullptr) p->Send_string(reason); + if (!reason.empty()) p->Send_string(reason); this->SendPacket(p); StringID strid = GetNetworkErrorMsg(error); @@ -447,7 +447,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err DEBUG(net, 1, "'%s' made an error and has been disconnected: %s", client_name, GetString(strid).c_str()); - if (error == NETWORK_ERROR_KICKED && reason != nullptr) { + if (error == NETWORK_ERROR_KICKED && !reason.empty()) { NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid); } else { NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid); @@ -2054,7 +2054,7 @@ void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std * @param client_id The client to kick. * @param reason In case of kicking a client, specifies the reason for kicking the client. */ -void NetworkServerKickClient(ClientID client_id, const char *reason) +void NetworkServerKickClient(ClientID client_id, const std::string &reason) { if (client_id == CLIENT_ID_SERVER) return; NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason); @@ -2066,7 +2066,7 @@ void NetworkServerKickClient(ClientID client_id, const char *reason) * @param ban Whether to ban or kick. * @param reason In case of kicking a client, specifies the reason for kicking the client. */ -uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason) +uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const std::string &reason) { return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason); } @@ -2077,7 +2077,7 @@ uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason) * @param ban Whether to ban or just kick. * @param reason In case of kicking a client, specifies the reason for kicking the client. */ -uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason) +uint NetworkServerKickOrBanIP(const std::string &ip, bool ban, const std::string &reason) { /* Add address to ban-list */ if (ban) { @@ -2101,7 +2101,7 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason) for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { if (cs->client_id == CLIENT_ID_SERVER) continue; if (cs->client_id == _redirect_console_to_client) continue; - if (cs->client_address.IsInNetmask(ip)) { + if (cs->client_address.IsInNetmask(ip.c_str())) { NetworkServerKickClient(cs->client_id, reason); n++; } diff --git a/src/network/network_server.h b/src/network/network_server.h index 850b560079..7a3fa3eacd 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -93,7 +93,7 @@ public: NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id); NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci); - NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason = nullptr); + NetworkRecvStatus SendError(NetworkErrorCode error, const std::string &reason = {}); NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64 data); NetworkRecvStatus SendJoin(ClientID client_id); NetworkRecvStatus SendFrame(); From 806f78aa04155c667f9f2090f54898d5f66c3144 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 19:52:11 +0200 Subject: [PATCH 282/800] Codechange: [Network] Use std::string to send the client name and rcon commands --- src/network/network_client.cpp | 8 ++++---- src/network/network_client.h | 4 ++-- src/network/network_func.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 161bbf4122..ae483508ad 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -491,7 +491,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetPassword(const std::str * Tell the server that we like to change the name of the client. * @param name The new name. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetName(const char *name) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetName(const std::string &name) { Packet *p = new Packet(PACKET_CLIENT_SET_NAME); @@ -516,7 +516,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendQuit() * @param pass The password for the remote command. * @param command The actual command. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const std::string &pass, const char *command) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const std::string &pass, const std::string &command) { Packet *p = new Packet(PACKET_CLIENT_RCON); p->Send_string(pass); @@ -1258,7 +1258,7 @@ void NetworkClient_Connected() * @param password The password. * @param command The command to execute. */ -void NetworkClientSendRcon(const std::string &password, const char *command) +void NetworkClientSendRcon(const std::string &password, const std::string &command) { MyClient::SendRCon(password, command); } @@ -1355,7 +1355,7 @@ void NetworkUpdateClientName(const std::string &client_name) /* Don't change the name if it is the same as the old name */ if (client_name.compare(ci->client_name) != 0) { if (!_network_server) { - MyClient::SendSetName(client_name.c_str()); + MyClient::SendSetName(client_name); } else { /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ char temporary_name[NETWORK_CLIENT_NAME_LENGTH]; diff --git a/src/network/network_client.h b/src/network/network_client.h index 169820d969..37deece813 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -95,8 +95,8 @@ public: static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data); static NetworkRecvStatus SendSetPassword(const std::string &password); - static NetworkRecvStatus SendSetName(const char *name); - static NetworkRecvStatus SendRCon(const std::string &password, const char *command); + static NetworkRecvStatus SendSetName(const std::string &name); + static NetworkRecvStatus SendRCon(const std::string &password, const std::string &command); static NetworkRecvStatus SendMove(CompanyID company, const std::string &password); static bool IsConnected(); diff --git a/src/network/network_func.h b/src/network/network_func.h index 22ed04c32e..ec27d4b785 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -55,7 +55,7 @@ void NetworkClientsToSpectators(CompanyID cid); bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password = "", const std::string &join_company_password = ""); void NetworkClientJoinGame(); void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); -void NetworkClientSendRcon(const std::string &password, const char *command); +void NetworkClientSendRcon(const std::string &password, const std::string &command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); bool NetworkCompanyIsPassworded(CompanyID company_id); From e3c9ed4d151a021e3f10492744915fc15b0bc0d6 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 20:22:41 +0200 Subject: [PATCH 283/800] Codechange: [Network] Use std::string to determine an unique name for clients --- src/network/network_client.cpp | 5 ++-- src/network/network_internal.h | 2 +- src/network/network_server.cpp | 47 +++++++++++++++------------------- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index ae483508ad..34129ad76b 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1358,9 +1358,8 @@ void NetworkUpdateClientName(const std::string &client_name) MyClient::SendSetName(client_name); } else { /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ - char temporary_name[NETWORK_CLIENT_NAME_LENGTH]; - strecpy(temporary_name, client_name.c_str(), lastof(temporary_name)); - if (NetworkFindName(temporary_name, lastof(temporary_name))) { + std::string temporary_name = client_name; + if (NetworkMakeClientNameUnique(temporary_name)) { NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); ci->client_name = temporary_name; NetworkUpdateClientInfo(CLIENT_ID_SERVER); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index d1db971a32..b7e6f4ecef 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -117,7 +117,7 @@ void ShowNetworkError(StringID error_string); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0); uint NetworkCalculateLag(const NetworkClientSocket *cs); StringID GetNetworkErrorMsg(NetworkErrorCode err); -bool NetworkFindName(char *new_name, const char *last); +bool NetworkMakeClientNameUnique(std::string &new_name); std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32 password_game_seed); NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index b981b11a00..49b1c8faf1 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -874,8 +874,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char name[NETWORK_CLIENT_NAME_LENGTH]; - CompanyID playas; char client_revision[NETWORK_REVISION_LENGTH]; p->Recv_string(client_revision, sizeof(client_revision)); @@ -887,8 +885,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) return this->SendError(NETWORK_ERROR_WRONG_REVISION); } - p->Recv_string(name, sizeof(name)); - playas = (Owner)p->Recv_uint8(); + std::string client_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH); + CompanyID playas = (Owner)p->Recv_uint8(); if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; @@ -911,14 +909,14 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) break; } - if (!NetworkIsValidClientName(name)) { + if (!NetworkIsValidClientName(client_name)) { /* An invalid client name was given. However, the client ensures the name * is valid before it is sent over the network, so something went horribly * wrong. This is probably someone trying to troll us. */ return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME); } - if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate + if (!NetworkMakeClientNameUnique(client_name)) { // Change name if duplicate /* We could not create a name for this client */ return this->SendError(NETWORK_ERROR_NAME_IN_USE); } @@ -927,7 +925,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) NetworkClientInfo *ci = new NetworkClientInfo(this->client_id); this->SetInfo(ci); ci->join_date = _date; - ci->client_name = name; + ci->client_name = client_name; ci->client_playas = playas; DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index); @@ -1394,10 +1392,9 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char client_name[NETWORK_CLIENT_NAME_LENGTH]; NetworkClientInfo *ci; - p->Recv_string(client_name, sizeof(client_name)); + std::string client_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH); ci = this->GetInfo(); if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; @@ -1411,7 +1408,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet } /* Display change */ - if (NetworkFindName(client_name, lastof(client_name))) { + if (NetworkMakeClientNameUnique(client_name)) { NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name); ci->client_name = client_name; NetworkUpdateClientInfo(ci->client_id); @@ -1673,42 +1670,40 @@ static void NetworkAutoCleanCompanies() /** * Check whether a name is unique, and otherwise try to make it unique. * @param new_name The name to check/modify. - * @param last The last writeable element of the buffer. * @return True if an unique name was achieved. */ -bool NetworkFindName(char *new_name, const char *last) +bool NetworkMakeClientNameUnique(std::string &name) { - bool found_name = false; + bool is_name_unique = false; uint number = 0; - char original_name[NETWORK_CLIENT_NAME_LENGTH]; + std::string original_name = name; - strecpy(original_name, new_name, lastof(original_name)); - - while (!found_name) { - found_name = true; + while (!is_name_unique) { + is_name_unique = true; for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (ci->client_name.compare(new_name) == 0) { + if (ci->client_name.compare(name) == 0) { /* Name already in use */ - found_name = false; + is_name_unique = false; break; } } /* Check if it is the same as the server-name */ const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); if (ci != nullptr) { - if (ci->client_name.compare(new_name) == 0) found_name = false; // name already in use + if (ci->client_name.compare(name) == 0) is_name_unique = false; // name already in use } - if (!found_name) { + if (!is_name_unique) { /* Try a new name ( #1, #2, and so on) */ + name = original_name + " #" + std::to_string(number); - /* Something's really wrong when there're more names than clients */ - if (number++ > MAX_CLIENTS) break; - seprintf(new_name, last, "%s #%d", original_name, number); + /* The constructed client name is larger than the limit, + * so... bail out as no valid name can be created. */ + if (name.size() >= NETWORK_CLIENT_NAME_LENGTH) return false; } } - return found_name; + return is_name_unique; } /** From 97c461d1e73f228dd366cd8f062701062edd9bd1 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 29 May 2021 14:02:04 +0200 Subject: [PATCH 284/800] Fix: limit heightmap sizes to something reasonable to prevent crafted heightmaps to OOM-crash the game --- src/heightmap.cpp | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/heightmap.cpp b/src/heightmap.cpp index 458b0c910a..0c726371ce 100644 --- a/src/heightmap.cpp +++ b/src/heightmap.cpp @@ -22,6 +22,40 @@ #include "safeguards.h" +/** + * Maximum number of pixels for one dimension of a heightmap image. + * Do not allow images for which the longest side is twice the maximum number of + * tiles along the longest side of the (tile) map. + */ +static const uint MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS = 2 * MAX_MAP_SIZE; + +/* + * Maximum size in pixels of the heightmap image. + */ +static const uint MAX_HEIGHTMAP_SIZE_PIXELS = 256 << 20; // ~256 million +/* + * When loading a PNG or BMP the 24 bpp variant requires at least 4 bytes per pixel + * of memory to load the data. Make sure the "reasonable" limit is well within the + * maximum amount of memory allocatable on 32 bit platforms. + */ +static_assert(MAX_HEIGHTMAP_SIZE_PIXELS < UINT32_MAX / 8); + +/** + * Check whether the loaded dimension of the heightmap image are considered valid enough + * to attempt to load the image. In other words, the width and height are not beyond the + * #MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS limit and the total number of pixels does not + * exceed #MAX_HEIGHTMAP_SIZE_PIXELS. A width or height less than 1 are disallowed too. + * @param width The width of the to be loaded height map. + * @param height The height of the to be loaded height map. + * @return True iff the dimensions are within the limits. + */ +static inline bool IsValidHeightmapDimension(size_t width, size_t height) +{ + return (uint64)width * height <= MAX_HEIGHTMAP_SIZE_PIXELS && + width > 0 && width <= MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS && + height > 0 && height <= MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS; +} + /** * Convert RGB colours to Grayscale using 29.9% Red, 58.7% Green, 11.4% Blue * (average luminosity formula, NTSC Colour Space) @@ -146,8 +180,7 @@ static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map) uint width = png_get_image_width(png_ptr, info_ptr); uint height = png_get_image_height(png_ptr, info_ptr); - /* Check if image dimensions don't overflow a size_t to avoid memory corruption. */ - if ((uint64)width * height >= (size_t)-1) { + if (!IsValidHeightmapDimension(width, height)) { ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); @@ -255,8 +288,7 @@ static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, byte **map) return false; } - /* Check if image dimensions don't overflow a size_t to avoid memory corruption. */ - if ((uint64)info.width * info.height >= (size_t)-1 / (info.bpp == 24 ? 3 : 1)) { + if (!IsValidHeightmapDimension(info.width, info.height)) { ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR); fclose(f); BmpDestroyData(&data); @@ -295,6 +327,8 @@ static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map) { /* Defines the detail of the aspect ratio (to avoid doubles) */ const uint num_div = 16384; + /* Ensure multiplication with num_div does not cause overflows. */ + static_assert(num_div <= std::numeric_limits::max() / MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS); uint width, height; uint row, col; From 8a918ce1709cb80191ba8e5195ec8ef02d484d9e Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 17:25:16 +0200 Subject: [PATCH 285/800] Codechange: [Network] Make admin name and version std::string --- src/network/core/tcp_admin.cpp | 8 +++----- src/network/core/tcp_admin.h | 6 +++--- src/network/network_admin.cpp | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index 0b48b419b6..234ab2e25a 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -30,8 +30,6 @@ static_assert((int)CRR_END == (int)ADMIN_CRR_END); NetworkAdminSocketHandler::NetworkAdminSocketHandler(SOCKET s) : status(ADMIN_STATUS_INACTIVE) { this->sock = s; - this->admin_name[0] = '\0'; - this->admin_version[0] = '\0'; } NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error) @@ -89,9 +87,9 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p) default: if (this->HasClientQuit()) { - DEBUG(net, 0, "[tcp/admin] Received invalid packet type %d from '%s' (%s)", type, this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received invalid packet type %d from '%s' (%s)", type, this->admin_name.c_str(), this->admin_version.c_str()); } else { - DEBUG(net, 0, "[tcp/admin] Received illegal packet from '%s' (%s)", this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received illegal packet from '%s' (%s)", this->admin_name.c_str(), this->admin_version.c_str()); } this->CloseConnection(); @@ -125,7 +123,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::ReceivePackets() */ NetworkRecvStatus NetworkAdminSocketHandler::ReceiveInvalidPacket(PacketAdminType type) { - DEBUG(net, 0, "[tcp/admin] Received illegal packet type %d from admin %s (%s)", type, this->admin_name, this->admin_version); + DEBUG(net, 0, "[tcp/admin] Received illegal packet type %d from admin %s (%s)", type, this->admin_name.c_str(), this->admin_version.c_str()); return NETWORK_RECV_STATUS_MALFORMED_PACKET; } diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h index 8b4a738bfa..6d498ce5df 100644 --- a/src/network/core/tcp_admin.h +++ b/src/network/core/tcp_admin.h @@ -109,9 +109,9 @@ enum AdminCompanyRemoveReason { /** Main socket handler for admin related connections. */ class NetworkAdminSocketHandler : public NetworkTCPSocketHandler { protected: - char admin_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the admin. - char admin_version[NETWORK_REVISION_LENGTH]; ///< Version string of the admin. - AdminStatus status; ///< Status of this admin. + std::string admin_name; ///< Name of the admin. + std::string admin_version; ///< Version string of the admin. + AdminStatus status; ///< Status of this admin. NetworkRecvStatus ReceiveInvalidPacket(PacketAdminType type); diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 09b039485a..c589967118 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -74,7 +74,7 @@ ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : Net ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler() { _network_admins_connected--; - DEBUG(net, 3, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version); + DEBUG(net, 3, "[admin] '%s' (%s) has disconnected", this->admin_name.c_str(), this->admin_version.c_str()); if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID; } @@ -135,7 +135,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode er std::string error_message = GetString(GetNetworkErrorMsg(error)); - DEBUG(net, 1, "[admin] The admin '%s' (%s) made an error and has been disconnected: '%s'", this->admin_name, this->admin_version, error_message.c_str()); + DEBUG(net, 1, "[admin] The admin '%s' (%s) made an error and has been disconnected: '%s'", this->admin_name.c_str(), this->admin_version.c_str(), error_message.c_str()); return this->CloseConnection(true); } @@ -502,7 +502,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) p->Recv_string(command, sizeof(command)); - DEBUG(net, 3, "[admin] Rcon command from '%s' (%s): %s", this->admin_name, this->admin_version, command); + DEBUG(net, 3, "[admin] Rcon command from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), command); _redirect_console_to_admin = this->index; IConsoleCmdExec(command); @@ -518,7 +518,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Pack p->Recv_string(json, sizeof(json)); - DEBUG(net, 6, "[admin] GameScript JSON from '%s' (%s): %s", this->admin_name, this->admin_version, json); + DEBUG(net, 6, "[admin] GameScript JSON from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), json); Game::NewEvent(new ScriptEventAdminPort(json)); return NETWORK_RECV_STATUS_OKAY; @@ -530,7 +530,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) uint32 d1 = p->Recv_uint32(); - DEBUG(net, 6, "[admin] Ping from '%s' (%s): %d", this->admin_name, this->admin_version, d1); + DEBUG(net, 6, "[admin] Ping from '%s' (%s): %d", this->admin_name.c_str(), this->admin_version.c_str(), d1); return this->SendPong(d1); } @@ -656,17 +656,17 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p) return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); } - p->Recv_string(this->admin_name, sizeof(this->admin_name)); - p->Recv_string(this->admin_version, sizeof(this->admin_version)); + this->admin_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH); + this->admin_version = p->Recv_string(NETWORK_REVISION_LENGTH); - if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) { + if (this->admin_name.empty() || this->admin_version.empty()) { /* no name or version supplied */ return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } this->status = ADMIN_STATUS_ACTIVE; - DEBUG(net, 3, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version); + DEBUG(net, 3, "[admin] '%s' (%s) has connected", this->admin_name.c_str(), this->admin_version.c_str()); return this->SendProtocol(); } @@ -686,7 +686,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENC if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) { /* The server does not know of this UpdateType. */ - DEBUG(net, 1, "[admin] Not supported update frequency %d (%d) from '%s' (%s)", type, freq, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Not supported update frequency %d (%d) from '%s' (%s)", type, freq, this->admin_name.c_str(), this->admin_version.c_str()); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } @@ -754,7 +754,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p) default: /* An unsupported "poll" update type. */ - DEBUG(net, 1, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name.c_str(), this->admin_version.c_str()); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } @@ -780,7 +780,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) break; default: - DEBUG(net, 1, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version); + DEBUG(net, 1, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name.c_str(), this->admin_version.c_str()); return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); } From 29f2bd27c44ef51f8af1299cf16012a4fa89cc61 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 16 May 2021 11:58:44 +0200 Subject: [PATCH 286/800] Codechange: [Game] Pass the length instead of '\0' terminating (and undoing that) in the middle of a C-string --- src/script/api/script_event_types.cpp | 17 ++++++++--------- src/script/api/script_event_types.hpp | 6 +++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/script/api/script_event_types.cpp b/src/script/api/script_event_types.cpp index 84c001836d..84d6d99cda 100644 --- a/src/script/api/script_event_types.cpp +++ b/src/script/api/script_event_types.cpp @@ -134,7 +134,7 @@ ScriptEventAdminPort::~ScriptEventAdminPort() SQInteger ScriptEventAdminPort::GetObject(HSQUIRRELVM vm) { - char *p = this->json; + const char *p = this->json; if (this->ReadTable(vm, p) == nullptr) { sq_pushnull(vm); @@ -144,9 +144,9 @@ SQInteger ScriptEventAdminPort::GetObject(HSQUIRRELVM vm) return 1; } -char *ScriptEventAdminPort::ReadString(HSQUIRRELVM vm, char *p) +const char *ScriptEventAdminPort::ReadString(HSQUIRRELVM vm, const char *p) { - char *value = p; + const char *value = p; bool escape = false; for (;;) { @@ -168,14 +168,13 @@ char *ScriptEventAdminPort::ReadString(HSQUIRRELVM vm, char *p) p++; } - *p = '\0'; - sq_pushstring(vm, value, -1); - *p++ = '"'; + sq_pushstring(vm, value, p - value); + p++; // Step past the end-of-string marker (") return p; } -char *ScriptEventAdminPort::ReadTable(HSQUIRRELVM vm, char *p) +const char *ScriptEventAdminPort::ReadTable(HSQUIRRELVM vm, const char *p) { sq_newtable(vm); @@ -218,7 +217,7 @@ char *ScriptEventAdminPort::ReadTable(HSQUIRRELVM vm, char *p) return p; } -char *ScriptEventAdminPort::ReadValue(HSQUIRRELVM vm, char *p) +const char *ScriptEventAdminPort::ReadValue(HSQUIRRELVM vm, const char *p) { SKIP_EMPTY(p); @@ -257,7 +256,7 @@ char *ScriptEventAdminPort::ReadValue(HSQUIRRELVM vm, char *p) sq_newarray(vm, 0); /* Empty array? */ - char *p2 = p + 1; + const char *p2 = p + 1; SKIP_EMPTY(p2); if (*p2 == ']') { p = p2 + 1; diff --git a/src/script/api/script_event_types.hpp b/src/script/api/script_event_types.hpp index 1d514389b5..b6ed7bfbcd 100644 --- a/src/script/api/script_event_types.hpp +++ b/src/script/api/script_event_types.hpp @@ -860,21 +860,21 @@ private: * @param vm The VM used. * @param p The (part of the) JSON string reading. */ - char *ReadTable(HSQUIRRELVM vm, char *p); + const char *ReadTable(HSQUIRRELVM vm, const char *p); /** * Read a value from a JSON string. * @param vm The VM used. * @param p The (part of the) JSON string reading. */ - char *ReadValue(HSQUIRRELVM vm, char *p); + const char *ReadValue(HSQUIRRELVM vm, const char *p); /** * Read a string from a JSON string. * @param vm The VM used. * @param p The (part of the) JSON string reading. */ - char *ReadString(HSQUIRRELVM vm, char *p); + const char *ReadString(HSQUIRRELVM vm, const char *p); }; /** From e58581f1f825da4d318b0b09fc12726788e95ccc Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 17:33:29 +0200 Subject: [PATCH 287/800] Codechange: [Network] Let admin-game script use std::string --- src/network/network_admin.cpp | 12 +++++------- src/network/network_admin.h | 4 ++-- src/script/api/script_admin.cpp | 2 +- src/script/api/script_event_types.cpp | 14 +++++--------- src/script/api/script_event_types.hpp | 5 ++--- 5 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index c589967118..82c9881bf1 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -514,11 +514,9 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Pack { if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - char json[NETWORK_GAMESCRIPT_JSON_LENGTH]; + std::string json = p->Recv_string(NETWORK_GAMESCRIPT_JSON_LENGTH); - p->Recv_string(json, sizeof(json)); - - DEBUG(net, 6, "[admin] GameScript JSON from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), json); + DEBUG(net, 6, "[admin] GameScript JSON from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), json.c_str()); Game::NewEvent(new ScriptEventAdminPort(json)); return NETWORK_RECV_STATUS_OKAY; @@ -561,12 +559,12 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origi * Send GameScript JSON output. * @param json The JSON string. */ -NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json) +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const std::string_view json) { /* At the moment we cannot transmit anything larger than MTU. So we limit * the maximum amount of json data that can be sent. Account also for * the trailing \0 of the string */ - if (strlen(json) + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY; + if (json.size() + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY; Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT); @@ -941,7 +939,7 @@ void NetworkAdminConsole(const char *origin, const char *string) * Send GameScript JSON to the admin network (if they did opt in for the respective update). * @param json The JSON data as received from the GameScript. */ -void NetworkAdminGameScript(const char *json) +void NetworkAdminGameScript(const std::string_view json) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) { diff --git a/src/network/network_admin.h b/src/network/network_admin.h index 0e443d08f2..189acb6f9c 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -64,7 +64,7 @@ public: NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data); NetworkRecvStatus SendRcon(uint16 colour, const char *command); NetworkRecvStatus SendConsole(const char *origin, const char *command); - NetworkRecvStatus SendGameScript(const char *json); + NetworkRecvStatus SendGameScript(const std::string_view json); NetworkRecvStatus SendCmdNames(); NetworkRecvStatus SendCmdLogging(ClientID client_id, const CommandPacket *cp); NetworkRecvStatus SendRconEnd(const char *command); @@ -110,7 +110,7 @@ void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_i void NetworkAdminUpdate(AdminUpdateFrequency freq); void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string); void NetworkAdminConsole(const char *origin, const char *string); -void NetworkAdminGameScript(const char *json); +void NetworkAdminGameScript(const std::string_view json); void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp); #endif /* NETWORK_ADMIN_H */ diff --git a/src/script/api/script_admin.cpp b/src/script/api/script_admin.cpp index 8f7371266d..24aa0bcaf3 100644 --- a/src/script/api/script_admin.cpp +++ b/src/script/api/script_admin.cpp @@ -139,7 +139,7 @@ return 1; } - NetworkAdminGameScript(json.c_str()); + NetworkAdminGameScript(json); sq_pushinteger(vm, 1); return 1; diff --git a/src/script/api/script_event_types.cpp b/src/script/api/script_event_types.cpp index 84d6d99cda..3cc5287eb8 100644 --- a/src/script/api/script_event_types.cpp +++ b/src/script/api/script_event_types.cpp @@ -118,23 +118,18 @@ bool ScriptEventCompanyAskMerger::AcceptMerger() return ScriptObject::DoCommand(0, this->owner, 0, CMD_BUY_COMPANY); } -ScriptEventAdminPort::ScriptEventAdminPort(const char *json) : +ScriptEventAdminPort::ScriptEventAdminPort(const std::string &json) : ScriptEvent(ET_ADMIN_PORT), - json(stredup(json)) + json(json) { } -ScriptEventAdminPort::~ScriptEventAdminPort() -{ - free(this->json); -} - #define SKIP_EMPTY(p) while (*(p) == ' ' || *(p) == '\n' || *(p) == '\r') (p)++; #define RETURN_ERROR(stack) { ScriptLog::Error("Received invalid JSON data from AdminPort."); if (stack != 0) sq_pop(vm, stack); return nullptr; } SQInteger ScriptEventAdminPort::GetObject(HSQUIRRELVM vm) { - const char *p = this->json; + const char *p = this->json.c_str(); if (this->ReadTable(vm, p) == nullptr) { sq_pushnull(vm); @@ -168,7 +163,8 @@ const char *ScriptEventAdminPort::ReadString(HSQUIRRELVM vm, const char *p) p++; } - sq_pushstring(vm, value, p - value); + size_t len = p - value; + sq_pushstring(vm, value, len); p++; // Step past the end-of-string marker (") return p; diff --git a/src/script/api/script_event_types.hpp b/src/script/api/script_event_types.hpp index b6ed7bfbcd..3ed6c5b10a 100644 --- a/src/script/api/script_event_types.hpp +++ b/src/script/api/script_event_types.hpp @@ -837,8 +837,7 @@ public: /** * @param json The JSON string which got sent. */ - ScriptEventAdminPort(const char *json); - ~ScriptEventAdminPort(); + ScriptEventAdminPort(const std::string &json); /** * Convert an ScriptEvent to the real instance. @@ -853,7 +852,7 @@ public: SQInteger GetObject(HSQUIRRELVM vm); private: - char *json; ///< The JSON string. + std::string json; ///< The JSON string. /** * Read a table from a JSON string. From 8c273ed598f59e18acb1c0bcbc9bc34beb307ecb Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 14 May 2021 17:38:05 +0200 Subject: [PATCH 288/800] Codechange: [Network] Let admin-console use std::string(_view) --- src/network/network_admin.cpp | 20 +++++++++----------- src/network/network_admin.h | 10 +++++----- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 82c9881bf1..8aa32d21e4 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -468,7 +468,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action * Send a notification indicating the rcon command has completed. * @param command The original command sent. */ -NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *command) +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const std::string_view command) { Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END); @@ -483,7 +483,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *comma * @param colour The colour of the text. * @param result The result of the command. */ -NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result) +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const std::string_view result) { Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON); @@ -498,14 +498,12 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) { if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - char command[NETWORK_RCONCOMMAND_LENGTH]; + std::string command = p->Recv_string(NETWORK_RCONCOMMAND_LENGTH); - p->Recv_string(command, sizeof(command)); - - DEBUG(net, 3, "[admin] Rcon command from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), command); + DEBUG(net, 3, "[admin] Rcon command from '%s' (%s): %s", this->admin_name.c_str(), this->admin_version.c_str(), command.c_str()); _redirect_console_to_admin = this->index; - IConsoleCmdExec(command); + IConsoleCmdExec(command.c_str()); _redirect_console_to_admin = INVALID_ADMIN_ID; return this->SendRconEnd(command); } @@ -538,13 +536,13 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) * @param origin The origin of the string. * @param string The string that's put on the console. */ -NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string) +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const std::string_view origin, const std::string_view string) { /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet * are bigger than the MTU, just ignore the message. Better safe than sorry. It should * never occur though as the longest strings are chat messages, which are still 30% * smaller than COMPAT_MTU. */ - if (strlen(origin) + strlen(string) + 2 + 3 >= COMPAT_MTU) return NETWORK_RECV_STATUS_OKAY; + if (origin.size() + string.size() + 2 + 3 >= COMPAT_MTU) return NETWORK_RECV_STATUS_OKAY; Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE); @@ -916,7 +914,7 @@ void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_i * @param colour_code The colour of the string. * @param string The string to show. */ -void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string) +void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const std::string_view string) { ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string); } @@ -926,7 +924,7 @@ void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, * @param origin the origin of the message. * @param string the message as printed on the console. */ -void NetworkAdminConsole(const char *origin, const char *string) +void NetworkAdminConsole(const std::string_view origin, const std::string_view string) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) { if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) { diff --git a/src/network/network_admin.h b/src/network/network_admin.h index 189acb6f9c..9d7f0eef42 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -62,12 +62,12 @@ public: NetworkRecvStatus SendCompanyStats(); NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data); - NetworkRecvStatus SendRcon(uint16 colour, const char *command); - NetworkRecvStatus SendConsole(const char *origin, const char *command); + NetworkRecvStatus SendRcon(uint16 colour, const std::string_view command); + NetworkRecvStatus SendConsole(const std::string_view origin, const std::string_view command); NetworkRecvStatus SendGameScript(const std::string_view json); NetworkRecvStatus SendCmdNames(); NetworkRecvStatus SendCmdLogging(ClientID client_id, const CommandPacket *cp); - NetworkRecvStatus SendRconEnd(const char *command); + NetworkRecvStatus SendRconEnd(const std::string_view command); static void Send(); static void AcceptConnection(SOCKET s, const NetworkAddress &address); @@ -108,8 +108,8 @@ void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bc void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data = 0, bool from_admin = false); void NetworkAdminUpdate(AdminUpdateFrequency freq); -void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string); -void NetworkAdminConsole(const char *origin, const char *string); +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); From bcd7a7aafe3d63117be74580298dcb20a53e4121 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 30 May 2021 10:40:03 +0200 Subject: [PATCH 289/800] Codechange: rename _SQ64 into POINTER_IS_64BIT (#9313) --- CMakeLists.txt | 2 +- src/blitter/32bpp_anim_sse4.cpp | 4 ++-- src/blitter/32bpp_sse_func.hpp | 4 ++-- src/crashlog.cpp | 2 +- src/os/macosx/osx_stdafx.h | 4 ++-- src/viewport_sprite_sorter_sse4.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8c6f040ed..d060ffbbff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,7 +370,7 @@ if(WIN32) endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) - add_definitions(-D_SQ64) + add_definitions(-DPOINTER_IS_64BIT) endif() include(CreateRegression) diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index c6213ce30b..adfe625287 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -198,7 +198,7 @@ bmno_full_transparency: m_colour = r == 0 ? m_colour : cmap; \ m_colour = m != 0 ? m_colour : srcm; \ } -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT uint64 srcs = _mm_cvtsi128_si64(srcABCD); uint64 dsts; if (animated) dsts = _mm_cvtsi128_si64(dstABCD); @@ -380,7 +380,7 @@ bm_normal: else Draw(bp, zoom); } } else { -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT if (sprite_flags & SF_TRANSLUCENT) { if (sprite_flags & SF_NO_ANIM) Draw(bp, zoom); else Draw(bp, zoom); diff --git a/src/blitter/32bpp_sse_func.hpp b/src/blitter/32bpp_sse_func.hpp index 083839b959..d6e12af619 100644 --- a/src/blitter/32bpp_sse_func.hpp +++ b/src/blitter/32bpp_sse_func.hpp @@ -34,7 +34,7 @@ static inline void InsertSecondUint32(const uint32 value, __m128i &into) static inline void LoadUint64(const uint64 value, __m128i &into) { -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT into = _mm_cvtsi64_si128(value); #else #if (SSE_VERSION >= 4) @@ -297,7 +297,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel m_colour = r == 0 ? m_colour : cmap; \ m_colour = m != 0 ? m_colour : srcm; \ } -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT uint64 srcs = _mm_cvtsi128_si64(srcABCD); uint64 remapped_src = 0; CMOV_REMAP(c0, 0, srcs, mvX2); diff --git a/src/crashlog.cpp b/src/crashlog.cpp index c69dddef84..b7c8c2bc49 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -126,7 +126,7 @@ char *CrashLog::LogOpenTTDVersion(char *buffer, const char *last) const _openttd_revision, _openttd_revision_modified, _openttd_newgrf_version, -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT 64, #else 32, diff --git a/src/os/macosx/osx_stdafx.h b/src/os/macosx/osx_stdafx.h index d90a19c5f7..e147fcf74c 100644 --- a/src/os/macosx/osx_stdafx.h +++ b/src/os/macosx/osx_stdafx.h @@ -73,8 +73,8 @@ #endif /* Check for mismatching 'architectures' */ -#if !defined(STRGEN) && !defined(SETTINGSGEN) && ((defined(__LP64__) && !defined(_SQ64)) || (!defined(__LP64__) && defined(_SQ64))) -# error "Compiling 64 bits without _SQ64 set! (or vice versa)" +#if !defined(STRGEN) && !defined(SETTINGSGEN) && ((defined(__LP64__) && !defined(POINTER_IS_64BIT)) || (!defined(__LP64__) && defined(POINTER_IS_64BIT))) +# error "Compiling 64 bits without POINTER_IS_64BIT set! (or vice versa)" #endif /* Name conflict */ diff --git a/src/viewport_sprite_sorter_sse4.cpp b/src/viewport_sprite_sorter_sse4.cpp index f3747b89b2..fc7eb49e40 100644 --- a/src/viewport_sprite_sorter_sse4.cpp +++ b/src/viewport_sprite_sorter_sse4.cpp @@ -19,7 +19,7 @@ #include "safeguards.h" -#ifdef _SQ64 +#ifdef POINTER_IS_64BIT static_assert((sizeof(ParentSpriteToDraw) % 16) == 0); # define LOAD_128 _mm_load_si128 #else From e9e4588db105f5827c5356933023f6ce698fe6aa Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 30 May 2021 10:40:59 +0200 Subject: [PATCH 290/800] Codechange: use setting name instead of index for HandleOldDiffCustom() (#9311) --- src/settings.cpp | 25 +++++++++++++++++++------ src/settings_type.h | 3 +++ src/table/settings/gameopt_settings.ini | 1 + src/table/settings/settings.ini | 18 +++++++++++++----- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 56c02e5e19..d39c045938 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -22,6 +22,7 @@ */ #include "stdafx.h" +#include #include #include "currency.h" #include "screenshot.h" @@ -1227,7 +1228,9 @@ static void PrepareOldDiffCustom() */ static void HandleOldDiffCustom(bool savegame) { - uint options_to_load = GAME_DIFFICULTY_NUM - ((savegame && IsSavegameVersionBefore(SLV_4)) ? 1 : 0); + /* Savegames before v4 didn't have "town_council_tolerance" in savegame yet. */ + bool has_no_town_council_tolerance = savegame && IsSavegameVersionBefore(SLV_4); + uint options_to_load = GAME_DIFFICULTY_NUM - (has_no_town_council_tolerance ? 1 : 0); if (!savegame) { /* If we did read to old_diff_custom, then at least one value must be non 0. */ @@ -1239,11 +1242,21 @@ static void HandleOldDiffCustom(bool savegame) if (!old_diff_custom_used) return; } - for (uint i = 0; i < options_to_load; i++) { - const SettingDesc *sd = GetSettingDescription(i); - /* Skip deprecated options */ - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - int32 value = (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]); + /* Iterate over all the old difficulty settings, and convert the list-value to the new setting. */ + uint i = 0; + for (const auto &name : _old_diff_settings) { + if (has_no_town_council_tolerance && name == "town_council_tolerance") continue; + + std::string fullname = "difficulty." + name; + const SettingDesc *sd = GetSettingFromName(fullname.c_str()); + + /* Some settings are no longer in use; skip reading those. */ + if (sd == nullptr) { + i++; + continue; + } + + int32 value = (int32)((name == "max_loan" ? 1000 : 1) * _old_diff_custom[i++]); sd->AsIntSetting()->MakeValueValidAndWrite(savegame ? &_settings_game : &_settings_newgame, value); } } diff --git a/src/settings_type.h b/src/settings_type.h index 39a73b3ed9..8023683848 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -61,6 +61,9 @@ enum IndustryDensity { /** Settings related to the difficulty of the game */ struct DifficultySettings { + byte competitor_start_time; ///< Unused value, used to load old savegames. + byte competitor_intelligence; ///< Unused value, used to load old savegames. + byte max_no_competitors; ///< the number of competitors (AIs) byte number_towns; ///< the amount of towns byte industry_density; ///< The industry density. @see IndustryDensity diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index 849c731b67..f24adb17a6 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -15,6 +15,7 @@ [pre-amble] static const uint GAME_DIFFICULTY_NUM = 18; +static const std::array _old_diff_settings{"max_no_competitors", "competitor_start_time", "number_towns", "industry_density", "max_loan", "initial_interest", "vehicle_costs", "competitor_speed", "competitor_intelligence", "vehicle_breakdowns", "subsidy_multiplier", "construction_cost", "terrain_type", "quantity_sea_lakes", "economy", "line_reverse_mode", "disasters", "town_council_tolerance"}; static uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; uint8 _old_diff_level; ///< Old difficulty level from old savegames uint8 _old_units; ///< Old units from old savegames diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 4f9ea607ab..9281ed6624 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -94,7 +94,7 @@ startup = false ; Saved settings variables. -; Do not ADD or REMOVE something in this "difficulty.XXX" table or before it. It breaks savegame compatibility. +; The next 18 entries are important for savegame compatibility. Do NOT remove those. See HandleOldDiffCustom() for more details. [SDT_VAR] var = difficulty.max_no_competitors type = SLE_UINT8 @@ -106,10 +106,14 @@ interval = 1 post_cb = MaxNoAIsChange cat = SC_BASIC -[SDT_NULL] -length = 1 +[SDT_VAR] +var = difficulty.competitor_start_time +type = SLE_UINT8 from = SLV_97 to = SLV_110 +def = 2 +min = 0 +max = 3 [SDT_VAR] var = difficulty.number_towns @@ -192,10 +196,14 @@ strhelp = STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT strval = STR_AI_SPEED_VERY_SLOW cat = SC_BASIC -[SDT_NULL] -length = 1 +[SDT_VAR] +var = difficulty.competitor_intelligence +type = SLE_UINT8 from = SLV_97 to = SLV_110 +def = 0 +min = 0 +max = 2 [SDT_VAR] var = difficulty.vehicle_breakdowns From 0c968847006ba7206265651ac45f8fa0ce6141ac Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 30 May 2021 10:55:52 +0200 Subject: [PATCH 291/800] Codechange: add a wrapper function to find all settings based on prefix (#9312) --- src/saveload/linkgraph_sl.cpp | 15 +++------------ src/settings.cpp | 26 +++++++++++++++----------- src/settings_internal.h | 1 + 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index af28902445..7d4fe56712 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -20,8 +20,6 @@ typedef LinkGraph::BaseNode Node; typedef LinkGraph::BaseEdge Edge; -const SettingDesc *GetSettingDescription(uint index); - static uint16 _num_nodes; /** @@ -70,17 +68,10 @@ const SaveLoad *GetLinkGraphJobDesc() /* Build the SaveLoad array on first call and don't touch it later on */ if (saveloads.size() == 0) { - size_t prefixlen = strlen(prefix); + GetSettingSaveLoadByPrefix(prefix, saveloads); - int setting = 0; - const SettingDesc *desc = GetSettingDescription(setting); - while (desc != nullptr) { - if (desc->name != nullptr && strncmp(desc->name, prefix, prefixlen) == 0) { - SaveLoad sl = desc->save; - sl.address_proc = proc; - saveloads.push_back(sl); - } - desc = GetSettingDescription(++setting); + for (auto &sl : saveloads) { + sl.address_proc = proc; } int i = 0; diff --git a/src/settings.cpp b/src/settings.cpp index d39c045938..f7a4ff5dec 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -93,17 +93,6 @@ typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList & static bool IsSignedVarMemType(VarType vt); -/** - * Get the setting at the given index into the settings table. - * @param index The index to look for. - * @return The setting at the given index, or nullptr when the index is invalid. - */ -const SettingDesc *GetSettingDescription(uint index) -{ - if (index >= _settings.size()) return nullptr; - return _settings.begin()[index].get(); -} - /** * Groups in openttd.cfg that are actually lists. */ @@ -1739,6 +1728,21 @@ static const SettingDesc *GetSettingFromName(const char *name, const SettingTabl return nullptr; } +/** + * Get the SaveLoad from all settings matching the prefix. + * @param prefix The prefix to look for. + * @param saveloads A vector to store the result in. + */ +void GetSettingSaveLoadByPrefix(const char *prefix, std::vector &saveloads) +{ + size_t prefixlen = strlen(prefix); + + for (auto &sd : _settings) { + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + if (strncmp(sd->name, prefix, prefixlen) == 0) saveloads.push_back(sd->save); + } +} + /** * Given a name of setting, return a company setting description of it. * @param name Name of the company setting to return a setting description of. diff --git a/src/settings_internal.h b/src/settings_internal.h index ba5331288c..632d4081d9 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -300,6 +300,7 @@ struct NullSettingDesc : SettingDesc { typedef std::initializer_list> SettingTable; const SettingDesc *GetSettingFromName(const char *name); +void GetSettingSaveLoadByPrefix(const char *prefix, std::vector &saveloads); bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame = false); bool SetSettingValue(const StringSettingDesc *sd, const std::string value, bool force_newgame = false); From 4613ababd3fea832d5b11832784768323c39b5a9 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 14:38:55 +0200 Subject: [PATCH 292/800] Fix #9316, 64eddaeb: at about 250.000 inhabitants the bridge length limit check overflows --- src/town_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 627d133b5d..bc29d39177 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1178,7 +1178,7 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi if (!(GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(bridge_dir))) & DiagDirToRoadBits(bridge_dir))) return false; /* We are in the right direction */ - uint8 bridge_length = 0; // This value stores the length of the possible bridge + int bridge_length = 0; // This value stores the length of the possible bridge TileIndex bridge_tile = tile; // Used to store the other waterside const int delta = TileOffsByDiagDir(bridge_dir); From 5ded596c8092aa73276431c51f6bee6fcb27c03a Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 30 May 2021 19:37:48 +0200 Subject: [PATCH 293/800] Fix #9320, 2e136285: nullptr could not be converted to string --- src/order_backup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/order_backup.cpp b/src/order_backup.cpp index f1263809b6..37579a3198 100644 --- a/src/order_backup.cpp +++ b/src/order_backup.cpp @@ -198,7 +198,7 @@ CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1, /* We need to circumvent the "prevention" from this command being executed * while the game is paused, so use the internal method. Nor do we want * this command to get its cost estimated when shift is pressed. */ - DoCommandPInternal(ob->tile, 0, user, CMD_CLEAR_ORDER_BACKUP, nullptr, nullptr, true, false); + DoCommandPInternal(ob->tile, 0, user, CMD_CLEAR_ORDER_BACKUP, nullptr, {}, true, false); } else { /* The command came from the game logic, i.e. the clearing of a tile. * In that case we have no need to actually sync this, just do it. */ From 043a5442482c852dc9d2bcdf311d588d137206cd Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 30 May 2021 19:56:14 +0000 Subject: [PATCH 294/800] Update: Translations from eints korean: 2 changes by telk5093 russian: 1 change by Ln-Wolf finnish: 1 change by hpiirai portuguese: 1 change by azulcosta portuguese (brazilian): 1 change by Vimerum --- src/lang/brazilian_portuguese.txt | 1 + src/lang/finnish.txt | 1 + src/lang/korean.txt | 3 ++- src/lang/portuguese.txt | 1 + src/lang/russian.txt | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 4776249796..4dd815985b 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a conexão foi encerrada STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multijogador +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Seu nome de servidor não foi definido. O nome pode ser definido no topo da janela de Multijogador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A versão deste cliente não condiz com a versão do servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Senha incorreta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}O servidor está cheio diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index f18298b802..ee4acaf91f 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Yhdistä STR_NETWORK_ERROR_TIMEOUT :{WHITE}Yhteys nro {NUM} aikakatkaistiin STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Protokollavirhe tapahtui ja yhteys suljettiin STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Et ole asettanut pelaajanimeäsi. Nimen voi asettaa moninpeli-ikkunan ylälaidassa. +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Et ole asettanut palvelimesi nimeä. Nimen voi asettaa moninpeli-ikkunan ylälaidassa. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Tämän asiakkaan versio ei vastaa palvelimen versiota STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Väärä salasana STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Palvelin on täynnä diff --git a/src/lang/korean.txt b/src/lang/korean.txt index c34def59aa..9e429e77bb 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -173,7 +173,7 @@ STR_CRATES :{G=f}{COMMA}{NB # Colours, do not shuffle STR_COLOUR_DARK_BLUE :어두운 파랑 -STR_COLOUR_PALE_GREEN :연한 초록 +STR_COLOUR_PALE_GREEN :연한 녹색 STR_COLOUR_PINK :분홍 STR_COLOUR_YELLOW :노랑 STR_COLOUR_RED :빨강 @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}접속 STR_NETWORK_ERROR_TIMEOUT :{WHITE}접속자 #{NUM}의 입력 시간이 초과되었습니다 STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}프로토콜 오류가 발생되어 연결이 끊어졌습니다 STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}접속자 이름을 설정하지 않았습니다. 이름은 멀티플레이 창의 상단에서 설정할 수 있습니다. +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}서버 이름을 지정하지 않았습니다. 서버 이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}이 접속자의 게임 버전이 서버의 버전과 일치하지 않습니다 STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못된 비밀번호입니다 STR_NETWORK_ERROR_SERVER_FULL :{WHITE}서버에 인원이 가득 찼습니다 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 4bf74f6f32..b716c04719 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM}. STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a ligação foi encerrada STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}O seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multi-jogador +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}O seu nome do seu servidor não foi definido. O nome pode ser definido no topo da janela de Multi-jogador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A revisão deste cliente não condiz com a revisão do servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Palavra-chave incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Servidor cheio diff --git a/src/lang/russian.txt b/src/lang/russian.txt index b9b5bc5fb6..1752a0cf8a 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2355,6 +2355,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Не у STR_NETWORK_ERROR_TIMEOUT :{WHITE}Истекло время ожидания соединения #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Произошла ошибка протокола, и соединение было закрыто STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Не указано имя игрока. Его можно ввести в верхней части окна «Сетевая игра». +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Не указано имя сервера. Его можно ввести в верхней части окна «Сетевая игра». STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Версия этого клиента не совместима с версией сервера STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неверный пароль STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен From 921ab68a480afc969d2d8c8150c23250f245ba52 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 31 May 2021 10:56:06 +0200 Subject: [PATCH 295/800] Codechange: use AsIntSetting()->Read() wrapper if possible (#9324) --- src/news_gui.cpp | 5 ++--- src/script/api/script_gamesettings.cpp | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/news_gui.cpp b/src/news_gui.cpp index a8d7c4398d..731eb95c22 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -254,9 +254,8 @@ static_assert(lengthof(_news_type_data) == NT_END); NewsDisplay NewsTypeData::GetDisplay() const { const SettingDesc *sd = GetSettingFromName(this->name); - assert(sd != nullptr); - void *ptr = GetVariableAddress(nullptr, &sd->save); - return (NewsDisplay)ReadValue(ptr, sd->save.conv); + assert(sd != nullptr && sd->IsIntSetting()); + return (NewsDisplay)sd->AsIntSetting()->Read(nullptr); } /** Window class displaying a news item. */ diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 0ade2d7cc6..b1699d94f6 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -26,9 +26,7 @@ if (!IsValid(setting)) return -1; const SettingDesc *sd = GetSettingFromName(setting); - - void *ptr = GetVariableAddress(&_settings_game, &sd->save); - return (int32)ReadValue(ptr, sd->save.conv); + return sd->AsIntSetting()->Read(&_settings_game); } /* static */ bool ScriptGameSettings::SetValue(const char *setting, int value) From 956d761e3ef1968c6470a9e78597c5531ed7c332 Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 31 May 2021 20:18:35 +0000 Subject: [PATCH 296/800] Update: Translations from eints japanese: 1 change by scabtert --- src/lang/japanese.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index c51e915f18..f265987604 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}接続 STR_NETWORK_ERROR_TIMEOUT :{WHITE}接続 {NUM} でタイムアウトエラーが発生しました STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}プロトコルエラーによって接続が切断されました STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}あなたのプレイヤー名は設定されていません。名前はマルチプレイヤーウィンドウの上部から設定できます。 +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}サーバー名が設定されていません。名前はマルチプレイヤーウィンドウの上部で設定できます STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}クライアントバージョンがサーバーバージョンと一致していません STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}不正なパスワードです STR_NETWORK_ERROR_SERVER_FULL :{WHITE}サーバが満員です From 9fff00ba205260ee5e11b50f87a3edee9b7e76a3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 31 May 2021 22:26:44 +0200 Subject: [PATCH 297/800] Codechange: C++-ify lists for SaveLoad (#9323) Basically, this changes "SaveLoad *" to either: 1) "SaveLoadTable" if a list of SaveLoads was meant 2) "SaveLoad &" if a single entry was meant As added bonus, this removes SL_END / SLE_END / SLEG_END. This also adds core/span.hpp, a "std::span"-lite. --- src/cargopacket.h | 9 +-- src/core/span_type.hpp | 98 +++++++++++++++++++++++++++++++ src/linkgraph/linkgraph.h | 6 +- src/linkgraph/linkgraphjob.h | 2 +- src/linkgraph/linkgraphschedule.h | 2 +- src/order_backup.h | 3 +- src/order_base.h | 7 ++- src/saveload/ai_sl.cpp | 1 - src/saveload/autoreplace_sl.cpp | 1 - src/saveload/cargomonitor_sl.cpp | 1 - src/saveload/cargopacket_sl.cpp | 4 +- src/saveload/company_sl.cpp | 11 ---- src/saveload/depot_sl.cpp | 1 - src/saveload/economy_sl.cpp | 2 - src/saveload/engine_sl.cpp | 3 - src/saveload/game_sl.cpp | 3 - src/saveload/gamelog_sl.cpp | 15 +---- src/saveload/goal_sl.cpp | 1 - src/saveload/group_sl.cpp | 1 - src/saveload/industry_sl.cpp | 4 -- src/saveload/labelmaps_sl.cpp | 1 - src/saveload/linkgraph_sl.cpp | 20 +++---- src/saveload/map_sl.cpp | 3 +- src/saveload/misc_sl.cpp | 9 +-- src/saveload/newgrf_sl.cpp | 2 - src/saveload/object_sl.cpp | 2 - src/saveload/order_sl.cpp | 9 +-- src/saveload/saveload.cpp | 94 ++++++++++++++--------------- src/saveload/saveload.h | 32 ++++------ src/saveload/saveload_internal.h | 2 +- src/saveload/signs_sl.cpp | 1 - src/saveload/station_sl.cpp | 23 ++------ src/saveload/storage_sl.cpp | 1 - src/saveload/story_sl.cpp | 2 - src/saveload/subsidy_sl.cpp | 1 - src/saveload/town_sl.cpp | 9 +-- src/saveload/vehicle_sl.cpp | 19 +----- src/saveload/waypoint_sl.cpp | 2 - src/script/script_instance.cpp | 1 - src/settings.cpp | 22 +++---- src/vehicle_base.h | 6 +- 41 files changed, 213 insertions(+), 223 deletions(-) create mode 100644 src/core/span_type.hpp diff --git a/src/cargopacket.h b/src/cargopacket.h index 9892956211..abb8d98c2c 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -17,6 +17,7 @@ #include "cargo_type.h" #include "vehicle_type.h" #include "core/multimap.hpp" +#include "saveload/saveload.h" #include /** Unique identifier for a single cargo packet. */ @@ -32,7 +33,7 @@ struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets() template class CargoList; class StationCargoList; // forward-declare, so we can use it in VehicleCargoList. -extern const struct SaveLoad *GetCargoPacketDesc(); +extern SaveLoadTable GetCargoPacketDesc(); typedef uint32 TileOrStationID; @@ -58,7 +59,7 @@ private: friend class VehicleCargoList; friend class StationCargoList; /** We want this to be saved, right? */ - friend const struct SaveLoad *GetCargoPacketDesc(); + friend SaveLoadTable GetCargoPacketDesc(); public: /** Maximum number of items in a single cargo packet. */ static const uint16 MAX_COUNT = UINT16_MAX; @@ -305,7 +306,7 @@ public: /** The super class ought to know what it's doing. */ friend class CargoList; /** The vehicles have a cargo list (and we want that saved). */ - friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); + friend SaveLoadTable GetVehicleDescription(VehicleType vt); friend class CargoShift; friend class CargoTransfer; @@ -456,7 +457,7 @@ public: /** The super class ought to know what it's doing. */ friend class CargoList; /** The stations, via GoodsEntry, have a CargoList. */ - friend const struct SaveLoad *GetGoodsDesc(); + friend SaveLoadTable GetGoodsDesc(); friend class CargoLoad; friend class CargoTransfer; diff --git a/src/core/span_type.hpp b/src/core/span_type.hpp new file mode 100644 index 0000000000..394b9ef38c --- /dev/null +++ b/src/core/span_type.hpp @@ -0,0 +1,98 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file span_type.hpp Minimized implementation of C++20 std::span. */ + +#ifndef CORE_SPAN_TYPE_HPP +#define CORE_SPAN_TYPE_HPP + +/* This is a partial copy/paste from https://github.com/gsl-lite/gsl-lite/blob/master/include/gsl/gsl-lite.hpp */ + +/* Template to check if a template variable defines size() and data(). */ +template +struct has_size_and_data : std::false_type{}; +template +struct has_size_and_data +< + C, std::void_t< + decltype(std::size(std::declval())), + decltype(std::data(std::declval()))> +> : std::true_type{}; + +/* Template to check if two elements are compatible. */ +template +struct is_compatible_element : std::false_type {}; +template +struct is_compatible_element +< + C, E, std::void_t< + decltype(std::data(std::declval())), + typename std::remove_pointer()))>::type(*)[]> +> : std::is_convertible()))>::type(*)[], E(*)[]>{}; + +/* Template to check if a container is compatible. gsl-lite also includes is_array and is_std_array, but as we don't use them, they are omitted. */ +template +struct is_compatible_container : std::bool_constant +< + has_size_and_data::value + && is_compatible_element::value +>{}; + +/** + * A trimmed down version of what std::span will be in C++20. + * + * It is fully forwards compatible, so if this codebase switches to C++20, + * all "span" instances can be replaced by "std::span" without loss of + * functionality. + * + * Currently it only supports basic functionality: + * - size() and friends + * - begin() and friends + * + * It is meant to simplify function parameters, where we only want to walk + * a continuous list. + */ +template +class span { +public: + typedef T element_type; + typedef typename std::remove_cv< T >::type value_type; + + typedef T &reference; + typedef T *pointer; + typedef const T &const_reference; + typedef const T *const_pointer; + + typedef pointer iterator; + typedef const_pointer const_iterator; + + typedef size_t size_type; + typedef std::ptrdiff_t difference_type; + + constexpr span(pointer data_in, size_t size_in) : first(data_in), last(data_in + size_in) {} + + template::value), int>::type = 0> + constexpr span(Container &list) noexcept : first(std::data(list)), last(std::data(list) + std::size(list)) {} + template::value && is_compatible_container::value), int>::type = 0> + constexpr span(const Container &list) noexcept : first(std::data(list)), last(std::data(list) + std::size(list)) {} + + constexpr size_t size() const noexcept { return static_cast( last - first ); } + constexpr std::ptrdiff_t ssize() const noexcept { return static_cast( last - first ); } + constexpr bool empty() const noexcept { return size() == 0; } + + constexpr iterator begin() const noexcept { return iterator(first); } + constexpr iterator end() const noexcept { return iterator(last); } + + constexpr const_iterator cbegin() const noexcept { return const_iterator(first); } + constexpr const_iterator cend() const noexcept { return const_iterator(last); } + +private: + pointer first; + pointer last; +}; + +#endif /* CORE_SPAN_TYPE_HPP */ diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index 32f94a3c8c..5eb85e4c3c 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -16,10 +16,10 @@ #include "../station_base.h" #include "../cargotype.h" #include "../date_func.h" +#include "../saveload/saveload.h" #include "linkgraph_type.h" #include -struct SaveLoad; class LinkGraph; /** @@ -525,8 +525,8 @@ public: protected: friend class LinkGraph::ConstNode; friend class LinkGraph::Node; - friend const SaveLoad *GetLinkGraphDesc(); - friend const SaveLoad *GetLinkGraphJobDesc(); + friend SaveLoadTable GetLinkGraphDesc(); + friend SaveLoadTable GetLinkGraphJobDesc(); friend void SaveLoad_LinkGraph(LinkGraph &lg); CargoID cargo; ///< Cargo of this component's link graph. diff --git a/src/linkgraph/linkgraphjob.h b/src/linkgraph/linkgraphjob.h index f434fa8097..812afd1f71 100644 --- a/src/linkgraph/linkgraphjob.h +++ b/src/linkgraph/linkgraphjob.h @@ -52,7 +52,7 @@ private: typedef std::vector NodeAnnotationVector; typedef SmallMatrix EdgeAnnotationMatrix; - friend const SaveLoad *GetLinkGraphJobDesc(); + friend SaveLoadTable GetLinkGraphJobDesc(); friend class LinkGraphSchedule; protected: diff --git a/src/linkgraph/linkgraphschedule.h b/src/linkgraph/linkgraphschedule.h index 6a6dff697f..fef49e98f2 100644 --- a/src/linkgraph/linkgraphschedule.h +++ b/src/linkgraph/linkgraphschedule.h @@ -39,7 +39,7 @@ private: ~LinkGraphSchedule(); typedef std::list GraphList; typedef std::list JobList; - friend const SaveLoad *GetLinkGraphScheduleDesc(); + friend SaveLoadTable GetLinkGraphScheduleDesc(); protected: ComponentHandler *handlers[6]; ///< Handlers to be run for each job. diff --git a/src/order_backup.h b/src/order_backup.h index 5d1dcef50e..e1b71a71d7 100644 --- a/src/order_backup.h +++ b/src/order_backup.h @@ -15,6 +15,7 @@ #include "tile_type.h" #include "vehicle_type.h" #include "base_consist.h" +#include "saveload/saveload.h" /** Unique identifier for an order backup. */ typedef uint8 OrderBackupID; @@ -34,7 +35,7 @@ static const uint32 MAKE_ORDER_BACKUP_FLAG = 1U << 31; */ struct OrderBackup : OrderBackupPool::PoolItem<&_order_backup_pool>, BaseConsist { private: - friend const struct SaveLoad *GetOrderBackupDescription(); ///< Saving and loading of order backups. + friend SaveLoadTable GetOrderBackupDescription(); ///< Saving and loading of order backups. friend void Load_BKOR(); ///< Creating empty orders upon savegame loading. uint32 user; ///< The user that requested the backup. TileIndex tile; ///< Tile of the depot where the order was changed. diff --git a/src/order_base.h b/src/order_base.h index 923e67d423..c510bd3e06 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -18,6 +18,7 @@ #include "station_type.h" #include "vehicle_type.h" #include "date_type.h" +#include "saveload/saveload.h" typedef Pool OrderPool; typedef Pool OrderListPool; @@ -31,9 +32,9 @@ extern OrderListPool _orderlist_pool; */ struct Order : OrderPool::PoolItem<&_order_pool> { private: - friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles. + friend SaveLoadTable GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles. friend void Load_VEHS(); ///< Loading of ancient vehicles. - friend const struct SaveLoad *GetOrderDescription(); ///< Saving and loading of orders. + friend SaveLoadTable GetOrderDescription(); ///< Saving and loading of orders. uint8 type; ///< The type of order + non-stop flags uint8 flags; ///< Load/unload types, depot order/action types. @@ -250,7 +251,7 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord); struct OrderList : OrderListPool::PoolItem<&_orderlist_pool> { private: friend void AfterLoadVehicles(bool part_of_load); ///< For instantiating the shared vehicle chain - friend const struct SaveLoad *GetOrderListDescription(); ///< Saving and loading of order lists. + friend SaveLoadTable GetOrderListDescription(); ///< Saving and loading of order lists. StationID GetBestLoadableNext(const Vehicle *v, const Order *o1, const Order *o2) const; diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index 3bc1d0f879..fcb78f2edd 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -30,7 +30,6 @@ static const SaveLoad _ai_company[] = { SLEG_SSTR(_ai_saveload_settings, SLE_STR), SLEG_CONDVAR(_ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION), SLEG_CONDVAR(_ai_saveload_is_random, SLE_BOOL, SLV_136, SL_MAX_VERSION), - SLE_END() }; static void SaveReal_AIPL(int *index_ptr) diff --git a/src/saveload/autoreplace_sl.cpp b/src/saveload/autoreplace_sl.cpp index 88f925cc5d..ef343fc179 100644 --- a/src/saveload/autoreplace_sl.cpp +++ b/src/saveload/autoreplace_sl.cpp @@ -21,7 +21,6 @@ static const SaveLoad _engine_renew_desc[] = { SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS), SLE_CONDVAR(EngineRenew, group_id, SLE_UINT16, SLV_60, SL_MAX_VERSION), SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, SLV_175, SL_MAX_VERSION), - SLE_END() }; static void Save_ERNW() diff --git a/src/saveload/cargomonitor_sl.cpp b/src/saveload/cargomonitor_sl.cpp index 75f081eb25..3ca64d77ef 100644 --- a/src/saveload/cargomonitor_sl.cpp +++ b/src/saveload/cargomonitor_sl.cpp @@ -24,7 +24,6 @@ struct TempStorage { static const SaveLoad _cargomonitor_pair_desc[] = { SLE_VAR(TempStorage, number, SLE_UINT32), SLE_VAR(TempStorage, amount, SLE_UINT32), - SLE_END() }; static CargoMonitorID FixupCargoMonitor(CargoMonitorID number) diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index e9476fd4b1..1b9bb5cb94 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -83,7 +83,7 @@ * some of the variables itself are private. * @return the saveload description for CargoPackets. */ -const SaveLoad *GetCargoPacketDesc() +SaveLoadTable GetCargoPacketDesc() { static const SaveLoad _cargopacket_desc[] = { SLE_VAR(CargoPacket, source, SLE_UINT16), @@ -97,8 +97,6 @@ const SaveLoad *GetCargoPacketDesc() /* Used to be paid_for, but that got changed. */ SLE_CONDNULL(1, SL_MIN_VERSION, SLV_121), - - SLE_END() }; return _cargopacket_desc; } diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 5770f9791e..21d02121b6 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -293,8 +293,6 @@ static const SaveLoad _company_desc[] = { SLE_CONDVAR(CompanyProperties, terraform_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION), SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION), SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, SLV_175, SL_MAX_VERSION), - - SLE_END() }; static const SaveLoad _company_settings_desc[] = { @@ -314,8 +312,6 @@ static const SaveLoad _company_settings_desc[] = { SLE_CONDVAR(Company, settings.vehicle.servint_ships, SLE_UINT16, SLV_120, SL_MAX_VERSION), SLE_CONDNULL(63, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _company_settings_skip_desc[] = { @@ -336,8 +332,6 @@ static const SaveLoad _company_settings_skip_desc[] = { SLE_CONDNULL(2, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_ships SLE_CONDNULL(63, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _company_economy_desc[] = { @@ -353,8 +347,6 @@ static const SaveLoad _company_economy_desc[] = { SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES), SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION), SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32), - - SLE_END() }; /* We do need to read this single value, as the bigger it gets, the more data is stored */ @@ -390,7 +382,6 @@ static const SaveLoad _company_ai_desc[] = { SLE_CONDNULL(32, SL_MIN_VERSION, SLV_107), SLE_CONDNULL(64, SLV_2, SLV_107), - SLE_END() }; static const SaveLoad _company_ai_build_rec_desc[] = { @@ -399,14 +390,12 @@ static const SaveLoad _company_ai_build_rec_desc[] = { SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6), SLE_CONDNULL(4, SLV_6, SLV_107), SLE_CONDNULL(8, SL_MIN_VERSION, SLV_107), - SLE_END() }; static const SaveLoad _company_livery_desc[] = { SLE_CONDVAR(Livery, in_use, SLE_UINT8, SLV_34, SL_MAX_VERSION), SLE_CONDVAR(Livery, colour1, SLE_UINT8, SLV_34, SL_MAX_VERSION), SLE_CONDVAR(Livery, colour2, SLE_UINT8, SLV_34, SL_MAX_VERSION), - SLE_END() }; static void SaveLoad_PLYR_common(Company *c, CompanyProperties *cprops) diff --git a/src/saveload/depot_sl.cpp b/src/saveload/depot_sl.cpp index bd84faefc0..fb8944dbae 100644 --- a/src/saveload/depot_sl.cpp +++ b/src/saveload/depot_sl.cpp @@ -25,7 +25,6 @@ static const SaveLoad _depot_desc[] = { SLE_CONDVAR(Depot, town_cn, SLE_UINT16, SLV_141, SL_MAX_VERSION), SLE_CONDSSTR(Depot, name, SLE_STR, SLV_141, SL_MAX_VERSION), SLE_CONDVAR(Depot, build_date, SLE_INT32, SLV_142, SL_MAX_VERSION), - SLE_END() }; static void Save_DEPT() diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index a7d1819468..2c785d554a 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -46,7 +46,6 @@ static const SaveLoad _economy_desc[] = { SLE_VAR(Economy, infl_amount, SLE_UINT8), SLE_VAR(Economy, infl_amount_pr, SLE_UINT8), SLE_CONDVAR(Economy, industry_daily_change_counter, SLE_UINT32, SLV_102, SL_MAX_VERSION), - SLE_END() }; /** Economy variables */ @@ -67,7 +66,6 @@ static const SaveLoad _cargopayment_desc[] = { SLE_VAR(CargoPayment, route_profit, SLE_INT64), SLE_VAR(CargoPayment, visual_profit, SLE_INT64), SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION), - SLE_END() }; static void Save_CAPY() diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index b0b9d02d4d..eea3a0bcf0 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -42,8 +42,6 @@ static const SaveLoad _engine_desc[] = { SLE_CONDSSTR(Engine, name, SLE_STR, SLV_84, SL_MAX_VERSION), SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static std::vector _temp_engine; @@ -173,7 +171,6 @@ static const SaveLoad _engine_id_mapping_desc[] = { SLE_VAR(EngineIDMapping, internal_id, SLE_UINT16), SLE_VAR(EngineIDMapping, type, SLE_UINT8), SLE_VAR(EngineIDMapping, substitute_id, SLE_UINT8), - SLE_END() }; static void Save_EIDS() diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index 00ca6d9ab9..055a5fbfc4 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -30,7 +30,6 @@ static const SaveLoad _game_script[] = { SLEG_SSTR(_game_saveload_settings, SLE_STR), SLEG_VAR(_game_saveload_version, SLE_UINT32), SLEG_VAR(_game_saveload_is_random, SLE_BOOL), - SLE_END() }; static void SaveReal_GSDT(int *index_ptr) @@ -117,12 +116,10 @@ static uint _game_saveload_strings; static const SaveLoad _game_language_header[] = { SLEG_SSTR(_game_saveload_string, SLE_STR), SLEG_VAR(_game_saveload_strings, SLE_UINT32), - SLE_END() }; static const SaveLoad _game_language_string[] = { SLEG_SSTR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL), - SLE_END() }; static void SaveReal_GSTR(const LanguageStrings *ls) diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index d68297c9a7..3d236b1368 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -17,13 +17,11 @@ static const SaveLoad _glog_action_desc[] = { SLE_VAR(LoggedAction, tick, SLE_UINT16), - SLE_END() }; static const SaveLoad _glog_mode_desc[] = { SLE_VAR(LoggedChange, mode.mode, SLE_UINT8), SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8), - SLE_END() }; static const SaveLoad _glog_revision_desc[] = { @@ -31,62 +29,53 @@ static const SaveLoad _glog_revision_desc[] = { SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32), SLE_VAR(LoggedChange, revision.slver, SLE_UINT16), SLE_VAR(LoggedChange, revision.modified, SLE_UINT8), - SLE_END() }; static const SaveLoad _glog_oldver_desc[] = { SLE_VAR(LoggedChange, oldver.type, SLE_UINT32), SLE_VAR(LoggedChange, oldver.version, SLE_UINT32), - SLE_END() }; static const SaveLoad _glog_setting_desc[] = { SLE_STR(LoggedChange, setting.name, SLE_STR, 128), SLE_VAR(LoggedChange, setting.oldval, SLE_INT32), SLE_VAR(LoggedChange, setting.newval, SLE_INT32), - SLE_END() }; static const SaveLoad _glog_grfadd_desc[] = { SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ), SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16), - SLE_END() }; static const SaveLoad _glog_grfrem_desc[] = { SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32), - SLE_END() }; static const SaveLoad _glog_grfcompat_desc[] = { SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ), SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16), - SLE_END() }; static const SaveLoad _glog_grfparam_desc[] = { SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32), - SLE_END() }; static const SaveLoad _glog_grfmove_desc[] = { SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32), SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32), - SLE_END() }; static const SaveLoad _glog_grfbug_desc[] = { SLE_VAR(LoggedChange, grfbug.data, SLE_UINT64), SLE_VAR(LoggedChange, grfbug.grfid, SLE_UINT32), SLE_VAR(LoggedChange, grfbug.bug, SLE_UINT8), - SLE_END() }; static const SaveLoad _glog_emergency_desc[] = { - SLE_END() + SLE_CONDNULL(0, SL_MIN_VERSION, SL_MIN_VERSION), // Just an empty list, to keep the rest of the code easier. }; -static const SaveLoad * const _glog_desc[] = { +static const SaveLoadTable _glog_desc[] = { _glog_mode_desc, _glog_revision_desc, _glog_oldver_desc, diff --git a/src/saveload/goal_sl.cpp b/src/saveload/goal_sl.cpp index 4ee9f39ebe..2c9d8fde9f 100644 --- a/src/saveload/goal_sl.cpp +++ b/src/saveload/goal_sl.cpp @@ -21,7 +21,6 @@ static const SaveLoad _goals_desc[] = { SLE_STR(Goal, text, SLE_STR | SLF_ALLOW_CONTROL, 0), SLE_CONDSTR(Goal, progress, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_182, SL_MAX_VERSION), SLE_CONDVAR(Goal, completed, SLE_BOOL, SLV_182, SL_MAX_VERSION), - SLE_END() }; static void Save_GOAL() diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp index c5f7e2b507..a6ae263f9d 100644 --- a/src/saveload/group_sl.cpp +++ b/src/saveload/group_sl.cpp @@ -26,7 +26,6 @@ static const SaveLoad _group_desc[] = { SLE_CONDVAR(Group, livery.colour1, SLE_UINT8, SLV_GROUP_LIVERIES, SL_MAX_VERSION), SLE_CONDVAR(Group, livery.colour2, SLE_UINT8, SLV_GROUP_LIVERIES, SL_MAX_VERSION), SLE_CONDVAR(Group, parent, SLE_UINT16, SLV_189, SL_MAX_VERSION), - SLE_END() }; static void Save_GRPS() diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index 6f41e34552..a59524de67 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -75,8 +75,6 @@ static const SaveLoad _industry_desc[] = { SLE_CONDSSTR(Industry, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_INDUSTRY_TEXT, SL_MAX_VERSION), SLE_CONDNULL(32, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static void Save_INDY() @@ -139,7 +137,6 @@ static void Ptrs_INDY() /** Description of the data to save and load in #IndustryBuildData. */ static const SaveLoad _industry_builder_desc[] = { SLEG_VAR(_industry_builder.wanted_inds, SLE_UINT32), - SLEG_END() }; /** Load/save industry builder. */ @@ -155,7 +152,6 @@ static const SaveLoad _industrytype_builder_desc[] = { SLE_VAR(IndustryTypeBuildData, target_count, SLE_UINT16), SLE_VAR(IndustryTypeBuildData, max_wait, SLE_UINT16), SLE_VAR(IndustryTypeBuildData, wait_count, SLE_UINT16), - SLE_END() }; /** Save industry-type build data. */ diff --git a/src/saveload/labelmaps_sl.cpp b/src/saveload/labelmaps_sl.cpp index 542b85b9f1..6c2cd1bcac 100644 --- a/src/saveload/labelmaps_sl.cpp +++ b/src/saveload/labelmaps_sl.cpp @@ -95,7 +95,6 @@ struct LabelObject { static const SaveLoad _label_object_desc[] = { SLE_VAR(LabelObject, label, SLE_UINT32), - SLE_END(), }; static void Save_RAIL() diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index 7d4fe56712..3983000286 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -26,13 +26,12 @@ static uint16 _num_nodes; * Get a SaveLoad array for a link graph. * @return SaveLoad array for link graph. */ -const SaveLoad *GetLinkGraphDesc() +SaveLoadTable GetLinkGraphDesc() { static const SaveLoad link_graph_desc[] = { SLE_VAR(LinkGraph, last_compression, SLE_INT32), SLEG_VAR(_num_nodes, SLE_UINT16), SLE_VAR(LinkGraph, cargo, SLE_UINT8), - SLE_END() }; return link_graph_desc; } @@ -46,7 +45,7 @@ const SaveLoad *GetLinkGraphDesc() * Of course the settings have to be saved and loaded, too, to avoid desyncs. * @return Array of SaveLoad structs. */ -const SaveLoad *GetLinkGraphJobDesc() +SaveLoadTable GetLinkGraphJobDesc() { static std::vector saveloads; static const char *prefix = "linkgraph."; @@ -54,7 +53,6 @@ const SaveLoad *GetLinkGraphJobDesc() static const SaveLoad job_desc[] = { SLE_VAR(LinkGraphJob, join_date, SLE_INT32), SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16), - SLE_END() }; /* The member offset arithmetic below is only valid if the types in question @@ -74,25 +72,23 @@ const SaveLoad *GetLinkGraphJobDesc() sl.address_proc = proc; } - int i = 0; - do { - saveloads.push_back(job_desc[i++]); - } while (saveloads.back().cmd != SL_END); + for (auto &sld : job_desc) { + saveloads.push_back(sld); + } } - return &saveloads[0]; + return saveloads; } /** * Get a SaveLoad array for the link graph schedule. * @return SaveLoad array for the link graph schedule. */ -const SaveLoad *GetLinkGraphScheduleDesc() +SaveLoadTable GetLinkGraphScheduleDesc() { static const SaveLoad schedule_desc[] = { SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH), SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB), - SLE_END() }; return schedule_desc; } @@ -108,7 +104,6 @@ static const SaveLoad _node_desc[] = { SLE_VAR(Node, demand, SLE_UINT32), SLE_VAR(Node, station, SLE_UINT16), SLE_VAR(Node, last_update, SLE_INT32), - SLE_END() }; /** @@ -121,7 +116,6 @@ static const SaveLoad _edge_desc[] = { SLE_VAR(Edge, last_unrestricted_update, SLE_INT32), SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION), SLE_VAR(Edge, next_edge, SLE_UINT16), - SLE_END() }; /** diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 51c56684a9..d08fc63899 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -20,10 +20,9 @@ static uint32 _map_dim_x; static uint32 _map_dim_y; -static const SaveLoadGlobVarList _map_dimensions[] = { +static const SaveLoad _map_dimensions[] = { SLEG_CONDVAR(_map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION), SLEG_CONDVAR(_map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION), - SLEG_END() }; static void Save_MAPS() diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 0d760c9d5c..ba49c11be4 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -68,7 +68,7 @@ void ResetViewportAfterLoadGame() byte _age_cargo_skip_counter; ///< Skip aging of cargo? Used before savegame version 162. -static const SaveLoadGlobVarList _date_desc[] = { +static const SaveLoad _date_desc[] = { SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR(_date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLEG_VAR(_date_fract, SLE_UINT16), @@ -90,10 +90,9 @@ static const SaveLoadGlobVarList _date_desc[] = { SLEG_VAR(_trees_tick_ctr, SLE_UINT8), SLEG_CONDVAR(_pause_mode, SLE_UINT8, SLV_4, SL_MAX_VERSION), SLE_CONDNULL(4, SLV_11, SLV_120), - SLEG_END() }; -static const SaveLoadGlobVarList _date_check_desc[] = { +static const SaveLoad _date_check_desc[] = { SLEG_CONDVAR(_load_check_data.current_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR(_load_check_data.current_date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLE_NULL(2), // _date_fract @@ -115,7 +114,6 @@ static const SaveLoadGlobVarList _date_check_desc[] = { SLE_NULL(1), // _trees_tick_ctr SLE_CONDNULL(1, SLV_4, SL_MAX_VERSION), // _pause_mode SLE_CONDNULL(4, SLV_11, SLV_120), - SLEG_END() }; /* Save load date related variables as well as persistent tick counters @@ -134,13 +132,12 @@ static void Check_DATE() } -static const SaveLoadGlobVarList _view_desc[] = { +static const SaveLoad _view_desc[] = { SLEG_CONDVAR(_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6), SLEG_CONDVAR(_saved_scrollpos_x, SLE_INT32, SLV_6, SL_MAX_VERSION), SLEG_CONDVAR(_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6), SLEG_CONDVAR(_saved_scrollpos_y, SLE_INT32, SLV_6, SL_MAX_VERSION), SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8), - SLEG_END() }; static void SaveLoad_VIEW() diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index 2e9f1ccaf6..3faf9a64a6 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -20,7 +20,6 @@ static const SaveLoad _newgrf_mapping_desc[] = { SLE_VAR(EntityIDMapping, grfid, SLE_UINT32), SLE_VAR(EntityIDMapping, entity_id, SLE_UINT8), SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT8), - SLE_END() }; /** @@ -65,7 +64,6 @@ static const SaveLoad _grfconfig_desc[] = { SLE_ARR(GRFConfig, param, SLE_UINT32, 0x80), SLE_VAR(GRFConfig, num_params, SLE_UINT8), SLE_CONDVAR(GRFConfig, palette, SLE_UINT8, SLV_101, SL_MAX_VERSION), - SLE_END() }; diff --git a/src/saveload/object_sl.cpp b/src/saveload/object_sl.cpp index 2c385b6552..40ca8cd110 100644 --- a/src/saveload/object_sl.cpp +++ b/src/saveload/object_sl.cpp @@ -25,8 +25,6 @@ static const SaveLoad _object_desc[] = { SLE_CONDVAR(Object, colour, SLE_UINT8, SLV_148, SL_MAX_VERSION), SLE_CONDVAR(Object, view, SLE_UINT8, SLV_155, SL_MAX_VERSION), SLE_CONDVAR(Object, type, SLE_UINT16, SLV_186, SL_MAX_VERSION), - - SLE_END() }; static void Save_OBJS() diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 1292c1b056..44080e695d 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -99,7 +99,7 @@ Order UnpackOldOrder(uint16 packed) return order; } -const SaveLoad *GetOrderDescription() +SaveLoadTable GetOrderDescription() { static const SaveLoad _order_desc[] = { SLE_VAR(Order, type, SLE_UINT8), @@ -115,7 +115,6 @@ const SaveLoad *GetOrderDescription() /* Leftover from the minor savegame version stuff * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */ SLE_CONDNULL(10, SLV_5, SLV_36), - SLE_END() }; return _order_desc; @@ -196,11 +195,10 @@ static void Ptrs_ORDR() } } -const SaveLoad *GetOrderListDescription() +SaveLoadTable GetOrderListDescription() { static const SaveLoad _orderlist_desc[] = { SLE_REF(OrderList, first, REF_ORDER), - SLE_END() }; return _orderlist_desc; @@ -233,7 +231,7 @@ static void Ptrs_ORDL() } } -const SaveLoad *GetOrderBackupDescription() +SaveLoadTable GetOrderBackupDescription() { static const SaveLoad _order_backup_desc[] = { SLE_VAR(OrderBackup, user, SLE_UINT32), @@ -252,7 +250,6 @@ const SaveLoad *GetOrderBackupDescription() SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_176, SLV_180), SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION), SLE_REF(OrderBackup, orders, REF_ORDER), - SLE_END() }; return _order_backup_desc; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9a9ed7cc5c..f056404b54 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1400,10 +1400,10 @@ static void SlDeque(void *deque, VarType conv) /** Are we going to save this object or not? */ -static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) +static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) { - if (_sl_version < sld->version_from || _sl_version >= sld->version_to) return false; - if (sld->conv & SLF_NOT_IN_SAVE) return false; + if (_sl_version < sld.version_from || _sl_version >= sld.version_to) return false; + if (sld.conv & SLF_NOT_IN_SAVE) return false; return true; } @@ -1413,10 +1413,10 @@ static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) * @note If the variable is skipped it is skipped in the savegame * bytestream itself as well, so there is no need to skip it somewhere else */ -static inline bool SlSkipVariableOnLoad(const SaveLoad *sld) +static inline bool SlSkipVariableOnLoad(const SaveLoad &sld) { - if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) { - SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length); + if ((sld.conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) { + SlSkipBytes(SlCalcConvMemLen(sld.conv) * sld.length); return true; } @@ -1425,26 +1425,26 @@ static inline bool SlSkipVariableOnLoad(const SaveLoad *sld) /** * Calculate the size of an object. - * @param object to be measured - * @param sld The SaveLoad description of the object so we know how to manipulate it - * @return size of given object + * @param object to be measured. + * @param slt The SaveLoad table with objects to save/load. + * @return size of given object. */ -size_t SlCalcObjLength(const void *object, const SaveLoad *sld) +size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt) { size_t length = 0; /* Need to determine the length and write a length tag. */ - for (; sld->cmd != SL_END; sld++) { + for (auto &sld : slt) { length += SlCalcObjMemberLength(object, sld); } return length; } -size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) +size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) { assert(_sl.action == SLA_SAVE); - switch (sld->cmd) { + switch (sld.cmd) { case SL_VAR: case SL_REF: case SL_ARR: @@ -1455,13 +1455,13 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) break; - switch (sld->cmd) { - case SL_VAR: return SlCalcConvFileLen(sld->conv); + switch (sld.cmd) { + case SL_VAR: return SlCalcConvFileLen(sld.conv); case SL_REF: return SlCalcRefLen(); - case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv); - case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv); + case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); + case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld)); - case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld->conv); + case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); default: NOT_REACHED(); } @@ -1481,41 +1481,41 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) * matches with the actual variable size. * @param sld The saveload configuration to test. */ -static bool IsVariableSizeRight(const SaveLoad *sld) +static bool IsVariableSizeRight(const SaveLoad &sld) { - switch (sld->cmd) { + switch (sld.cmd) { case SL_VAR: - switch (GetVarMemType(sld->conv)) { + switch (GetVarMemType(sld.conv)) { case SLE_VAR_BL: - return sld->size == sizeof(bool); + return sld.size == sizeof(bool); case SLE_VAR_I8: case SLE_VAR_U8: - return sld->size == sizeof(int8); + return sld.size == sizeof(int8); case SLE_VAR_I16: case SLE_VAR_U16: - return sld->size == sizeof(int16); + return sld.size == sizeof(int16); case SLE_VAR_I32: case SLE_VAR_U32: - return sld->size == sizeof(int32); + return sld.size == sizeof(int32); case SLE_VAR_I64: case SLE_VAR_U64: - return sld->size == sizeof(int64); + return sld.size == sizeof(int64); case SLE_VAR_NAME: - return sld->size == sizeof(std::string); + return sld.size == sizeof(std::string); default: - return sld->size == sizeof(void *); + return sld.size == sizeof(void *); } case SL_REF: /* These should all be pointer sized. */ - return sld->size == sizeof(void *); + return sld.size == sizeof(void *); case SL_STR: /* These should be pointer sized, or fixed array. */ - return sld->size == sizeof(void *) || sld->size == sld->length; + return sld.size == sizeof(void *) || sld.size == sld.length; case SL_STDSTR: /* These should be all pointers to std::string. */ - return sld->size == sizeof(std::string); + return sld.size == sizeof(std::string); default: return true; @@ -1524,14 +1524,14 @@ static bool IsVariableSizeRight(const SaveLoad *sld) #endif /* OTTD_ASSERT */ -bool SlObjectMember(void *ptr, const SaveLoad *sld) +bool SlObjectMember(void *ptr, const SaveLoad &sld) { #ifdef OTTD_ASSERT assert(IsVariableSizeRight(sld)); #endif - VarType conv = GB(sld->conv, 0, 8); - switch (sld->cmd) { + VarType conv = GB(sld.conv, 0, 8); + switch (sld.cmd) { case SL_VAR: case SL_REF: case SL_ARR: @@ -1543,7 +1543,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) if (!SlIsObjectValidInSavegame(sld)) return false; if (SlSkipVariableOnLoad(sld)) return false; - switch (sld->cmd) { + switch (sld.cmd) { case SL_VAR: SlSaveLoadConv(ptr, conv); break; case SL_REF: // Reference variable, translate switch (_sl.action) { @@ -1563,11 +1563,11 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) default: NOT_REACHED(); } break; - case SL_ARR: SlArray(ptr, sld->length, conv); break; - case SL_STR: SlString(ptr, sld->length, sld->conv); break; + case SL_ARR: SlArray(ptr, sld.length, conv); break; + case SL_STR: SlString(ptr, sld.length, sld.conv); break; case SL_LST: SlList(ptr, (SLRefType)conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; - case SL_STDSTR: SlStdString(ptr, sld->conv); break; + case SL_STDSTR: SlStdString(ptr, sld.conv); break; default: NOT_REACHED(); } break; @@ -1602,30 +1602,30 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) /** * Main SaveLoad function. - * @param object The object that is being saved or loaded - * @param sld The SaveLoad description of the object so we know how to manipulate it + * @param object The object that is being saved or loaded. + * @param slt The SaveLoad table with objects to save/load. */ -void SlObject(void *object, const SaveLoad *sld) +void SlObject(void *object, const SaveLoadTable &slt) { /* Automatically calculate the length? */ if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcObjLength(object, sld)); + SlSetLength(SlCalcObjLength(object, slt)); if (_sl.need_length == NL_CALCLENGTH) return; } - for (; sld->cmd != SL_END; sld++) { + for (auto &sld : slt) { void *ptr = GetVariableAddress(object, sld); SlObjectMember(ptr, sld); } } /** - * Save or Load (a list of) global variables - * @param sldg The global variable that is being loaded or saved + * Save or Load (a list of) global variables. + * @param slt The SaveLoad table with objects to save/load. */ -void SlGlobList(const SaveLoadGlobVarList *sldg) +void SlGlobList(const SaveLoadTable &slt) { - SlObject(nullptr, (const SaveLoad*)sldg); + SlObject(nullptr, slt); } /** diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index d28b81692f..1c763a93fc 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -12,6 +12,7 @@ #include "../fileio_type.h" #include "../strings_type.h" +#include "../core/span_type.hpp" #include /** SaveLoad versions @@ -506,7 +507,6 @@ enum SaveLoadType : byte { SL_WRITEBYTE = 8, SL_VEH_INCLUDE = 9, SL_ST_INCLUDE = 10, - SL_END = 15 }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -523,8 +523,8 @@ struct SaveLoad { size_t extra_data; ///< extra data for the callback proc }; -/** Same as #SaveLoad but global variables are used (for better readability); */ -typedef SaveLoad SaveLoadGlobVarList; +/** A table of SaveLoad entries. */ +using SaveLoadTable = span; /** * Storage of simple variables, references (pointers), and arrays. @@ -681,9 +681,6 @@ typedef SaveLoad SaveLoadGlobVarList; #define SLE_VEH_INCLUDE() {SL_VEH_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0, [] (void *b, size_t) { return b; }, 0} #define SLE_ST_INCLUDE() {SL_ST_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0, [] (void *b, size_t) { return b; }, 0} -/** End marker of a struct/class save or load. */ -#define SLE_END() {SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, 0, nullptr, 0} - /** * Storage of global simple variables, references (pointers), and arrays. * @param cmd Load/save type. @see SaveLoadType @@ -802,9 +799,6 @@ typedef SaveLoad SaveLoadGlobVarList; */ #define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, 0, nullptr, 0} -/** End marker of global variables save or load. */ -#define SLEG_END() {SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, 0, nullptr, 0} - /** * Checks whether the savegame is below \a major.\a minor. * @param major Major number of the version to check against. @@ -883,17 +877,17 @@ static inline bool IsNumericType(VarType conv) * everything else has a callback function that returns the address based * on the saveload data and the current object for non-globals. */ -static inline void *GetVariableAddress(const void *object, const SaveLoad *sld) +static inline void *GetVariableAddress(const void *object, const SaveLoad &sld) { /* Entry is a null-variable, mostly used to read old savegames etc. */ - if (GetVarMemType(sld->conv) == SLE_VAR_NULL) { - assert(sld->address_proc == nullptr); + if (GetVarMemType(sld.conv) == SLE_VAR_NULL) { + assert(sld.address_proc == nullptr); return nullptr; } /* Everything else should be a non-null pointer. */ - assert(sld->address_proc != nullptr); - return sld->address_proc(const_cast(object), sld->extra_data); + assert(sld.address_proc != nullptr); + return sld.address_proc(const_cast(object), sld.extra_data); } int64 ReadValue(const void *ptr, VarType conv); @@ -905,16 +899,16 @@ int SlIterateArray(); void SlAutolength(AutolengthProc *proc, void *arg); size_t SlGetFieldLength(); void SlSetLength(size_t length); -size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld); -size_t SlCalcObjLength(const void *object, const SaveLoad *sld); +size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld); +size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt); byte SlReadByte(); void SlWriteByte(byte b); -void SlGlobList(const SaveLoadGlobVarList *sldg); +void SlGlobList(const SaveLoadTable &slt); void SlArray(void *array, size_t length, VarType conv); -void SlObject(void *object, const SaveLoad *sld); -bool SlObjectMember(void *object, const SaveLoad *sld); +void SlObject(void *object, const SaveLoadTable &slt); +bool SlObjectMember(void *object, const SaveLoad &sld); void NORETURN SlError(StringID string, const char *extra_msg = nullptr); void NORETURN SlErrorCorrupt(const char *msg); void NORETURN SlErrorCorruptFmt(const char *format, ...) WARN_FORMAT(1, 2); diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index bca0e87cda..920be04178 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -23,7 +23,7 @@ void ResetOldNames(); void ResetOldWaypoints(); void MoveBuoysToWaypoints(); void MoveWaypointsToBaseStations(); -const SaveLoad *GetBaseStationDescription(); +SaveLoadTable GetBaseStationDescription(); void AfterLoadVehicles(bool part_of_load); void FixupTrainLengths(); diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 99e24435b9..86a1468a56 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -26,7 +26,6 @@ static const SaveLoad _sign_desc[] = { SLE_CONDVAR(Sign, owner, SLE_UINT8, SLV_6, SL_MAX_VERSION), SLE_CONDVAR(Sign, z, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164), SLE_CONDVAR(Sign, z, SLE_INT32, SLV_164, SL_MAX_VERSION), - SLE_END() }; /** Save all signs */ diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 74f3a5fb9b..cd1b93138e 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -154,8 +154,6 @@ static const SaveLoad _roadstop_desc[] = { SLE_CONDNULL(4, SL_MIN_VERSION, SLV_25), SLE_CONDNULL(1, SLV_25, SLV_26), - - SLE_END() }; static const SaveLoad _old_station_desc[] = { @@ -213,8 +211,6 @@ static const SaveLoad _old_station_desc[] = { /* reserve extra space in savegame here. (currently 32 bytes) */ SLE_CONDNULL(32, SLV_2, SL_MAX_VERSION), - - SLE_END() }; static uint16 _waiting_acceptance; @@ -227,8 +223,6 @@ static Money _cargo_feeder_share; static const SaveLoad _station_speclist_desc[] = { SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, SLV_27, SL_MAX_VERSION), SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8, SLV_27, SL_MAX_VERSION), - - SLE_END() }; std::list _packets; @@ -247,7 +241,6 @@ static const SaveLoad _flow_desc[] = { SLE_VAR(FlowSaveLoad, via, SLE_UINT16), SLE_VAR(FlowSaveLoad, share, SLE_UINT32), SLE_CONDVAR(FlowSaveLoad, restricted, SLE_BOOL, SLV_187, SL_MAX_VERSION), - SLE_END() }; /** @@ -255,7 +248,7 @@ static const SaveLoad _flow_desc[] = { * some of the variables itself are private. * @return the saveload description for GoodsEntry. */ -const SaveLoad *GetGoodsDesc() +SaveLoadTable GetGoodsDesc() { static const SaveLoad goods_desc[] = { SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, SL_MIN_VERSION, SLV_68), @@ -279,7 +272,6 @@ const SaveLoad *GetGoodsDesc() SLE_CONDVAR(GoodsEntry, node, SLE_UINT16, SLV_183, SL_MAX_VERSION), SLEG_CONDVAR( _num_flows, SLE_UINT32, SLV_183, SL_MAX_VERSION), SLE_CONDVAR(GoodsEntry, max_waiting_cargo, SLE_UINT32, SLV_183, SL_MAX_VERSION), - SLE_END() }; return goods_desc; @@ -290,7 +282,6 @@ typedef std::pair > StationCargoPair; static const SaveLoad _cargo_list_desc[] = { SLE_VAR(StationCargoPair, first, SLE_UINT16), SLE_LST(StationCargoPair, second, REF_CARGO_PACKET), - SLE_END() }; /** @@ -398,8 +389,6 @@ static const SaveLoad _base_station_desc[] = { SLE_VAR(BaseStation, random_bits, SLE_UINT16), SLE_VAR(BaseStation, waiting_triggers, SLE_UINT8), SLE_VAR(BaseStation, num_specs, SLE_UINT8), - - SLE_END() }; static OldPersistentStorage _old_st_persistent_storage; @@ -440,8 +429,6 @@ static const SaveLoad _station_desc[] = { SLE_LST(Station, loading_vehicles, REF_VEHICLE), SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES), SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION), - - SLE_END() }; static const SaveLoad _waypoint_desc[] = { @@ -453,15 +440,13 @@ static const SaveLoad _waypoint_desc[] = { SLE_CONDVAR(Waypoint, train_station.tile, SLE_UINT32, SLV_124, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, train_station.w, SLE_FILE_U8 | SLE_VAR_U16, SLV_124, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, train_station.h, SLE_FILE_U8 | SLE_VAR_U16, SLV_124, SL_MAX_VERSION), - - SLE_END() }; /** * Get the base station description to be used for SL_ST_INCLUDE * @return the base station description. */ -const SaveLoad *GetBaseStationDescription() +SaveLoadTable GetBaseStationDescription() { return _base_station_desc; } @@ -469,7 +454,7 @@ const SaveLoad *GetBaseStationDescription() static void RealSave_STNN(BaseStation *bst) { bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0; - SlObject(bst, waypoint ? _waypoint_desc : _station_desc); + SlObject(bst, waypoint ? SaveLoadTable(_waypoint_desc) : SaveLoadTable(_station_desc)); if (!waypoint) { Station *st = Station::From(bst); @@ -524,7 +509,7 @@ static void Load_STNN() bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0; BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station(); - SlObject(bst, waypoint ? _waypoint_desc : _station_desc); + SlObject(bst, waypoint ? SaveLoadTable(_waypoint_desc) : SaveLoadTable(_station_desc)); if (!waypoint) { Station *st = Station::From(bst); diff --git a/src/saveload/storage_sl.cpp b/src/saveload/storage_sl.cpp index 7abe396f38..a01904e3a1 100644 --- a/src/saveload/storage_sl.cpp +++ b/src/saveload/storage_sl.cpp @@ -18,7 +18,6 @@ static const SaveLoad _storage_desc[] = { SLE_CONDVAR(PersistentStorage, grfid, SLE_UINT32, SLV_6, SL_MAX_VERSION), SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 16, SLV_161, SLV_EXTEND_PERSISTENT_STORAGE), SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 256, SLV_EXTEND_PERSISTENT_STORAGE, SL_MAX_VERSION), - SLE_END() }; /** Load persistent storage data. */ diff --git a/src/saveload/story_sl.cpp b/src/saveload/story_sl.cpp index dba2a064f5..06083fb103 100644 --- a/src/saveload/story_sl.cpp +++ b/src/saveload/story_sl.cpp @@ -34,7 +34,6 @@ static const SaveLoad _story_page_elements_desc[] = { SLE_CONDVAR(StoryPageElement, type, SLE_UINT8, SLV_185, SL_MAX_VERSION), SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32), SLE_STR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL, 0), - SLE_END() }; static void Save_STORY_PAGE_ELEMENT() @@ -69,7 +68,6 @@ static const SaveLoad _story_pages_desc[] = { SLE_CONDVAR(StoryPage, company, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_185), SLE_CONDVAR(StoryPage, company, SLE_UINT8, SLV_185, SL_MAX_VERSION), SLE_STR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL, 0), - SLE_END() }; static void Save_STORY_PAGE() diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index d0db78b61d..dbd04c8adb 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -24,7 +24,6 @@ static const SaveLoad _subsidies_desc[] = { SLE_CONDVAR(Subsidy, src, SLE_UINT16, SLV_5, SL_MAX_VERSION), SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5), SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION), - SLE_END() }; static void Save_SUBS() diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 4e9e0afebb..3ba25f6406 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -194,8 +194,6 @@ static const SaveLoad _town_desc[] = { SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use SLE_CONDNULL(30, SLV_2, SLV_REMOVE_TOWN_CARGO_CACHE), ///< old reserved space - - SLE_END() }; static const SaveLoad _town_supplied_desc[] = { @@ -203,8 +201,6 @@ static const SaveLoad _town_supplied_desc[] = { SLE_CONDVAR(TransportedCargoStat, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION), SLE_CONDVAR(TransportedCargoStat, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION), SLE_CONDVAR(TransportedCargoStat, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION), - - SLE_END() }; static const SaveLoad _town_received_desc[] = { @@ -212,8 +208,6 @@ static const SaveLoad _town_received_desc[] = { SLE_CONDVAR(TransportedCargoStat, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION), SLE_CONDVAR(TransportedCargoStat, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION), SLE_CONDVAR(TransportedCargoStat, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION), - - SLE_END() }; static void Save_HIDS() @@ -226,14 +220,13 @@ static void Load_HIDS() Load_NewGRFMapping(_house_mngr); } -const SaveLoad *GetTileMatrixDesc() +SaveLoadTable GetTileMatrixDesc() { /* Here due to private member vars. */ static const SaveLoad _tilematrix_desc[] = { SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32), SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16), SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16), - SLE_END() }; return _tilematrix_desc; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 131d31519a..e637f03b26 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -578,7 +578,7 @@ static uint32 _cargo_loaded_at_xy; * @param vt the vehicle type. Can be VEH_END for the common vehicle description data * @return the saveload description */ -const SaveLoad *GetVehicleDescription(VehicleType vt) +SaveLoadTable GetVehicleDescription(VehicleType vt) { /** Save and load of vehicles */ static const SaveLoad _common_veh_desc[] = { @@ -712,11 +712,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDVAR(Vehicle, lateness_counter, SLE_INT32, SLV_67, SL_MAX_VERSION), SLE_CONDNULL(10, SLV_2, SLV_144), // old reserved space - - SLE_END() }; - static const SaveLoad _train_desc[] = { SLE_WRITEBYTE(Vehicle, type), SLE_VEH_INCLUDE(), @@ -734,8 +731,6 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDNULL(2, SLV_2, SLV_20), SLE_CONDVAR(Train, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION), SLE_CONDNULL(11, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _roadveh_desc[] = { @@ -756,8 +751,6 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDNULL(4, SLV_69, SLV_131), SLE_CONDNULL(2, SLV_6, SLV_131), SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _ship_desc[] = { @@ -768,8 +761,6 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDVAR(Ship, rotation, SLE_UINT8, SLV_SHIP_ROTATION, SL_MAX_VERSION), SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _aircraft_desc[] = { @@ -791,8 +782,6 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDVAR(Aircraft, flags, SLE_UINT8, SLV_167, SL_MAX_VERSION), SLE_CONDNULL(13, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _special_desc[] = { @@ -821,8 +810,6 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDVAR(Vehicle, spritenum, SLE_UINT8, SLV_2, SL_MAX_VERSION), SLE_CONDNULL(15, SLV_2, SLV_144), // old reserved space - - SLE_END() }; static const SaveLoad _disaster_desc[] = { @@ -862,12 +849,10 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDVAR(DisasterVehicle, flags, SLE_UINT8, SLV_194, SL_MAX_VERSION), SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space - - SLE_END() }; - static const SaveLoad * const _veh_descs[] = { + static const SaveLoadTable _veh_descs[] = { _train_desc, _roadveh_desc, _ship_desc, diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 663c61f6a8..9ad3da1f3b 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -180,8 +180,6 @@ static const SaveLoad _old_waypoint_desc[] = { SLE_CONDVAR(OldWaypoint, localidx, SLE_UINT8, SLV_3, SL_MAX_VERSION), SLE_CONDVAR(OldWaypoint, grfid, SLE_UINT32, SLV_17, SL_MAX_VERSION), SLE_CONDVAR(OldWaypoint, owner, SLE_UINT8, SLV_101, SL_MAX_VERSION), - - SLE_END() }; static void Load_WAYP() diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index fadbba70dd..24dbb9c395 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -343,7 +343,6 @@ static byte _script_sl_byte; ///< Used as source/target by the script saveload c /** SaveLoad array that saves/loads exactly one byte. */ static const SaveLoad _script_byte[] = { SLEG_VAR(_script_sl_byte, SLE_UINT8), - SLE_END() }; /* static */ bool ScriptInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test) diff --git a/src/settings.cpp b/src/settings.cpp index f7a4ff5dec..619d762d2d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -258,7 +258,7 @@ static bool LoadIntList(const char *str, void *array, int nelems, VarType type) */ void ListSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - const byte *p = static_cast(GetVariableAddress(object, &this->save)); + const byte *p = static_cast(GetVariableAddress(object, this->save)); int i, v = 0; for (i = 0; i != this->save.length; i++) { @@ -446,7 +446,7 @@ void IntSettingDesc::MakeValueValid(int32 &val) const */ void IntSettingDesc::Write(const void *object, int32 val) const { - void *ptr = GetVariableAddress(object, &this->save); + void *ptr = GetVariableAddress(object, this->save); WriteValue(ptr, this->save.conv, (int64)val); } @@ -457,7 +457,7 @@ void IntSettingDesc::Write(const void *object, int32 val) const */ int32 IntSettingDesc::Read(const void *object) const { - void *ptr = GetVariableAddress(object, &this->save); + void *ptr = GetVariableAddress(object, this->save); return (int32)ReadValue(ptr, this->save.conv); } @@ -486,7 +486,7 @@ void StringSettingDesc::MakeValueValid(std::string &str) const */ void StringSettingDesc::Write(const void *object, const std::string &str) const { - reinterpret_cast(GetVariableAddress(object, &this->save))->assign(str); + reinterpret_cast(GetVariableAddress(object, this->save))->assign(str); } /** @@ -496,7 +496,7 @@ void StringSettingDesc::Write(const void *object, const std::string &str) const */ const std::string &StringSettingDesc::Read(const void *object) const { - return *reinterpret_cast(GetVariableAddress(object, &this->save)); + return *reinterpret_cast(GetVariableAddress(object, this->save)); } /** @@ -560,7 +560,7 @@ void StringSettingDesc::ParseValue(const IniItem *item, void *object) const void ListSettingDesc::ParseValue(const IniItem *item, void *object) const { const char *str = (item == nullptr) ? this->def : item->value.has_value() ? item->value->c_str() : nullptr; - void *ptr = GetVariableAddress(object, &this->save); + void *ptr = GetVariableAddress(object, this->save); if (!LoadIntList(str, ptr, this->save.length, GetVarMemType(this->save.conv))) { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY); msg.SetDParamStr(0, this->name); @@ -2025,9 +2025,9 @@ void IConsoleListSettings(const char *prefilter) static void LoadSettings(const SettingTable &settings, void *object) { for (auto &osd : settings) { - void *ptr = GetVariableAddress(object, &osd->save); + void *ptr = GetVariableAddress(object, osd->save); - if (!SlObjectMember(ptr, &osd->save)) continue; + if (!SlObjectMember(ptr, osd->save)) continue; if (osd->IsIntSetting()) { const IntSettingDesc *int_setting = osd->AsIntSetting(); int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); @@ -2047,13 +2047,13 @@ static void SaveSettings(const SettingTable &settings, void *object) * SlCalcLength() because we have a different format. So do this manually */ size_t length = 0; for (auto &sd : settings) { - length += SlCalcObjMemberLength(object, &sd->save); + length += SlCalcObjMemberLength(object, sd->save); } SlSetLength(length); for (auto &sd : settings) { - void *ptr = GetVariableAddress(object, &sd->save); - SlObjectMember(ptr, &sd->save); + void *ptr = GetVariableAddress(object, sd->save); + SlObjectMember(ptr, sd->save); } } diff --git a/src/vehicle_base.h b/src/vehicle_base.h index f80faf1e39..029ddcf667 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -22,6 +22,7 @@ #include "group_type.h" #include "base_consist.h" #include "network/network.h" +#include "saveload/saveload.h" #include #include @@ -198,9 +199,8 @@ typedef Pool VehiclePool; extern VehiclePool _vehicle_pool; /* Some declarations of functions, so we can make them friendly */ -struct SaveLoad; struct GroundVehicleCache; -extern const SaveLoad *GetVehicleDescription(VehicleType vt); +extern SaveLoadTable GetVehicleDescription(VehicleType vt); struct LoadgameState; extern bool LoadOldVehicle(LoadgameState *ls, int num); extern void FixOldVehicles(); @@ -232,7 +232,7 @@ private: Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain public: - friend const SaveLoad *GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code + friend SaveLoadTable GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code friend void FixOldVehicles(); friend void AfterLoadVehicles(bool part_of_load); ///< So we can set the #previous and #first pointers while loading friend bool LoadOldVehicle(LoadgameState *ls, int num); ///< So we can set the proper next pointer while loading From c936f8b7699f194efa4939f01c31db6501d09736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0efl?= Date: Tue, 1 Jun 2021 16:41:23 +0200 Subject: [PATCH 298/800] Fix b791ffc6: use the correct parameter in CmdSignalTrackHelper --- src/rail_cmd.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 2526fe401c..59c1d27ab0 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1381,15 +1381,15 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin last_suitable_trackdir = trackdir; } else if (!test_only && last_suitable_tile != INVALID_TILE) { /* If a signal can't be placed, place it at the last possible position. */ - SB(p1, 0, 3, TrackdirToTrack(last_suitable_trackdir)); - ClrBit(p1, 17); + SB(param1, 0, 3, TrackdirToTrack(last_suitable_trackdir)); + ClrBit(param1, 17); /* Pick the correct orientation for the track direction. */ signals = 0; if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(last_suitable_trackdir); if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(last_suitable_trackdir); - ret = DoCommand(last_suitable_tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); + ret = DoCommand(last_suitable_tile, param1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); } /* Collect cost. */ From 30f5938eed1159f448b9eb2746a602a603383be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0efl?= Date: Tue, 1 Jun 2021 17:37:39 +0200 Subject: [PATCH 299/800] Fix b791ffc6: use the correct name in CmdPlantTree --- src/tree_cmd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 0ee91b4cd9..e2460f3b08 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -448,9 +448,9 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 break; } - if (IsTileType(tile, MP_CLEAR)) { + if (IsTileType(current_tile, MP_CLEAR)) { /* Remove fields or rocks. Note that the ground will get barrened */ - switch (GetRawClearGround(tile)) { + switch (GetRawClearGround(current_tile)) { case CLEAR_FIELDS: case CLEAR_ROCKS: { CommandCost ret = DoCommand(current_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); From 48ecc481ee3b38702eb58f3cfef009d2ee5a9693 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 1 Jun 2021 20:58:39 +0000 Subject: [PATCH 300/800] Update: Translations from eints swedish: 1 change by joeax910 --- src/lang/swedish.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 03ea486cb9..98ac033fae 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kunde in STR_NETWORK_ERROR_TIMEOUT :{WHITE}Nätverkskoppling #{NUM} timeout STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ett protokollfel uppstod och anslutningen stängdes. STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Du har inte angivit något spelarnamn. Namninställning kan göras högst upp i flerspelarfönstret +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Du har inte angivit något servernamn. Namninställning kan göras högst upp i flerspelarfönstret STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Servern har en annan version än denna klient STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Fel lösenord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Servern är full From 28e90769f74e55ea7c8f75146d5b33e0aa777da8 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 16:55:08 +0200 Subject: [PATCH 301/800] Codechange: use "[[maybe_unused]]" instead of a wide variety of other ways we had While at it, replace OTTD_ASSERT with WITH_ASSERT, as this is always set if assert() is valid. No matter if NDEBUG is set or not. --- src/3rdparty/squirrel/squirrel/sqcompiler.cpp | 3 +-- src/3rdparty/squirrel/squirrel/sqvm.cpp | 6 +----- src/autoreplace_cmd.cpp | 6 ++---- src/core/pool_func.hpp | 8 ++++---- src/core/pool_type.hpp | 8 ++++---- src/engine.cpp | 3 +-- src/gfxinit.cpp | 3 +-- src/industry_cmd.cpp | 3 +-- src/misc/hashtable.hpp | 3 +-- src/pathfinder/npf/npf.cpp | 3 +-- src/saveload/saveload.cpp | 8 +------- src/script/squirrel.cpp | 3 +-- src/spritecache.cpp | 4 +--- src/stdafx.h | 5 ----- src/tgp.cpp | 4 +--- src/town_cmd.cpp | 18 ++++++++++-------- src/townname.cpp | 4 +--- src/tunnelbridge_cmd.cpp | 3 +-- src/vehicle.cpp | 4 +--- src/vehiclelist.cpp | 3 +-- src/widget.cpp | 8 ++------ 21 files changed, 37 insertions(+), 73 deletions(-) diff --git a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp index 00e5df04f4..a80e08639b 100644 --- a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp +++ b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp @@ -835,8 +835,7 @@ public: nkeys++; SQInteger val = _fs->PopTarget(); SQInteger key = _fs->PopTarget(); - SQInteger attrs = hasattrs ? _fs->PopTarget():-1; - (void)attrs; // assert only + [[maybe_unused]] SQInteger attrs = hasattrs ? _fs->PopTarget():-1; assert((hasattrs && attrs == key-1) || !hasattrs); unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); SQInteger table = _fs->TopTarget(); //<_can_suspend); @@ -1504,11 +1502,9 @@ bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObj default: return false; } -#ifdef WITH_ASSERT if(!_suspended) { assert(_stackbase == prevstackbase); } -#endif return true; } diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index de5617a4d9..9e82944b64 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -596,8 +596,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon assert(RailVehInfo(wagon->engine_type)->railveh_type == RAILVEH_WAGON); /* Sell wagon */ - CommandCost ret = DoCommand(0, wagon->index, 0, DC_EXEC, GetCmdSellVeh(wagon)); - (void)ret; // assert only + [[maybe_unused]] CommandCost ret = DoCommand(0, wagon->index, 0, DC_EXEC, GetCmdSellVeh(wagon)); assert(ret.Succeeded()); new_vehs[i] = nullptr; @@ -650,8 +649,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon assert(Train::From(old_head)->GetNextUnit() == nullptr); for (int i = num_units - 1; i > 0; i--) { - CommandCost ret = CmdMoveVehicle(old_vehs[i], old_head, DC_EXEC | DC_AUTOREPLACE, false); - (void)ret; // assert only + [[maybe_unused]] CommandCost ret = CmdMoveVehicle(old_vehs[i], old_head, DC_EXEC | DC_AUTOREPLACE, false); assert(ret.Succeeded()); } } diff --git a/src/core/pool_func.hpp b/src/core/pool_func.hpp index dea108f08d..3b2d24b145 100644 --- a/src/core/pool_func.hpp +++ b/src/core/pool_func.hpp @@ -33,9 +33,9 @@ DEFINE_POOL_METHOD(inline)::Pool(const char *name) : first_free(0), first_unused(0), items(0), -#ifdef OTTD_ASSERT +#ifdef WITH_ASSERT checked(0), -#endif /* OTTD_ASSERT */ +#endif /* WITH_ASSERT */ cleaning(false), data(nullptr), alloc_cache(nullptr) @@ -133,10 +133,10 @@ DEFINE_POOL_METHOD(void *)::GetNew(size_t size) { size_t index = this->FindFirstFree(); -#ifdef OTTD_ASSERT +#ifdef WITH_ASSERT assert(this->checked != 0); this->checked--; -#endif /* OTTD_ASSERT */ +#endif /* WITH_ASSERT */ if (index == NO_FREE_ITEM) { error("%s: no more free items", this->name); } diff --git a/src/core/pool_type.hpp b/src/core/pool_type.hpp index 33f952dde4..2201d5cb01 100644 --- a/src/core/pool_type.hpp +++ b/src/core/pool_type.hpp @@ -90,9 +90,9 @@ struct Pool : PoolBase { size_t first_free; ///< No item with index lower than this is free (doesn't say anything about this one!) size_t first_unused; ///< This and all higher indexes are free (doesn't say anything about first_unused-1 !) size_t items; ///< Number of used indexes (non-nullptr) -#ifdef OTTD_ASSERT +#ifdef WITH_ASSERT size_t checked; ///< Number of items we checked for -#endif /* OTTD_ASSERT */ +#endif /* WITH_ASSERT */ bool cleaning; ///< True if cleaning pool (deleting all items) Titem **data; ///< Pointer to array of pointers to Titem @@ -130,9 +130,9 @@ struct Pool : PoolBase { inline bool CanAllocate(size_t n = 1) { bool ret = this->items <= Tmax_size - n; -#ifdef OTTD_ASSERT +#ifdef WITH_ASSERT this->checked = ret ? n : 0; -#endif /* OTTD_ASSERT */ +#endif /* WITH_ASSERT */ return ret; } diff --git a/src/engine.cpp b/src/engine.cpp index 114cc1db6a..f330cf6048 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -537,8 +537,7 @@ void SetupEngines() /* Assert is safe; there won't be more than 256 original vehicles * in any case, and we just cleaned the pool. */ assert(Engine::CanAllocateItem()); - const Engine *e = new Engine(eid.type, eid.internal_id); - (void)e; // assert only + [[maybe_unused]] const Engine *e = new Engine(eid.type, eid.internal_id); assert(e->index == index); index++; } diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 713f6e5439..8816c8db37 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -101,8 +101,7 @@ static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, uint end = *index_tbl++; do { - bool b = LoadNextSprite(start, file, sprite_id); - (void)b; // Unused without asserts + [[maybe_unused]] bool b = LoadNextSprite(start, file, sprite_id); assert(b); sprite_id++; } while (++start <= end); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index d88f7b692f..8be44488db 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2139,8 +2139,7 @@ static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAv uint32 seed2 = Random(); Industry *i = nullptr; size_t layout_index = RandomRange((uint32)indspec->layouts.size()); - CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i); - (void)ret; // assert only + [[maybe_unused]] CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i); assert(i != nullptr || ret.Failed()); return i; } diff --git a/src/misc/hashtable.hpp b/src/misc/hashtable.hpp index c7bb600dad..13dadc01ac 100644 --- a/src/misc/hashtable.hpp +++ b/src/misc/hashtable.hpp @@ -239,8 +239,7 @@ public: /** non-const item search & removal */ void Pop(Titem_ &item) { - bool ret = TryPop(item); - (void)ret; // assert only + [[maybe_unused]] bool ret = TryPop(item); assert(ret); } diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index 0094521615..604ead52bb 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -1045,8 +1045,7 @@ static NPFFoundTargetData NPFRouteInternal(AyStarNode *start1, bool ignore_start _npf_aystar.user_data = user; /* GO! */ - int r = _npf_aystar.Main(); - (void)r; // assert only + [[maybe_unused]] int r = _npf_aystar.Main(); assert(r != AYSTAR_STILL_BUSY); if (result.best_bird_dist != 0) { diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index f056404b54..01f0e0fd3a 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1474,14 +1474,12 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) return 0; } -#ifdef OTTD_ASSERT - /** * Check whether the variable size of the variable in the saveload configuration * matches with the actual variable size. * @param sld The saveload configuration to test. */ -static bool IsVariableSizeRight(const SaveLoad &sld) +[[maybe_unused]] static bool IsVariableSizeRight(const SaveLoad &sld) { switch (sld.cmd) { case SL_VAR: @@ -1522,13 +1520,9 @@ static bool IsVariableSizeRight(const SaveLoad &sld) } } -#endif /* OTTD_ASSERT */ - bool SlObjectMember(void *ptr, const SaveLoad &sld) { -#ifdef OTTD_ASSERT assert(IsVariableSizeRight(sld)); -#endif VarType conv = GB(sld.conv, 0, 8); switch (sld.cmd) { diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index aa698af83a..41024b2f9a 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -651,8 +651,7 @@ SQRESULT Squirrel::LoadFile(HSQUIRRELVM vm, const char *filename, SQBool printer } unsigned short bom = 0; if (size >= 2) { - size_t sr = fread(&bom, 1, sizeof(bom), file); - (void)sr; // Inside tar, no point checking return value of fread + [[maybe_unused]] size_t sr = fread(&bom, 1, sizeof(bom), file); } SQLEXREADFUNC func; diff --git a/src/spritecache.cpp b/src/spritecache.cpp index f2840c1b02..cf53aaf558 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -262,9 +262,7 @@ static void ResizeSpriteOut(SpriteLoader::Sprite *sprite, ZoomLevel zoom) SpriteLoader::CommonPixel *dst = sprite[zoom].data; const SpriteLoader::CommonPixel *src = sprite[zoom - 1].data; -#ifdef WITH_ASSERT - const SpriteLoader::CommonPixel *src_end = src + sprite[zoom - 1].height * sprite[zoom - 1].width; -#endif + [[maybe_unused]] const SpriteLoader::CommonPixel *src_end = src + sprite[zoom - 1].height * sprite[zoom - 1].width; for (uint y = 0; y < sprite[zoom].height; y++) { const SpriteLoader::CommonPixel *src_ln = src + sprite[zoom - 1].width; diff --git a/src/stdafx.h b/src/stdafx.h index dc52fc0d53..e593344bf4 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -435,11 +435,6 @@ void NORETURN CDECL error(const char *str, ...) WARN_FORMAT(1, 2); # define assert(expression) if (unlikely(!(expression))) error("Assertion failed at line %i of %s: %s", __LINE__, __FILE__, #expression); #endif -/* Asserts are enabled if NDEBUG isn't defined or WITH_ASSERT is defined. */ -#if !defined(NDEBUG) || defined(WITH_ASSERT) -# define OTTD_ASSERT -#endif - #if defined(OPENBSD) /* OpenBSD uses strcasecmp(3) */ # define _stricmp strcasecmp diff --git a/src/tgp.cpp b/src/tgp.cpp index e23b2643df..2c0c479100 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -658,9 +658,7 @@ static void HeightMapCurves(uint level) for (uint t = 0; t < lengthof(curve_maps); t++) { if (!HasBit(corner_bits, t)) continue; -#ifdef WITH_ASSERT - bool found = false; -#endif + [[maybe_unused]] bool found = false; const control_point_t *cm = curve_maps[t].list; for (uint i = 0; i < curve_maps[t].length - 1; i++) { const control_point_t &p1 = cm[i]; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index bc29d39177..d397825afc 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -106,13 +106,17 @@ Town::~Town() * and remove from list of sorted towns */ CloseWindowById(WC_TOWN_VIEW, this->index); - /* Check no industry is related to us. */ #ifdef WITH_ASSERT - for (const Industry *i : Industry::Iterate()) assert(i->town != this); + /* Check no industry is related to us. */ + for (const Industry *i : Industry::Iterate()) { + assert(i->town != this); + } /* ... and no object is related to us. */ - for (const Object *o : Object::Iterate()) assert(o->town != this); -#endif + for (const Object *o : Object::Iterate()) { + assert(o->town != this); + } +#endif /* WITH_ASSERT */ /* Check no tile is related to us. */ for (TileIndex tile = 0; tile < MapSize(); ++tile) { @@ -2177,8 +2181,7 @@ static Town *CreateRandomTown(uint attempts, uint32 townnameparts, TownSize size if (t->cache.population > 0) return t; Backup cur_company(_current_company, OWNER_TOWN, FILE_LINE); - CommandCost rc = DoCommand(t->xy, t->index, 0, DC_EXEC, CMD_DELETE_TOWN); - (void)rc; // assert only + [[maybe_unused]] CommandCost rc = DoCommand(t->xy, t->index, 0, DC_EXEC, CMD_DELETE_TOWN); cur_company.Restore(); assert(rc.Succeeded()); @@ -2279,8 +2282,7 @@ HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile) */ static inline void ClearMakeHouseTile(TileIndex tile, Town *t, byte counter, byte stage, HouseID type, byte random_bits) { - CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); - (void)cc; // assert only + [[maybe_unused]] CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); assert(cc.Succeeded()); IncreaseBuildingCount(t, type); diff --git a/src/townname.cpp b/src/townname.cpp index 519391f14e..bce894bfcf 100644 --- a/src/townname.cpp +++ b/src/townname.cpp @@ -600,9 +600,7 @@ static char *MakeCzechTownName(char *buf, const char *last, uint32 seed) return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last); } -#ifdef WITH_ASSERT - const char *orig = buf; -#endif + [[maybe_unused]] const char *orig = buf; /* Probability of prefixes/suffixes * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */ diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 05ad1025e8..5181dfdca2 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1846,8 +1846,7 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner if (tt == TRANSPORT_RAIL) { /* Since all of our vehicles have been removed, it is safe to remove the rail * bridge / tunnel. */ - CommandCost ret = DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR); - (void)ret; // assert only + [[maybe_unused]] CommandCost ret = DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR); assert(ret.Succeeded()); } else { /* In any other case, we can safely reassign the ownership to OWNER_NONE. */ diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 3c3125606d..0f40e33dac 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -953,9 +953,7 @@ void CallVehicleTicks() PerformanceAccumulator::Reset(PFE_GL_AIRCRAFT); for (Vehicle *v : Vehicle::Iterate()) { -#ifdef WITH_ASSERT - size_t vehicle_index = v->index; -#endif + [[maybe_unused]] size_t vehicle_index = v->index; /* Vehicle could be deleted in this tick */ if (!v->Tick()) { diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index ea34c443cf..18dbef35f2 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -53,8 +53,7 @@ bool VehicleListIdentifier::UnpackIfValid(uint32 data) /* static */ VehicleListIdentifier VehicleListIdentifier::UnPack(uint32 data) { VehicleListIdentifier result; - bool ret = result.UnpackIfValid(data); - (void)ret; // assert only + [[maybe_unused]] bool ret = result.UnpackIfValid(data); assert(ret); return result; } diff --git a/src/widget.cpp b/src/widget.cpp index 638aa05fe7..abd413ca28 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1272,9 +1272,7 @@ void NWidgetHorizontal::SetupSmallestSize(Window *w, bool init_array) this->smallest_y = std::max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom); } /* 1b. Make the container higher if needed to accommodate all children nicely. */ -#ifdef WITH_ASSERT - uint max_smallest = this->smallest_y + 3 * max_vert_fill; // Upper limit to computing smallest height. -#endif + [[maybe_unused]] uint max_smallest = this->smallest_y + 3 * max_vert_fill; // Upper limit to computing smallest height. uint cur_height = this->smallest_y; for (;;) { for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { @@ -1439,9 +1437,7 @@ void NWidgetVertical::SetupSmallestSize(Window *w, bool init_array) this->smallest_x = std::max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right); } /* 1b. Make the container wider if needed to accommodate all children nicely. */ -#ifdef WITH_ASSERT - uint max_smallest = this->smallest_x + 3 * max_hor_fill; // Upper limit to computing smallest height. -#endif + [[maybe_unused]] uint max_smallest = this->smallest_x + 3 * max_hor_fill; // Upper limit to computing smallest height. uint cur_width = this->smallest_x; for (;;) { for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { From f8dd5dd00a7aa3cc5769b4bce0a1b7a63073c8ce Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 16:21:32 +0200 Subject: [PATCH 302/800] Codechange: remove unused assert_msg() macro --- src/stdafx.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/stdafx.h b/src/stdafx.h index 78188f8fa1..dc52fc0d53 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -438,9 +438,6 @@ void NORETURN CDECL error(const char *str, ...) WARN_FORMAT(1, 2); /* Asserts are enabled if NDEBUG isn't defined or WITH_ASSERT is defined. */ #if !defined(NDEBUG) || defined(WITH_ASSERT) # define OTTD_ASSERT -# define assert_msg(expression, msg, ...) if (unlikely(!(expression))) error("Assertion failed at line %i of %s: %s\n\t" msg, __LINE__, __FILE__, #expression, __VA_ARGS__); -#else -# define assert_msg(expression, msg, ...) #endif #if defined(OPENBSD) From feb2ddbefa5f6f702b996b00dfd92db53a52d174 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 21:18:29 +0200 Subject: [PATCH 303/800] Codechange: rename SettingGuiFlag to SettingFlag (#9332) It is a lovely organicly grown enum, where it started off with GUI-only flags, and after that a few flags got added that can be considered GUI-only (the GUI disables/enables based on them), to only have flags added that has nothing to do with the GUI. So be less confusing, and rename them to what they do. Additionally, I took this opportunity to rename 0ISDISABLED to reflect what it really does. --- src/settings.cpp | 32 +-- src/settings_gui.cpp | 24 +- src/settings_internal.h | 51 ++-- src/table/settings/company_settings.ini | 14 +- src/table/settings/currency_settings.ini | 2 +- src/table/settings/gameopt_settings.ini | 2 +- src/table/settings/misc_settings.ini | 2 +- src/table/settings/settings.ini | 308 +++++++++++------------ src/table/settings/win32_settings.ini | 2 +- src/table/settings/window_settings.ini | 2 +- 10 files changed, 219 insertions(+), 220 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 619d762d2d..aa1e915f88 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -386,9 +386,9 @@ void IntSettingDesc::MakeValueValidAndWrite(const void *object, int32 val) const * Make the value valid given the limitations of this setting. * * In the case of int settings this is ensuring the value is between the minimum and - * maximum value, with a special case for 0 if SGF_0ISDISABLED is set. + * maximum value, with a special case for 0 if SF_GUI_0_IS_SPECIAL is set. * This is generally done by clamping the value so it is within the allowed value range. - * However, for SGF_MULTISTRING the default is used when the value is not valid. + * However, for SF_GUI_DROPDOWN the default is used when the value is not valid. * @param val The value to make valid. */ void IntSettingDesc::MakeValueValid(int32 &val) const @@ -407,8 +407,8 @@ void IntSettingDesc::MakeValueValid(int32 &val) const case SLE_VAR_U16: case SLE_VAR_I32: { /* Override the minimum value. No value below this->min, except special value 0 */ - if (!(this->flags & SGF_0ISDISABLED) || val != 0) { - if (!(this->flags & SGF_MULTISTRING)) { + if (!(this->flags & SF_GUI_0_IS_SPECIAL) || val != 0) { + if (!(this->flags & SF_GUI_DROPDOWN)) { /* Clamp value-type setting to its valid range */ val = Clamp(val, this->min, this->max); } else if (val < this->min || val > (int32)this->max) { @@ -421,8 +421,8 @@ void IntSettingDesc::MakeValueValid(int32 &val) const case SLE_VAR_U32: { /* Override the minimum value. No value below this->min, except special value 0 */ uint32 uval = (uint32)val; - if (!(this->flags & SGF_0ISDISABLED) || uval != 0) { - if (!(this->flags & SGF_MULTISTRING)) { + if (!(this->flags & SF_GUI_0_IS_SPECIAL) || uval != 0) { + if (!(this->flags & SF_GUI_DROPDOWN)) { /* Clamp value-type setting to its valid range */ uval = ClampU(uval, this->min, this->max); } else if (uval < (uint)this->min || uval > this->max) { @@ -743,13 +743,13 @@ void IniSaveWindowSettings(IniFile *ini, const char *grpname, void *desc) */ bool SettingDesc::IsEditable(bool do_command) const { - if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SGF_PER_COMPANY)) return false; - if ((this->flags & SGF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false; - if ((this->flags & SGF_NO_NETWORK) && _networking) return false; - if ((this->flags & SGF_NEWGAME_ONLY) && + if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SF_PER_COMPANY)) return false; + if ((this->flags & SF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false; + if ((this->flags & SF_NO_NETWORK) && _networking) return false; + if ((this->flags & SF_NEWGAME_ONLY) && (_game_mode == GM_NORMAL || - (_game_mode == GM_EDITOR && !(this->flags & SGF_SCENEDIT_TOO)))) return false; - if ((this->flags & SGF_SCENEDIT_ONLY) && _game_mode != GM_EDITOR) return false; + (_game_mode == GM_EDITOR && !(this->flags & SF_SCENEDIT_TOO)))) return false; + if ((this->flags & SF_SCENEDIT_ONLY) && _game_mode != GM_EDITOR) return false; return true; } @@ -759,7 +759,7 @@ bool SettingDesc::IsEditable(bool do_command) const */ SettingType SettingDesc::GetType() const { - if (this->flags & SGF_PER_COMPANY) return ST_COMPANY; + if (this->flags & SF_PER_COMPANY) return ST_COMPANY; return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; } @@ -1689,7 +1689,7 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const this->Write(object, newval); if (this->post_callback != nullptr) this->post_callback(newval); - if (this->flags & SGF_NO_NETWORK) { + if (this->flags & SF_NO_NETWORK) { GamelogStartAction(GLAT_SETTING); GamelogSetting(this->name, oldval, newval); GamelogStopAction(); @@ -1833,7 +1833,7 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) { const IntSettingDesc *setting = sd->AsIntSetting(); - if ((setting->flags & SGF_PER_COMPANY) != 0) { + if ((setting->flags & SF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { return DoCommandP(0, 0, value, CMD_CHANGE_COMPANY_SETTING, nullptr, setting->name); } @@ -1992,7 +1992,7 @@ void IConsoleGetSetting(const char *name, bool force_newgame) sd->FormatValue(value, lastof(value), object); const IntSettingDesc *int_setting = sd->AsIntSetting(); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)", - name, value, (sd->flags & SGF_0ISDISABLED) ? "(0) " : "", int_setting->min, int_setting->max); + name, value, (sd->flags & SF_GUI_0_IS_SPECIAL) ? "(0) " : "", int_setting->min, int_setting->max); } } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index f038617d13..1bd58c13b9 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1147,7 +1147,7 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) static const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd) { - if ((sd->flags & SGF_PER_COMPANY) != 0) { + if ((sd->flags & SF_PER_COMPANY) != 0) { if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { return &Company::Get(_local_company)->settings; } @@ -1166,13 +1166,13 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const if (this->setting->IsBoolSetting()) { SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); } else { - if ((this->setting->flags & SGF_MULTISTRING) != 0) { + if ((this->setting->flags & SF_GUI_DROPDOWN) != 0) { SetDParam(first_param++, this->setting->str_val - this->setting->min + value); - } else if ((this->setting->flags & SGF_DISPLAY_ABS) != 0) { + } else if ((this->setting->flags & SF_GUI_NEGATIVE_IS_SPECIAL) != 0) { SetDParam(first_param++, this->setting->str_val + ((value >= 0) ? 1 : 0)); value = abs(value); } else { - SetDParam(first_param++, this->setting->str_val + ((value == 0 && (this->setting->flags & SGF_0ISDISABLED) != 0) ? 1 : 0)); + SetDParam(first_param++, this->setting->str_val + ((value == 0 && (this->setting->flags & SF_GUI_0_IS_SPECIAL) != 0) ? 1 : 0)); } SetDParam(first_param++, value); } @@ -1205,13 +1205,13 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, if (sd->IsBoolSetting()) { /* Draw checkbox for boolean-value either on/off */ DrawBoolButton(buttons_left, button_y, value != 0, editable); - } else if ((sd->flags & SGF_MULTISTRING) != 0) { + } else if ((sd->flags & SF_GUI_DROPDOWN) != 0) { /* Draw [v] button for settings of an enum-type */ DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable); } else { /* Draw [<][>] boxes for settings of an integer-type */ DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state, - editable && value != (sd->flags & SGF_0ISDISABLED ? 0 : sd->min), editable && (uint32)value != sd->max); + editable && value != (sd->flags & SF_GUI_0_IS_SPECIAL ? 0 : sd->min), editable && (uint32)value != sd->max); } this->SetValueDParams(1, value); DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sd->str, highlight ? TC_WHITE : TC_LIGHT_BLUE); @@ -2182,7 +2182,7 @@ struct GameSettingsWindow : Window { int32 value = sd->Read(ResolveObject(settings_ptr, sd)); /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */ - if (x < SETTING_BUTTON_WIDTH && (sd->flags & SGF_MULTISTRING)) { + if (x < SETTING_BUTTON_WIDTH && (sd->flags & SF_GUI_DROPDOWN)) { this->SetDisplayedHelpText(pe); if (this->valuedropdown_entry == pe) { @@ -2250,7 +2250,7 @@ struct GameSettingsWindow : Window { if (value < sd->min) value = sd->min; // skip between "disabled" and minimum } else { value -= step; - if (value < sd->min) value = (sd->flags & SGF_0ISDISABLED) ? 0 : sd->min; + if (value < sd->min) value = (sd->flags & SF_GUI_0_IS_SPECIAL) ? 0 : sd->min; } /* Set up scroller timeout for numeric values */ @@ -2271,10 +2271,10 @@ struct GameSettingsWindow : Window { } } else { /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */ - if (this->last_clicked == pe && !sd->IsBoolSetting() && !(sd->flags & SGF_MULTISTRING)) { + if (this->last_clicked == pe && !sd->IsBoolSetting() && !(sd->flags & SF_GUI_DROPDOWN)) { int64 value64 = value; /* Show the correct currency-translated value */ - if (sd->flags & SGF_CURRENCY) value64 *= _currency->rate; + if (sd->flags & SF_GUI_CURRENCY) value64 *= _currency->rate; this->valuewindow_entry = pe; SetDParam(0, value64); @@ -2307,7 +2307,7 @@ struct GameSettingsWindow : Window { long long llvalue = atoll(str); /* Save the correct currency-translated value */ - if (sd->flags & SGF_CURRENCY) llvalue /= _currency->rate; + if (sd->flags & SF_GUI_CURRENCY) llvalue /= _currency->rate; value = (int32)ClampToI32(llvalue); } else { @@ -2348,7 +2348,7 @@ struct GameSettingsWindow : Window { /* Deal with drop down boxes on the panel. */ assert(this->valuedropdown_entry != nullptr); const IntSettingDesc *sd = this->valuedropdown_entry->setting; - assert(sd->flags & SGF_MULTISTRING); + assert(sd->flags & SF_GUI_DROPDOWN); SetSettingValue(sd, index); this->SetDirty(); diff --git a/src/settings_internal.h b/src/settings_internal.h index 632d4081d9..351c66ea3c 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -12,21 +12,20 @@ #include "saveload/saveload.h" -enum SettingGuiFlag : uint16 { - /* 2 bytes allocated for a maximum of 16 flags. */ - SGF_NONE = 0, - SGF_0ISDISABLED = 1 << 0, ///< a value of zero means the feature is disabled - SGF_DISPLAY_ABS = 1 << 1, ///< display absolute value of the setting - SGF_MULTISTRING = 1 << 2, ///< the value represents a limited number of string-options (internally integer) - SGF_NETWORK_ONLY = 1 << 3, ///< this setting only applies to network games - SGF_CURRENCY = 1 << 4, ///< the number represents money, so when reading value multiply by exchange rate - SGF_NO_NETWORK = 1 << 5, ///< this setting does not apply to network games; it may not be changed during the game - SGF_NEWGAME_ONLY = 1 << 6, ///< this setting cannot be changed in a game - SGF_SCENEDIT_TOO = 1 << 7, ///< this setting can be changed in the scenario editor (only makes sense when SGF_NEWGAME_ONLY is set) - SGF_PER_COMPANY = 1 << 8, ///< this setting can be different for each company (saved in company struct) - SGF_SCENEDIT_ONLY = 1 << 9, ///< this setting can only be changed in the scenario editor +enum SettingFlag : uint16 { + SF_NONE = 0, + SF_GUI_0_IS_SPECIAL = 1 << 0, ///< A value of zero is possible and has a custom string (the one after "strval"). + SF_GUI_NEGATIVE_IS_SPECIAL = 1 << 1, ///< A negative value has another string (the one after "strval"). + SF_GUI_DROPDOWN = 1 << 2, ///< The value represents a limited number of string-options (internally integer) presented as dropdown. + SF_GUI_CURRENCY = 1 << 3, ///< The number represents money, so when reading value multiply by exchange rate. + SF_NETWORK_ONLY = 1 << 4, ///< This setting only applies to network games. + SF_NO_NETWORK = 1 << 5, ///< This setting does not apply to network games; it may not be changed during the game. + SF_NEWGAME_ONLY = 1 << 6, ///< This setting cannot be changed in a game. + SF_SCENEDIT_TOO = 1 << 7, ///< This setting can be changed in the scenario editor (only makes sense when SF_NEWGAME_ONLY is set). + SF_SCENEDIT_ONLY = 1 << 8, ///< This setting can only be changed in the scenario editor. + SF_PER_COMPANY = 1 << 9, ///< This setting can be different for each company (saved in company struct). }; -DECLARE_ENUM_AS_BIT_SET(SettingGuiFlag) +DECLARE_ENUM_AS_BIT_SET(SettingFlag) /** * A SettingCategory defines a grouping of the settings. @@ -67,14 +66,14 @@ struct IniItem; /** Properties of config file settings. */ struct SettingDesc { - SettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup) : + SettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup) : name(name), flags(flags), startup(startup), save(save) {} virtual ~SettingDesc() {} - const char *name; ///< name of the setting. Used in configuration file and for console - SettingGuiFlag flags; ///< handles how a setting would show up in the GUI (text/currency, etc.) - bool startup; ///< setting has to be loaded directly at startup? - SaveLoad save; ///< Internal structure (going to savegame, parts to config) + const char *name; ///< Name of the setting. Used in configuration file and for console. + SettingFlag flags; ///< Handles how a setting would show up in the GUI (text/currency, etc.). + bool startup; ///< Setting has to be loaded directly at startup?. + SaveLoad save; ///< Internal structure (going to savegame, parts to config). bool IsEditable(bool do_command = false) const; SettingType GetType() const; @@ -138,7 +137,7 @@ struct IntSettingDesc : SettingDesc { */ typedef void PostChangeCallback(int32 value); - IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, + IntSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def), min(min), max(max), interval(interval), @@ -180,7 +179,7 @@ private: /** Boolean setting. */ struct BoolSettingDesc : IntSettingDesc { - BoolSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, bool def, + BoolSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, bool def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, @@ -196,7 +195,7 @@ struct BoolSettingDesc : IntSettingDesc { struct OneOfManySettingDesc : IntSettingDesc { typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error - OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, int32 def, + OneOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -220,7 +219,7 @@ struct OneOfManySettingDesc : IntSettingDesc { /** Many of many setting. */ struct ManyOfManySettingDesc : OneOfManySettingDesc { - ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, + ManyOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -249,7 +248,7 @@ struct StringSettingDesc : SettingDesc { */ typedef void PostChangeCallback(const std::string &value); - StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def, + StringSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def, uint32 max_length, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def == nullptr ? "" : def), max_length(max_length), pre_check(pre_check), post_callback(post_callback) {} @@ -275,7 +274,7 @@ private: /** List/array settings. */ struct ListSettingDesc : SettingDesc { - ListSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, bool startup, const char *def) : + ListSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def) : SettingDesc(save, name, flags, startup), def(def) {} virtual ~ListSettingDesc() {} @@ -289,7 +288,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, "", SGF_NONE, false) {} + SettingDesc(save, "", SF_NONE, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index 5767100651..6b6a17c967 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -24,7 +24,7 @@ SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CompanySettings.$v [defaults] flags = 0 -guiflags = SGF_PER_COMPANY +guiflags = SF_PER_COMPANY interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT @@ -50,7 +50,7 @@ cat = SC_BASIC [SDT_VAR] var = engine_renew_months type = SLE_INT16 -guiflags = SGF_PER_COMPANY | SGF_DISPLAY_ABS +guiflags = SF_PER_COMPANY | SF_GUI_NEGATIVE_IS_SPECIAL def = 6 min = -12 max = 12 @@ -61,7 +61,7 @@ strval = STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE [SDT_VAR] var = engine_renew_money type = SLE_UINT -guiflags = SGF_PER_COMPANY | SGF_CURRENCY +guiflags = SF_PER_COMPANY | SF_GUI_CURRENCY def = 100000 min = 0 max = 2000000 @@ -83,7 +83,7 @@ post_cb = UpdateServiceInterval [SDT_VAR] var = vehicle.servint_trains type = SLE_UINT16 -guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED +guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 150 min = 5 max = 800 @@ -96,7 +96,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_TRAIN, new_value); } [SDT_VAR] var = vehicle.servint_roadveh type = SLE_UINT16 -guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED +guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 150 min = 5 max = 800 @@ -109,7 +109,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_ROAD, new_value); } [SDT_VAR] var = vehicle.servint_ships type = SLE_UINT16 -guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED +guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 360 min = 5 max = 800 @@ -122,7 +122,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_SHIP, new_value); } [SDT_VAR] var = vehicle.servint_aircraft type = SLE_UINT16 -guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED +guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 100 min = 5 max = 800 diff --git a/src/table/settings/currency_settings.ini b/src/table/settings/currency_settings.ini index a10583150e..8e359d5c02 100644 --- a/src/table/settings/currency_settings.ini +++ b/src/table/settings/currency_settings.ini @@ -19,7 +19,7 @@ SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CurrencySpec.$var [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index f24adb17a6..195bae365f 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -63,7 +63,7 @@ SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var [defaults] flags = 0 -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index bafdf2369b..45da1db52b 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -37,7 +37,7 @@ SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds st [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 9281ed6624..be4d7ea941 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -77,7 +77,7 @@ SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var [defaults] flags = 0 -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT @@ -119,7 +119,7 @@ max = 3 var = difficulty.number_towns type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = 2 min = 0 max = 4 @@ -131,7 +131,7 @@ cat = SC_BASIC var = difficulty.industry_density type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = ID_END - 1 min = 0 max = ID_END - 1 @@ -145,7 +145,7 @@ cat = SC_BASIC var = difficulty.max_loan type = SLE_UINT32 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO | SGF_CURRENCY +guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_CURRENCY def = 300000 min = 0 max = 2000000000 @@ -159,7 +159,7 @@ cat = SC_BASIC var = difficulty.initial_interest type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO +guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO def = 2 min = 2 max = 4 @@ -172,7 +172,7 @@ strval = STR_CONFIG_SETTING_PERCENTAGE var = difficulty.vehicle_costs type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO | SGF_MULTISTRING +guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -186,7 +186,7 @@ cat = SC_BASIC var = difficulty.competitor_speed type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 4 @@ -209,7 +209,7 @@ max = 2 var = difficulty.vehicle_breakdowns type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -223,7 +223,7 @@ cat = SC_BASIC var = difficulty.subsidy_multiplier type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 3 @@ -236,7 +236,7 @@ strval = STR_SUBSIDY_X1_5 var = difficulty.construction_cost type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO | SGF_MULTISTRING +guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -250,7 +250,7 @@ cat = SC_BASIC var = difficulty.terrain_type type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = 0 max = 5 @@ -264,7 +264,7 @@ cat = SC_BASIC var = difficulty.quantity_sea_lakes type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = 0 min = 0 max = 4 @@ -298,7 +298,7 @@ cat = SC_BASIC var = difficulty.town_council_tolerance type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -326,7 +326,7 @@ cat = SC_BASIC var = game_creation.town_name type = SLE_UINT8 from = SLV_97 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 0 max = 255 full = _town_names @@ -336,7 +336,7 @@ cat = SC_BASIC var = game_creation.landscape type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 0 max = 3 full = _climates @@ -356,7 +356,7 @@ to = SLV_164 var = vehicle.road_side type = SLE_UINT8 from = SLV_97 -guiflags = SGF_MULTISTRING | SGF_NO_NETWORK +guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 max = 1 full = _roadsides @@ -372,7 +372,7 @@ cat = SC_BASIC var = construction.map_height_limit type = SLE_UINT8 from = SLV_194 -guiflags = SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO | SGF_0ISDISABLED +guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_0_IS_SPECIAL def = 0 min = MIN_MAP_HEIGHT_LIMIT max = MAX_MAP_HEIGHT_LIMIT @@ -388,7 +388,7 @@ cat = SC_ADVANCED var = game_creation.heightmap_height type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = MAP_HEIGHT_LIMIT_AUTO_MINIMUM min = MIN_HEIGHTMAP_HEIGHT max = MAX_MAP_HEIGHT_LIMIT @@ -396,7 +396,7 @@ interval = 1 [SDT_BOOL] var = construction.build_on_slopes -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -404,7 +404,7 @@ cat = SC_EXPERT var = construction.command_pause_level type = SLE_UINT8 from = SLV_154 -guiflags = SGF_MULTISTRING | SGF_NO_NETWORK +guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 min = 0 max = 3 @@ -491,7 +491,7 @@ strhelp = STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT var = construction.max_bridge_length type = SLE_UINT16 from = SLV_159 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 64 min = 1 max = MAX_MAP_SIZE @@ -504,7 +504,7 @@ strval = STR_CONFIG_SETTING_TILE_LENGTH var = construction.max_bridge_height type = SLE_UINT8 from = SLV_194 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 12 min = 1 max = MAX_TILE_HEIGHT @@ -518,7 +518,7 @@ cat = SC_EXPERT var = construction.max_tunnel_length type = SLE_UINT16 from = SLV_159 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 64 min = 1 max = MAX_MAP_SIZE @@ -535,7 +535,7 @@ to = SLV_159 [SDT_VAR] var = construction.train_signal_side type = SLE_UINT8 -guiflags = SGF_MULTISTRING | SGF_NO_NETWORK +guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 min = 0 max = 2 @@ -547,7 +547,7 @@ cat = SC_BASIC [SDT_BOOL] var = station.never_expire_airports -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT @@ -556,7 +556,7 @@ strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT var = economy.town_layout type = SLE_UINT8 from = SLV_59 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = TL_ORIGINAL min = TL_BEGIN max = NUM_TLS - 1 @@ -569,7 +569,7 @@ post_cb = TownFoundingChanged [SDT_BOOL] var = economy.allow_town_roads from = SLV_113 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT @@ -578,7 +578,7 @@ strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT var = economy.found_town type = SLE_UINT8 from = SLV_128 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = TF_FORBIDDEN min = TF_BEGIN max = TF_END - 1 @@ -592,7 +592,7 @@ cat = SC_BASIC [SDT_BOOL] var = economy.allow_town_level_crossings from = SLV_143 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT @@ -601,7 +601,7 @@ strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT var = economy.town_cargogen_mode type = SLE_UINT8 from = SLV_TOWN_CARGOGEN -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = TCGM_BITCOUNT min = TCGM_BEGIN max = TCGM_END - 1 @@ -644,7 +644,7 @@ extra = offsetof(LinkGraphSettings, recalc_time) var = linkgraph.distribution_pax type = SLE_UINT8 from = SLV_183 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -659,7 +659,7 @@ extra = offsetof(LinkGraphSettings, distribution_pax) var = linkgraph.distribution_mail type = SLE_UINT8 from = SLV_183 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -674,7 +674,7 @@ extra = offsetof(LinkGraphSettings, distribution_mail) var = linkgraph.distribution_armoured type = SLE_UINT8 from = SLV_183 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -689,7 +689,7 @@ extra = offsetof(LinkGraphSettings, distribution_armoured) var = linkgraph.distribution_default type = SLE_UINT8 from = SLV_183 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_BEGIN max = DT_MAX_NONSYMMETRIC @@ -761,7 +761,7 @@ extra = offsetof(LinkGraphSettings, short_path_saturation) [SDT_VAR] var = vehicle.train_acceleration_model type = SLE_UINT8 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -775,7 +775,7 @@ post_cb = TrainAccelerationModelChanged var = vehicle.roadveh_acceleration_model type = SLE_UINT8 from = SLV_139 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -843,7 +843,7 @@ to = SLV_159 var = vehicle.smoke_amount type = SLE_UINT8 from = SLV_145 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -895,7 +895,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_trains type = SLE_UINT8 from = SLV_87 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -909,7 +909,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_roadvehs type = SLE_UINT8 from = SLV_87 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -923,7 +923,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_ships type = SLE_UINT8 from = SLV_87 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -936,7 +936,7 @@ cat = SC_EXPERT [SDT_BOOL] var = vehicle.never_expire_vehicles -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT @@ -991,7 +991,7 @@ cat = SC_BASIC [SDTG_BOOL] name = nullptr -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK var = _old_vds.servint_ispercent def = false to = SLV_120 @@ -999,7 +999,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_trains def = 150 min = 5 @@ -1009,7 +1009,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_roadveh def = 150 min = 5 @@ -1019,7 +1019,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_ships def = 360 min = 5 @@ -1029,7 +1029,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_aircraft def = 150 min = 5 @@ -1044,7 +1044,7 @@ strhelp = STR_CONFIG_SETTING_NOSERVICE_HELPTEXT [SDT_BOOL] var = vehicle.wagon_speed_limits -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_WAGONSPEEDLIMITS strhelp = STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT @@ -1053,7 +1053,7 @@ post_cb = UpdateConsists [SDT_BOOL] var = vehicle.disable_elrails from = SLV_38 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_DISABLE_ELRAILS strhelp = STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT @@ -1064,7 +1064,7 @@ cat = SC_EXPERT var = vehicle.freight_trains type = SLE_UINT8 from = SLV_39 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 1 min = 1 max = 255 @@ -1084,7 +1084,7 @@ to = SLV_159 var = vehicle.plane_speed type = SLE_UINT8 from = SLV_90 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = 4 min = 1 max = 4 @@ -1095,7 +1095,7 @@ strval = STR_CONFIG_SETTING_PLANE_SPEED_VALUE [SDT_BOOL] var = vehicle.dynamic_engines from = SLV_95 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true pre_cb = CheckDynamicEngines cat = SC_EXPERT @@ -1104,7 +1104,7 @@ cat = SC_EXPERT var = vehicle.plane_crashes type = SLE_UINT8 from = SLV_138 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -1127,7 +1127,7 @@ def = true [SDT_BOOL] var = order.improved_load -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -1185,7 +1185,7 @@ post_cb = StationCatchmentChanged [SDT_BOOL] var = order.gradual_loading from = SLV_40 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -1214,7 +1214,7 @@ cat = SC_EXPERT [SDT_BOOL] var = economy.station_noise_level from = SLV_96 -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NOISE_LEVEL strhelp = STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT @@ -1231,7 +1231,7 @@ post_cb = [](auto) { CloseWindowById(WC_SELECT_STATION, 0); } ## [SDT_BOOL] var = economy.inflation -guiflags = SGF_NO_NETWORK +guiflags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_INFLATION strhelp = STR_CONFIG_SETTING_INFLATION_HELPTEXT @@ -1240,7 +1240,7 @@ cat = SC_BASIC [SDT_VAR] var = construction.raw_industry_construction type = SLE_UINT8 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -1318,7 +1318,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.snow_line_height type = SLE_UINT8 -guiflags = SGF_SCENEDIT_ONLY +guiflags = SF_SCENEDIT_ONLY def = DEF_SNOWLINE_HEIGHT min = MIN_SNOWLINE_HEIGHT max = MAX_SNOWLINE_HEIGHT @@ -1332,7 +1332,7 @@ cat = SC_BASIC var = game_creation.snow_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = DEF_SNOW_COVERAGE min = 0 max = 100 @@ -1346,7 +1346,7 @@ cat = SC_BASIC var = game_creation.desert_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = DEF_DESERT_COVERAGE min = 0 max = 100 @@ -1379,7 +1379,7 @@ to = SLV_105 var = game_creation.ending_year type = SLE_INT32 from = SLV_ENDING_YEAR -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL def = DEF_END_YEAR min = MIN_YEAR max = MAX_YEAR - 1 @@ -1392,7 +1392,7 @@ cat = SC_ADVANCED [SDT_VAR] var = economy.type type = SLE_UINT8 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = ET_SMOOTH min = ET_BEGIN max = ET_END - 1 @@ -1438,7 +1438,7 @@ cat = SC_EXPERT var = economy.town_growth_rate type = SLE_UINT8 from = SLV_54 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 4 @@ -1450,7 +1450,7 @@ strval = STR_CONFIG_SETTING_TOWN_GROWTH_NONE var = economy.larger_towns type = SLE_UINT8 from = SLV_54 -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL def = 4 min = 0 max = 255 @@ -1486,7 +1486,7 @@ to = SLV_107 var = script.settings_profile type = SLE_UINT8 from = SLV_178 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = SP_EASY min = SP_EASY max = SP_HARD @@ -1531,7 +1531,7 @@ strhelp = STR_CONFIG_SETTING_AI_BUILDS_SHIPS_HELPTEXT var = script.script_max_opcode_till_suspend type = SLE_UINT32 from = SLV_107 -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = 10000 min = 500 max = 250000 @@ -1545,7 +1545,7 @@ cat = SC_EXPERT var = script.script_max_memory_megabytes type = SLE_UINT32 from = SLV_SCRIPT_MEMLIMIT -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = 1024 min = 8 max = 8192 @@ -2119,7 +2119,7 @@ cat = SC_EXPERT var = game_creation.land_generator type = SLE_UINT8 from = SLV_30 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = 0 max = 1 @@ -2142,7 +2142,7 @@ strhelp = STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT var = game_creation.tgen_smoothness type = SLE_UINT8 from = SLV_30 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = TGEN_SMOOTHNESS_BEGIN max = TGEN_SMOOTHNESS_END - 1 @@ -2155,7 +2155,7 @@ cat = SC_BASIC var = game_creation.variety type = SLE_UINT8 from = SLV_197 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 0 min = 0 max = 5 @@ -2176,7 +2176,7 @@ cat = SC_EXPERT var = game_creation.tree_placer type = SLE_UINT8 from = SLV_30 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY | SF_SCENEDIT_TOO def = 2 min = 0 max = 2 @@ -2189,7 +2189,7 @@ cat = SC_BASIC var = game_creation.heightmap_rotation type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 1 @@ -2256,7 +2256,7 @@ cat = SC_BASIC var = construction.extra_tree_placement type = SLE_UINT8 from = SLV_132 -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 3 @@ -2269,7 +2269,7 @@ cat = SC_BASIC var = game_creation.custom_terrain_type type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SGF_NEWGAME_ONLY +guiflags = SF_NEWGAME_ONLY def = MAP_HEIGHT_LIMIT_AUTO_MINIMUM min = MIN_CUSTOM_TERRAIN_TYPE max = MAX_MAP_HEIGHT_LIMIT @@ -2306,7 +2306,7 @@ cat = SC_EXPERT var = game_creation.amount_of_rivers type = SLE_UINT8 from = SLV_163 -guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY +guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 2 min = 0 max = 3 @@ -2345,7 +2345,7 @@ var = locale.units_velocity type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 3 full = _locale_units @@ -2360,7 +2360,7 @@ var = locale.units_power type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2375,7 +2375,7 @@ var = locale.units_weight type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2390,7 +2390,7 @@ var = locale.units_volume type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2405,7 +2405,7 @@ var = locale.units_force type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _locale_units @@ -2420,7 +2420,7 @@ var = locale.units_height type = SLE_UINT8 from = SLV_184 flags = SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2465,7 +2465,7 @@ cat = SC_BASIC var = gui.autosave type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 4 full = _autosave_interval @@ -2484,7 +2484,7 @@ cat = SC_EXPERT var = gui.date_format_in_default_names type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _savegame_date @@ -2504,7 +2504,7 @@ cat = SC_BASIC var = gui.auto_scrolling type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 3 @@ -2517,7 +2517,7 @@ cat = SC_BASIC var = gui.scroll_mode type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 3 @@ -2547,7 +2547,7 @@ ifdef = __APPLE__ var = gui.right_mouse_btn_emulation type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2579,7 +2579,7 @@ strval = STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE var = gui.hover_delay_ms type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL def = 250 min = 50 max = 6000 @@ -2595,7 +2595,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC str = STR_CONFIG_SETTING_OSK_ACTIVATION strhelp = STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT strval = STR_CONFIG_SETTING_OSK_ACTIVATION_DISABLED -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN full = _osk_activation def = 1 min = 0 @@ -2606,7 +2606,7 @@ cat = SC_BASIC var = gui.toolbar_pos type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2620,7 +2620,7 @@ cat = SC_BASIC var = gui.statusbar_pos type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2634,7 +2634,7 @@ cat = SC_BASIC var = gui.window_snap_radius type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL def = 10 min = 1 max = 32 @@ -2647,7 +2647,7 @@ cat = SC_EXPERT var = gui.window_soft_limit type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED +guiflags = SF_GUI_0_IS_SPECIAL def = 20 min = 5 max = 255 @@ -2661,7 +2661,7 @@ cat = SC_EXPERT var = gui.zoom_min type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = ZOOM_LVL_MIN min = ZOOM_LVL_MIN max = ZOOM_LVL_OUT_4X @@ -2675,7 +2675,7 @@ startup = true var = gui.zoom_max type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = ZOOM_LVL_MAX min = ZOOM_LVL_OUT_8X max = ZOOM_LVL_MAX @@ -2689,7 +2689,7 @@ startup = true var = gui.sprite_zoom_min type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = ZOOM_LVL_MIN min = ZOOM_LVL_MIN max = ZOOM_LVL_OUT_4X @@ -2717,7 +2717,7 @@ strhelp = STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR_HELPTEXT var = gui.smallmap_land_colour type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2730,7 +2730,7 @@ post_cb = RedrawSmallmap var = gui.liveries type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -2743,7 +2743,7 @@ post_cb = InvalidateCompanyLiveryWindow var = gui.starting_colour type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = COLOUR_END min = 0 max = COLOUR_END @@ -2771,7 +2771,7 @@ cat = SC_BASIC var = gui.scrollwheel_scrolling type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2805,7 +2805,7 @@ cat = SC_BASIC var = gui.advanced_vehicle_list type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2842,7 +2842,7 @@ cat = SC_BASIC var = gui.loading_indicators type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2856,7 +2856,7 @@ cat = SC_BASIC var = gui.default_rail_type type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2933,7 +2933,7 @@ cat = SC_BASIC var = gui.order_review_system type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -2961,7 +2961,7 @@ cat = SC_BASIC var = gui.stop_location type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -3022,7 +3022,7 @@ cat = SC_BASIC var = gui.default_signal_type type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -3036,7 +3036,7 @@ cat = SC_BASIC var = gui.cycle_signal_types type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -3207,7 +3207,7 @@ cat = SC_EXPERT var = gui.newgrf_default_palette type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -3244,7 +3244,7 @@ startup = true var = gui.fast_forward_speed_limit type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED | SGF_NO_NETWORK +guiflags = SF_GUI_0_IS_SPECIAL | SF_NO_NETWORK def = 2500 min = 0 max = 50000 @@ -3370,7 +3370,7 @@ cat = SC_BASIC var = news_display.arrival_player type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3382,7 +3382,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.arrival_other type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3394,7 +3394,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.accident type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3406,7 +3406,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.company_info type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3418,7 +3418,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.open type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3430,7 +3430,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.close type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3442,7 +3442,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.economy type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3454,7 +3454,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.production_player type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3466,7 +3466,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.production_other type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 max = 2 full = _news_display @@ -3478,7 +3478,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.production_nobody type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 0 max = 2 full = _news_display @@ -3490,7 +3490,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.advice type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3502,7 +3502,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.new_vehicles type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3514,7 +3514,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.acceptance type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3526,7 +3526,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.subsidies type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3538,7 +3538,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF var = news_display.general type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING +guiflags = SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3577,7 +3577,7 @@ cat = SC_EXPERT var = network.sync_freq type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NOT_IN_CONFIG | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 100 min = 0 max = 100 @@ -3587,7 +3587,7 @@ cat = SC_EXPERT var = network.frame_freq type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NOT_IN_CONFIG | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 0 min = 0 max = 100 @@ -3597,7 +3597,7 @@ cat = SC_EXPERT var = network.commands_per_frame type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 2 min = 1 max = 65535 @@ -3607,7 +3607,7 @@ cat = SC_EXPERT var = network.max_commands_in_queue type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 16 min = 1 max = 65535 @@ -3617,7 +3617,7 @@ cat = SC_EXPERT var = network.bytes_per_frame type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 8 min = 1 max = 65535 @@ -3627,7 +3627,7 @@ cat = SC_EXPERT var = network.bytes_per_frame_burst type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 256 min = 1 max = 65535 @@ -3637,7 +3637,7 @@ cat = SC_EXPERT var = network.max_init_time type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 100 min = 0 max = 32000 @@ -3647,7 +3647,7 @@ cat = SC_EXPERT var = network.max_join_time type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 500 min = 0 max = 32000 @@ -3656,7 +3656,7 @@ max = 32000 var = network.max_download_time type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 1000 min = 0 max = 32000 @@ -3665,7 +3665,7 @@ max = 32000 var = network.max_password_time type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 2000 min = 0 max = 32000 @@ -3674,7 +3674,7 @@ max = 32000 var = network.max_lag_time type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 500 min = 0 max = 32000 @@ -3682,14 +3682,14 @@ max = 32000 [SDTC_BOOL] var = network.pause_on_join flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = true [SDTC_VAR] var = network.server_port type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = NETWORK_DEFAULT_PORT min = 0 max = 65535 @@ -3699,7 +3699,7 @@ cat = SC_EXPERT var = network.server_admin_port type = SLE_UINT16 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = NETWORK_ADMIN_PORT min = 0 max = 65535 @@ -3708,14 +3708,14 @@ cat = SC_EXPERT [SDTC_BOOL] var = network.server_admin_chat flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = true cat = SC_EXPERT [SDTC_BOOL] var = network.server_advertise flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = false [SDTC_SSTR] @@ -3733,7 +3733,7 @@ var = network.server_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = nullptr pre_cb = ReplaceAsteriskWithEmptyPassword post_cb = [](auto) { NetworkServerUpdateGameInfo(); } @@ -3744,7 +3744,7 @@ var = network.rcon_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = nullptr pre_cb = ReplaceAsteriskWithEmptyPassword cat = SC_BASIC @@ -3754,7 +3754,7 @@ var = network.admin_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = nullptr cat = SC_BASIC @@ -3770,7 +3770,7 @@ var = network.server_name type = SLE_STR length = NETWORK_NAME_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = nullptr pre_cb = NetworkValidateServerName post_cb = [](auto) { UpdateClientConfigValues(); } @@ -3788,20 +3788,20 @@ var = network.network_id type = SLE_STR length = NETWORK_SERVER_ID_LENGTH flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = nullptr [SDTC_BOOL] var = network.autoclean_companies flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = false [SDTC_VAR] var = network.autoclean_unprotected type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED | SGF_NETWORK_ONLY +guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 12 min = 0 max = 240 @@ -3810,7 +3810,7 @@ max = 240 var = network.autoclean_protected type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED | SGF_NETWORK_ONLY +guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 36 min = 0 max = 240 @@ -3819,7 +3819,7 @@ max = 240 var = network.autoclean_novehicles type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED | SGF_NETWORK_ONLY +guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 0 min = 0 max = 240 @@ -3828,7 +3828,7 @@ max = 240 var = network.max_companies type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 15 min = 1 max = MAX_COMPANIES @@ -3839,7 +3839,7 @@ cat = SC_BASIC var = network.max_clients type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 25 min = 2 max = MAX_CLIENTS @@ -3850,7 +3850,7 @@ cat = SC_BASIC var = network.max_spectators type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 15 min = 0 max = MAX_CLIENTS @@ -3861,7 +3861,7 @@ cat = SC_BASIC var = network.restart_game_year type = SLE_INT32 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_0ISDISABLED | SGF_NETWORK_ONLY +guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 0 min = MIN_YEAR max = MAX_YEAR @@ -3871,7 +3871,7 @@ interval = 1 var = network.min_active_clients type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = 0 min = 0 max = MAX_CLIENTS @@ -3879,7 +3879,7 @@ max = MAX_CLIENTS [SDTC_BOOL] var = network.reload_cfg flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NETWORK_ONLY +guiflags = SF_NETWORK_ONLY def = false cat = SC_EXPERT diff --git a/src/table/settings/win32_settings.ini b/src/table/settings/win32_settings.ini index 7a3fb9a5c6..32a5cf5c93 100644 --- a/src/table/settings/win32_settings.ini +++ b/src/table/settings/win32_settings.ini @@ -25,7 +25,7 @@ SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds stor [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/window_settings.ini b/src/table/settings/window_settings.ini index 17596a4d58..f9301ef2ce 100644 --- a/src/table/settings/window_settings.ini +++ b/src/table/settings/window_settings.ini @@ -21,7 +21,7 @@ SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for WindowDesc.$var ex [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_NONE +guiflags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT From 5e44da30101769a177c9cab654336a31c93df09b Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 22:07:44 +0200 Subject: [PATCH 304/800] Fix ef991b17: server was trying to free() a packet created with "new CommandPacket()" (#9334) --- src/network/network.cpp | 2 +- src/network/network_server.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index d89789cf94..862169c1d8 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1072,7 +1072,7 @@ void NetworkGameLoop() if (cp != nullptr) { NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text, cp->company); DEBUG(desync, 0, "Injecting: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text.c_str(), GetCommandName(cp->cmd)); - free(cp); + delete cp; cp = nullptr; } if (check_sync_state) { diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 49b1c8faf1..5b1da8fa2a 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1758,7 +1758,7 @@ static void NetworkHandleCommandQueue(NetworkClientSocket *cs) CommandPacket *cp; while ((cp = cs->outgoing_queue.Pop()) != nullptr) { cs->SendCommand(cp); - free(cp); + delete cp; } } From d816ff0361a559f0382e40fc7291168418e3683f Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 3 Jun 2021 20:24:19 +0000 Subject: [PATCH 305/800] Update: Translations from eints korean: 1 change by telk5093 --- src/lang/korean.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 9e429e77bb..338fe7cfa9 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2204,7 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}서버 STR_NETWORK_ERROR_CLIENT_START :{WHITE}접속할 수 없습니다 STR_NETWORK_ERROR_TIMEOUT :{WHITE}접속자 #{NUM}의 입력 시간이 초과되었습니다 STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}프로토콜 오류가 발생되어 연결이 끊어졌습니다 -STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}접속자 이름을 설정하지 않았습니다. 이름은 멀티플레이 창의 상단에서 설정할 수 있습니다. +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}접속자 이름을 지정하지 않았습니다. 접속자이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}서버 이름을 지정하지 않았습니다. 서버 이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}이 접속자의 게임 버전이 서버의 버전과 일치하지 않습니다 STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못된 비밀번호입니다 From ea23a9cdb66d3e43447af8131f04f5b05a100319 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 4 Jun 2021 20:11:37 +0000 Subject: [PATCH 306/800] Update: Translations from eints korean: 1 change by telk5093 dutch: 1 change by Afoklala french: 1 change by MalaGaM --- src/lang/dutch.txt | 1 + src/lang/french.txt | 1 + src/lang/korean.txt | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index a156876303..aa8ad733de 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kan geen STR_NETWORK_ERROR_TIMEOUT :{WHITE}Verbinding nr. {NUM} kostte te veel tijd STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Er is een protocolfout gedetecteerd en de verbinding werd gesloten STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Je spelernaam is nog niet ingesteld. Je stelt de naam in bovenin het venster Meerdere spelers +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Je servernaam is niet ingesteld. Je kunt de naam instellen bovenin het venster Netwerkspel STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}De revisie van deze client komt niet overeen met de revisie van de server STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Ongeldig wachtwoord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}De server is vol diff --git a/src/lang/french.txt b/src/lang/french.txt index 5b766de94e..bafaed87a8 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Échec d STR_NETWORK_ERROR_TIMEOUT :{WHITE}La connexion n°{NBSP}{NUM} a dépassé le temps d'attente STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Une erreur de protocole a été détectée et la connexion a été fermée STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Vous n'avez pas de nom. Il doit être entré en haut de la fenêtre Multijoueur +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Le nom de serveur n'a pas été défini. Le nom peut être défini en haut de la fenêtre multijoueur STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Le numéro de version/révision de ce client ne correspond pas à celui du serveur STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Mot de passe incorrect STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Le serveur est complet diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 338fe7cfa9..552ec2612c 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2204,7 +2204,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}서버 STR_NETWORK_ERROR_CLIENT_START :{WHITE}접속할 수 없습니다 STR_NETWORK_ERROR_TIMEOUT :{WHITE}접속자 #{NUM}의 입력 시간이 초과되었습니다 STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}프로토콜 오류가 발생되어 연결이 끊어졌습니다 -STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}접속자 이름을 지정하지 않았습니다. 접속자이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}접속자 이름을 지정하지 않았습니다. 접속자 이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}서버 이름을 지정하지 않았습니다. 서버 이름은 멀티플레이 창 맨 위에서 설정할 수 있습니다. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}이 접속자의 게임 버전이 서버의 버전과 일치하지 않습니다 STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못된 비밀번호입니다 From 3559e55b9145c5b6c146003b357a158c73efee4e Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 5 Jun 2021 19:36:47 +0000 Subject: [PATCH 307/800] Update: Translations from eints spanish (mexican): 1 change by absay latvian: 2 changes by osprinkis --- src/lang/latvian.txt | 3 ++- src/lang/spanish_MX.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index dbc16f5c16..1de03dded7 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -2480,7 +2480,7 @@ STR_AIRPORT_METRO :Metropolitēns STR_AIRPORT_INTERNATIONAL :Starptautiskā lidosta STR_AIRPORT_COMMUTER :Ikdienas satiksme STR_AIRPORT_INTERCONTINENTAL :Starpkontinentālā -STR_AIRPORT_HELIPORT :Helikopteru osta +STR_AIRPORT_HELIPORT :Helikopteru lidosta STR_AIRPORT_HELIDEPOT :Helikopteru depo STR_AIRPORT_HELISTATION :Helikopteru stacija @@ -3722,6 +3722,7 @@ STR_REPLACE_MAGLEV_VEHICLES :Magleva transpo STR_REPLACE_ROAD_VEHICLES :Autotransporta līdzekļi STR_REPLACE_TRAM_VEHICLES :Tramvaji +STR_REPLACE_REMOVE_WAGON :{BLACK}Vagona noņemšana ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automātiskā aizvietošana saglabās esošo vilciena garumu noņemot vagonus (sākot no priekšgala), ja mainot lokomotīvi tas kļūtu garāks # Vehicle view diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 310fa82d5e..f314f9deae 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pu STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se produjo un error de protocolo y la conexión fue cerrada STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Aún no tienes nombre de jugador, pero lo puedes poner en la parte superior de la ventana de Multijugador. +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}El servidor aún no tiene nombre, pero lo puedes poner en la parte superior de la ventana de Multijugador. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo From c27afdf3f6b8e7e073b70d4935ca1c871855f3ca Mon Sep 17 00:00:00 2001 From: glx22 Date: Sun, 2 May 2021 22:41:34 +0200 Subject: [PATCH 308/800] Codechange: Remove FOR_ALL_CHUNK_HANDLERS Co-Authored-By: Patric Stout --- src/saveload/ai_sl.cpp | 6 +- src/saveload/airport_sl.cpp | 6 +- src/saveload/animated_tile_sl.cpp | 6 +- src/saveload/autoreplace_sl.cpp | 6 +- src/saveload/cargomonitor_sl.cpp | 8 +- src/saveload/cargopacket_sl.cpp | 6 +- src/saveload/cheat_sl.cpp | 6 +- src/saveload/company_sl.cpp | 6 +- src/saveload/depot_sl.cpp | 6 +- src/saveload/economy_sl.cpp | 12 +- src/saveload/engine_sl.cpp | 10 +- src/saveload/game_sl.cpp | 6 +- src/saveload/gamelog_sl.cpp | 6 +- src/saveload/goal_sl.cpp | 6 +- src/saveload/group_sl.cpp | 6 +- src/saveload/industry_sl.cpp | 14 +- src/saveload/labelmaps_sl.cpp | 6 +- src/saveload/linkgraph_sl.cpp | 6 +- src/saveload/map_sl.cpp | 6 +- src/saveload/misc_sl.cpp | 8 +- src/saveload/newgrf_sl.cpp | 6 +- src/saveload/object_sl.cpp | 6 +- src/saveload/order_sl.cpp | 10 +- src/saveload/saveload.cpp | 220 +++++++++++++++--------------- src/saveload/saveload.h | 22 +-- src/saveload/signs_sl.cpp | 6 +- src/saveload/station_sl.cpp | 6 +- src/saveload/storage_sl.cpp | 6 +- src/saveload/story_sl.cpp | 8 +- src/saveload/strings_sl.cpp | 6 +- src/saveload/subsidy_sl.cpp | 6 +- src/saveload/town_sl.cpp | 6 +- src/saveload/vehicle_sl.cpp | 6 +- src/saveload/waypoint_sl.cpp | 6 +- src/settings.cpp | 8 +- 35 files changed, 272 insertions(+), 198 deletions(-) diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index fcb78f2edd..7eb2a5ce1c 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -120,6 +120,8 @@ static void Save_AIPL() } } -extern const ChunkHandler _ai_chunk_handlers[] = { - { 'AIPL', Save_AIPL, Load_AIPL, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler ai_chunk_handlers[] = { + { 'AIPL', Save_AIPL, Load_AIPL, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _ai_chunk_handlers(ai_chunk_handlers); diff --git a/src/saveload/airport_sl.cpp b/src/saveload/airport_sl.cpp index a7470d268f..114e5672ab 100644 --- a/src/saveload/airport_sl.cpp +++ b/src/saveload/airport_sl.cpp @@ -34,7 +34,9 @@ static void Load_ATID() Load_NewGRFMapping(_airporttile_mngr); } -extern const ChunkHandler _airport_chunk_handlers[] = { +static const ChunkHandler airport_chunk_handlers[] = { { 'ATID', Save_ATID, Load_ATID, nullptr, nullptr, CH_ARRAY }, - { 'APID', Save_APID, Load_APID, nullptr, nullptr, CH_ARRAY | CH_LAST }, + { 'APID', Save_APID, Load_APID, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _airport_chunk_handlers(airport_chunk_handlers); diff --git a/src/saveload/animated_tile_sl.cpp b/src/saveload/animated_tile_sl.cpp index 9f03e598d7..2b38421046 100644 --- a/src/saveload/animated_tile_sl.cpp +++ b/src/saveload/animated_tile_sl.cpp @@ -55,6 +55,8 @@ static void Load_ANIT() * "Definition" imported by the saveload code to be able to load and save * the animated tile table. */ -extern const ChunkHandler _animated_tile_chunk_handlers[] = { - { 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_RIFF | CH_LAST}, +static const ChunkHandler animated_tile_chunk_handlers[] = { + { 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _animated_tile_chunk_handlers(animated_tile_chunk_handlers); diff --git a/src/saveload/autoreplace_sl.cpp b/src/saveload/autoreplace_sl.cpp index ef343fc179..f54866c107 100644 --- a/src/saveload/autoreplace_sl.cpp +++ b/src/saveload/autoreplace_sl.cpp @@ -55,6 +55,8 @@ static void Ptrs_ERNW() } } -extern const ChunkHandler _autoreplace_chunk_handlers[] = { - { 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler autoreplace_chunk_handlers[] = { + { 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _autoreplace_chunk_handlers(autoreplace_chunk_handlers); diff --git a/src/saveload/cargomonitor_sl.cpp b/src/saveload/cargomonitor_sl.cpp index 3ca64d77ef..abb0d59b99 100644 --- a/src/saveload/cargomonitor_sl.cpp +++ b/src/saveload/cargomonitor_sl.cpp @@ -117,7 +117,9 @@ static void LoadPickup() } /** Chunk definition of the cargomonitoring maps. */ -extern const ChunkHandler _cargomonitor_chunk_handlers[] = { - { 'CMDL', SaveDelivery, LoadDelivery, nullptr, nullptr, CH_ARRAY}, - { 'CMPU', SavePickup, LoadPickup, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler cargomonitor_chunk_handlers[] = { + { 'CMDL', SaveDelivery, LoadDelivery, nullptr, nullptr, CH_ARRAY }, + { 'CMPU', SavePickup, LoadPickup, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _cargomonitor_chunk_handlers(cargomonitor_chunk_handlers); diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index 1b9bb5cb94..96c96cabcb 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -126,6 +126,8 @@ static void Load_CAPA() } /** Chunk handlers related to cargo packets. */ -extern const ChunkHandler _cargopacket_chunk_handlers[] = { - { 'CAPA', Save_CAPA, Load_CAPA, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler cargopacket_chunk_handlers[] = { + { 'CAPA', Save_CAPA, Load_CAPA, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _cargopacket_chunk_handlers(cargopacket_chunk_handlers); diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index 9af1759221..970e5f3be1 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -48,6 +48,8 @@ static void Load_CHTS() } /** Chunk handlers related to cheats. */ -extern const ChunkHandler _cheat_chunk_handlers[] = { - { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF | CH_LAST}, +static const ChunkHandler cheat_chunk_handlers[] = { + { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _cheat_chunk_handlers(cheat_chunk_handlers); diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 21d02121b6..4c64376385 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -527,6 +527,8 @@ static void Ptrs_PLYR() } -extern const ChunkHandler _company_chunk_handlers[] = { - { 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY | CH_LAST}, +static const ChunkHandler company_chunk_handlers[] = { + { 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY }, }; + +extern const ChunkHandlerTable _company_chunk_handlers(company_chunk_handlers); diff --git a/src/saveload/depot_sl.cpp b/src/saveload/depot_sl.cpp index fb8944dbae..da195416bd 100644 --- a/src/saveload/depot_sl.cpp +++ b/src/saveload/depot_sl.cpp @@ -56,6 +56,8 @@ static void Ptrs_DEPT() } } -extern const ChunkHandler _depot_chunk_handlers[] = { - { 'DEPT', Save_DEPT, Load_DEPT, Ptrs_DEPT, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler depot_chunk_handlers[] = { + { 'DEPT', Save_DEPT, Load_DEPT, Ptrs_DEPT, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _depot_chunk_handlers(depot_chunk_handlers); diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index 2c785d554a..b51151c146 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -94,9 +94,11 @@ static void Ptrs_CAPY() } -extern const ChunkHandler _economy_chunk_handlers[] = { - { 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, nullptr, CH_ARRAY}, - { 'PRIC', nullptr, Load_PRIC, nullptr, nullptr, CH_RIFF }, - { 'CAPR', nullptr, Load_CAPR, nullptr, nullptr, CH_RIFF }, - { 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_RIFF | CH_LAST}, +static const ChunkHandler economy_chunk_handlers[] = { + { 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, nullptr, CH_ARRAY }, + { 'PRIC', nullptr, Load_PRIC, nullptr, nullptr, CH_RIFF }, + { 'CAPR', nullptr, Load_CAPR, nullptr, nullptr, CH_RIFF }, + { 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _economy_chunk_handlers(economy_chunk_handlers); diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index eea3a0bcf0..430ae29d19 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -193,8 +193,10 @@ static void Load_EIDS() } } -extern const ChunkHandler _engine_chunk_handlers[] = { - { 'EIDS', Save_EIDS, Load_EIDS, nullptr, nullptr, CH_ARRAY }, - { 'ENGN', Save_ENGN, Load_ENGN, nullptr, nullptr, CH_ARRAY }, - { 'ENGS', nullptr, Load_ENGS, nullptr, nullptr, CH_RIFF | CH_LAST }, +static const ChunkHandler engine_chunk_handlers[] = { + { 'EIDS', Save_EIDS, Load_EIDS, nullptr, nullptr, CH_ARRAY }, + { 'ENGN', Save_ENGN, Load_ENGN, nullptr, nullptr, CH_ARRAY }, + { 'ENGS', nullptr, Load_ENGS, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _engine_chunk_handlers(engine_chunk_handlers); diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index 055a5fbfc4..4034df3c96 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -173,7 +173,9 @@ static void Save_GSTR() } } -extern const ChunkHandler _game_chunk_handlers[] = { +static const ChunkHandler game_chunk_handlers[] = { { 'GSTR', Save_GSTR, Load_GSTR, nullptr, nullptr, CH_ARRAY }, - { 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_ARRAY | CH_LAST}, + { 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _game_chunk_handlers(game_chunk_handlers); diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index 3d236b1368..6569954f87 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -168,6 +168,8 @@ static void Check_GLOG() Load_GLOG_common(_load_check_data.gamelog_action, _load_check_data.gamelog_actions); } -extern const ChunkHandler _gamelog_chunk_handlers[] = { - { 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_RIFF | CH_LAST } +static const ChunkHandler gamelog_chunk_handlers[] = { + { 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_RIFF } }; + +extern const ChunkHandlerTable _gamelog_chunk_handlers(gamelog_chunk_handlers); diff --git a/src/saveload/goal_sl.cpp b/src/saveload/goal_sl.cpp index 2c9d8fde9f..2f66797594 100644 --- a/src/saveload/goal_sl.cpp +++ b/src/saveload/goal_sl.cpp @@ -40,6 +40,8 @@ static void Load_GOAL() } } -extern const ChunkHandler _goal_chunk_handlers[] = { - { 'GOAL', Save_GOAL, Load_GOAL, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler goal_chunk_handlers[] = { + { 'GOAL', Save_GOAL, Load_GOAL, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _goal_chunk_handlers(goal_chunk_handlers); diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp index a6ae263f9d..f41091611c 100644 --- a/src/saveload/group_sl.cpp +++ b/src/saveload/group_sl.cpp @@ -55,6 +55,8 @@ static void Load_GRPS() } } -extern const ChunkHandler _group_chunk_handlers[] = { - { 'GRPS', Save_GRPS, Load_GRPS, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler group_chunk_handlers[] = { + { 'GRPS', Save_GRPS, Load_GRPS, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _group_chunk_handlers(group_chunk_handlers); diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index a59524de67..c75674069e 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -176,10 +176,12 @@ static void Load_ITBL() } } -extern const ChunkHandler _industry_chunk_handlers[] = { - { 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, nullptr, CH_ARRAY}, - { 'IIDS', Save_IIDS, Load_IIDS, nullptr, nullptr, CH_ARRAY}, - { 'TIDS', Save_TIDS, Load_TIDS, nullptr, nullptr, CH_ARRAY}, - { 'IBLD', LoadSave_IBLD, LoadSave_IBLD, nullptr, nullptr, CH_RIFF}, - { 'ITBL', Save_ITBL, Load_ITBL, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler industry_chunk_handlers[] = { + { 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, nullptr, CH_ARRAY }, + { 'IIDS', Save_IIDS, Load_IIDS, nullptr, nullptr, CH_ARRAY }, + { 'TIDS', Save_TIDS, Load_TIDS, nullptr, nullptr, CH_ARRAY }, + { 'IBLD', LoadSave_IBLD, LoadSave_IBLD, nullptr, nullptr, CH_RIFF }, + { 'ITBL', Save_ITBL, Load_ITBL, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _industry_chunk_handlers(industry_chunk_handlers); diff --git a/src/saveload/labelmaps_sl.cpp b/src/saveload/labelmaps_sl.cpp index 6c2cd1bcac..5a7d6fae98 100644 --- a/src/saveload/labelmaps_sl.cpp +++ b/src/saveload/labelmaps_sl.cpp @@ -121,7 +121,9 @@ static void Load_RAIL() } } -extern const ChunkHandler _labelmaps_chunk_handlers[] = { - { 'RAIL', Save_RAIL, Load_RAIL, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler labelmaps_chunk_handlers[] = { + { 'RAIL', Save_RAIL, Load_RAIL, nullptr, nullptr, CH_ARRAY }, }; +extern const ChunkHandlerTable _labelmaps_chunk_handlers(labelmaps_chunk_handlers); + diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index 3983000286..470d00be48 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -280,8 +280,10 @@ static void Ptrs_LGRS() SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); } -extern const ChunkHandler _linkgraph_chunk_handlers[] = { +static const ChunkHandler linkgraph_chunk_handlers[] = { { 'LGRP', Save_LGRP, Load_LGRP, nullptr, nullptr, CH_ARRAY }, { 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr, nullptr, CH_ARRAY }, - { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_LAST } + { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_RIFF } }; + +extern const ChunkHandlerTable _linkgraph_chunk_handlers(linkgraph_chunk_handlers); diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index d08fc63899..d13900fc64 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -294,7 +294,7 @@ static void Save_MAP8() } -extern const ChunkHandler _map_chunk_handlers[] = { +static const ChunkHandler map_chunk_handlers[] = { { 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_RIFF }, { 'MAPT', Save_MAPT, Load_MAPT, nullptr, nullptr, CH_RIFF }, { 'MAPH', Save_MAPH, Load_MAPH, nullptr, nullptr, CH_RIFF }, @@ -305,5 +305,7 @@ extern const ChunkHandler _map_chunk_handlers[] = { { 'MAP5', Save_MAP5, Load_MAP5, nullptr, nullptr, CH_RIFF }, { 'MAPE', Save_MAP6, Load_MAP6, nullptr, nullptr, CH_RIFF }, { 'MAP7', Save_MAP7, Load_MAP7, nullptr, nullptr, CH_RIFF }, - { 'MAP8', Save_MAP8, Load_MAP8, nullptr, nullptr, CH_RIFF | CH_LAST }, + { 'MAP8', Save_MAP8, Load_MAP8, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers); diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index ba49c11be4..027d68bae4 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -145,7 +145,9 @@ static void SaveLoad_VIEW() SlGlobList(_view_desc); } -extern const ChunkHandler _misc_chunk_handlers[] = { - { 'DATE', SaveLoad_DATE, SaveLoad_DATE, nullptr, Check_DATE, CH_RIFF}, - { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, nullptr, nullptr, CH_RIFF | CH_LAST}, +static const ChunkHandler misc_chunk_handlers[] = { + { 'DATE', SaveLoad_DATE, SaveLoad_DATE, nullptr, Check_DATE, CH_RIFF }, + { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, nullptr, nullptr, CH_RIFF }, }; + +extern const ChunkHandlerTable _misc_chunk_handlers(misc_chunk_handlers); diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index 3faf9a64a6..f92da0db31 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -111,6 +111,8 @@ static void Check_NGRF() Load_NGRF_common(_load_check_data.grfconfig); } -extern const ChunkHandler _newgrf_chunk_handlers[] = { - { 'NGRF', Save_NGRF, Load_NGRF, nullptr, Check_NGRF, CH_ARRAY | CH_LAST } +static const ChunkHandler newgrf_chunk_handlers[] = { + { 'NGRF', Save_NGRF, Load_NGRF, nullptr, Check_NGRF, CH_ARRAY } }; + +extern const ChunkHandlerTable _newgrf_chunk_handlers(newgrf_chunk_handlers); diff --git a/src/saveload/object_sl.cpp b/src/saveload/object_sl.cpp index 40ca8cd110..dcf5fd65cb 100644 --- a/src/saveload/object_sl.cpp +++ b/src/saveload/object_sl.cpp @@ -66,7 +66,9 @@ static void Load_OBID() Load_NewGRFMapping(_object_mngr); } -extern const ChunkHandler _object_chunk_handlers[] = { +static const ChunkHandler object_chunk_handlers[] = { { 'OBID', Save_OBID, Load_OBID, nullptr, nullptr, CH_ARRAY }, - { 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, nullptr, CH_ARRAY | CH_LAST}, + { 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _object_chunk_handlers(object_chunk_handlers); diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 44080e695d..523a8b804b 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -286,8 +286,10 @@ static void Ptrs_BKOR() } } -extern const ChunkHandler _order_chunk_handlers[] = { - { 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, nullptr, CH_ARRAY}, - { 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, nullptr, CH_ARRAY}, - { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler order_chunk_handlers[] = { + { 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, nullptr, CH_ARRAY }, + { 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, nullptr, CH_ARRAY }, + { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _order_chunk_handlers(order_chunk_handlers); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 01f0e0fd3a..3c95e61e2d 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -214,86 +214,92 @@ struct SaveLoadParams { static SaveLoadParams _sl; ///< Parameters used for/at saveload. -/* these define the chunks */ -extern const ChunkHandler _gamelog_chunk_handlers[]; -extern const ChunkHandler _map_chunk_handlers[]; -extern const ChunkHandler _misc_chunk_handlers[]; -extern const ChunkHandler _name_chunk_handlers[]; -extern const ChunkHandler _cheat_chunk_handlers[] ; -extern const ChunkHandler _setting_chunk_handlers[]; -extern const ChunkHandler _company_chunk_handlers[]; -extern const ChunkHandler _engine_chunk_handlers[]; -extern const ChunkHandler _veh_chunk_handlers[]; -extern const ChunkHandler _waypoint_chunk_handlers[]; -extern const ChunkHandler _depot_chunk_handlers[]; -extern const ChunkHandler _order_chunk_handlers[]; -extern const ChunkHandler _town_chunk_handlers[]; -extern const ChunkHandler _sign_chunk_handlers[]; -extern const ChunkHandler _station_chunk_handlers[]; -extern const ChunkHandler _industry_chunk_handlers[]; -extern const ChunkHandler _economy_chunk_handlers[]; -extern const ChunkHandler _subsidy_chunk_handlers[]; -extern const ChunkHandler _cargomonitor_chunk_handlers[]; -extern const ChunkHandler _goal_chunk_handlers[]; -extern const ChunkHandler _story_page_chunk_handlers[]; -extern const ChunkHandler _ai_chunk_handlers[]; -extern const ChunkHandler _game_chunk_handlers[]; -extern const ChunkHandler _animated_tile_chunk_handlers[]; -extern const ChunkHandler _newgrf_chunk_handlers[]; -extern const ChunkHandler _group_chunk_handlers[]; -extern const ChunkHandler _cargopacket_chunk_handlers[]; -extern const ChunkHandler _autoreplace_chunk_handlers[]; -extern const ChunkHandler _labelmaps_chunk_handlers[]; -extern const ChunkHandler _linkgraph_chunk_handlers[]; -extern const ChunkHandler _airport_chunk_handlers[]; -extern const ChunkHandler _object_chunk_handlers[]; -extern const ChunkHandler _persistent_storage_chunk_handlers[]; +static const std::vector &ChunkHandlers() +{ + /* These define the chunks */ + extern const ChunkHandlerTable _gamelog_chunk_handlers; + extern const ChunkHandlerTable _map_chunk_handlers; + extern const ChunkHandlerTable _misc_chunk_handlers; + extern const ChunkHandlerTable _name_chunk_handlers; + extern const ChunkHandlerTable _cheat_chunk_handlers; + extern const ChunkHandlerTable _setting_chunk_handlers; + extern const ChunkHandlerTable _company_chunk_handlers; + extern const ChunkHandlerTable _engine_chunk_handlers; + extern const ChunkHandlerTable _veh_chunk_handlers; + extern const ChunkHandlerTable _waypoint_chunk_handlers; + extern const ChunkHandlerTable _depot_chunk_handlers; + extern const ChunkHandlerTable _order_chunk_handlers; + extern const ChunkHandlerTable _town_chunk_handlers; + extern const ChunkHandlerTable _sign_chunk_handlers; + extern const ChunkHandlerTable _station_chunk_handlers; + extern const ChunkHandlerTable _industry_chunk_handlers; + extern const ChunkHandlerTable _economy_chunk_handlers; + extern const ChunkHandlerTable _subsidy_chunk_handlers; + extern const ChunkHandlerTable _cargomonitor_chunk_handlers; + extern const ChunkHandlerTable _goal_chunk_handlers; + extern const ChunkHandlerTable _story_page_chunk_handlers; + extern const ChunkHandlerTable _ai_chunk_handlers; + extern const ChunkHandlerTable _game_chunk_handlers; + extern const ChunkHandlerTable _animated_tile_chunk_handlers; + extern const ChunkHandlerTable _newgrf_chunk_handlers; + extern const ChunkHandlerTable _group_chunk_handlers; + extern const ChunkHandlerTable _cargopacket_chunk_handlers; + extern const ChunkHandlerTable _autoreplace_chunk_handlers; + extern const ChunkHandlerTable _labelmaps_chunk_handlers; + extern const ChunkHandlerTable _linkgraph_chunk_handlers; + extern const ChunkHandlerTable _airport_chunk_handlers; + extern const ChunkHandlerTable _object_chunk_handlers; + extern const ChunkHandlerTable _persistent_storage_chunk_handlers; -/** Array of all chunks in a savegame, \c nullptr terminated. */ -static const ChunkHandler * const _chunk_handlers[] = { - _gamelog_chunk_handlers, - _map_chunk_handlers, - _misc_chunk_handlers, - _name_chunk_handlers, - _cheat_chunk_handlers, - _setting_chunk_handlers, - _veh_chunk_handlers, - _waypoint_chunk_handlers, - _depot_chunk_handlers, - _order_chunk_handlers, - _industry_chunk_handlers, - _economy_chunk_handlers, - _subsidy_chunk_handlers, - _cargomonitor_chunk_handlers, - _goal_chunk_handlers, - _story_page_chunk_handlers, - _engine_chunk_handlers, - _town_chunk_handlers, - _sign_chunk_handlers, - _station_chunk_handlers, - _company_chunk_handlers, - _ai_chunk_handlers, - _game_chunk_handlers, - _animated_tile_chunk_handlers, - _newgrf_chunk_handlers, - _group_chunk_handlers, - _cargopacket_chunk_handlers, - _autoreplace_chunk_handlers, - _labelmaps_chunk_handlers, - _linkgraph_chunk_handlers, - _airport_chunk_handlers, - _object_chunk_handlers, - _persistent_storage_chunk_handlers, - nullptr, -}; + /** List of all chunks in a savegame. */ + static const ChunkHandlerTable _chunk_handler_tables[] = { + _gamelog_chunk_handlers, + _map_chunk_handlers, + _misc_chunk_handlers, + _name_chunk_handlers, + _cheat_chunk_handlers, + _setting_chunk_handlers, + _veh_chunk_handlers, + _waypoint_chunk_handlers, + _depot_chunk_handlers, + _order_chunk_handlers, + _industry_chunk_handlers, + _economy_chunk_handlers, + _subsidy_chunk_handlers, + _cargomonitor_chunk_handlers, + _goal_chunk_handlers, + _story_page_chunk_handlers, + _engine_chunk_handlers, + _town_chunk_handlers, + _sign_chunk_handlers, + _station_chunk_handlers, + _company_chunk_handlers, + _ai_chunk_handlers, + _game_chunk_handlers, + _animated_tile_chunk_handlers, + _newgrf_chunk_handlers, + _group_chunk_handlers, + _cargopacket_chunk_handlers, + _autoreplace_chunk_handlers, + _labelmaps_chunk_handlers, + _linkgraph_chunk_handlers, + _airport_chunk_handlers, + _object_chunk_handlers, + _persistent_storage_chunk_handlers, + }; -/** - * Iterate over all chunk handlers. - * @param ch the chunk handler iterator - */ -#define FOR_ALL_CHUNK_HANDLERS(ch) \ - for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != nullptr; chsc++) \ - for (const ChunkHandler *ch = *chsc; ch != nullptr; ch = (ch->flags & CH_LAST) ? nullptr : ch + 1) + static std::vector _chunk_handlers; + + if (_chunk_handlers.empty()) { + for (auto &chunk_handler_table : _chunk_handler_tables) { + for (auto &chunk_handler : chunk_handler_table) { + _chunk_handlers.push_back(chunk_handler); + } + } + } + + return _chunk_handlers; +} /** Null all pointers (convert index -> nullptr) */ static void SlNullPointers() @@ -305,10 +311,10 @@ static void SlNullPointers() * pointers from other pools. */ _sl_version = SAVEGAME_VERSION; - FOR_ALL_CHUNK_HANDLERS(ch) { - if (ch->ptrs_proc != nullptr) { - DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); - ch->ptrs_proc(); + for (auto &ch : ChunkHandlers()) { + if (ch.ptrs_proc != nullptr) { + DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + ch.ptrs_proc(); } } @@ -1654,7 +1660,7 @@ void SlAutolength(AutolengthProc *proc, void *arg) * Load a chunk of data (eg vehicles, stations, etc.) * @param ch The chunkhandler that will be used for the operation */ -static void SlLoadChunk(const ChunkHandler *ch) +static void SlLoadChunk(const ChunkHandler &ch) { byte m = SlReadByte(); size_t len; @@ -1666,11 +1672,11 @@ static void SlLoadChunk(const ChunkHandler *ch) switch (m) { case CH_ARRAY: _sl.array_index = 0; - ch->load_proc(); + ch.load_proc(); if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); break; case CH_SPARSE_ARRAY: - ch->load_proc(); + ch.load_proc(); if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); break; default: @@ -1680,7 +1686,7 @@ static void SlLoadChunk(const ChunkHandler *ch) len += SlReadUint16(); _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; - ch->load_proc(); + ch.load_proc(); if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size"); } else { SlErrorCorrupt("Invalid chunk type"); @@ -1694,7 +1700,7 @@ static void SlLoadChunk(const ChunkHandler *ch) * If the chunkhandler is nullptr, the chunk is skipped. * @param ch The chunkhandler that will be used for the operation */ -static void SlLoadCheckChunk(const ChunkHandler *ch) +static void SlLoadCheckChunk(const ChunkHandler &ch) { byte m = SlReadByte(); size_t len; @@ -1706,15 +1712,15 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) switch (m) { case CH_ARRAY: _sl.array_index = 0; - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipArray(); } break; case CH_SPARSE_ARRAY: - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipArray(); } @@ -1726,8 +1732,8 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) len += SlReadUint16(); _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipBytes(len); } @@ -1744,18 +1750,18 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) * prefixed by an ID identifying it, followed by data, and terminator where appropriate * @param ch The chunkhandler that will be used for the operation */ -static void SlSaveChunk(const ChunkHandler *ch) +static void SlSaveChunk(const ChunkHandler &ch) { - ChunkSaveLoadProc *proc = ch->save_proc; + ChunkSaveLoadProc *proc = ch.save_proc; /* Don't save any chunk information if there is no save handler. */ if (proc == nullptr) return; - SlWriteUint32(ch->id); - DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); + SlWriteUint32(ch.id); + DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); - _sl.block_mode = ch->flags & CH_TYPE_MASK; - switch (ch->flags & CH_TYPE_MASK) { + _sl.block_mode = ch.type; + switch (ch.type) { case CH_RIFF: _sl.need_length = NL_WANTLENGTH; proc(); @@ -1778,7 +1784,7 @@ static void SlSaveChunk(const ChunkHandler *ch) /** Save all chunks */ static void SlSaveChunks() { - FOR_ALL_CHUNK_HANDLERS(ch) { + for (auto &ch : ChunkHandlers()) { SlSaveChunk(ch); } @@ -1794,7 +1800,7 @@ static void SlSaveChunks() */ static const ChunkHandler *SlFindChunkHandler(uint32 id) { - FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch; + for (auto &ch : ChunkHandlers()) if (ch.id == id) return &ch; return nullptr; } @@ -1809,7 +1815,7 @@ static void SlLoadChunks() ch = SlFindChunkHandler(id); if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); - SlLoadChunk(ch); + SlLoadChunk(*ch); } } @@ -1824,7 +1830,7 @@ static void SlLoadCheckChunks() ch = SlFindChunkHandler(id); if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); - SlLoadCheckChunk(ch); + SlLoadCheckChunk(*ch); } } @@ -1833,10 +1839,10 @@ static void SlFixPointers() { _sl.action = SLA_PTRS; - FOR_ALL_CHUNK_HANDLERS(ch) { - if (ch->ptrs_proc != nullptr) { - DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); - ch->ptrs_proc(); + for (auto &ch : ChunkHandlers()) { + if (ch.ptrs_proc != nullptr) { + DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + ch.ptrs_proc(); } } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 1c763a93fc..41880952e0 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -14,6 +14,7 @@ #include "../strings_type.h" #include "../core/span_type.hpp" #include +#include /** SaveLoad versions * Previous savegame versions, the trunk revision where they were @@ -378,6 +379,13 @@ SaveOrLoadResult LoadWithFilter(struct LoadFilter *reader); typedef void ChunkSaveLoadProc(); typedef void AutolengthProc(void *arg); +/** Type of a chunk. */ +enum ChunkType { + CH_RIFF = 0, + CH_ARRAY = 1, + CH_SPARSE_ARRAY = 2, +}; + /** Handlers and description of chunk. */ struct ChunkHandler { uint32 id; ///< Unique ID (4 letters). @@ -385,9 +393,12 @@ struct ChunkHandler { ChunkSaveLoadProc *load_proc; ///< Load procedure of the chunk. ChunkSaveLoadProc *ptrs_proc; ///< Manipulate pointers in the chunk. ChunkSaveLoadProc *load_check_proc; ///< Load procedure for game preview. - uint32 flags; ///< Flags of the chunk. @see ChunkType + ChunkType type; ///< Type of the chunk. @see ChunkType }; +/** A table of ChunkHandler entries. */ +using ChunkHandlerTable = span; + /** Type of reference (#SLE_REF, #SLE_CONDREF). */ enum SLRefType { REF_ORDER = 0, ///< Load/save a reference to an order. @@ -404,15 +415,6 @@ enum SLRefType { REF_LINK_GRAPH_JOB = 11, ///< Load/save a reference to a link graph job. }; -/** Flags of a chunk. */ -enum ChunkType { - CH_RIFF = 0, - CH_ARRAY = 1, - CH_SPARSE_ARRAY = 2, - CH_TYPE_MASK = 3, - CH_LAST = 8, ///< Last chunk in this array. -}; - /** * VarTypes is the general bitmasked magic type that tells us * certain characteristics about the variable it refers to. For example diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 86a1468a56..388a92af92 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -62,6 +62,8 @@ static void Load_SIGN() } /** Chunk handlers related to signs. */ -extern const ChunkHandler _sign_chunk_handlers[] = { - { 'SIGN', Save_SIGN, Load_SIGN, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler sign_chunk_handlers[] = { + { 'SIGN', Save_SIGN, Load_SIGN, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _sign_chunk_handlers(sign_chunk_handlers); diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index cd1b93138e..75b6043e7a 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -613,8 +613,10 @@ static void Ptrs_ROADSTOP() } } -extern const ChunkHandler _station_chunk_handlers[] = { +static const ChunkHandler station_chunk_handlers[] = { { 'STNS', nullptr, Load_STNS, Ptrs_STNS, nullptr, CH_ARRAY }, { 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, nullptr, CH_ARRAY }, - { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, nullptr, CH_ARRAY | CH_LAST}, + { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _station_chunk_handlers(station_chunk_handlers); diff --git a/src/saveload/storage_sl.cpp b/src/saveload/storage_sl.cpp index a01904e3a1..50f858f116 100644 --- a/src/saveload/storage_sl.cpp +++ b/src/saveload/storage_sl.cpp @@ -44,6 +44,8 @@ static void Save_PSAC() } /** Chunk handler for persistent storages. */ -extern const ChunkHandler _persistent_storage_chunk_handlers[] = { - { 'PSAC', Save_PSAC, Load_PSAC, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler persistent_storage_chunk_handlers[] = { + { 'PSAC', Save_PSAC, Load_PSAC, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _persistent_storage_chunk_handlers(persistent_storage_chunk_handlers); diff --git a/src/saveload/story_sl.cpp b/src/saveload/story_sl.cpp index 06083fb103..df5b1406f0 100644 --- a/src/saveload/story_sl.cpp +++ b/src/saveload/story_sl.cpp @@ -95,7 +95,9 @@ static void Load_STORY_PAGE() _story_page_next_sort_value = max_sort_value + 1; } -extern const ChunkHandler _story_page_chunk_handlers[] = { - { 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, nullptr, nullptr, CH_ARRAY}, - { 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler story_page_chunk_handlers[] = { + { 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, nullptr, nullptr, CH_ARRAY }, + { 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _story_page_chunk_handlers(story_page_chunk_handlers); diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index dad7eb1abd..52f70b8d58 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -131,6 +131,8 @@ static void Load_NAME() } /** Chunk handlers related to strings. */ -extern const ChunkHandler _name_chunk_handlers[] = { - { 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler name_chunk_handlers[] = { + { 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _name_chunk_handlers(name_chunk_handlers); diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index dbd04c8adb..b17ae1f252 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -43,6 +43,8 @@ static void Load_SUBS() } } -extern const ChunkHandler _subsidy_chunk_handlers[] = { - { 'SUBS', Save_SUBS, Load_SUBS, nullptr, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler subsidy_chunk_handlers[] = { + { 'SUBS', Save_SUBS, Load_SUBS, nullptr, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _subsidy_chunk_handlers(subsidy_chunk_handlers); diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 3ba25f6406..908ff2dd71 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -296,7 +296,9 @@ static void Ptrs_TOWN() } /** Chunk handler for towns. */ -extern const ChunkHandler _town_chunk_handlers[] = { +static const ChunkHandler town_chunk_handlers[] = { { 'HIDS', Save_HIDS, Load_HIDS, nullptr, nullptr, CH_ARRAY }, - { 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_ARRAY | CH_LAST}, + { 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _town_chunk_handlers(town_chunk_handlers); diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index e637f03b26..7e9005779d 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -931,6 +931,8 @@ static void Ptrs_VEHS() } } -extern const ChunkHandler _veh_chunk_handlers[] = { - { 'VEHS', Save_VEHS, Load_VEHS, Ptrs_VEHS, nullptr, CH_SPARSE_ARRAY | CH_LAST}, +static const ChunkHandler veh_chunk_handlers[] = { + { 'VEHS', Save_VEHS, Load_VEHS, Ptrs_VEHS, nullptr, CH_SPARSE_ARRAY }, }; + +extern const ChunkHandlerTable _veh_chunk_handlers(veh_chunk_handlers); diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 9ad3da1f3b..97e2d12c9f 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -224,6 +224,8 @@ static void Ptrs_WAYP() } } -extern const ChunkHandler _waypoint_chunk_handlers[] = { - { 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_ARRAY | CH_LAST}, +static const ChunkHandler waypoint_chunk_handlers[] = { + { 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_ARRAY }, }; + +extern const ChunkHandlerTable _waypoint_chunk_handlers(waypoint_chunk_handlers); diff --git a/src/settings.cpp b/src/settings.cpp index aa1e915f88..50dc387907 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2085,11 +2085,13 @@ static void Save_PATS() SaveSettings(_settings, &_settings_game); } -extern const ChunkHandler _setting_chunk_handlers[] = { - { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_RIFF}, - { 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_RIFF | CH_LAST}, +static const ChunkHandler setting_chunk_handlers[] = { + { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_RIFF }, + { 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_RIFF }, }; +extern const ChunkHandlerTable _setting_chunk_handlers(setting_chunk_handlers); + static bool IsSignedVarMemType(VarType vt) { switch (GetVarMemType(vt)) { From d835a42c05f6a48f120b47e94a042848a20edd5c Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 6 Jun 2021 19:37:57 +0000 Subject: [PATCH 309/800] Update: Translations from eints english (us): 1 change by 2TallTyler catalan: 5 changes by J0anJosep --- src/lang/catalan.txt | 7 +++++-- src/lang/english_US.txt | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 45eb3a9951..2d9b85ffa8 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}No s'ha STR_NETWORK_ERROR_TIMEOUT :{WHITE}La connexió #{NUM} ha esgotat el temps d'espera STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}S'ha obtingut un error de protocol i s'ha tancat la connexió STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No s'ha escollit un nom per al vostre jugador. El nom es pot establir a la part superior de la finestra de mode multijugador. +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}No s'ha establit un nom per al vostre servidor. El nom s'estableix a la part superior de la finestra multijugador. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La revisió d'aquest client no concorda amb la revisió del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contrasenya incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor està ple @@ -3559,7 +3560,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Clica pe STR_GROUP_DELETE_TOOLTIP :{BLACK}Elimina el grup seleccionat STR_GROUP_RENAME_TOOLTIP :{BLACK}Canvia el nom del grup seleccionat STR_GROUP_LIVERY_TOOLTIP :{BLACK}Canvia l'aspecte dels vehicles del grup seleccionat. -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clica per protegir aquest grup de l'autosubstitueix global +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clica per protegir aquest grup de l'autosubstitució global. Ctrl + clic també protegeix els subgrups. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Esborrar grup STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Estàs segur que vols esborrar aquest grup i tots els seus subgrups? @@ -3812,7 +3813,9 @@ STR_REPLACE_MAGLEV_VEHICLES :Trens maglev STR_REPLACE_ROAD_VEHICLES :Automòbils STR_REPLACE_TRAM_VEHICLES :Tramvies +STR_REPLACE_REMOVE_WAGON :{BLACK}Treure vagons ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Fer que la substitució automàtica mantingui la llargada del tren eliminant vagons (començant pel front), si substituint la màquina el tren es fa més llarg +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl + clic també ho aplica als subgrups. # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} @@ -4221,7 +4224,7 @@ STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Mostra l STR_AI_GAME_SCRIPT :{BLACK}Script de partida STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Mostra el registre de l'script de partida. -STR_ERROR_AI_NO_AI_FOUND :No s'ha trobat una IA adequada per carregar.{}Aquesta IA és una IA falsa i no farà res.{}Pots descarregar diverses IA via el sistema de "Contingut en línia" +STR_ERROR_AI_NO_AI_FOUND :No s'ha trobat una IA adequada per carregar.{}Aquesta IA és una IA que no fa res.{}Podeu descarregar diverses IA via el sistema de «Contingut en línia». STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}Un dels scripts que s'estava executant ha fallat. Si us plau, informeu l'autor de l'script amb una captura de pantalla de la finestra de depuració de l'script d'IA/partida. STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}La finestra de depuració de les IA i l'script de partida només està disponible al servidor. diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index a76b1d9079..6155a1f84e 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -2204,6 +2204,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Could no STR_NETWORK_ERROR_TIMEOUT :{WHITE}Connection #{NUM} timed out 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_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 From 414e12d26be88043000aa7fe540edc974244dcc8 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 4 Jun 2021 09:28:38 +0200 Subject: [PATCH 310/800] Codechange: move SLF_NOT_IN_SAVE into settings It is a settings-only flag, so don't pollute SaveLoad code with it. --- src/saveload/saveload.cpp | 5 +---- src/settings.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 3c95e61e2d..427a19aa95 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1408,10 +1408,7 @@ static void SlDeque(void *deque, VarType conv) /** Are we going to save this object or not? */ static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) { - if (_sl_version < sld.version_from || _sl_version >= sld.version_to) return false; - if (sld.conv & SLF_NOT_IN_SAVE) return false; - - return true; + return (_sl_version >= sld.version_from && _sl_version < sld.version_to); } /** diff --git a/src/settings.cpp b/src/settings.cpp index 60ae20d82e..93caff15dd 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2023,6 +2023,8 @@ void IConsoleListSettings(const char *prefilter) static void LoadSettings(const SettingTable &settings, void *object) { for (auto &osd : settings) { + if (osd->save.conv & SLF_NOT_IN_SAVE) continue; + void *ptr = GetVariableAddress(object, osd->save); if (!SlObjectMember(ptr, osd->save)) continue; @@ -2045,11 +2047,15 @@ static void SaveSettings(const SettingTable &settings, void *object) * SlCalcLength() because we have a different format. So do this manually */ size_t length = 0; for (auto &sd : settings) { + if (sd->save.conv & SLF_NOT_IN_SAVE) continue; + length += SlCalcObjMemberLength(object, sd->save); } SlSetLength(length); for (auto &sd : settings) { + if (sd->save.conv & SLF_NOT_IN_SAVE) continue; + void *ptr = GetVariableAddress(object, sd->save); SlObjectMember(ptr, sd->save); } From 264991dfa506c0bdebb2e2c936f79a2412dad442 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 4 Jun 2021 09:31:28 +0200 Subject: [PATCH 311/800] Codechange: move SLF_NO_NETWORK_SYNC into settings It is a settings-only flag, so don't pollute SaveLoad code with it. --- src/saveload/saveload.cpp | 18 +----------------- src/saveload/saveload.h | 1 + src/settings.cpp | 10 ++++++++-- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 427a19aa95..35a6437e18 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -584,7 +584,7 @@ static inline uint SlGetArrayLength(size_t length) * @param conv VarType type of variable that is used for calculating the size * @return Return the size of this type in bytes */ -static inline uint SlCalcConvMemLen(VarType conv) +uint SlCalcConvMemLen(VarType conv) { static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0}; byte length = GB(conv, 4, 4); @@ -1411,21 +1411,6 @@ static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) return (_sl_version >= sld.version_from && _sl_version < sld.version_to); } -/** - * Are we going to load this variable when loading a savegame or not? - * @note If the variable is skipped it is skipped in the savegame - * bytestream itself as well, so there is no need to skip it somewhere else - */ -static inline bool SlSkipVariableOnLoad(const SaveLoad &sld) -{ - if ((sld.conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) { - SlSkipBytes(SlCalcConvMemLen(sld.conv) * sld.length); - return true; - } - - return false; -} - /** * Calculate the size of an object. * @param object to be measured. @@ -1538,7 +1523,6 @@ bool SlObjectMember(void *ptr, const SaveLoad &sld) case SL_STDSTR: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) return false; - if (SlSkipVariableOnLoad(sld)) return false; switch (sld.cmd) { case SL_VAR: SlSaveLoadConv(ptr, conv); break; diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index ce597affc4..c178c47313 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -896,6 +896,7 @@ void WriteValue(void *ptr, VarType conv, int64 val); void SlSetArrayIndex(uint index); int SlIterateArray(); +uint SlCalcConvMemLen(VarType conv); void SlAutolength(AutolengthProc *proc, void *arg); size_t SlGetFieldLength(); void SlSetLength(size_t length); diff --git a/src/settings.cpp b/src/settings.cpp index 93caff15dd..c2594277d6 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2025,9 +2025,15 @@ static void LoadSettings(const SettingTable &settings, void *object) for (auto &osd : settings) { if (osd->save.conv & SLF_NOT_IN_SAVE) continue; - void *ptr = GetVariableAddress(object, osd->save); + SaveLoad sl = osd->save; + if ((osd->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server) { + /* We don't want to read this setting, so we do need to skip over it. */ + sl = SLE_NULL(static_cast(SlCalcConvMemLen(osd->save.conv) * osd->save.length)); + } + + void *ptr = GetVariableAddress(object, sl); + if (!SlObjectMember(ptr, sl)) continue; - if (!SlObjectMember(ptr, osd->save)) continue; if (osd->IsIntSetting()) { const IntSettingDesc *int_setting = osd->AsIntSetting(); int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); From 648ee88a02fef70172a108ed7bc511e27984d2c4 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 20:55:03 +0200 Subject: [PATCH 312/800] Codechange: merge guiflags and flags in settings .ini files It was rather confusing which one was for what, especially as some SaveLoad flags were settings-only. Clean up this mess a bit by having only Setting flags. --- src/saveload/saveload.h | 11 +- src/script/api/script_gamesettings.cpp | 2 +- src/settings.cpp | 18 +- src/settings_internal.h | 25 +- src/table/settings.h.preamble | 68 +-- src/table/settings/company_settings.ini | 19 +- src/table/settings/currency_settings.ini | 7 +- src/table/settings/gameopt_settings.ini | 29 +- src/table/settings/misc_settings.ini | 15 +- src/table/settings/settings.ini | 584 ++++++++++------------- src/table/settings/win32_settings.ini | 7 +- src/table/settings/window_settings.ini | 7 +- 12 files changed, 352 insertions(+), 440 deletions(-) diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index c178c47313..94138eb747 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -485,11 +485,8 @@ enum VarTypes { /* 8 bits allocated for a maximum of 8 flags * Flags directing saving/loading of a variable */ - SLF_NOT_IN_SAVE = 1 << 8, ///< do not save with savegame, basically client-based - SLF_NOT_IN_CONFIG = 1 << 9, ///< do not save to config file - SLF_NO_NETWORK_SYNC = 1 << 10, ///< do not synchronize over network (but it is saved if SLF_NOT_IN_SAVE is not set) - SLF_ALLOW_CONTROL = 1 << 11, ///< allow control codes in the strings - SLF_ALLOW_NEWLINE = 1 << 12, ///< allow new lines in the strings + SLF_ALLOW_CONTROL = 1 << 8, ///< Allow control codes in the strings. + SLF_ALLOW_NEWLINE = 1 << 9, ///< Allow new lines in the strings. }; typedef uint32 VarType; @@ -673,7 +670,7 @@ using SaveLoadTable = span; * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLE_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, 0, nullptr, 0} +#define SLE_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0} /** Translate values ingame to different values in the savegame and vv. */ #define SLE_WRITEBYTE(base, variable) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0) @@ -797,7 +794,7 @@ using SaveLoadTable = span; * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, 0, nullptr, 0} +#define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0} /** * Checks whether the savegame is below \a major.\a minor. diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index b1699d94f6..458545226f 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -35,7 +35,7 @@ const SettingDesc *sd = GetSettingFromName(setting); - if ((sd->save.conv & SLF_NO_NETWORK_SYNC) != 0) return false; + if ((sd->flags & SF_NO_NETWORK_SYNC) != 0) return false; return ScriptObject::DoCommand(0, 0, value, CMD_CHANGE_SETTING, sd->name); } diff --git a/src/settings.cpp b/src/settings.cpp index c2594277d6..c3afd55089 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -591,7 +591,7 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co /* If the setting is not saved to the configuration * file, just continue with the next setting */ if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (sd->save.conv & SLF_NOT_IN_CONFIG) continue; + if (sd->flags & SF_NOT_IN_CONFIG) continue; /* XXX - wtf is this?? (group override?) */ std::string s{ sd->name }; @@ -741,7 +741,7 @@ void IniSaveWindowSettings(IniFile *ini, const char *grpname, void *desc) */ bool SettingDesc::IsEditable(bool do_command) const { - if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SF_PER_COMPANY)) return false; + if (!do_command && !(this->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SF_PER_COMPANY)) return false; if ((this->flags & SF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false; if ((this->flags & SF_NO_NETWORK) && _networking) return false; if ((this->flags & SF_NEWGAME_ONLY) && @@ -758,7 +758,7 @@ bool SettingDesc::IsEditable(bool do_command) const SettingType SettingDesc::GetType() const { if (this->flags & SF_PER_COMPANY) return ST_COMPANY; - return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; + return (this->flags & SF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME; } /** @@ -1844,7 +1844,7 @@ bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) * (if any) to change. Also *hack*hack* we update the _newgame version * of settings because changing a company-based setting in a game also * changes its defaults. At least that is the convention we have chosen */ - if (setting->save.conv & SLF_NO_NETWORK_SYNC) { + if (setting->flags & SF_NO_NETWORK_SYNC) { if (_game_mode != GM_MENU) { setting->ChangeValue(&_settings_newgame, value); } @@ -1899,7 +1899,7 @@ void SyncCompanySettings() */ bool SetSettingValue(const StringSettingDesc *sd, std::string value, bool force_newgame) { - assert(sd->save.conv & SLF_NO_NETWORK_SYNC); + assert(sd->flags & SF_NO_NETWORK_SYNC); if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && value.compare("(null)") == 0) { value.clear(); @@ -2023,10 +2023,10 @@ void IConsoleListSettings(const char *prefilter) static void LoadSettings(const SettingTable &settings, void *object) { for (auto &osd : settings) { - if (osd->save.conv & SLF_NOT_IN_SAVE) continue; + if (osd->flags & SF_NOT_IN_SAVE) continue; SaveLoad sl = osd->save; - if ((osd->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !_network_server) { + if ((osd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) { /* We don't want to read this setting, so we do need to skip over it. */ sl = SLE_NULL(static_cast(SlCalcConvMemLen(osd->save.conv) * osd->save.length)); } @@ -2053,14 +2053,14 @@ static void SaveSettings(const SettingTable &settings, void *object) * SlCalcLength() because we have a different format. So do this manually */ size_t length = 0; for (auto &sd : settings) { - if (sd->save.conv & SLF_NOT_IN_SAVE) continue; + if (sd->flags & SF_NOT_IN_SAVE) continue; length += SlCalcObjMemberLength(object, sd->save); } SlSetLength(length); for (auto &sd : settings) { - if (sd->save.conv & SLF_NOT_IN_SAVE) continue; + if (sd->flags & SF_NOT_IN_SAVE) continue; void *ptr = GetVariableAddress(object, sd->save); SlObjectMember(ptr, sd->save); diff --git a/src/settings_internal.h b/src/settings_internal.h index 351c66ea3c..a625f576c2 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -14,16 +14,19 @@ enum SettingFlag : uint16 { SF_NONE = 0, - SF_GUI_0_IS_SPECIAL = 1 << 0, ///< A value of zero is possible and has a custom string (the one after "strval"). - SF_GUI_NEGATIVE_IS_SPECIAL = 1 << 1, ///< A negative value has another string (the one after "strval"). - SF_GUI_DROPDOWN = 1 << 2, ///< The value represents a limited number of string-options (internally integer) presented as dropdown. - SF_GUI_CURRENCY = 1 << 3, ///< The number represents money, so when reading value multiply by exchange rate. - SF_NETWORK_ONLY = 1 << 4, ///< This setting only applies to network games. - SF_NO_NETWORK = 1 << 5, ///< This setting does not apply to network games; it may not be changed during the game. - SF_NEWGAME_ONLY = 1 << 6, ///< This setting cannot be changed in a game. - SF_SCENEDIT_TOO = 1 << 7, ///< This setting can be changed in the scenario editor (only makes sense when SF_NEWGAME_ONLY is set). - SF_SCENEDIT_ONLY = 1 << 8, ///< This setting can only be changed in the scenario editor. - SF_PER_COMPANY = 1 << 9, ///< This setting can be different for each company (saved in company struct). + SF_GUI_0_IS_SPECIAL = 1 << 0, ///< A value of zero is possible and has a custom string (the one after "strval"). + SF_GUI_NEGATIVE_IS_SPECIAL = 1 << 1, ///< A negative value has another string (the one after "strval"). + SF_GUI_DROPDOWN = 1 << 2, ///< The value represents a limited number of string-options (internally integer) presented as dropdown. + SF_GUI_CURRENCY = 1 << 3, ///< The number represents money, so when reading value multiply by exchange rate. + SF_NETWORK_ONLY = 1 << 4, ///< This setting only applies to network games. + SF_NO_NETWORK = 1 << 5, ///< This setting does not apply to network games; it may not be changed during the game. + SF_NEWGAME_ONLY = 1 << 6, ///< This setting cannot be changed in a game. + SF_SCENEDIT_TOO = 1 << 7, ///< This setting can be changed in the scenario editor (only makes sense when SF_NEWGAME_ONLY is set). + SF_SCENEDIT_ONLY = 1 << 8, ///< This setting can only be changed in the scenario editor. + SF_PER_COMPANY = 1 << 9, ///< This setting can be different for each company (saved in company struct). + SF_NOT_IN_SAVE = 1 << 10, ///< Do not save with savegame, basically client-based. + SF_NOT_IN_CONFIG = 1 << 11, ///< Do not save to config file. + SF_NO_NETWORK_SYNC = 1 << 12, ///< Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set). }; DECLARE_ENUM_AS_BIT_SET(SettingFlag) @@ -288,7 +291,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, "", SF_NONE, false) {} + SettingDesc(save, "", SF_NOT_IN_CONFIG, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 3c8e6cb721..c9b47626c4 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -58,62 +58,62 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for global variables */ -#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) +#define SDTG_VAR(name, type, flags, var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Int, SLEG_GENERAL(SL_VAR, var, type, 1, from, to, extra), name, flags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) -#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) +#define SDTG_BOOL(name, flags, var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Bool, SLEG_GENERAL(SL_VAR, var, SLE_BOOL, 1, from, to, extra), name, flags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) -#define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, cat, extra, startup)\ - NSD(List, SLEG_GENERAL(SL_ARR, var, type | flags, length, from, to, extra), name, guiflags, startup, def) +#define SDTG_LIST(name, type, flags, var, def, length, from, to, cat, extra, startup)\ + NSD(List, SLEG_GENERAL(SL_ARR, var, type, length, from, to, extra), name, flags, startup, def) -#define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, startup, def, max_length, pre_check, post_callback) +#define SDTG_SSTR(name, type, flags, var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(String, SLEG_GENERAL(SL_STDSTR, var, type, sizeof(var), from, to, extra), name, flags, startup, def, max_length, pre_check, post_callback) -#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) +#define SDTG_OMANY(name, type, flags, var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type, 1, from, to, extra), name, flags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) -#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) +#define SDTG_MMANY(name, type, flags, var, def, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type, 1, from, to, extra), name, flags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) #define SDTG_NULL(length, from, to)\ NSD(Null, SLEG_NULL(length, from, to)) /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ -#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) +#define SDT_VAR(base, var, type, flags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Int, SLE_GENERAL(SL_VAR, base, var, type, 1, from, to, extra), #var, flags, startup, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback) -#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) +#define SDT_BOOL(base, var, flags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(Bool, SLE_GENERAL(SL_VAR, base, var, SLE_BOOL, 1, from, to, extra), #var, flags, startup, def, str, strhelp, strval, cat, pre_check, post_callback) -#define SDT_LIST(base, var, type, flags, guiflags, def, from, to, cat, extra, startup)\ - NSD(List, SLE_GENERAL(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def) +#define SDT_LIST(base, var, type, flags, def, from, to, cat, extra, startup)\ + NSD(List, SLE_GENERAL(SL_ARR, base, var, type, lengthof(((base*)8)->var), from, to, extra), #var, flags, startup, def) -#define SDT_SSTR(base, var, type, flags, guiflags, def, pre_check, post_callback, from, to, cat, extra, startup)\ - NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, startup, def, 0, pre_check, post_callback) +#define SDT_SSTR(base, var, type, flags, def, pre_check, post_callback, from, to, cat, extra, startup)\ + NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type, sizeof(((base*)8)->var), from, to, extra), #var, flags, startup, def, 0, pre_check, post_callback) -#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, load, cat, extra, startup)\ - NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, load) +#define SDT_OMANY(base, var, type, flags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, load, cat, extra, startup)\ + NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type, 1, from, to, extra), #var, flags, startup, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, load) -#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, pre_check, post_callback, strhelp, strval, from, to, cat, extra, startup)\ - NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) +#define SDT_MMANY(base, var, type, flags, def, full, str, pre_check, post_callback, strhelp, strval, from, to, cat, extra, startup)\ + NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type, 1, from, to, extra), #var, flags, startup, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) #define SDT_NULL(length, from, to)\ NSD(Null, SLE_CONDNULL(length, from, to)) -#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - SDTG_VAR(#var, type, flags, guiflags, _settings_client.var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) +#define SDTC_VAR(var, type, flags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_VAR(#var, type, flags, _settings_client.var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) -#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - SDTG_BOOL(#var, flags, guiflags, _settings_client.var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) +#define SDTC_BOOL(var, flags, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_BOOL(#var, flags, _settings_client.var, def, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) -#define SDTC_LIST(var, type, flags, guiflags, def, from, to, cat, extra, startup)\ - SDTG_LIST(#var, type, flags, guiflags, _settings_client.var, def, lengthof(_settings_client.var), from, to, cat, extra, startup) +#define SDTC_LIST(var, type, flags, def, from, to, cat, extra, startup)\ + SDTG_LIST(#var, type, flags, _settings_client.var, def, lengthof(_settings_client.var), from, to, cat, extra, startup) -#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ - SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ +#define SDTC_SSTR(var, type, flags, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_SSTR(#var, type, flags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, cat, extra, startup)\ -#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ - SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) +#define SDTC_OMANY(var, type, flags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup)\ + SDTG_OMANY(#var, type, flags, _settings_client.var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, cat, extra, startup) diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index 6b6a17c967..469e1aceae 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -16,15 +16,14 @@ static const SettingTable _company_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL(CompanySettings, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR(CompanySettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(CompanySettings, $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(CompanySettings, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CompanySettings.$var exceeds storage size"); [defaults] -flags = 0 -guiflags = SF_PER_COMPANY +flags = SF_PER_COMPANY interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT @@ -50,7 +49,7 @@ cat = SC_BASIC [SDT_VAR] var = engine_renew_months type = SLE_INT16 -guiflags = SF_PER_COMPANY | SF_GUI_NEGATIVE_IS_SPECIAL +flags = SF_PER_COMPANY | SF_GUI_NEGATIVE_IS_SPECIAL def = 6 min = -12 max = 12 @@ -61,7 +60,7 @@ strval = STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE [SDT_VAR] var = engine_renew_money type = SLE_UINT -guiflags = SF_PER_COMPANY | SF_GUI_CURRENCY +flags = SF_PER_COMPANY | SF_GUI_CURRENCY def = 100000 min = 0 max = 2000000 @@ -83,7 +82,7 @@ post_cb = UpdateServiceInterval [SDT_VAR] var = vehicle.servint_trains type = SLE_UINT16 -guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL +flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 150 min = 5 max = 800 @@ -96,7 +95,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_TRAIN, new_value); } [SDT_VAR] var = vehicle.servint_roadveh type = SLE_UINT16 -guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL +flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 150 min = 5 max = 800 @@ -109,7 +108,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_ROAD, new_value); } [SDT_VAR] var = vehicle.servint_ships type = SLE_UINT16 -guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL +flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 360 min = 5 max = 800 @@ -122,7 +121,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_SHIP, new_value); } [SDT_VAR] var = vehicle.servint_aircraft type = SLE_UINT16 -guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL +flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL def = 100 min = 5 max = 800 diff --git a/src/table/settings/currency_settings.ini b/src/table/settings/currency_settings.ini index 8e359d5c02..c8ba3d76cd 100644 --- a/src/table/settings/currency_settings.ini +++ b/src/table/settings/currency_settings.ini @@ -11,15 +11,14 @@ static const SettingTable _currency_settings{ [post-amble] }; [templates] -SDT_VAR = SDT_VAR (CurrencySpec, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR(CurrencySpec, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR (CurrencySpec, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR(CurrencySpec, $var, $type, $flags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CurrencySpec.$var exceeds storage size"); [defaults] -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NONE +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index 195bae365f..addcbeb027 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -46,13 +46,13 @@ static const SettingTable _gameopt_settings{ [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL( $length, $from, $to), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), -SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); @@ -62,8 +62,7 @@ SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$va SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); [defaults] -flags = 0 -guiflags = SF_NONE +flags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT @@ -84,7 +83,7 @@ name = ""diff_custom"" sdt_cmd = SDT_INTLIST sle_cmd = SL_ARR type = SLE_FILE_I16 | SLE_VAR_U16 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG var = _old_diff_custom length = 17 def = nullptr @@ -95,19 +94,18 @@ name = ""diff_custom"" sdt_cmd = SDT_INTLIST sle_cmd = SL_ARR type = SLE_UINT16 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG var = _old_diff_custom length = 18 def = nullptr full = nullptr from = SLV_4 -## [SDTG_VAR] name = ""diff_level"" var = _old_diff_level type = SLE_UINT8 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG def = SP_CUSTOM min = SP_EASY max = SP_CUSTOM @@ -116,7 +114,7 @@ cat = SC_BASIC [SDT_OMANY] var = locale.currency type = SLE_UINT8 -flags = SLF_NO_NETWORK_SYNC +flags = SF_NO_NETWORK_SYNC def = 0 max = CURRENCY_END - 1 full = _locale_currencies @@ -126,7 +124,7 @@ cat = SC_BASIC name = ""units"" var = _old_units type = SLE_UINT8 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG def = 1 max = 2 full = _locale_units @@ -172,8 +170,7 @@ to = SLV_23 [SDTC_OMANY] var = gui.autosave type = SLE_UINT8 -from = SLV_23 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 1 max = 4 full = _autosave_interval diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 45da1db52b..453c6e8162 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -24,20 +24,19 @@ static const SettingTable _misc_settings{ [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $cat, $extra, $startup), -SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_LIST = SDTG_LIST($name, $type, $flags, $var, $def, $length, $from, $to, $cat, $extra, $startup), +SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $var, $def, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); [defaults] -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NONE +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index be4d7ea941..f9f1cb87b7 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -53,18 +53,18 @@ const SettingTable _settings{ [post-amble] }; [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $from, $to, $cat, $extra, $startup), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $guiflags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_BOOL = SDT_BOOL(GameSettings, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), -SDT_SSTR = SDT_SSTR(GameSettings, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_BOOL = SDTC_BOOL( $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_LIST = SDTC_LIST( $var, $type, $flags, $def, $from, $to, $cat, $extra, $startup), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_SSTR = SDTC_SSTR( $var, $type, $flags, $def, $length, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTC_VAR = SDTC_VAR( $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(GameSettings, $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup), +SDT_SSTR = SDT_SSTR(GameSettings, $var, $type, $flags, $def, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), SDT_NULL = SDT_NULL( $length, $from, $to), [validation] @@ -76,8 +76,7 @@ SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$va SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size"); [defaults] -flags = 0 -guiflags = SF_NONE +flags = SF_NONE interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT @@ -119,7 +118,7 @@ max = 3 var = difficulty.number_towns type = SLE_UINT8 from = SLV_97 -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = 2 min = 0 max = 4 @@ -131,7 +130,7 @@ cat = SC_BASIC var = difficulty.industry_density type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = ID_END - 1 min = 0 max = ID_END - 1 @@ -145,7 +144,7 @@ cat = SC_BASIC var = difficulty.max_loan type = SLE_UINT32 from = SLV_97 -guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_CURRENCY +flags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_CURRENCY def = 300000 min = 0 max = 2000000000 @@ -159,7 +158,7 @@ cat = SC_BASIC var = difficulty.initial_interest type = SLE_UINT8 from = SLV_97 -guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO +flags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO def = 2 min = 2 max = 4 @@ -172,7 +171,7 @@ strval = STR_CONFIG_SETTING_PERCENTAGE var = difficulty.vehicle_costs type = SLE_UINT8 from = SLV_97 -guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN +flags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -186,7 +185,7 @@ cat = SC_BASIC var = difficulty.competitor_speed type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 0 max = 4 @@ -209,7 +208,7 @@ max = 2 var = difficulty.vehicle_breakdowns type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -223,7 +222,7 @@ cat = SC_BASIC var = difficulty.subsidy_multiplier type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 0 max = 3 @@ -236,7 +235,7 @@ strval = STR_SUBSIDY_X1_5 var = difficulty.construction_cost type = SLE_UINT8 from = SLV_97 -guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN +flags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -250,7 +249,7 @@ cat = SC_BASIC var = difficulty.terrain_type type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = 0 max = 5 @@ -264,7 +263,7 @@ cat = SC_BASIC var = difficulty.quantity_sea_lakes type = SLE_UINT8 from = SLV_97 -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = 0 min = 0 max = 4 @@ -298,7 +297,7 @@ cat = SC_BASIC var = difficulty.town_council_tolerance type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -312,7 +311,7 @@ post_cb = DifficultyNoiseChange name = ""diff_level"" var = _old_diff_level type = SLE_UINT8 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG from = SLV_97 to = SLV_178 def = 3 @@ -326,7 +325,7 @@ cat = SC_BASIC var = game_creation.town_name type = SLE_UINT8 from = SLV_97 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 0 max = 255 full = _town_names @@ -336,7 +335,7 @@ cat = SC_BASIC var = game_creation.landscape type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 0 max = 3 full = _climates @@ -356,7 +355,7 @@ to = SLV_164 var = vehicle.road_side type = SLE_UINT8 from = SLV_97 -guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK +flags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 max = 1 full = _roadsides @@ -372,7 +371,7 @@ cat = SC_BASIC var = construction.map_height_limit type = SLE_UINT8 from = SLV_194 -guiflags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_0_IS_SPECIAL +flags = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_0_IS_SPECIAL def = 0 min = MIN_MAP_HEIGHT_LIMIT max = MAX_MAP_HEIGHT_LIMIT @@ -388,7 +387,7 @@ cat = SC_ADVANCED var = game_creation.heightmap_height type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = MAP_HEIGHT_LIMIT_AUTO_MINIMUM min = MIN_HEIGHTMAP_HEIGHT max = MAX_MAP_HEIGHT_LIMIT @@ -396,7 +395,7 @@ interval = 1 [SDT_BOOL] var = construction.build_on_slopes -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -404,7 +403,7 @@ cat = SC_EXPERT var = construction.command_pause_level type = SLE_UINT8 from = SLV_154 -guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK +flags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 min = 0 max = 3 @@ -491,7 +490,7 @@ strhelp = STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT var = construction.max_bridge_length type = SLE_UINT16 from = SLV_159 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 64 min = 1 max = MAX_MAP_SIZE @@ -504,7 +503,7 @@ strval = STR_CONFIG_SETTING_TILE_LENGTH var = construction.max_bridge_height type = SLE_UINT8 from = SLV_194 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 12 min = 1 max = MAX_TILE_HEIGHT @@ -518,7 +517,7 @@ cat = SC_EXPERT var = construction.max_tunnel_length type = SLE_UINT16 from = SLV_159 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 64 min = 1 max = MAX_MAP_SIZE @@ -535,7 +534,7 @@ to = SLV_159 [SDT_VAR] var = construction.train_signal_side type = SLE_UINT8 -guiflags = SF_GUI_DROPDOWN | SF_NO_NETWORK +flags = SF_GUI_DROPDOWN | SF_NO_NETWORK def = 1 min = 0 max = 2 @@ -547,7 +546,7 @@ cat = SC_BASIC [SDT_BOOL] var = station.never_expire_airports -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT @@ -556,7 +555,7 @@ strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT var = economy.town_layout type = SLE_UINT8 from = SLV_59 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = TL_ORIGINAL min = TL_BEGIN max = NUM_TLS - 1 @@ -569,7 +568,7 @@ post_cb = TownFoundingChanged [SDT_BOOL] var = economy.allow_town_roads from = SLV_113 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT @@ -578,7 +577,7 @@ strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT var = economy.found_town type = SLE_UINT8 from = SLV_128 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = TF_FORBIDDEN min = TF_BEGIN max = TF_END - 1 @@ -592,7 +591,7 @@ cat = SC_BASIC [SDT_BOOL] var = economy.allow_town_level_crossings from = SLV_143 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT @@ -601,7 +600,7 @@ strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT var = economy.town_cargogen_mode type = SLE_UINT8 from = SLV_TOWN_CARGOGEN -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = TCGM_BITCOUNT min = TCGM_BEGIN max = TCGM_END - 1 @@ -644,7 +643,7 @@ extra = offsetof(LinkGraphSettings, recalc_time) var = linkgraph.distribution_pax type = SLE_UINT8 from = SLV_183 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -659,7 +658,7 @@ extra = offsetof(LinkGraphSettings, distribution_pax) var = linkgraph.distribution_mail type = SLE_UINT8 from = SLV_183 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -674,7 +673,7 @@ extra = offsetof(LinkGraphSettings, distribution_mail) var = linkgraph.distribution_armoured type = SLE_UINT8 from = SLV_183 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_MIN max = DT_MAX @@ -689,7 +688,7 @@ extra = offsetof(LinkGraphSettings, distribution_armoured) var = linkgraph.distribution_default type = SLE_UINT8 from = SLV_183 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = DT_MANUAL min = DT_BEGIN max = DT_MAX_NONSYMMETRIC @@ -761,7 +760,7 @@ extra = offsetof(LinkGraphSettings, short_path_saturation) [SDT_VAR] var = vehicle.train_acceleration_model type = SLE_UINT8 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -775,7 +774,7 @@ post_cb = TrainAccelerationModelChanged var = vehicle.roadveh_acceleration_model type = SLE_UINT8 from = SLV_139 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -843,7 +842,7 @@ to = SLV_159 var = vehicle.smoke_amount type = SLE_UINT8 from = SLV_145 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -895,7 +894,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_trains type = SLE_UINT8 from = SLV_87 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -909,7 +908,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_roadvehs type = SLE_UINT8 from = SLV_87 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -923,7 +922,7 @@ cat = SC_EXPERT var = pf.pathfinder_for_ships type = SLE_UINT8 from = SLV_87 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 1 max = 2 @@ -936,7 +935,7 @@ cat = SC_EXPERT [SDT_BOOL] var = vehicle.never_expire_vehicles -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES strhelp = STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT @@ -991,7 +990,7 @@ cat = SC_BASIC [SDTG_BOOL] name = nullptr -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK var = _old_vds.servint_ispercent def = false to = SLV_120 @@ -999,7 +998,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_trains def = 150 min = 5 @@ -1009,7 +1008,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_roadveh def = 150 min = 5 @@ -1019,7 +1018,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_ships def = 360 min = 5 @@ -1029,7 +1028,7 @@ to = SLV_120 [SDTG_VAR] name = nullptr type = SLE_UINT16 -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_aircraft def = 150 min = 5 @@ -1044,7 +1043,7 @@ strhelp = STR_CONFIG_SETTING_NOSERVICE_HELPTEXT [SDT_BOOL] var = vehicle.wagon_speed_limits -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true str = STR_CONFIG_SETTING_WAGONSPEEDLIMITS strhelp = STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT @@ -1053,7 +1052,7 @@ post_cb = UpdateConsists [SDT_BOOL] var = vehicle.disable_elrails from = SLV_38 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_DISABLE_ELRAILS strhelp = STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT @@ -1064,7 +1063,7 @@ cat = SC_EXPERT var = vehicle.freight_trains type = SLE_UINT8 from = SLV_39 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 1 min = 1 max = 255 @@ -1084,7 +1083,7 @@ to = SLV_159 var = vehicle.plane_speed type = SLE_UINT8 from = SLV_90 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = 4 min = 1 max = 4 @@ -1095,7 +1094,7 @@ strval = STR_CONFIG_SETTING_PLANE_SPEED_VALUE [SDT_BOOL] var = vehicle.dynamic_engines from = SLV_95 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true pre_cb = CheckDynamicEngines cat = SC_EXPERT @@ -1104,7 +1103,7 @@ cat = SC_EXPERT var = vehicle.plane_crashes type = SLE_UINT8 from = SLV_138 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -1127,7 +1126,7 @@ def = true [SDT_BOOL] var = order.improved_load -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -1185,7 +1184,7 @@ post_cb = StationCatchmentChanged [SDT_BOOL] var = order.gradual_loading from = SLV_40 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = true cat = SC_EXPERT @@ -1214,7 +1213,7 @@ cat = SC_EXPERT [SDT_BOOL] var = economy.station_noise_level from = SLV_96 -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_NOISE_LEVEL strhelp = STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT @@ -1231,7 +1230,7 @@ post_cb = [](auto) { CloseWindowById(WC_SELECT_STATION, 0); } ## [SDT_BOOL] var = economy.inflation -guiflags = SF_NO_NETWORK +flags = SF_NO_NETWORK def = false str = STR_CONFIG_SETTING_INFLATION strhelp = STR_CONFIG_SETTING_INFLATION_HELPTEXT @@ -1240,7 +1239,7 @@ cat = SC_BASIC [SDT_VAR] var = construction.raw_industry_construction type = SLE_UINT8 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -1318,7 +1317,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.snow_line_height type = SLE_UINT8 -guiflags = SF_SCENEDIT_ONLY +flags = SF_SCENEDIT_ONLY def = DEF_SNOWLINE_HEIGHT min = MIN_SNOWLINE_HEIGHT max = MAX_SNOWLINE_HEIGHT @@ -1332,7 +1331,7 @@ cat = SC_BASIC var = game_creation.snow_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = DEF_SNOW_COVERAGE min = 0 max = 100 @@ -1346,7 +1345,7 @@ cat = SC_BASIC var = game_creation.desert_coverage type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = DEF_DESERT_COVERAGE min = 0 max = 100 @@ -1379,7 +1378,7 @@ to = SLV_105 var = game_creation.ending_year type = SLE_INT32 from = SLV_ENDING_YEAR -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL def = DEF_END_YEAR min = MIN_YEAR max = MAX_YEAR - 1 @@ -1392,7 +1391,7 @@ cat = SC_ADVANCED [SDT_VAR] var = economy.type type = SLE_UINT8 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = ET_SMOOTH min = ET_BEGIN max = ET_END - 1 @@ -1438,7 +1437,7 @@ cat = SC_EXPERT var = economy.town_growth_rate type = SLE_UINT8 from = SLV_54 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 0 max = 4 @@ -1450,7 +1449,7 @@ strval = STR_CONFIG_SETTING_TOWN_GROWTH_NONE var = economy.larger_towns type = SLE_UINT8 from = SLV_54 -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_GUI_0_IS_SPECIAL def = 4 min = 0 max = 255 @@ -1486,7 +1485,7 @@ to = SLV_107 var = script.settings_profile type = SLE_UINT8 from = SLV_178 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = SP_EASY min = SP_EASY max = SP_HARD @@ -1531,7 +1530,7 @@ strhelp = STR_CONFIG_SETTING_AI_BUILDS_SHIPS_HELPTEXT var = script.script_max_opcode_till_suspend type = SLE_UINT32 from = SLV_107 -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = 10000 min = 500 max = 250000 @@ -1545,7 +1544,7 @@ cat = SC_EXPERT var = script.script_max_memory_megabytes type = SLE_UINT32 from = SLV_SCRIPT_MEMLIMIT -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = 1024 min = 8 max = 8192 @@ -2119,7 +2118,7 @@ cat = SC_EXPERT var = game_creation.land_generator type = SLE_UINT8 from = SLV_30 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = 0 max = 1 @@ -2142,7 +2141,7 @@ strhelp = STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT var = game_creation.tgen_smoothness type = SLE_UINT8 from = SLV_30 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 1 min = TGEN_SMOOTHNESS_BEGIN max = TGEN_SMOOTHNESS_END - 1 @@ -2155,7 +2154,7 @@ cat = SC_BASIC var = game_creation.variety type = SLE_UINT8 from = SLV_197 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 0 min = 0 max = 5 @@ -2176,7 +2175,7 @@ cat = SC_EXPERT var = game_creation.tree_placer type = SLE_UINT8 from = SLV_30 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY | SF_SCENEDIT_TOO +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY | SF_SCENEDIT_TOO def = 2 min = 0 max = 2 @@ -2188,8 +2187,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.heightmap_rotation type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 1 @@ -2200,7 +2198,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.se_flat_world_height type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 1 min = 0 max = 15 @@ -2212,7 +2210,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.map_x type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 8 min = MIN_MAP_SIZE_BITS max = MAX_MAP_SIZE_BITS @@ -2221,7 +2219,7 @@ cat = SC_BASIC [SDT_VAR] var = game_creation.map_y type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 8 min = MIN_MAP_SIZE_BITS max = MAX_MAP_SIZE_BITS @@ -2256,7 +2254,7 @@ cat = SC_BASIC var = construction.extra_tree_placement type = SLE_UINT8 from = SLV_132 -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN def = 2 min = 0 max = 3 @@ -2269,7 +2267,7 @@ cat = SC_BASIC var = game_creation.custom_terrain_type type = SLE_UINT8 from = SLV_MAPGEN_SETTINGS_REVAMP -guiflags = SF_NEWGAME_ONLY +flags = SF_NEWGAME_ONLY def = MAP_HEIGHT_LIMIT_AUTO_MINIMUM min = MIN_CUSTOM_TERRAIN_TYPE max = MAX_MAP_HEIGHT_LIMIT @@ -2306,7 +2304,7 @@ cat = SC_EXPERT var = game_creation.amount_of_rivers type = SLE_UINT8 from = SLV_163 -guiflags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY def = 2 min = 0 max = 3 @@ -2320,7 +2318,7 @@ strval = STR_RIVERS_NONE var = locale.currency type = SLE_UINT8 from = SLV_97 -flags = SLF_NO_NETWORK_SYNC +flags = SF_NO_NETWORK_SYNC def = 0 max = CURRENCY_END - 1 full = _locale_currencies @@ -2333,7 +2331,7 @@ var = _old_units type = SLE_UINT8 from = SLV_97 to = SLV_184 -flags = SLF_NOT_IN_CONFIG +flags = SF_NOT_IN_CONFIG def = 1 max = 2 full = _locale_units @@ -2344,8 +2342,7 @@ cat = SC_BASIC var = locale.units_velocity type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 3 full = _locale_units @@ -2359,8 +2356,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL var = locale.units_power type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2374,8 +2370,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_IMPERIAL var = locale.units_weight type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2389,8 +2384,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_IMPERIAL var = locale.units_volume type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2404,8 +2398,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_IMPERIAL var = locale.units_force type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _locale_units @@ -2419,8 +2412,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_IMPERIAL var = locale.units_height type = SLE_UINT8 from = SLV_184 -flags = SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _locale_units @@ -2434,7 +2426,7 @@ strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL var = locale.digit_group_separator type = SLE_STRQ from = SLV_118 -flags = SLF_NO_NETWORK_SYNC +flags = SF_NO_NETWORK_SYNC def = nullptr post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC @@ -2443,7 +2435,7 @@ cat = SC_BASIC var = locale.digit_group_separator_currency type = SLE_STRQ from = SLV_118 -flags = SLF_NO_NETWORK_SYNC +flags = SF_NO_NETWORK_SYNC def = nullptr post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC @@ -2452,7 +2444,7 @@ cat = SC_BASIC var = locale.digit_decimal_separator type = SLE_STRQ from = SLV_126 -flags = SLF_NO_NETWORK_SYNC +flags = SF_NO_NETWORK_SYNC def = nullptr post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC @@ -2464,8 +2456,7 @@ cat = SC_BASIC [SDTC_OMANY] var = gui.autosave type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 4 full = _autosave_interval @@ -2476,15 +2467,14 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.threaded_saves -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true cat = SC_EXPERT [SDTC_OMANY] var = gui.date_format_in_default_names type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _savegame_date @@ -2494,7 +2484,7 @@ strval = STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG [SDTC_BOOL] var = gui.show_finances -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SHOWFINANCES strhelp = STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT @@ -2503,8 +2493,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.auto_scrolling type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 3 @@ -2516,8 +2505,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.scroll_mode type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 3 @@ -2528,14 +2516,14 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.smooth_scroll -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_SMOOTH_SCROLLING strhelp = STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT [SDTC_BOOL] var = gui.right_mouse_wnd_close -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT @@ -2546,8 +2534,7 @@ cat = SC_BASIC ifdef = __APPLE__ var = gui.right_mouse_btn_emulation type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2558,7 +2545,7 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.measure_tooltip -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_MEASURE_TOOLTIP strhelp = STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT @@ -2567,7 +2554,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.errmsg_duration type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 5 min = 0 max = 20 @@ -2578,8 +2565,7 @@ strval = STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE [SDTC_VAR] var = gui.hover_delay_ms type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL def = 250 min = 50 max = 6000 @@ -2591,11 +2577,11 @@ strval = STR_CONFIG_SETTING_HOVER_DELAY_VALUE [SDTC_OMANY] var = gui.osk_activation type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC str = STR_CONFIG_SETTING_OSK_ACTIVATION strhelp = STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT strval = STR_CONFIG_SETTING_OSK_ACTIVATION_DISABLED -guiflags = SF_GUI_DROPDOWN +flags = SF_GUI_DROPDOWN full = _osk_activation def = 1 min = 0 @@ -2605,8 +2591,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.toolbar_pos type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2619,8 +2604,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.statusbar_pos type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2633,8 +2617,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.window_snap_radius type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL def = 10 min = 1 max = 32 @@ -2646,8 +2629,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.window_soft_limit type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL def = 20 min = 5 max = 255 @@ -2660,8 +2642,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.zoom_min type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = ZOOM_LVL_MIN min = ZOOM_LVL_MIN max = ZOOM_LVL_OUT_4X @@ -2674,8 +2655,7 @@ startup = true [SDTC_VAR] var = gui.zoom_max type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = ZOOM_LVL_MAX min = ZOOM_LVL_OUT_8X max = ZOOM_LVL_MAX @@ -2688,8 +2668,7 @@ startup = true [SDTC_VAR] var = gui.sprite_zoom_min type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = ZOOM_LVL_MIN min = ZOOM_LVL_MIN max = ZOOM_LVL_OUT_4X @@ -2700,7 +2679,7 @@ post_cb = SpriteZoomMinChanged [SDTC_BOOL] var = gui.population_in_label -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_POPULATION_IN_LABEL strhelp = STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT @@ -2708,7 +2687,7 @@ post_cb = [](auto) { UpdateAllTownVirtCoords(); } [SDTC_BOOL] var = gui.link_terraform_toolbar -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR strhelp = STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR_HELPTEXT @@ -2716,8 +2695,7 @@ strhelp = STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR_HELPTEXT [SDTC_VAR] var = gui.smallmap_land_colour type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2729,8 +2707,7 @@ post_cb = RedrawSmallmap [SDTC_VAR] var = gui.liveries type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -2742,8 +2719,7 @@ post_cb = InvalidateCompanyLiveryWindow [SDTC_VAR] var = gui.starting_colour type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = COLOUR_END min = 0 max = COLOUR_END @@ -2753,7 +2729,7 @@ strval = STR_COLOUR_DARK_BLUE [SDTC_BOOL] var = gui.auto_remove_signals -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS strhelp = STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT @@ -2761,7 +2737,7 @@ cat = SC_ADVANCED [SDTC_BOOL] var = gui.prefer_teamchat -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_PREFER_TEAMCHAT strhelp = STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT @@ -2770,8 +2746,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.scrollwheel_scrolling type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2783,7 +2758,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.scrollwheel_multiplier type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 5 min = 1 max = 15 @@ -2795,7 +2770,7 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.pause_on_newgame -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME strhelp = STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT @@ -2804,8 +2779,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.advanced_vehicle_list type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2815,7 +2789,7 @@ strval = STR_CONFIG_SETTING_COMPANIES_OFF [SDTC_BOOL] var = gui.timetable_in_ticks -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_TIMETABLE_IN_TICKS strhelp = STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT @@ -2824,7 +2798,7 @@ cat = SC_EXPERT [SDTC_BOOL] var = gui.timetable_arrival_departure -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE strhelp = STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT @@ -2832,7 +2806,7 @@ post_cb = [](auto) { InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE, VIWD_MOD [SDTC_BOOL] var = gui.quick_goto -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_QUICKGOTO strhelp = STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT @@ -2841,8 +2815,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.loading_indicators type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -2855,8 +2828,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.default_rail_type type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 min = 0 max = 2 @@ -2867,7 +2839,7 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.enable_signal_gui -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI strhelp = STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI_HELPTEXT @@ -2877,7 +2849,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.coloured_news_year type = SLE_INT32 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 2000 min = MIN_YEAR max = MAX_YEAR @@ -2890,7 +2862,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.drag_signals_density type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 4 min = 1 max = 20 @@ -2902,7 +2874,7 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.drag_signals_fixed_distance -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE strhelp = STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT @@ -2911,7 +2883,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.semaphore_build_before type = SLE_INT32 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 1950 min = MIN_YEAR max = MAX_YEAR @@ -2923,7 +2895,7 @@ post_cb = ResetSignalVariant [SDTC_BOOL] var = gui.vehicle_income_warn -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_WARN_INCOME_LESS strhelp = STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT @@ -2932,8 +2904,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.order_review_system type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -2944,14 +2915,14 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.lost_vehicle_warn -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_WARN_LOST_VEHICLE strhelp = STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT [SDTC_BOOL] var = gui.new_nonstop -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT strhelp = STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT @@ -2960,8 +2931,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.stop_location type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -2973,45 +2943,45 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.keep_all_autosave -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false [SDTC_BOOL] var = gui.autosave_on_exit -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false cat = SC_BASIC [SDTC_BOOL] var = gui.autosave_on_network_disconnect -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true cat = SC_EXPERT [SDTC_VAR] var = gui.max_num_autosaves type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 16 min = 0 max = 255 [SDTC_BOOL] var = gui.auto_euro -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true [SDTC_VAR] var = gui.news_message_timeout type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 2 min = 1 max = 255 [SDTC_BOOL] var = gui.show_track_reservation -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION strhelp = STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT @@ -3021,8 +2991,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.default_signal_type type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 2 @@ -3035,8 +3004,7 @@ cat = SC_BASIC [SDTC_VAR] var = gui.cycle_signal_types type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 min = 0 max = 2 @@ -3048,7 +3016,7 @@ strval = STR_CONFIG_SETTING_CYCLE_SIGNAL_NORMAL [SDTC_VAR] var = gui.station_numtracks type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 1 min = 1 max = 7 @@ -3056,7 +3024,7 @@ max = 7 [SDTC_VAR] var = gui.station_platlength type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 5 min = 1 max = 7 @@ -3064,19 +3032,19 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.station_dragdrop -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true cat = SC_BASIC [SDTC_BOOL] var = gui.station_show_coverage -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false cat = SC_BASIC [SDTC_BOOL] var = gui.persistent_buildingtools -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS strhelp = STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT @@ -3084,7 +3052,7 @@ cat = SC_BASIC [SDTC_BOOL] var = gui.expenses_layout -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_EXPENSES_LAYOUT strhelp = STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT @@ -3093,7 +3061,7 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } [SDTC_VAR] var = gui.station_gui_group_order type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 0 min = 0 max = 5 @@ -3102,7 +3070,7 @@ interval = 1 [SDTC_VAR] var = gui.station_gui_sort_by type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 0 min = 0 max = 3 @@ -3111,7 +3079,7 @@ interval = 1 [SDTC_VAR] var = gui.station_gui_sort_order type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 0 min = 0 max = 1 @@ -3120,7 +3088,7 @@ interval = 1 [SDTC_VAR] var = gui.missing_strings_threshold type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 25 min = 1 max = UINT8_MAX @@ -3129,7 +3097,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.graph_line_thickness type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 3 min = 1 max = 5 @@ -3140,7 +3108,7 @@ post_cb = [](auto) { MarkWholeScreenDirty(); } [SDTC_BOOL] var = gui.show_newgrf_name -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false str = STR_CONFIG_SETTING_SHOW_NEWGRF_NAME strhelp = STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT @@ -3151,19 +3119,19 @@ cat = SC_ADVANCED [SDTC_BOOL] ifdef = DEDICATED var = gui.show_date_in_logs -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true [SDTC_BOOL] ifndef = DEDICATED var = gui.show_date_in_logs -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false [SDTC_VAR] var = gui.settings_restriction_mode type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 0 min = 0 max = 2 @@ -3171,7 +3139,7 @@ max = 2 [SDTC_VAR] var = gui.developer type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 1 min = 0 max = 2 @@ -3179,35 +3147,34 @@ cat = SC_EXPERT [SDTC_BOOL] var = gui.newgrf_developer_tools -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false post_cb = InvalidateNewGRFChangeWindows cat = SC_EXPERT [SDTC_BOOL] var = gui.ai_developer_tools -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false post_cb = [](auto) { InvalidateWindowClassesData(WC_AI_SETTINGS); } cat = SC_EXPERT [SDTC_BOOL] var = gui.scenario_developer -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false post_cb = InvalidateNewGRFChangeWindows [SDTC_BOOL] var = gui.newgrf_show_old_versions -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false cat = SC_EXPERT [SDTC_VAR] var = gui.newgrf_default_palette type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 min = 0 max = 1 @@ -3217,7 +3184,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.console_backlog_timeout type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 100 min = 10 max = 65500 @@ -3225,7 +3192,7 @@ max = 65500 [SDTC_VAR] var = gui.console_backlog_length type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 100 min = 10 max = 65500 @@ -3233,7 +3200,7 @@ max = 65500 [SDTC_VAR] var = gui.refresh_rate type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 60 min = 10 max = 1000 @@ -3243,8 +3210,7 @@ startup = true [SDTC_VAR] var = gui.fast_forward_speed_limit type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL | SF_NO_NETWORK +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NO_NETWORK def = 2500 min = 0 max = 50000 @@ -3256,56 +3222,56 @@ cat = SC_BASIC [SDTC_BOOL] var = sound.news_ticker -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_TICKER strhelp = STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT [SDTC_BOOL] var = sound.news_full -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_NEWS strhelp = STR_CONFIG_SETTING_SOUND_NEWS_HELPTEXT [SDTC_BOOL] var = sound.new_year -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_NEW_YEAR strhelp = STR_CONFIG_SETTING_SOUND_NEW_YEAR_HELPTEXT [SDTC_BOOL] var = sound.confirm -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_CONFIRM strhelp = STR_CONFIG_SETTING_SOUND_CONFIRM_HELPTEXT [SDTC_BOOL] var = sound.click_beep -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_CLICK strhelp = STR_CONFIG_SETTING_SOUND_CLICK_HELPTEXT [SDTC_BOOL] var = sound.disaster -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_DISASTER strhelp = STR_CONFIG_SETTING_SOUND_DISASTER_HELPTEXT [SDTC_BOOL] var = sound.vehicle -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_VEHICLE strhelp = STR_CONFIG_SETTING_SOUND_VEHICLE_HELPTEXT [SDTC_BOOL] var = sound.ambient -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true str = STR_CONFIG_SETTING_SOUND_AMBIENT strhelp = STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT @@ -3313,7 +3279,7 @@ strhelp = STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT [SDTC_VAR] var = music.playlist type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 0 min = 0 max = 5 @@ -3323,7 +3289,7 @@ cat = SC_BASIC [SDTC_VAR] var = music.music_vol type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 50 min = 0 max = 127 @@ -3333,7 +3299,7 @@ cat = SC_BASIC [SDTC_VAR] var = music.effect_vol type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 100 min = 0 max = 127 @@ -3343,34 +3309,33 @@ cat = SC_BASIC [SDTC_LIST] var = music.custom_1 type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = nullptr cat = SC_BASIC [SDTC_LIST] var = music.custom_2 type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = nullptr cat = SC_BASIC [SDTC_BOOL] var = music.playing -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = true cat = SC_BASIC [SDTC_BOOL] var = music.shuffle -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false cat = SC_BASIC [SDTC_OMANY] var = news_display.arrival_player type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3381,8 +3346,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.arrival_other type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3393,8 +3357,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.accident type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3405,8 +3368,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.company_info type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3417,8 +3379,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.open type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3429,8 +3390,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.close type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3441,8 +3401,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.economy type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3453,8 +3412,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.production_player type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3465,8 +3423,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.production_other type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 max = 2 full = _news_display @@ -3477,8 +3434,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.production_nobody type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 0 max = 2 full = _news_display @@ -3489,8 +3445,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.advice type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3501,8 +3456,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.new_vehicles type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3513,8 +3467,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.acceptance type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3525,8 +3478,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.subsidies type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 max = 2 full = _news_display @@ -3537,8 +3489,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_OMANY] var = news_display.general type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_DROPDOWN +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 2 max = 2 full = _news_display @@ -3549,7 +3500,7 @@ strval = STR_CONFIG_SETTING_NEWS_MESSAGES_OFF [SDTC_VAR] var = gui.network_chat_box_width_pct type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 40 min = 10 max = 100 @@ -3558,7 +3509,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.network_chat_box_height type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 25 min = 5 max = 255 @@ -3567,7 +3518,7 @@ cat = SC_EXPERT [SDTC_VAR] var = gui.network_chat_timeout type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = 20 min = 1 max = 65535 @@ -3576,8 +3527,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.sync_freq type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NOT_IN_CONFIG | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NOT_IN_CONFIG | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 100 min = 0 max = 100 @@ -3586,8 +3536,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.frame_freq type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NOT_IN_CONFIG | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NOT_IN_CONFIG | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 0 min = 0 max = 100 @@ -3596,8 +3545,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.commands_per_frame type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 2 min = 1 max = 65535 @@ -3606,8 +3554,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.max_commands_in_queue type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 16 min = 1 max = 65535 @@ -3616,8 +3563,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.bytes_per_frame type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 8 min = 1 max = 65535 @@ -3626,8 +3572,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.bytes_per_frame_burst type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 256 min = 1 max = 65535 @@ -3636,8 +3581,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.max_init_time type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 100 min = 0 max = 32000 @@ -3646,8 +3590,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.max_join_time type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 500 min = 0 max = 32000 @@ -3655,8 +3598,7 @@ max = 32000 [SDTC_VAR] var = network.max_download_time type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 1000 min = 0 max = 32000 @@ -3664,8 +3606,7 @@ max = 32000 [SDTC_VAR] var = network.max_password_time type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 2000 min = 0 max = 32000 @@ -3673,23 +3614,20 @@ max = 32000 [SDTC_VAR] var = network.max_lag_time type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 500 min = 0 max = 32000 [SDTC_BOOL] var = network.pause_on_join -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = true [SDTC_VAR] var = network.server_port type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = NETWORK_DEFAULT_PORT min = 0 max = 65535 @@ -3698,8 +3636,7 @@ cat = SC_EXPERT [SDTC_VAR] var = network.server_admin_port type = SLE_UINT16 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = NETWORK_ADMIN_PORT min = 0 max = 65535 @@ -3707,22 +3644,20 @@ cat = SC_EXPERT [SDTC_BOOL] var = network.server_admin_chat -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = true cat = SC_EXPERT [SDTC_BOOL] var = network.server_advertise -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = false [SDTC_SSTR] var = network.client_name type = SLE_STR length = NETWORK_CLIENT_NAME_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = nullptr pre_cb = NetworkValidateClientName post_cb = NetworkUpdateClientName @@ -3732,8 +3667,7 @@ cat = SC_BASIC var = network.server_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = nullptr pre_cb = ReplaceAsteriskWithEmptyPassword post_cb = [](auto) { NetworkServerUpdateGameInfo(); } @@ -3743,8 +3677,7 @@ cat = SC_BASIC var = network.rcon_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = nullptr pre_cb = ReplaceAsteriskWithEmptyPassword cat = SC_BASIC @@ -3753,8 +3686,7 @@ cat = SC_BASIC var = network.admin_password type = SLE_STR length = NETWORK_PASSWORD_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = nullptr cat = SC_BASIC @@ -3762,15 +3694,14 @@ cat = SC_BASIC var = network.default_company_pass type = SLE_STR length = NETWORK_PASSWORD_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = nullptr [SDTC_SSTR] var = network.server_name type = SLE_STR length = NETWORK_NAME_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = nullptr pre_cb = NetworkValidateServerName post_cb = [](auto) { UpdateClientConfigValues(); } @@ -3780,28 +3711,25 @@ cat = SC_BASIC var = network.connect_to_ip type = SLE_STR length = 0 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = nullptr [SDTC_SSTR] var = network.network_id type = SLE_STR length = NETWORK_SERVER_ID_LENGTH -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = nullptr [SDTC_BOOL] var = network.autoclean_companies -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = false [SDTC_VAR] var = network.autoclean_unprotected type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 12 min = 0 max = 240 @@ -3809,8 +3737,7 @@ max = 240 [SDTC_VAR] var = network.autoclean_protected type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 36 min = 0 max = 240 @@ -3818,8 +3745,7 @@ max = 240 [SDTC_VAR] var = network.autoclean_novehicles type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 0 min = 0 max = 240 @@ -3827,8 +3753,7 @@ max = 240 [SDTC_VAR] var = network.max_companies type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 15 min = 1 max = MAX_COMPANIES @@ -3838,8 +3763,7 @@ cat = SC_BASIC [SDTC_VAR] var = network.max_clients type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 25 min = 2 max = MAX_CLIENTS @@ -3849,8 +3773,7 @@ cat = SC_BASIC [SDTC_VAR] var = network.max_spectators type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 15 min = 0 max = MAX_CLIENTS @@ -3860,8 +3783,7 @@ cat = SC_BASIC [SDTC_VAR] var = network.restart_game_year type = SLE_INT32 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY def = 0 min = MIN_YEAR max = MAX_YEAR @@ -3870,16 +3792,14 @@ interval = 1 [SDTC_VAR] var = network.min_active_clients type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = 0 min = 0 max = MAX_CLIENTS [SDTC_BOOL] var = network.reload_cfg -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NETWORK_ONLY +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = false cat = SC_EXPERT @@ -3887,12 +3807,12 @@ cat = SC_EXPERT var = network.last_joined type = SLE_STR length = 0 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = """" cat = SC_EXPERT [SDTC_BOOL] var = network.no_http_content_downloads -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC def = false cat = SC_EXPERT diff --git a/src/table/settings/win32_settings.ini b/src/table/settings/win32_settings.ini index 32a5cf5c93..df1e0cb272 100644 --- a/src/table/settings/win32_settings.ini +++ b/src/table/settings/win32_settings.ini @@ -17,15 +17,14 @@ static const SettingTable _win32_settings{ }; #endif /* _WIN32 */ [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); [defaults] -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NONE +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT diff --git a/src/table/settings/window_settings.ini b/src/table/settings/window_settings.ini index f9301ef2ce..3a7669754f 100644 --- a/src/table/settings/window_settings.ini +++ b/src/table/settings/window_settings.ini @@ -13,15 +13,14 @@ static const SettingTable _window_settings{ [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL(WindowDesc, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), -SDT_VAR = SDT_VAR(WindowDesc, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_BOOL = SDT_BOOL(WindowDesc, $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), +SDT_VAR = SDT_VAR(WindowDesc, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup), [validation] SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for WindowDesc.$var exceeds storage size"); [defaults] -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SF_NONE +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC interval = 0 str = STR_NULL strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT From 7572603c9d97215afe62cd79e25048237a637616 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 3 Jun 2021 21:01:00 +0200 Subject: [PATCH 313/800] Codechange: remove the unused SLF_HEX flag --- src/saveload/saveload.h | 2 -- src/settings.cpp | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 41880952e0..ce597affc4 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -490,8 +490,6 @@ enum VarTypes { SLF_NO_NETWORK_SYNC = 1 << 10, ///< do not synchronize over network (but it is saved if SLF_NOT_IN_SAVE is not set) SLF_ALLOW_CONTROL = 1 << 11, ///< allow control codes in the strings SLF_ALLOW_NEWLINE = 1 << 12, ///< allow new lines in the strings - SLF_HEX = 1 << 13, ///< print numbers as hex in the config file (only useful for unsigned) - /* 2 more possible flags */ }; typedef uint32 VarType; diff --git a/src/settings.cpp b/src/settings.cpp index 50dc387907..60ae20d82e 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -274,8 +274,6 @@ void ListSettingDesc::FormatValue(char *buf, const char *last, const void *objec } if (IsSignedVarMemType(this->save.conv)) { buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v); - } else if (this->save.conv & SLF_HEX) { - buf += seprintf(buf, last, (i == 0) ? "0x%X" : ",0x%X", v); } else { buf += seprintf(buf, last, (i == 0) ? "%u" : ",%u", v); } @@ -621,7 +619,7 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { uint32 i = (uint32)this->Read(object); - seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); + seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : "%u", i); } void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const From 1e564b333fa2d7bde2f21d7a05bb3e81305185c5 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 7 Jun 2021 23:03:12 +0200 Subject: [PATCH 314/800] Codechange: make [Save|Load]Settings() behave more like other Save/Load code (#9335) Prepare the full description and send it to SlObject. This does require some code to be able to read to a SLE_VAR_NULL, like strings etc, as there is no way to know their length beforehand. --- src/saveload/saveload.cpp | 13 ++++++-- src/saveload/saveload.h | 1 - src/settings.cpp | 62 +++++++++++++++++++++++---------------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 35a6437e18..29fcf89daf 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -584,7 +584,7 @@ static inline uint SlGetArrayLength(size_t length) * @param conv VarType type of variable that is used for calculating the size * @return Return the size of this type in bytes */ -uint SlCalcConvMemLen(VarType conv) +static inline uint SlCalcConvMemLen(VarType conv) { static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0}; byte length = GB(conv, 4, 4); @@ -943,6 +943,9 @@ static void SlString(void *ptr, size_t length, VarType conv) switch (GetVarMemType(conv)) { default: NOT_REACHED(); + case SLE_VAR_NULL: + SlSkipBytes(len); + return; case SLE_VAR_STRB: if (len >= length) { DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating"); @@ -1007,8 +1010,12 @@ static void SlStdString(void *ptr, VarType conv) case SLA_LOAD_CHECK: case SLA_LOAD: { size_t len = SlReadArrayLength(); - char *buf = AllocaM(char, len + 1); + if (GetVarMemType(conv) == SLE_VAR_NULL) { + SlSkipBytes(len); + return; + } + char *buf = AllocaM(char, len + 1); SlCopyBytes(buf, len); buf[len] = '\0'; // properly terminate the string @@ -1469,6 +1476,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) */ [[maybe_unused]] static bool IsVariableSizeRight(const SaveLoad &sld) { + if (GetVarMemType(sld.conv) == SLE_VAR_NULL) return true; + switch (sld.cmd) { case SL_VAR: switch (GetVarMemType(sld.conv)) { diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 94138eb747..53a81f7c2f 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -893,7 +893,6 @@ void WriteValue(void *ptr, VarType conv, int64 val); void SlSetArrayIndex(uint index); int SlIterateArray(); -uint SlCalcConvMemLen(VarType conv); void SlAutolength(AutolengthProc *proc, void *arg); size_t SlGetFieldLength(); void SlSetLength(size_t length); diff --git a/src/settings.cpp b/src/settings.cpp index c3afd55089..24039c564a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2014,6 +2014,31 @@ void IConsoleListSettings(const char *prefilter) IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); } +/** + * Get the SaveLoad description for the SettingTable. + * @param settings SettingDesc struct containing all information. + * @param is_loading True iff the SaveLoad table is for loading. + * @return Vector with SaveLoad entries for the SettingTable. + */ +static std::vector GetSettingsDesc(const SettingTable &settings, bool is_loading) +{ + std::vector saveloads; + for (auto &sd : settings) { + if (sd->flags & SF_NOT_IN_SAVE) continue; + + if (is_loading && (sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) { + /* We don't want to read this setting, so we do need to skip over it. */ + saveloads.push_back({sd->save.cmd, GetVarFileType(sd->save.conv) | SLE_VAR_NULL, sd->save.length, sd->save.version_from, sd->save.version_to, 0, nullptr, 0}); + continue; + } + + saveloads.push_back(sd->save); + } + + return saveloads; +} + + /** * Save and load handler for settings * @param settings SettingDesc struct containing all information @@ -2022,20 +2047,18 @@ void IConsoleListSettings(const char *prefilter) */ static void LoadSettings(const SettingTable &settings, void *object) { - for (auto &osd : settings) { - if (osd->flags & SF_NOT_IN_SAVE) continue; + const std::vector slt = GetSettingsDesc(settings, true); - SaveLoad sl = osd->save; - if ((osd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) { - /* We don't want to read this setting, so we do need to skip over it. */ - sl = SLE_NULL(static_cast(SlCalcConvMemLen(osd->save.conv) * osd->save.length)); - } + SlObject(object, slt); - void *ptr = GetVariableAddress(object, sl); - if (!SlObjectMember(ptr, sl)) continue; + /* Ensure all IntSettings are valid (min/max could have changed between versions etc). */ + for (auto &sd : settings) { + if (sd->flags & SF_NOT_IN_SAVE) continue; + if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue; + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (osd->IsIntSetting()) { - const IntSettingDesc *int_setting = osd->AsIntSetting(); + if (sd->IsIntSetting()) { + const IntSettingDesc *int_setting = sd->AsIntSetting(); int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); } } @@ -2049,22 +2072,9 @@ static void LoadSettings(const SettingTable &settings, void *object) */ static void SaveSettings(const SettingTable &settings, void *object) { - /* We need to write the CH_RIFF header, but unfortunately can't call - * SlCalcLength() because we have a different format. So do this manually */ - size_t length = 0; - for (auto &sd : settings) { - if (sd->flags & SF_NOT_IN_SAVE) continue; + const std::vector slt = GetSettingsDesc(settings, false); - length += SlCalcObjMemberLength(object, sd->save); - } - SlSetLength(length); - - for (auto &sd : settings) { - if (sd->flags & SF_NOT_IN_SAVE) continue; - - void *ptr = GetVariableAddress(object, sd->save); - SlObjectMember(ptr, sd->save); - } + SlObject(object, slt); } static void Load_OPTS() From f997eb6ca4177b577387306b4c15ec4815f0f13c Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 8 Jun 2021 20:30:44 +0200 Subject: [PATCH 315/800] Fix: compatible NewGRFs in crash-log reported wrong md5 (#9340) The text suggests it reports the original md5, but it does in fact report the replaced md5. Now it reports both. --- src/saveload/afterload.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index f60c12b91b..ff21599963 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -402,9 +402,11 @@ static void CDECL HandleSavegameLoadCrash(int signum) for (const GRFConfig *c = _grfconfig; c != nullptr; c = c->next) { if (HasBit(c->flags, GCF_COMPATIBLE)) { const GRFIdentifier *replaced = GetOverriddenIdentifier(c); - char buf[40]; - md5sumToString(buf, lastof(buf), replaced->md5sum); - p += seprintf(p, lastof(buffer), "NewGRF %08X (checksum %s) not found.\n Loaded NewGRF \"%s\" with same GRF ID instead.\n", BSWAP32(c->ident.grfid), buf, c->filename); + char original_md5[40]; + char replaced_md5[40]; + md5sumToString(original_md5, lastof(original_md5), c->original_md5sum); + md5sumToString(replaced_md5, lastof(replaced_md5), replaced->md5sum); + p += seprintf(p, lastof(buffer), "NewGRF %08X (checksum %s) not found.\n Loaded NewGRF \"%s\" (checksum %s) with same GRF ID instead.\n", BSWAP32(c->ident.grfid), original_md5, c->filename, replaced_md5); } if (c->status == GCS_NOT_FOUND) { char buf[40]; From 12de256b72fb7442cd84c6a0e0c6a61636255a6b Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 8 Jun 2021 19:22:42 +0000 Subject: [PATCH 316/800] Update: Translations from eints german: 1 change by Wuzzy2 spanish: 1 change by ilyabakhlin --- src/lang/german.txt | 1 + src/lang/spanish.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lang/german.txt b/src/lang/german.txt index 7088b47303..64d2f71bcb 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Verbindu STR_NETWORK_ERROR_TIMEOUT :{WHITE}Verbindung #{NUM} hat das Zeitlimit überschritten STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Protokollfehler: Die Verbindung musste getrennt werden STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Ihr Spielername wurde nicht gesetzt. Der Name kann im Mehrspielerfenster oben gesetzt werden +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Ihr Servername wurde nicht gesetzt. Der Name kann oben im Mehrspielerfenster gesetzt werden STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Diese Version des Spiels entspricht nicht der des Servers STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Falsches Passwort STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Der Server ist voll diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 8bdbbe7a76..e69260ca03 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -2205,6 +2205,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pu STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se ha producido un error de protocolo y la conexión ha sido cerrada STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No se ha establecido tu nombre de jugador. El nombre se puede establecer en la parte superior de la ventana de Multijugador +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}El nombre de tu servidor no se ha definido. El nombre puede definirse al principio de la ventana de Multijugador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo From 37b285ad83207d98136a8a36da85f2dec9e415c8 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 9 Jun 2021 19:13:47 +0000 Subject: [PATCH 317/800] Update: Translations from eints spanish (mexican): 2 changes by absay --- src/lang/spanish_MX.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index f314f9deae..c74c5685ab 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -3560,7 +3560,7 @@ STR_GROUP_CREATE_TOOLTIP :{BLACK}Clic par STR_GROUP_DELETE_TOOLTIP :{BLACK}Eliminar el grupo seleccionado STR_GROUP_RENAME_TOOLTIP :{BLACK}Cambiar nombre del grupo seleccionado STR_GROUP_LIVERY_TOOLTIP :{BLACK}Cambiar cromática del grupo elegido -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clic para evitar que los vehículos en este grupo se reemplacen automáticamente. +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clic para evitar que los vehículos en este grupo se reemplacen automáticamente. Ctrl+Clic incluye a los subgrupos. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Eliminar grupo STR_GROUP_DELETE_QUERY_TEXT :{WHITE}¿Eliminar este grupo y todos sus subgrupos? @@ -3815,6 +3815,7 @@ STR_REPLACE_TRAM_VEHICLES :Vehículos de t STR_REPLACE_REMOVE_WAGON :{BLACK}Quitar vagó ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Hacer que el reemplazo automático mantenga la longitud del tren quitando vagones (empezando por el frente), si el cambio de locomotora produce un tren más largo +STR_REPLACE_REMOVE_WAGON_GROUP_HELP :{STRING}. Ctrl+Clic para incluir subgrupos # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} From f899772ec29b9b802ab07e074dc0421f4e2d1a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0efl?= Date: Thu, 10 Jun 2021 15:49:25 +0200 Subject: [PATCH 318/800] Fix 2e136285: Crash when CTRL-clicking on a sign (#9345) --- src/signs_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index 27c618087c..711cd735ee 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -566,7 +566,7 @@ static WindowDesc _query_sign_edit_desc( void HandleClickOnSign(const Sign *si) { if (_ctrl_pressed && (si->owner == _local_company || (si->owner == OWNER_DEITY && _game_mode == GM_EDITOR))) { - RenameSign(si->index, nullptr); + RenameSign(si->index, ""); return; } ShowRenameSignWindow(si); From fba86f711fe091fa0802a65979df019f690e8827 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 31 May 2021 22:49:44 +0200 Subject: [PATCH 319/800] Codechange: move GetVariableAddress inside SlObjectMember Also move it to static, as nobody else is using it. --- src/saveload/saveload.cpp | 7 ++++--- src/saveload/saveload.h | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 29fcf89daf..c325c1ee58 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1517,8 +1517,10 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) } } -bool SlObjectMember(void *ptr, const SaveLoad &sld) +static bool SlObjectMember(void *object, const SaveLoad &sld) { + void *ptr = GetVariableAddress(object, sld); + assert(IsVariableSizeRight(sld)); VarType conv = GB(sld.conv, 0, 8); @@ -1604,8 +1606,7 @@ void SlObject(void *object, const SaveLoadTable &slt) } for (auto &sld : slt) { - void *ptr = GetVariableAddress(object, sld); - SlObjectMember(ptr, sld); + SlObjectMember(object, sld); } } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 53a81f7c2f..e320c7d8b9 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -905,7 +905,6 @@ void SlWriteByte(byte b); void SlGlobList(const SaveLoadTable &slt); void SlArray(void *array, size_t length, VarType conv); void SlObject(void *object, const SaveLoadTable &slt); -bool SlObjectMember(void *object, const SaveLoad &sld); void NORETURN SlError(StringID string, const char *extra_msg = nullptr); void NORETURN SlErrorCorrupt(const char *msg); void NORETURN SlErrorCorruptFmt(const char *format, ...) WARN_FORMAT(1, 2); From a2147d437e970b22da0290f6ac8e75c12ed6fe92 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 4 Jun 2021 10:33:38 +0200 Subject: [PATCH 320/800] Codechange: use wrappers to get Var[Mem|File]Type, instead of GB() --- src/saveload/saveload.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index c325c1ee58..40f631e312 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -587,17 +587,17 @@ static inline uint SlGetArrayLength(size_t length) static inline uint SlCalcConvMemLen(VarType conv) { static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0}; - byte length = GB(conv, 4, 4); - switch (length << 4) { + switch (GetVarMemType(conv)) { case SLE_VAR_STRB: case SLE_VAR_STR: case SLE_VAR_STRQ: return SlReadArrayLength(); default: - assert(length < lengthof(conv_mem_size)); - return conv_mem_size[length]; + uint8 type = GetVarMemType(conv) >> 4; + assert(type < lengthof(conv_mem_size)); + return conv_mem_size[type]; } } @@ -610,9 +610,10 @@ static inline uint SlCalcConvMemLen(VarType conv) static inline byte SlCalcConvFileLen(VarType conv) { static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2}; - byte length = GB(conv, 0, 4); - assert(length < lengthof(conv_file_size)); - return conv_file_size[length]; + + uint8 type = GetVarFileType(conv); + assert(type < lengthof(conv_file_size)); + return conv_file_size[type]; } /** Return the size in bytes of a reference (pointer) */ From 23857af6931e1cd4dc22d15e75850b83cc8af198 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 10:22:55 +0200 Subject: [PATCH 321/800] Codechange: refactor SlDequeueHelper to work with unsigned and be more generic Future additions will start using it for std::list too. --- src/saveload/saveload.cpp | 179 +++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 101 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 40f631e312..97f4a82d0b 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1217,6 +1217,66 @@ static void *IntToReference(size_t index, SLRefType rt) } } +/** + * Template class to help with list-like types. + */ +template typename Tstorage, typename Tvar, typename Tallocator = std::allocator> +class SlStorageHelper { + typedef Tstorage SlStorageT; +public: + /** + * Internal templated helper to return the size in bytes of a list-like type. + * @param storage The storage to find the size of + * @param conv VarType type of variable that is used for calculating the size + */ + static size_t SlCalcLen(const void *storage, VarType conv) + { + const SlStorageT *list = static_cast(storage); + + int type_size = SlCalcConvFileLen(SLE_FILE_U32); // Size of the length of the list. + int item_size = SlCalcConvFileLen(conv); + return list->size() * item_size + type_size; + } + + /** + * Internal templated helper to save/load a list-like type. + * @param storage The storage being manipulated. + * @param conv VarType type of variable that is used for calculating the size. + */ + static void SlSaveLoad(void *storage, VarType conv) + { + SlStorageT *list = static_cast(storage); + + switch (_sl.action) { + case SLA_SAVE: { + SlWriteUint32((uint32)list->size()); + + for (auto &item : *list) { + SlSaveLoadConv(&item, conv); + } + break; + } + case SLA_LOAD_CHECK: + case SLA_LOAD: { + size_t length = SlReadUint32(); + + /* Load each value and push to the end of the storage. */ + for (size_t i = 0; i < length; i++) { + Tvar &data = list->emplace_back(); + SlSaveLoadConv(&data, conv); + } + break; + } + case SLA_PTRS: + break; + case SLA_NULL: + list->clear(); + break; + default: NOT_REACHED(); + } + } +}; + /** * Return the size in bytes of a list * @param list The std::list to find the size of @@ -1231,7 +1291,6 @@ static inline size_t SlCalcListLen(const void *list) return l->size() * type_size + type_size; } - /** * Save/Load a list. * @param list The list being manipulated @@ -1289,71 +1348,6 @@ static void SlList(void *list, SLRefType conv) } } - -/** - * Template class to help with std::deque. - */ -template -class SlDequeHelper { - typedef std::deque SlDequeT; -public: - /** - * Internal templated helper to return the size in bytes of a std::deque. - * @param deque The std::deque to find the size of - * @param conv VarType type of variable that is used for calculating the size - */ - static size_t SlCalcDequeLen(const void *deque, VarType conv) - { - const SlDequeT *l = (const SlDequeT *)deque; - - int type_size = 4; - /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length - * of the list */ - return l->size() * SlCalcConvFileLen(conv) + type_size; - } - - /** - * Internal templated helper to save/load a std::deque. - * @param deque The std::deque being manipulated - * @param conv VarType type of variable that is used for calculating the size - */ - static void SlDeque(void *deque, VarType conv) - { - SlDequeT *l = (SlDequeT *)deque; - - switch (_sl.action) { - case SLA_SAVE: { - SlWriteUint32((uint32)l->size()); - - typename SlDequeT::iterator iter; - for (iter = l->begin(); iter != l->end(); ++iter) { - SlSaveLoadConv(&(*iter), conv); - } - break; - } - case SLA_LOAD_CHECK: - case SLA_LOAD: { - size_t length = SlReadUint32(); - - /* Load each value and push to the end of the deque */ - for (size_t i = 0; i < length; i++) { - T data; - SlSaveLoadConv(&data, conv); - l->push_back(data); - } - break; - } - case SLA_PTRS: - break; - case SLA_NULL: - l->clear(); - break; - default: NOT_REACHED(); - } - } -}; - - /** * Return the size in bytes of a std::deque. * @param deque The std::deque to find the size of @@ -1362,25 +1356,19 @@ public: static inline size_t SlCalcDequeLen(const void *deque, VarType conv) { switch (GetVarMemType(conv)) { - case SLE_VAR_BL: - return SlDequeHelper::SlCalcDequeLen(deque, conv); - case SLE_VAR_I8: - case SLE_VAR_U8: - return SlDequeHelper::SlCalcDequeLen(deque, conv); - case SLE_VAR_I16: - case SLE_VAR_U16: - return SlDequeHelper::SlCalcDequeLen(deque, conv); - case SLE_VAR_I32: - case SLE_VAR_U32: - return SlDequeHelper::SlCalcDequeLen(deque, conv); - case SLE_VAR_I64: - case SLE_VAR_U64: - return SlDequeHelper::SlCalcDequeLen(deque, conv); + case SLE_VAR_BL: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_I8: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_U8: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_I16: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_U16: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_I32: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(deque, conv); default: NOT_REACHED(); } } - /** * Save/load a std::deque. * @param deque The std::deque being manipulated @@ -1389,30 +1377,19 @@ static inline size_t SlCalcDequeLen(const void *deque, VarType conv) static void SlDeque(void *deque, VarType conv) { switch (GetVarMemType(conv)) { - case SLE_VAR_BL: - SlDequeHelper::SlDeque(deque, conv); - break; - case SLE_VAR_I8: - case SLE_VAR_U8: - SlDequeHelper::SlDeque(deque, conv); - break; - case SLE_VAR_I16: - case SLE_VAR_U16: - SlDequeHelper::SlDeque(deque, conv); - break; - case SLE_VAR_I32: - case SLE_VAR_U32: - SlDequeHelper::SlDeque(deque, conv); - break; - case SLE_VAR_I64: - case SLE_VAR_U64: - SlDequeHelper::SlDeque(deque, conv); - break; + case SLE_VAR_BL: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_I8: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_U8: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_I16: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_U16: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_I32: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(deque, conv); break; default: NOT_REACHED(); } } - /** Are we going to save this object or not? */ static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) { From aa6443d57a6e821fabeee65541d3eb869b96772b Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 11:05:03 +0200 Subject: [PATCH 322/800] Codechange: refactor SlList to use SlStorageHelper --- src/saveload/saveload.cpp | 157 ++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 97f4a82d0b..733ff509da 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1217,6 +1217,31 @@ static void *IntToReference(size_t index, SLRefType rt) } } +/** + * Handle conversion for references. + * @param ptr The object being filled/read. + * @param conv VarType type of the current element of the struct. + */ +void SlSaveLoadRef(void *ptr, VarType conv) +{ + switch (_sl.action) { + case SLA_SAVE: + SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv)); + break; + case SLA_LOAD_CHECK: + case SLA_LOAD: + *(size_t *)ptr = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); + break; + case SLA_PTRS: + *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv); + break; + case SLA_NULL: + *(void **)ptr = nullptr; + break; + default: NOT_REACHED(); + } +} + /** * Template class to help with list-like types. */ @@ -1228,124 +1253,107 @@ public: * Internal templated helper to return the size in bytes of a list-like type. * @param storage The storage to find the size of * @param conv VarType type of variable that is used for calculating the size + * @param cmd The SaveLoadType ware are saving/loading. */ - static size_t SlCalcLen(const void *storage, VarType conv) + static size_t SlCalcLen(const void *storage, VarType conv, SaveLoadType cmd = SL_VAR) { + assert(cmd == SL_VAR || cmd == SL_REF); + const SlStorageT *list = static_cast(storage); int type_size = SlCalcConvFileLen(SLE_FILE_U32); // Size of the length of the list. - int item_size = SlCalcConvFileLen(conv); + int item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); return list->size() * item_size + type_size; } + static void SlSaveLoadMember(SaveLoadType cmd, Tvar *item, VarType conv) + { + switch (cmd) { + case SL_VAR: SlSaveLoadConv(item, conv); break; + case SL_REF: SlSaveLoadRef(item, conv); break; + default: + NOT_REACHED(); + } + } + /** * Internal templated helper to save/load a list-like type. * @param storage The storage being manipulated. * @param conv VarType type of variable that is used for calculating the size. - */ - static void SlSaveLoad(void *storage, VarType conv) + * @param cmd The SaveLoadType ware are saving/loading. + */ + static void SlSaveLoad(void *storage, VarType conv, SaveLoadType cmd = SL_VAR) { + assert(cmd == SL_VAR || cmd == SL_REF); + SlStorageT *list = static_cast(storage); switch (_sl.action) { - case SLA_SAVE: { + case SLA_SAVE: SlWriteUint32((uint32)list->size()); for (auto &item : *list) { - SlSaveLoadConv(&item, conv); + SlSaveLoadMember(cmd, &item, conv); } break; - } + case SLA_LOAD_CHECK: case SLA_LOAD: { - size_t length = SlReadUint32(); + size_t length; + switch (cmd) { + case SL_VAR: length = SlReadUint32(); break; + case SL_REF: length = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); break; + default: NOT_REACHED(); + } /* Load each value and push to the end of the storage. */ for (size_t i = 0; i < length; i++) { Tvar &data = list->emplace_back(); - SlSaveLoadConv(&data, conv); + SlSaveLoadMember(cmd, &data, conv); } break; } + case SLA_PTRS: + for (auto &item : *list) { + SlSaveLoadMember(cmd, &item, conv); + } break; + case SLA_NULL: list->clear(); break; + default: NOT_REACHED(); } } }; /** - * Return the size in bytes of a list - * @param list The std::list to find the size of + * Return the size in bytes of a list. + * @param list The std::list to find the size of. + * @param conv VarType type of variable that is used for calculating the size. */ -static inline size_t SlCalcListLen(const void *list) +static inline size_t SlCalcListLen(const void *list, VarType conv) { - const std::list *l = (const std::list *) list; - - int type_size = IsSavegameVersionBefore(SLV_69) ? 2 : 4; - /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length - * of the list */ - return l->size() * type_size + type_size; + return SlStorageHelper::SlCalcLen(list, conv, SL_REF); } /** * Save/Load a list. - * @param list The list being manipulated - * @param conv SLRefType type of the list (Vehicle *, Station *, etc) + * @param list The list being manipulated. + * @param conv VarType type of variable that is used for calculating the size. */ -static void SlList(void *list, SLRefType conv) +static void SlList(void *list, VarType conv) { /* Automatically calculate the length? */ if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcListLen(list)); + SlSetLength(SlCalcListLen(list, conv)); /* Determine length only? */ if (_sl.need_length == NL_CALCLENGTH) return; } - typedef std::list PtrList; - PtrList *l = (PtrList *)list; - - switch (_sl.action) { - case SLA_SAVE: { - SlWriteUint32((uint32)l->size()); - - PtrList::iterator iter; - for (iter = l->begin(); iter != l->end(); ++iter) { - void *ptr = *iter; - SlWriteUint32((uint32)ReferenceToInt(ptr, conv)); - } - break; - } - case SLA_LOAD_CHECK: - case SLA_LOAD: { - size_t length = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); - - /* Load each reference and push to the end of the list */ - for (size_t i = 0; i < length; i++) { - size_t data = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); - l->push_back((void *)data); - } - break; - } - case SLA_PTRS: { - PtrList temp = *l; - - l->clear(); - PtrList::iterator iter; - for (iter = temp.begin(); iter != temp.end(); ++iter) { - void *ptr = IntToReference((size_t)*iter, conv); - l->push_back(ptr); - } - break; - } - case SLA_NULL: - l->clear(); - break; - default: NOT_REACHED(); - } + SlStorageHelper::SlSaveLoad(list, conv, SL_REF); } /** @@ -1433,7 +1441,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_REF: return SlCalcRefLen(); case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); - case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld)); + case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld), sld.conv); case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); default: NOT_REACHED(); @@ -1515,27 +1523,10 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) switch (sld.cmd) { case SL_VAR: SlSaveLoadConv(ptr, conv); break; - case SL_REF: // Reference variable, translate - switch (_sl.action) { - case SLA_SAVE: - SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv)); - break; - case SLA_LOAD_CHECK: - case SLA_LOAD: - *(size_t *)ptr = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); - break; - case SLA_PTRS: - *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv); - break; - case SLA_NULL: - *(void **)ptr = nullptr; - break; - default: NOT_REACHED(); - } - break; + case SL_REF: SlSaveLoadRef(ptr, conv); break; case SL_ARR: SlArray(ptr, sld.length, conv); break; case SL_STR: SlString(ptr, sld.length, sld.conv); break; - case SL_LST: SlList(ptr, (SLRefType)conv); break; + case SL_LST: SlList(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; case SL_STDSTR: SlStdString(ptr, sld.conv); break; default: NOT_REACHED(); From 8f323855b11faa039ce547cff9826be8e5437555 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 11:21:39 +0200 Subject: [PATCH 323/800] Codechange: rename SL_LST to SL_REFLIST to highlight the "reference" part You can easily mistake SlList / SL_LST to be a list of SL_VAR, but it is a list of SL_REF. With this rename, it hopefully saves a few people from "wtf?" moments. --- src/saveload/linkgraph_sl.cpp | 4 ++-- src/saveload/saveload.cpp | 14 +++++++------- src/saveload/saveload.h | 32 ++++++++++++++++---------------- src/saveload/station_sl.cpp | 8 ++++---- src/saveload/town_sl.cpp | 2 +- src/saveload/vehicle_sl.cpp | 2 +- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index 470d00be48..0640dba19c 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -87,8 +87,8 @@ SaveLoadTable GetLinkGraphJobDesc() SaveLoadTable GetLinkGraphScheduleDesc() { static const SaveLoad schedule_desc[] = { - SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH), - SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB), + SLE_REFLIST(LinkGraphSchedule, schedule, REF_LINK_GRAPH), + SLE_REFLIST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB), }; return schedule_desc; } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 733ff509da..8059348584 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1334,7 +1334,7 @@ public: * @param list The std::list to find the size of. * @param conv VarType type of variable that is used for calculating the size. */ -static inline size_t SlCalcListLen(const void *list, VarType conv) +static inline size_t SlCalcRefListLen(const void *list, VarType conv) { return SlStorageHelper::SlCalcLen(list, conv, SL_REF); } @@ -1344,11 +1344,11 @@ static inline size_t SlCalcListLen(const void *list, VarType conv) * @param list The list being manipulated. * @param conv VarType type of variable that is used for calculating the size. */ -static void SlList(void *list, VarType conv) +static void SlRefList(void *list, VarType conv) { /* Automatically calculate the length? */ if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcListLen(list, conv)); + SlSetLength(SlCalcRefListLen(list, conv)); /* Determine length only? */ if (_sl.need_length == NL_CALCLENGTH) return; } @@ -1430,7 +1430,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_REF: case SL_ARR: case SL_STR: - case SL_LST: + case SL_REFLIST: case SL_DEQUE: case SL_STDSTR: /* CONDITIONAL saveload types depend on the savegame version */ @@ -1441,7 +1441,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_REF: return SlCalcRefLen(); case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); - case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld), sld.conv); + case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); default: NOT_REACHED(); @@ -1515,7 +1515,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_REF: case SL_ARR: case SL_STR: - case SL_LST: + case SL_REFLIST: case SL_DEQUE: case SL_STDSTR: /* CONDITIONAL saveload types depend on the savegame version */ @@ -1526,7 +1526,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_REF: SlSaveLoadRef(ptr, conv); break; case SL_ARR: SlArray(ptr, sld.length, conv); break; case SL_STR: SlString(ptr, sld.length, sld.conv); break; - case SL_LST: SlList(ptr, conv); break; + case SL_REFLIST: SlRefList(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; case SL_STDSTR: SlStdString(ptr, sld.conv); break; default: NOT_REACHED(); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index e320c7d8b9..3a2427c933 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -495,10 +495,10 @@ typedef uint32 VarType; enum SaveLoadType : byte { SL_VAR = 0, ///< Save/load a variable. SL_REF = 1, ///< Save/load a reference. - SL_ARR = 2, ///< Save/load an array. + SL_ARR = 2, ///< Save/load a fixed-size array of #SL_VAR elements. SL_STR = 3, ///< Save/load a string. - SL_LST = 4, ///< Save/load a list. - SL_DEQUE = 5, ///< Save/load a deque. + SL_REFLIST = 4, ///< Save/load a list of #SL_REF elements. + SL_DEQUE = 5, ///< Save/load a deque of #SL_VAR elements. SL_STDSTR = 6, ///< Save/load a \c std::string. /* non-normal save-load types */ SL_WRITEBYTE = 8, @@ -557,7 +557,7 @@ using SaveLoadTable = span; #define SLE_CONDREF(base, variable, type, from, to) SLE_GENERAL(SL_REF, base, variable, type, 0, from, to, 0) /** - * Storage of an array in some savegame versions. + * Storage of a fixed-size array of #SL_VAR elements in some savegame versions. * @param base Name of the class or struct containing the array. * @param variable Name of the variable in the class or struct referenced by \a base. * @param type Storage of the data in memory and in the savegame. @@ -589,17 +589,17 @@ using SaveLoadTable = span; #define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to, 0) /** - * Storage of a list in some savegame versions. + * Storage of a list of #SL_REF elements in some savegame versions. * @param base Name of the class or struct containing the list. * @param variable Name of the variable in the class or struct referenced by \a base. * @param type Storage of the data in memory and in the savegame. * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLE_CONDLST(base, variable, type, from, to) SLE_GENERAL(SL_LST, base, variable, type, 0, from, to, 0) +#define SLE_CONDREFLIST(base, variable, type, from, to) SLE_GENERAL(SL_REFLIST, base, variable, type, 0, from, to, 0) /** - * Storage of a deque in some savegame versions. + * Storage of a deque of #SL_VAR elements in some savegame versions. * @param base Name of the class or struct containing the list. * @param variable Name of the variable in the class or struct referenced by \a base. * @param type Storage of the data in memory and in the savegame. @@ -625,7 +625,7 @@ using SaveLoadTable = span; #define SLE_REF(base, variable, type) SLE_CONDREF(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** - * Storage of an array in every version of a savegame. + * Storage of fixed-size array of #SL_VAR elements in every version of a savegame. * @param base Name of the class or struct containing the array. * @param variable Name of the variable in the class or struct referenced by \a base. * @param type Storage of the data in memory and in the savegame. @@ -651,12 +651,12 @@ using SaveLoadTable = span; #define SLE_SSTR(base, variable, type) SLE_CONDSSTR(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** - * Storage of a list in every savegame version. + * Storage of a list of #SL_REF elements in every savegame version. * @param base Name of the class or struct containing the list. * @param variable Name of the variable in the class or struct referenced by \a base. * @param type Storage of the data in memory and in the savegame. */ -#define SLE_LST(base, variable, type) SLE_CONDLST(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) +#define SLE_REFLIST(base, variable, type) SLE_CONDREFLIST(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** * Empty space in every savegame version. @@ -709,7 +709,7 @@ using SaveLoadTable = span; #define SLEG_CONDREF(variable, type, from, to) SLEG_GENERAL(SL_REF, variable, type, 0, from, to, 0) /** - * Storage of a global array in some savegame versions. + * Storage of a global fixed-size array of #SL_VAR elements in some savegame versions. * @param variable Name of the global variable. * @param type Storage of the data in memory and in the savegame. * @param length Number of elements in the array. @@ -738,13 +738,13 @@ using SaveLoadTable = span; #define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to, 0) /** - * Storage of a global list in some savegame versions. + * Storage of a global reference list in some savegame versions. * @param variable Name of the global variable. * @param type Storage of the data in memory and in the savegame. * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLEG_CONDLST(variable, type, from, to) SLEG_GENERAL(SL_LST, variable, type, 0, from, to, 0) +#define SLEG_CONDREFLIST(variable, type, from, to) SLEG_GENERAL(SL_REFLIST, variable, type, 0, from, to, 0) /** * Storage of a global variable in every savegame version. @@ -761,7 +761,7 @@ using SaveLoadTable = span; #define SLEG_REF(variable, type) SLEG_CONDREF(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** - * Storage of a global array in every savegame version. + * Storage of a global fixed-size array of #SL_VAR elements in every savegame version. * @param variable Name of the global variable. * @param type Storage of the data in memory and in the savegame. */ @@ -782,11 +782,11 @@ using SaveLoadTable = span; #define SLEG_SSTR(variable, type) SLEG_CONDSSTR(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** - * Storage of a global list in every savegame version. + * Storage of a global reference list in every savegame version. * @param variable Name of the global variable. * @param type Storage of the data in memory and in the savegame. */ -#define SLEG_LST(variable, type) SLEG_CONDLST(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) +#define SLEG_REFLIST(variable, type) SLEG_CONDREFLIST(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) /** * Empty global space in some savegame versions. diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 75b6043e7a..92fa2bafdf 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -207,7 +207,7 @@ static const SaveLoad _old_station_desc[] = { SLE_CONDVAR(Station, waiting_triggers, SLE_UINT8, SLV_27, SL_MAX_VERSION), SLE_CONDVAR(Station, num_specs, SLE_UINT8, SLV_27, SL_MAX_VERSION), - SLE_CONDLST(Station, loading_vehicles, REF_VEHICLE, SLV_57, SL_MAX_VERSION), + SLE_CONDREFLIST(Station, loading_vehicles, REF_VEHICLE, SLV_57, SL_MAX_VERSION), /* reserve extra space in savegame here. (currently 32 bytes) */ SLE_CONDNULL(32, SLV_2, SL_MAX_VERSION), @@ -265,7 +265,7 @@ SaveLoadTable GetGoodsDesc() SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, SLV_14, SLV_65), SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68), SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, SLV_150, SL_MAX_VERSION), - SLEG_CONDLST( _packets, REF_CARGO_PACKET, SLV_68, SLV_183), + SLEG_CONDREFLIST( _packets, REF_CARGO_PACKET, SLV_68, SLV_183), SLEG_CONDVAR( _num_dests, SLE_UINT32, SLV_183, SL_MAX_VERSION), SLE_CONDVAR(GoodsEntry, cargo.reserved_count, SLE_UINT, SLV_181, SL_MAX_VERSION), SLE_CONDVAR(GoodsEntry, link_graph, SLE_UINT16, SLV_183, SL_MAX_VERSION), @@ -281,7 +281,7 @@ typedef std::pair > StationCargoPair; static const SaveLoad _cargo_list_desc[] = { SLE_VAR(StationCargoPair, first, SLE_UINT16), - SLE_LST(StationCargoPair, second, REF_CARGO_PACKET), + SLE_REFLIST(StationCargoPair, second, REF_CARGO_PACKET), }; /** @@ -426,7 +426,7 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, time_since_unload, SLE_UINT8), SLE_VAR(Station, last_vehicle_type, SLE_UINT8), SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8), - SLE_LST(Station, loading_vehicles, REF_VEHICLE), + SLE_REFLIST(Station, loading_vehicles, REF_VEHICLE), SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES), SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION), }; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 908ff2dd71..581d26cd77 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -189,7 +189,7 @@ static const SaveLoad _town_desc[] = { SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION), SLE_CONDVAR(Town, layout, SLE_UINT8, SLV_113, SL_MAX_VERSION), - SLE_CONDLST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION), + SLE_CONDREFLIST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION), SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 7e9005779d..2609730506 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -629,7 +629,7 @@ SaveLoadTable GetVehicleDescription(VehicleType vt) SLE_VAR(Vehicle, cargo_cap, SLE_UINT16), SLE_CONDVAR(Vehicle, refit_cap, SLE_UINT16, SLV_182, SL_MAX_VERSION), SLEG_CONDVAR( _cargo_count, SLE_UINT16, SL_MIN_VERSION, SLV_68), - SLE_CONDLST(Vehicle, cargo.packets, REF_CARGO_PACKET, SLV_68, SL_MAX_VERSION), + SLE_CONDREFLIST(Vehicle, cargo.packets, REF_CARGO_PACKET, SLV_68, SL_MAX_VERSION), SLE_CONDARR(Vehicle, cargo.action_counts, SLE_UINT, VehicleCargoList::NUM_MOVE_TO_ACTION, SLV_181, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, cargo_age_counter, SLE_UINT16, SLV_162, SL_MAX_VERSION), From 174952440a1e0440ed61ca8cdbc9fa36cf66d757 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 14:01:42 +0200 Subject: [PATCH 324/800] Codechange: rework CHTS-chunk save/load to be more like the others --- src/cheat_type.h | 3 --- src/saveload/cheat_sl.cpp | 57 +++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/cheat_type.h b/src/cheat_type.h index 3d70d527f9..8ca032c860 100644 --- a/src/cheat_type.h +++ b/src/cheat_type.h @@ -28,12 +28,9 @@ struct Cheats { Cheat switch_company; ///< change to another company Cheat money; ///< get rich or poor Cheat crossing_tunnels; ///< allow tunnels that cross each other - Cheat dummy1; ///< empty cheat (build while in pause mode) Cheat no_jetcrash; ///< no jet will crash on small airports anymore - Cheat dummy2; ///< empty cheat (change the climate of the map) Cheat change_date; ///< changes date ingame Cheat setup_prod; ///< setup raw-material production in game - Cheat dummy3; ///< empty cheat (enable running el-engines on normal rail) Cheat edit_max_hl; ///< edit the maximum heightlevel; this is a cheat because of the fact that it needs to reset NewGRF game state and doing so as a simple configuration breaks the expectation of many }; diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index 970e5f3be1..fde1fc1761 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -14,21 +14,38 @@ #include "../safeguards.h" +static const SaveLoad _cheats_desc[] = { + SLE_VAR(Cheats, magic_bulldozer.been_used, SLE_BOOL), + SLE_VAR(Cheats, magic_bulldozer.value, SLE_BOOL), + SLE_VAR(Cheats, switch_company.been_used, SLE_BOOL), + SLE_VAR(Cheats, switch_company.value, SLE_BOOL), + SLE_VAR(Cheats, money.been_used, SLE_BOOL), + SLE_VAR(Cheats, money.value, SLE_BOOL), + SLE_VAR(Cheats, crossing_tunnels.been_used, SLE_BOOL), + SLE_VAR(Cheats, crossing_tunnels.value, SLE_BOOL), + SLE_NULL(1), + SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS(). + SLE_VAR(Cheats, no_jetcrash.been_used, SLE_BOOL), + SLE_VAR(Cheats, no_jetcrash.value, SLE_BOOL), + SLE_NULL(1), + SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS(). + SLE_VAR(Cheats, change_date.been_used, SLE_BOOL), + SLE_VAR(Cheats, change_date.value, SLE_BOOL), + SLE_VAR(Cheats, setup_prod.been_used, SLE_BOOL), + SLE_VAR(Cheats, setup_prod.value, SLE_BOOL), + SLE_NULL(1), + SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS(). + SLE_VAR(Cheats, edit_max_hl.been_used, SLE_BOOL), + SLE_VAR(Cheats, edit_max_hl.value, SLE_BOOL), +}; + /** * Save the cheat values. */ static void Save_CHTS() { - /* Cannot use lengthof because _cheats is of type Cheats, not Cheat */ - byte count = sizeof(_cheats) / sizeof(Cheat); - Cheat *cht = (Cheat*) &_cheats; - Cheat *cht_last = &cht[count]; - - SlSetLength(count * 2); - for (; cht != cht_last; cht++) { - SlWriteByte(cht->been_used); - SlWriteByte(cht->value); - } + SlSetLength(std::size(_cheats_desc)); + SlObject(&_cheats, _cheats_desc); } /** @@ -36,15 +53,21 @@ static void Save_CHTS() */ static void Load_CHTS() { - Cheat *cht = (Cheat*)&_cheats; - size_t count = SlGetFieldLength() / 2; - /* Cannot use lengthof because _cheats is of type Cheats, not Cheat */ - if (count > sizeof(_cheats) / sizeof(Cheat)) SlErrorCorrupt("Too many cheat values"); + size_t count = SlGetFieldLength(); + std::vector slt; - for (uint i = 0; i < count; i++) { - cht[i].been_used = (SlReadByte() != 0); - cht[i].value = (SlReadByte() != 0); + /* Cheats were added over the years without a savegame bump. They are + * stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs + * are stored for this savegame. So read only "count" SLE_BOOLs (and in + * result "count / 2" cheats). */ + for (auto &sld : _cheats_desc) { + count--; + slt.push_back(sld); + + if (count == 0) break; } + + SlObject(&_cheats, slt); } /** Chunk handlers related to cheats. */ From 37ae6b8ae3762ddccdeb96a178b2634791e2bbe0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 10 Jun 2021 19:34:53 +0200 Subject: [PATCH 325/800] Add: adhere the autosave_on_exit setting for Null videodriver (#9343) This is especially useful for automated-testing, to make a save when the game quits while using "-vnull:ticks=N". --- src/video/null_v.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/video/null_v.cpp b/src/video/null_v.cpp index 4f7843b75a..e4f4ecf472 100644 --- a/src/video/null_v.cpp +++ b/src/video/null_v.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../gfx_func.h" #include "../blitter/factory.hpp" +#include "../saveload/saveload.h" #include "../window_func.h" #include "null_v.h" @@ -52,6 +53,12 @@ void VideoDriver_Null::MainLoop() ::InputLoop(); ::UpdateWindows(); } + + /* If requested, make a save just before exit. The normal exit-flow is + * not triggered from this driver, so we have to do this manually. */ + if (_settings_client.gui.autosave_on_exit) { + DoExitSave(); + } } bool VideoDriver_Null::ChangeResolution(int w, int h) { return false; } From 6bb3f034e4788b67c7c3b4c8cf4a5de44c8644d0 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 12:32:59 +0200 Subject: [PATCH 326/800] Cleanup: [ContentInfo] Remove unused function --- src/network/core/tcp_content.cpp | 16 ---------------- src/network/core/tcp_content_type.h | 1 - 2 files changed, 17 deletions(-) diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index a53a352c28..abeb3d9255 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -48,22 +48,6 @@ void ContentInfo::TransferFrom(ContentInfo *other) } } -/** - * Get the size of the data as send over the network. - * @return the size. - */ -size_t ContentInfo::Size() const -{ - size_t len = 0; - for (uint i = 0; i < this->tag_count; i++) len += strlen(this->tags[i]) + 1; - - /* The size is never larger than the content info size plus the size of the - * tags and dependencies */ - return sizeof(*this) + - sizeof(this->dependency_count) + - sizeof(*this->dependencies) * this->dependency_count; -} - /** * Is the state either selected or autoselected? * @return true iff that's the case diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 4dc20f46bb..739cf1379f 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -79,7 +79,6 @@ struct ContentInfo { void TransferFrom(ContentInfo *other); - size_t Size() const; bool IsSelected() const; bool IsValid() const; const char *GetTextfile(TextfileType type) const; From dfb89f3891ec73b4d5a6f46092ad825dabec6bb7 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 12:41:45 +0200 Subject: [PATCH 327/800] Codechange: [ContentInfo] Do not use memset/memcpy to make it possible to use vector/string --- src/network/core/tcp_content.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index abeb3d9255..ddea9fd5ea 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -22,8 +22,11 @@ /** Clear everything in the struct */ ContentInfo::ContentInfo() + : /* Temporary... will be removed later in the PR. */ + type((ContentType)0), id((ContentID)0), filesize(0), filename(""), name(""), version(""), + url(""), description(""), unique_id(0), md5sum(""), dependency_count(0), dependencies(nullptr), + tag_count(0), tags(nullptr), state((State)0), upgrade(false) { - memset(this, 0, sizeof(*this)); } /** Free everything allocated */ @@ -42,7 +45,7 @@ void ContentInfo::TransferFrom(ContentInfo *other) if (other != this) { free(this->dependencies); free(this->tags); - memcpy(this, other, sizeof(ContentInfo)); + *this = *other; other->dependencies = nullptr; other->tags = nullptr; } From 9c424ab741218238205e8d1f2644a3912fda250a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 12:47:50 +0200 Subject: [PATCH 328/800] Codechange: [ContentInfo] Use StringList for tags instead of custom allocations --- src/network/core/config.h | 1 + src/network/core/tcp_content.cpp | 6 ++---- src/network/core/tcp_content_type.h | 3 +-- src/network/network_content.cpp | 6 +++--- src/network/network_content_gui.cpp | 11 +++++------ 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/network/core/config.h b/src/network/core/config.h index cacc907faf..ce614188dd 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -65,6 +65,7 @@ static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maxim static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU-3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes) static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0' +static const uint NETWORK_CONTENT_TAG_LENGTH = 32; ///< The maximum length of a content's tag, in bytes including '\0'. static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index ddea9fd5ea..041e932e4e 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -25,7 +25,7 @@ ContentInfo::ContentInfo() : /* Temporary... will be removed later in the PR. */ type((ContentType)0), id((ContentID)0), filesize(0), filename(""), name(""), version(""), url(""), description(""), unique_id(0), md5sum(""), dependency_count(0), dependencies(nullptr), - tag_count(0), tags(nullptr), state((State)0), upgrade(false) + state((State)0), upgrade(false) { } @@ -33,7 +33,6 @@ ContentInfo::ContentInfo() ContentInfo::~ContentInfo() { free(this->dependencies); - free(this->tags); } /** @@ -44,10 +43,9 @@ void ContentInfo::TransferFrom(ContentInfo *other) { if (other != this) { free(this->dependencies); - free(this->tags); *this = *other; other->dependencies = nullptr; - other->tags = nullptr; + other->tags.clear(); } } diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 739cf1379f..93367746db 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -69,8 +69,7 @@ struct ContentInfo { byte md5sum[16]; ///< The MD5 checksum uint8 dependency_count; ///< Number of dependencies ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids) - uint8 tag_count; ///< Number of tags - char (*tags)[32]; ///< Malloced array of tags (strings) + StringList tags; ///< Tags associated with the content State state; ///< Whether the content info is selected (for download) bool upgrade; ///< This item is an upgrade diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index f78a839b81..27ffee9706 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -70,9 +70,9 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) ci->dependencies = MallocT(ci->dependency_count); for (uint i = 0; i < ci->dependency_count; i++) ci->dependencies[i] = (ContentID)p->Recv_uint32(); - ci->tag_count = p->Recv_uint8(); - ci->tags = MallocT(ci->tag_count); - for (uint i = 0; i < ci->tag_count; i++) p->Recv_string(ci->tags[i], lengthof(*ci->tags)); + uint tag_count = p->Recv_uint8(); + ci->tags.reserve(tag_count); + for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p->Recv_string(NETWORK_CONTENT_TAG_LENGTH)); if (!ci->IsValid()) { delete ci; diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index a74d902a3c..a617f4e499 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -443,9 +443,8 @@ class NetworkContentListWindow : public Window, ContentCallback { static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter) { filter.string_filter.ResetState(); - for (int i = 0; i < (*a)->tag_count; i++) { - filter.string_filter.AddLine((*a)->tags[i]); - } + for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag.c_str()); + filter.string_filter.AddLine((*a)->name); return filter.string_filter.GetState(); } @@ -747,12 +746,12 @@ public: y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES); } - if (this->selected->tag_count != 0) { + if (!this->selected->tags.empty()) { /* List all tags */ char buf[DRAW_STRING_BUFFER] = ""; char *p = buf; - for (uint i = 0; i < this->selected->tag_count; i++) { - p += seprintf(p, lastof(buf), i == 0 ? "%s" : ", %s", this->selected->tags[i]); + for (auto &tag : this->selected->tags) { + p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", tag.c_str()); } SetDParamStr(0, buf); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS); From df181bb641a75e9fae557c683b790cfba961ec5a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 12:53:42 +0200 Subject: [PATCH 329/800] Codechange: [ContentInfo] Use a vector for dependencies instead of custom allocation --- src/network/core/tcp_content.cpp | 6 ++---- src/network/core/tcp_content_type.h | 3 +-- src/network/network_content.cpp | 22 +++++++++++----------- src/network/network_content_gui.cpp | 6 ++---- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index 041e932e4e..fb726e2e7c 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -24,7 +24,7 @@ ContentInfo::ContentInfo() : /* Temporary... will be removed later in the PR. */ type((ContentType)0), id((ContentID)0), filesize(0), filename(""), name(""), version(""), - url(""), description(""), unique_id(0), md5sum(""), dependency_count(0), dependencies(nullptr), + url(""), description(""), unique_id(0), md5sum(""), state((State)0), upgrade(false) { } @@ -32,7 +32,6 @@ ContentInfo::ContentInfo() /** Free everything allocated */ ContentInfo::~ContentInfo() { - free(this->dependencies); } /** @@ -42,9 +41,8 @@ ContentInfo::~ContentInfo() void ContentInfo::TransferFrom(ContentInfo *other) { if (other != this) { - free(this->dependencies); *this = *other; - other->dependencies = nullptr; + other->dependencies.clear(); other->tags.clear(); } } diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 93367746db..2186997e8e 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -67,8 +67,7 @@ struct ContentInfo { char description[512]; ///< Description of the content uint32 unique_id; ///< Unique ID; either GRF ID or shortname byte md5sum[16]; ///< The MD5 checksum - uint8 dependency_count; ///< Number of dependencies - ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids) + std::vector dependencies; ///< The dependencies (unique server side ids) StringList tags; ///< Tags associated with the content State state; ///< Whether the content info is selected (for download) bool upgrade; ///< This item is an upgrade diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 27ffee9706..37df60877a 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -66,9 +66,9 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) ci->md5sum[j] = p->Recv_uint8(); } - ci->dependency_count = p->Recv_uint8(); - ci->dependencies = MallocT(ci->dependency_count); - for (uint i = 0; i < ci->dependency_count; i++) ci->dependencies[i] = (ContentID)p->Recv_uint32(); + uint dependency_count = p->Recv_uint8(); + ci->dependencies.reserve(dependency_count); + for (uint i = 0; i < dependency_count; i++) ci->dependencies.push_back((ContentID)p->Recv_uint32()); uint tag_count = p->Recv_uint8(); ci->tags.reserve(tag_count); @@ -927,8 +927,8 @@ void ClientNetworkContentSocketHandler::ReverseLookupDependency(ConstContentVect for (const ContentInfo *ci : this->infos) { if (ci == child) continue; - for (uint i = 0; i < ci->dependency_count; i++) { - if (ci->dependencies[i] == child->id) { + for (auto &dependency : ci->dependencies) { + if (dependency == child->id) { parents.push_back(ci); break; } @@ -969,10 +969,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci) /* Selection is easy; just walk all children and set the * autoselected state. That way we can see what we automatically * selected and thus can unselect when a dependency is removed. */ - for (uint i = 0; i < ci->dependency_count; i++) { - ContentInfo *c = this->GetContent(ci->dependencies[i]); + for (auto &dependency : ci->dependencies) { + ContentInfo *c = this->GetContent(dependency); if (c == nullptr) { - this->DownloadContentInfo(ci->dependencies[i]); + this->DownloadContentInfo(dependency); } else if (c->state == ContentInfo::UNSELECTED) { c->state = ContentInfo::AUTOSELECTED; this->CheckDependencyState(c); @@ -995,10 +995,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci) this->Unselect(c->id); } - for (uint i = 0; i < ci->dependency_count; i++) { - const ContentInfo *c = this->GetContent(ci->dependencies[i]); + for (auto &dependency : ci->dependencies) { + const ContentInfo *c = this->GetContent(dependency); if (c == nullptr) { - DownloadContentInfo(ci->dependencies[i]); + DownloadContentInfo(dependency); continue; } if (c->state != ContentInfo::AUTOSELECTED) continue; diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index a617f4e499..5a03561c9c 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -725,13 +725,11 @@ public: SetDParam(0, this->selected->filesize); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_FILESIZE); - if (this->selected->dependency_count != 0) { + if (!this->selected->dependencies.empty()) { /* List dependencies */ char buf[DRAW_STRING_BUFFER] = ""; char *p = buf; - for (uint i = 0; i < this->selected->dependency_count; i++) { - ContentID cid = this->selected->dependencies[i]; - + for (auto &cid : this->selected->dependencies) { /* Try to find the dependency */ ConstContentIterator iter = _network_content_client.Begin(); for (; iter != _network_content_client.End(); iter++) { From e3717ae903cb770ae2ebc4abe45fa0cc77326409 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 13:02:44 +0200 Subject: [PATCH 330/800] Codechange: [ContentInfo] Use std::string instead of string buffers --- src/console_cmds.cpp | 4 ++-- src/network/core/config.h | 5 +++++ src/network/core/tcp_content_type.h | 10 +++++----- src/network/network_content.cpp | 14 +++++++------- src/network/network_content_gui.cpp | 20 ++++++++++---------- src/newgrf_gui.cpp | 2 +- 6 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 3c5ca5d24b..7a756a657a 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1812,7 +1812,7 @@ static void OutputContentState(const ContentInfo *const ci) char buf[sizeof(ci->md5sum) * 2 + 1]; md5sumToString(buf, lastof(buf), ci->md5sum); - IConsolePrintF(state_to_colour[ci->state], "%d, %s, %s, %s, %08X, %s", ci->id, types[ci->type - 1], states[ci->state], ci->name, ci->unique_id, buf); + IConsolePrintF(state_to_colour[ci->state], "%d, %s, %s, %s, %08X, %s", ci->id, types[ci->type - 1], states[ci->state], ci->name.c_str(), ci->unique_id, buf); } DEF_CONSOLE_CMD(ConContent) @@ -1882,7 +1882,7 @@ DEF_CONSOLE_CMD(ConContent) if (strcasecmp(argv[1], "state") == 0) { IConsolePrintF(CC_WHITE, "id, type, state, name"); for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) { - if (argc > 2 && strcasestr((*iter)->name, argv[2]) == nullptr) continue; + if (argc > 2 && strcasestr((*iter)->name.c_str(), argv[2]) == nullptr) continue; OutputContentState(*iter); } return true; diff --git a/src/network/core/config.h b/src/network/core/config.h index ce614188dd..6d6038ec75 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -65,6 +65,11 @@ static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maxim static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU-3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes) static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0' +static const uint NETWORK_CONTENT_FILENAME_LENGTH = 48; ///< The maximum length of a content's filename, in bytes including '\0'. +static const uint NETWORK_CONTENT_NAME_LENGTH = 32; ///< The maximum length of a content's name, in bytes including '\0'. +static const uint NETWORK_CONTENT_VERSION_LENGTH = 16; ///< The maximum length of a content's version, in bytes including '\0'. +static const uint NETWORK_CONTENT_URL_LENGTH = 96; ///< The maximum length of a content's url, in bytes including '\0'. +static const uint NETWORK_CONTENT_DESC_LENGTH = 512; ///< The maximum length of a content's description, in bytes including '\0'. static const uint NETWORK_CONTENT_TAG_LENGTH = 32; ///< The maximum length of a content's tag, in bytes including '\0'. static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 2186997e8e..25097c3ab1 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -60,11 +60,11 @@ struct ContentInfo { ContentType type; ///< Type of content ContentID id; ///< Unique (server side) ID for the content uint32 filesize; ///< Size of the file - char filename[48]; ///< Filename (for the .tar.gz; only valid on download) - char name[32]; ///< Name of the content - char version[16]; ///< Version of the content - char url[96]; ///< URL related to the content - char description[512]; ///< Description of the content + std::string filename; ///< Filename (for the .tar.gz; only valid on download) + std::string name; ///< Name of the content + std::string version; ///< Version of the content + std::string url; ///< URL related to the content + std::string description; ///< Description of the content uint32 unique_id; ///< Unique ID; either GRF ID or shortname byte md5sum[16]; ///< The MD5 checksum std::vector dependencies; ///< The dependencies (unique server side ids) diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 37df60877a..f85c942afd 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -56,10 +56,10 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) ci->id = (ContentID)p->Recv_uint32(); ci->filesize = p->Recv_uint32(); - p->Recv_string(ci->name, lengthof(ci->name)); - p->Recv_string(ci->version, lengthof(ci->version)); - p->Recv_string(ci->url, lengthof(ci->url)); - p->Recv_string(ci->description, lengthof(ci->description), SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); + ci->name = p->Recv_string(NETWORK_CONTENT_NAME_LENGTH); + ci->version = p->Recv_string(NETWORK_CONTENT_VERSION_LENGTH); + ci->url = p->Recv_string(NETWORK_CONTENT_URL_LENGTH); + ci->description = p->Recv_string(NETWORK_CONTENT_DESC_LENGTH, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); ci->unique_id = p->Recv_uint32(); for (uint j = 0; j < sizeof(ci->md5sum); j++) { @@ -143,7 +143,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) if (ici->type == ci->type && ici->unique_id == ci->unique_id && memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) { /* Preserve the name if possible */ - if (StrEmpty(ci->name)) strecpy(ci->name, ici->name, lastof(ci->name)); + if (ci->name.empty()) ci->name = ici->name; if (ici->IsSelected()) ci->state = ici->state; /* @@ -485,7 +485,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) this->curInfo->type = (ContentType)p->Recv_uint8(); this->curInfo->id = (ContentID)p->Recv_uint32(); this->curInfo->filesize = p->Recv_uint32(); - p->Recv_string(this->curInfo->filename, lengthof(this->curInfo->filename)); + this->curInfo->filename = p->Recv_string(NETWORK_CONTENT_FILENAME_LENGTH); if (!this->BeforeDownload()) { this->CloseConnection(); @@ -704,7 +704,7 @@ void ClientNetworkContentSocketHandler::OnReceiveData(const char *data, size_t l } /* Copy the string, without extension, to the filename. */ - strecpy(this->curInfo->filename, tmp, lastof(this->curInfo->filename)); + this->curInfo->filename = tmp; /* Request the next file. */ if (!this->BeforeDownload()) { diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 5a03561c9c..dfd4370b36 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -147,7 +147,7 @@ void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widge void BaseNetworkContentDownloadStatusWindow::OnDownloadProgress(const ContentInfo *ci, int bytes) { if (ci->id != this->cur_id) { - strecpy(this->name, ci->filename, lastof(this->name)); + strecpy(this->name, ci->filename.c_str(), lastof(this->name)); this->cur_id = ci->id; this->downloaded_files++; } @@ -408,7 +408,7 @@ class NetworkContentListWindow : public Window, ContentCallback { /** Sort content by name. */ static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b) { - return strnatcmp(a->name, b->name, true) < 0; // Sort by name (natural sorting). + return strnatcmp(a->name.c_str(), b->name.c_str(), true) < 0; // Sort by name (natural sorting). } /** Sort content by type. */ @@ -445,7 +445,7 @@ class NetworkContentListWindow : public Window, ContentCallback { filter.string_filter.ResetState(); for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag.c_str()); - filter.string_filter.AddLine((*a)->name); + filter.string_filter.AddLine((*a)->name.c_str()); return filter.string_filter.GetState(); } @@ -703,17 +703,17 @@ public: SetDParamStr(0, this->selected->name); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_NAME); - if (!StrEmpty(this->selected->version)) { + if (!this->selected->version.empty()) { SetDParamStr(0, this->selected->version); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_VERSION); } - if (!StrEmpty(this->selected->description)) { + if (!this->selected->description.empty()) { SetDParamStr(0, this->selected->description); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DESCRIPTION); } - if (!StrEmpty(this->selected->url)) { + if (!this->selected->url.empty()) { SetDParamStr(0, this->selected->url); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL); } @@ -736,7 +736,7 @@ public: const ContentInfo *ci = *iter; if (ci->id != cid) continue; - p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name); + p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name.c_str()); break; } } @@ -765,7 +765,7 @@ public: for (const ContentInfo *ci : tree) { if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue; - p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name); + p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name.c_str()); } if (p != buf) { SetDParamStr(0, buf); @@ -842,7 +842,7 @@ public: case WID_NCL_OPEN_URL: if (this->selected != nullptr) { extern void OpenBrowser(const char *url); - OpenBrowser(this->selected->url); + OpenBrowser(this->selected->url.c_str()); } break; @@ -983,7 +983,7 @@ public: this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0); this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all); this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade); - this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || StrEmpty(this->selected->url)); + this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || this->selected->url.empty()); for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr); } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index f017cbf7f9..1b7ab44f6c 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1550,7 +1550,7 @@ void ShowMissingContentWindow(const GRFConfig *list) ContentInfo *ci = new ContentInfo(); ci->type = CONTENT_TYPE_NEWGRF; ci->state = ContentInfo::DOES_NOT_EXIST; - strecpy(ci->name, c->GetName(), lastof(ci->name)); + ci->name = c->GetName(); ci->unique_id = BSWAP32(c->ident.grfid); memcpy(ci->md5sum, HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum, sizeof(ci->md5sum)); cv.push_back(ci); From e2417193c9dbe8a7ecf00521bed7bf6c3fb573fc Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 13:12:00 +0200 Subject: [PATCH 331/800] Cleanup: [ContentInfo] Remove some functions that are not needed anymore --- src/network/core/tcp_content.cpp | 27 ----------------------- src/network/core/tcp_content_type.h | 34 +++++++++++++---------------- src/network/network_content.cpp | 3 +-- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index fb726e2e7c..84c82ead12 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -20,33 +20,6 @@ #include "../../safeguards.h" -/** Clear everything in the struct */ -ContentInfo::ContentInfo() - : /* Temporary... will be removed later in the PR. */ - type((ContentType)0), id((ContentID)0), filesize(0), filename(""), name(""), version(""), - url(""), description(""), unique_id(0), md5sum(""), - state((State)0), upgrade(false) -{ -} - -/** Free everything allocated */ -ContentInfo::~ContentInfo() -{ -} - -/** - * Copy data from other #ContentInfo and take ownership of allocated stuff. - * @param other Source to copy from. #dependencies and #tags will be NULLed. - */ -void ContentInfo::TransferFrom(ContentInfo *other) -{ - if (other != this) { - *this = *other; - other->dependencies.clear(); - other->tags.clear(); - } -} - /** * Is the state either selected or autoselected? * @return true iff that's the case diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 25097c3ab1..5daae39dc6 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -26,6 +26,7 @@ enum ContentType { CONTENT_TYPE_GAME = 9, ///< The content consists of a game script CONTENT_TYPE_GAME_LIBRARY = 10, ///< The content consists of a GS library CONTENT_TYPE_END, ///< Helper to mark the end of the types + INVALID_CONTENT_TYPE = 0xFF, ///< Invalid/uninitialized content }; /** Enum with all types of TCP content packets. The order MUST not be changed **/ @@ -57,25 +58,20 @@ struct ContentInfo { INVALID, ///< The content's invalid }; - ContentType type; ///< Type of content - ContentID id; ///< Unique (server side) ID for the content - uint32 filesize; ///< Size of the file - std::string filename; ///< Filename (for the .tar.gz; only valid on download) - std::string name; ///< Name of the content - std::string version; ///< Version of the content - std::string url; ///< URL related to the content - std::string description; ///< Description of the content - uint32 unique_id; ///< Unique ID; either GRF ID or shortname - byte md5sum[16]; ///< The MD5 checksum - std::vector dependencies; ///< The dependencies (unique server side ids) - StringList tags; ///< Tags associated with the content - State state; ///< Whether the content info is selected (for download) - bool upgrade; ///< This item is an upgrade - - ContentInfo(); - ~ContentInfo(); - - void TransferFrom(ContentInfo *other); + ContentType type = INVALID_CONTENT_TYPE; ///< Type of content + ContentID id = INVALID_CONTENT_ID; ///< Unique (server side) ID for the content + uint32 filesize = 0; ///< Size of the file + std::string filename; ///< Filename (for the .tar.gz; only valid on download) + std::string name; ///< Name of the content + std::string version; ///< Version of the content + std::string url; ///< URL related to the content + std::string description; ///< Description of the content + uint32 unique_id = 0; ///< Unique ID; either GRF ID or shortname + byte md5sum[16] = {0}; ///< The MD5 checksum + std::vector dependencies; ///< The dependencies (unique server side ids) + StringList tags; ///< Tags associated with the content + State state = State::UNSELECTED; ///< Whether the content info is selected (for download) + bool upgrade = false; ///< This item is an upgrade bool IsSelected() const; bool IsValid() const; diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index f85c942afd..eff54885de 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -150,9 +150,8 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) * As ici might be selected by the content window we cannot delete that. * However, we want to keep most of the values of ci, except the values * we (just) already preserved. - * So transfer data and ownership of allocated memory from ci to ici. */ - ici->TransferFrom(ci); + *ici = *ci; delete ci; this->OnReceiveContentInfo(ici); From 849a10520cc26a98d91981a7705775a2481beef2 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 10 Jun 2021 20:11:50 +0200 Subject: [PATCH 332/800] Change: allow pause/unpause console command in single player too (#9342) --- src/console_cmds.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 7a756a657a..b5c1748ab8 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -160,11 +160,24 @@ DEF_CONSOLE_HOOK(ConHookNoNetwork) return CHR_ALLOW; } +/** + * Check if are either in singleplayer or a server. + * @return True iff we are either in singleplayer or a server. + */ +DEF_CONSOLE_HOOK(ConHookServerOrNoNetwork) +{ + if (_networking && !_network_server) { + if (echo) IConsoleError("This command is only available to a network server."); + return CHR_DISALLOW; + } + return CHR_ALLOW; +} + DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperTool) { if (_settings_client.gui.newgrf_developer_tools) { if (_game_mode == GM_MENU) { - if (echo) IConsoleError("This command is only available in game and editor."); + if (echo) IConsoleError("This command is only available in-game and in the editor."); return CHR_DISALLOW; } return ConHookNoNetwork(echo); @@ -209,7 +222,7 @@ DEF_CONSOLE_CMD(ConResetEnginePool) } if (_game_mode == GM_MENU) { - IConsoleError("This command is only available in game and editor."); + IConsoleError("This command is only available in-game and in the editor."); return true; } @@ -622,6 +635,11 @@ DEF_CONSOLE_CMD(ConPauseGame) return true; } + if (_game_mode == GM_MENU) { + IConsoleError("This command is only available in-game and in the editor."); + return true; + } + if ((_pause_mode & PM_PAUSED_NORMAL) == PM_UNPAUSED) { DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE); if (!_networking) IConsolePrint(CC_DEFAULT, "Game paused."); @@ -639,6 +657,11 @@ DEF_CONSOLE_CMD(ConUnpauseGame) return true; } + if (_game_mode == GM_MENU) { + IConsoleError("This command is only available in-game and in the editor."); + return true; + } + if ((_pause_mode & PM_PAUSED_NORMAL) != PM_UNPAUSED) { DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); if (!_networking) IConsolePrint(CC_DEFAULT, "Game unpaused."); @@ -2393,8 +2416,8 @@ void IConsoleStdLibRegister() IConsole::CmdRegister("unban", ConUnBan, ConHookServerOnly); IConsole::CmdRegister("banlist", ConBanList, ConHookServerOnly); - IConsole::CmdRegister("pause", ConPauseGame, ConHookServerOnly); - IConsole::CmdRegister("unpause", ConUnpauseGame, ConHookServerOnly); + IConsole::CmdRegister("pause", ConPauseGame, ConHookServerOrNoNetwork); + IConsole::CmdRegister("unpause", ConUnpauseGame, ConHookServerOrNoNetwork); IConsole::CmdRegister("company_pw", ConCompanyPassword, ConHookNeedNetwork); IConsole::AliasRegister("company_password", "company_pw %+"); From ab9b937ab7a80562b88d72ec17c6b2a6b3ed2b61 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 13:34:58 +0200 Subject: [PATCH 333/800] Codechange: [Network] Use std::string to get a NewGRF's name --- src/network/network_udp.cpp | 5 ++--- src/newgrf_text.cpp | 4 ++-- src/newgrf_text.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 0da5a8b260..a0d9ae136c 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -415,15 +415,14 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd if (num_grfs > NETWORK_MAX_GRF_COUNT) return; for (i = 0; i < num_grfs; i++) { - char name[NETWORK_GRF_NAME_LENGTH]; GRFIdentifier c; DeserializeGRFIdentifier(p, &c); - p->Recv_string(name, sizeof(name)); + std::string name = p->Recv_string(NETWORK_GRF_NAME_LENGTH); /* An empty name is not possible under normal circumstances * and causes problems when showing the NewGRF list. */ - if (StrEmpty(name)) continue; + if (name.empty()) continue; /* Try to find the GRFTextWrapper for the name of this GRF ID and MD5sum tuple. * If it exists and not resolved yet, then name of the fake GRF is diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index f1fac8b510..2bb8fd6365 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -539,10 +539,10 @@ void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allo * @param list The list where the text should be added to. * @param text_to_add The text to add to the list. */ -void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add) +void AddGRFTextToList(GRFTextWrapper &list, const std::string &text_to_add) { if (!list) list.reset(new GRFTextList()); - AddGRFTextToList(*list, GRFLX_UNSPECIFIED, std::string(text_to_add)); + AddGRFTextToList(*list, GRFLX_UNSPECIFIED, text_to_add); } /** diff --git a/src/newgrf_text.h b/src/newgrf_text.h index 2c7eb731db..dc33710a43 100644 --- a/src/newgrf_text.h +++ b/src/newgrf_text.h @@ -42,7 +42,7 @@ void SetCurrentGrfLangID(byte language_id); std::string TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const std::string &str, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID); void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add); void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add); -void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add); +void AddGRFTextToList(GRFTextWrapper &list, const std::string &text_to_add); bool CheckGrfLangID(byte lang_id, byte grf_version); From bb8fd007605c17c4f96fdda75e3d2780b8944faf Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 13:36:07 +0200 Subject: [PATCH 334/800] Cleanup: [Network] Remove C-string Recv_string and its last use --- src/network/core/packet.cpp | 31 ------------------------------- src/network/core/packet.h | 1 - src/network/network_server.cpp | 6 ++---- 3 files changed, 2 insertions(+), 36 deletions(-) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index c27a37d461..737b4624c9 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -366,37 +366,6 @@ uint64 Packet::Recv_uint64() return n; } -/** - * Reads a string till it finds a '\0' in the stream. - * @param buffer The buffer to put the data into. - * @param size The size of the buffer. - * @param settings The string validation settings. - */ -void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings) -{ - char *bufp = buffer; - const char *last = buffer + size - 1; - - /* Don't allow reading from a closed socket */ - if (cs->HasClientQuit()) return; - - size_t pos = this->pos; - while (--size > 0 && pos < this->Size() && (*buffer++ = this->buffer[pos++]) != '\0') {} - - if (size == 0 || pos == this->Size()) { - *buffer = '\0'; - /* If size was sooner to zero then the string in the stream - * skip till the \0, so than packet can be read out correctly for the rest */ - while (pos < this->Size() && this->buffer[pos] != '\0') pos++; - pos++; - } - - assert(pos <= std::numeric_limits::max()); - this->pos = static_cast(pos); - - StrMakeValidInPlace(bufp, last, settings); -} - /** * Reads characters (bytes) from the packet until it finds a '\0', or reaches a * maximum of \c length characters. diff --git a/src/network/core/packet.h b/src/network/core/packet.h index 21a88e3ea9..277ff8bba1 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -87,7 +87,6 @@ public: uint16 Recv_uint16(); uint32 Recv_uint32(); uint64 Recv_uint64(); - void Recv_string(char *buffer, size_t size, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); std::string Recv_string(size_t length, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); size_t RemainingBytesToTransfer() const; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 5b1da8fa2a..9b9dc6fc91 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -874,13 +874,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); } - char client_revision[NETWORK_REVISION_LENGTH]; - - p->Recv_string(client_revision, sizeof(client_revision)); + std::string client_revision = p->Recv_string(NETWORK_REVISION_LENGTH); uint32 newgrf_version = p->Recv_uint32(); /* Check if the client has revision control enabled */ - if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) { + if (!IsNetworkCompatibleVersion(client_revision.c_str()) || _openttd_newgrf_version != newgrf_version) { /* Different revisions!! */ return this->SendError(NETWORK_ERROR_WRONG_REVISION); } From 2924ac48c5013acf18b7577de4f610612d88dd6c Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Fri, 4 Jun 2021 18:59:13 +0200 Subject: [PATCH 335/800] Fix: [Script] Ensure the saved script strings are properly validated and terminated when being read from the savegame --- src/script/script_instance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index 24dbb9c395..7c2fa43d67 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -569,8 +569,9 @@ bool ScriptInstance::IsPaused() case SQSL_STRING: { SlObject(nullptr, _script_byte); - static char buf[256]; + static char buf[std::numeric_limits::max()]; SlArray(buf, _script_sl_byte, SLE_CHAR); + StrMakeValidInPlace(buf, buf + _script_sl_byte); if (vm != nullptr) sq_pushstring(vm, buf, -1); return true; } From 076f3d26c238a9443b367629ab97dc1a5cf9b931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Thu, 10 Jun 2021 22:14:08 +0200 Subject: [PATCH 336/800] Fix #9329: [CMake] FindVersion.cmake relied on internal cmake variable (#9330) --- CMakeLists.txt | 1 + cmake/scripts/FindVersion.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d060ffbbff..6cc2f7e2a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ add_custom_target(find_version -DREV_MAJOR=${PROJECT_VERSION_MAJOR} -DREV_MINOR=${PROJECT_VERSION_MINOR} -DREV_BUILD=${PROJECT_VERSION_PATCH} + -DWINDOWS=${WIN32} -P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} BYPRODUCTS ${GENERATED_SOURCE_FILES} diff --git a/cmake/scripts/FindVersion.cmake b/cmake/scripts/FindVersion.cmake index 6e4a2b3909..43255e8011 100644 --- a/cmake/scripts/FindVersion.cmake +++ b/cmake/scripts/FindVersion.cmake @@ -138,7 +138,7 @@ else() configure_file("${CMAKE_SOURCE_DIR}/src/rev.cpp.in" "${FIND_VERSION_BINARY_DIR}/rev.cpp") - if(WIN32) + if(WINDOWS) message(STATUS "Generating ottdres.rc") configure_file("${CMAKE_SOURCE_DIR}/src/os/windows/ottdres.rc.in" "${FIND_VERSION_BINARY_DIR}/ottdres.rc") From ed3946e295f0e74880d85ffb6f6a933ca87e460d Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 10 Jun 2021 23:13:34 +0200 Subject: [PATCH 337/800] Add: '-X' option to ignore global folders in the search path (#9341) This is extreme useful for automated testing. Without this, OpenTTD will always look in your personal-dir (like ~/.local/share/openttd or %USER%\Documents\OpenTTD). For most users this is exactly what we want, that there is a shared place for all their files. However, for automated testing this is rather annoying, as your local development files influence the automated test. As such, '-X' counters this, and only gives the local folders. This is especially useful in combination with '-x' and '-c'. --- src/fileio.cpp | 29 +++++++++++++++++++++++++---- src/fileio_func.h | 2 +- src/openttd.cpp | 10 +++++++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index bd05a4e7d5..c958684dd7 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -79,10 +79,22 @@ static bool IsValidSearchPath(Searchpath sp) return sp < _searchpaths.size() && !_searchpaths[sp].empty(); } -static void FillValidSearchPaths() +static void FillValidSearchPaths(bool only_local_path) { _valid_searchpaths.clear(); for (Searchpath sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) { + if (only_local_path) { + switch (sp) { + case SP_WORKING_DIR: // Can be influence by "-c" option. + case SP_BINARY_DIR: // Most likely contains all the language files. + case SP_AUTODOWNLOAD_DIR: // Otherwise we cannot download in-game content. + break; + + default: + continue; + } + } + if (IsValidSearchPath(sp)) _valid_searchpaths.emplace_back(sp); } } @@ -952,11 +964,12 @@ std::string _personal_dir; * fill all other paths (save dir, autosave dir etc) and * make the save and scenario directories. * @param exe the path from the current path to the executable + * @param only_local_path Whether we shouldn't fill searchpaths with global folders. */ -void DeterminePaths(const char *exe) +void DeterminePaths(const char *exe, bool only_local_path) { DetermineBasePaths(exe); - FillValidSearchPaths(); + FillValidSearchPaths(only_local_path); #ifdef USE_XDG std::string config_home; @@ -1023,6 +1036,13 @@ void DeterminePaths(const char *exe) /* We are using the XDG configuration home for the config file, * then store the rest in the XDG data home folder. */ _personal_dir = _searchpaths[SP_PERSONAL_DIR_XDG]; + if (only_local_path) { + /* In case of XDG and we only want local paths and we detected that + * the user either manually indicated the XDG path or didn't use + * "-c" option, we change the working-dir to the XDG personal-dir, + * as this is most likely what the user is expecting. */ + _searchpaths[SP_WORKING_DIR] = _searchpaths[SP_PERSONAL_DIR_XDG]; + } } else #endif { @@ -1047,8 +1067,9 @@ void DeterminePaths(const char *exe) /* If we have network we make a directory for the autodownloading of content */ _searchpaths[SP_AUTODOWNLOAD_DIR] = _personal_dir + "content_download" PATHSEP; + DEBUG(misc, 4, "%s added as search path", _searchpaths[SP_AUTODOWNLOAD_DIR].c_str()); FioCreateDirectory(_searchpaths[SP_AUTODOWNLOAD_DIR]); - FillValidSearchPaths(); + FillValidSearchPaths(only_local_path); /* Create the directory for each of the types of content */ const Subdirectory dirs[] = { SCENARIO_DIR, HEIGHTMAP_DIR, BASESET_DIR, NEWGRF_DIR, AI_DIR, AI_LIBRARY_DIR, GAME_DIR, GAME_LIBRARY_DIR }; diff --git a/src/fileio_func.h b/src/fileio_func.h index baa8cb1bb1..3556849a0f 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -27,7 +27,7 @@ const char *FiosGetScreenshotDir(); void SanitizeFilename(char *filename); void AppendPathSeparator(std::string &buf); -void DeterminePaths(const char *exe); +void DeterminePaths(const char *exe, bool only_local_path); std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize); bool FileExists(const std::string &filename); bool ExtractTar(const std::string &tar_filename, Subdirectory subdir); diff --git a/src/openttd.cpp b/src/openttd.cpp index f39b87c87e..fcd8fcd34b 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -197,6 +197,7 @@ static void ShowHelp() " -M music_set = Force the music set (see below)\n" " -c config_file = Use 'config_file' instead of 'openttd.cfg'\n" " -x = Never save configuration changes to disk\n" + " -X = Don't use global folders to search for files\n" " -q savegame = Write some information about the savegame and exit\n" "\n", lastof(buf) @@ -506,6 +507,7 @@ static const OptionData _options[] = { GETOPT_SHORT_VALUE('G'), GETOPT_SHORT_VALUE('c'), GETOPT_SHORT_NOVAL('x'), + GETOPT_SHORT_NOVAL('X'), GETOPT_SHORT_VALUE('q'), GETOPT_SHORT_NOVAL('h'), GETOPT_END() @@ -530,6 +532,7 @@ int openttd_main(int argc, char *argv[]) std::unique_ptr scanner(new AfterNewGRFScan()); bool dedicated = false; char *debuglog_conn = nullptr; + bool only_local_path = false; extern bool _dedicated_forks; _dedicated_forks = false; @@ -608,7 +611,7 @@ int openttd_main(int argc, char *argv[]) } break; case 'q': { - DeterminePaths(argv[0]); + DeterminePaths(argv[0], only_local_path); if (StrEmpty(mgo.opt)) { ret = 1; return ret; @@ -637,6 +640,7 @@ int openttd_main(int argc, char *argv[]) case 'G': scanner->generation_seed = strtoul(mgo.opt, nullptr, 10); break; case 'c': _config_file = mgo.opt; break; case 'x': scanner->save_config = false; break; + case 'X': only_local_path = true; break; case 'h': i = -2; // Force printing of help. break; @@ -650,7 +654,7 @@ int openttd_main(int argc, char *argv[]) * * The next two functions are needed to list the graphics sets. We can't do them earlier * because then we cannot show it on the debug console as that hasn't been configured yet. */ - DeterminePaths(argv[0]); + DeterminePaths(argv[0], only_local_path); TarScanner::DoScan(TarScanner::BASESET); BaseGraphics::FindSets(); BaseSounds::FindSets(); @@ -659,7 +663,7 @@ int openttd_main(int argc, char *argv[]) return ret; } - DeterminePaths(argv[0]); + DeterminePaths(argv[0], only_local_path); TarScanner::DoScan(TarScanner::BASESET); if (dedicated) DEBUG(net, 3, "Starting dedicated server, version %s", _openttd_revision); From f4c7d5577ed83d426371f86d780aed01c5370953 Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 20 May 2021 18:40:11 +0200 Subject: [PATCH 338/800] Codechange: [WIN32] Use VersionHelpers where appropriate --- src/os/windows/win32.cpp | 32 -------------------------------- src/os/windows/win32.h | 1 - src/sound/win32_s.cpp | 3 ++- src/video/win32_v.cpp | 1 + 4 files changed, 3 insertions(+), 34 deletions(-) diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 3ed0cdb2a7..4478caa650 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -707,38 +707,6 @@ int OTTDStringCompare(const char *s1, const char *s2) return CompareString(MAKELCID(_current_language->winlangid, SORT_DEFAULT), NORM_IGNORECASE, s1_buf, -1, s2_buf, -1); } -/** - * Is the current Windows version Vista or later? - * @return True if the current Windows is Vista or later. - */ -bool IsWindowsVistaOrGreater() -{ - typedef BOOL (WINAPI * LPVERIFYVERSIONINFO)(LPOSVERSIONINFOEX, DWORD, DWORDLONG); - typedef ULONGLONG (NTAPI * LPVERSETCONDITIONMASK)(ULONGLONG, DWORD, BYTE); -#ifdef UNICODE - static LPVERIFYVERSIONINFO _VerifyVersionInfo = (LPVERIFYVERSIONINFO)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerifyVersionInfoW"); -#else - static LPVERIFYVERSIONINFO _VerifyVersionInfo = (LPVERIFYVERSIONINFO)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerifyVersionInfoA"); -#endif - static LPVERSETCONDITIONMASK _VerSetConditionMask = (LPVERSETCONDITIONMASK)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerSetConditionMask"); - - if (_VerifyVersionInfo != nullptr && _VerSetConditionMask != nullptr) { - OSVERSIONINFOEX osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; - DWORDLONG dwlConditionMask = 0; - dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - - osvi.dwMajorVersion = 6; - osvi.dwMinorVersion = 0; - osvi.wServicePackMajor = 0; - - return _VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; - } else { - return LOBYTE(GetVersion()) >= 6; - } -} - #ifdef _MSC_VER /* Based on code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ const DWORD MS_VC_EXCEPTION = 0x406D1388; diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index 095181c46c..b2048375b9 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -25,6 +25,5 @@ wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); void Win32SetCurrentLocaleName(const char *iso_code); int OTTDStringCompare(const char *s1, const char *s2); -bool IsWindowsVistaOrGreater(); #endif /* WIN32_H */ diff --git a/src/sound/win32_s.cpp b/src/sound/win32_s.cpp index eccbb4f42a..87959e5860 100644 --- a/src/sound/win32_s.cpp +++ b/src/sound/win32_s.cpp @@ -17,6 +17,7 @@ #include "win32_s.h" #include #include +#include #include "../os/windows/win32.h" #include "../thread.h" @@ -69,7 +70,7 @@ const char *SoundDriver_Win32::Start(const StringList &parm) wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; /* Limit buffer size to prevent overflows. */ - _bufsize = GetDriverParamInt(parm, "bufsize", (GB(GetVersion(), 0, 8) > 5) ? 8192 : 4096); + _bufsize = GetDriverParamInt(parm, "bufsize", IsWindowsVistaOrGreater() ? 8192 : 4096); _bufsize = std::min(_bufsize, UINT16_MAX); try { diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index f0291db714..7dfc0034a5 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -25,6 +25,7 @@ #include "win32_v.h" #include #include +#include #include "../safeguards.h" From 5d05c4919bd5b5cb9cf1e0123f0c65769e67bd2d Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 20 May 2021 18:28:14 +0200 Subject: [PATCH 339/800] Codechange: [WIN32] Reduce manual dynamic loading as WinXP is the minimum version --- CMakeLists.txt | 2 ++ src/os/windows/crashlog_win.cpp | 23 +++++++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cc2f7e2a9..fe03b5ae11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -360,6 +360,7 @@ if(WIN32) -DUNICODE -D_UNICODE -DWITH_UNISCRIBE + -DPSAPI_VERSION=1 ) target_link_libraries(openttd @@ -367,6 +368,7 @@ if(WIN32) winmm imm32 usp10 + psapi ) endif() diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index a7ff8e4110..0e1d2f8ccd 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "../../safeguards.h" @@ -206,25 +207,19 @@ static char *PrintModuleInfo(char *output, const char *last, HMODULE mod) /* virtual */ char *CrashLogWindows::LogModules(char *output, const char *last) const { MakeCRCTable(AllocaM(uint32, 256)); - BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD); - output += seprintf(output, last, "Module information:\n"); - if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0\0")) { + HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); + if (proc != nullptr) { HMODULE modules[100]; DWORD needed; - BOOL res; + BOOL res = EnumProcessModules(proc, modules, sizeof(modules), &needed); + CloseHandle(proc); + if (res) { + size_t count = std::min(needed / sizeof(HMODULE), lengthof(modules)); - HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); - if (proc != nullptr) { - res = EnumProcessModules(proc, modules, sizeof(modules), &needed); - CloseHandle(proc); - if (res) { - size_t count = std::min(needed / sizeof(HMODULE), lengthof(modules)); - - for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]); - return output + seprintf(output, last, "\n"); - } + for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]); + return output + seprintf(output, last, "\n"); } } output = PrintModuleInfo(output, last, nullptr); From 3ca023998574548fee50ad4c42e0b0996b9f0919 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 19 Feb 2021 23:49:14 +0100 Subject: [PATCH 340/800] Fix: [MinGW32] SHGFP_TYPE_CURRENT is now present in win32api --- src/os/windows/win32.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index b2048375b9..bf88e312a7 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -19,10 +19,6 @@ bool LoadLibraryList(Function proc[], const char *dll); char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); -#if defined(__MINGW32__) && !defined(__MINGW64__) -#define SHGFP_TYPE_CURRENT 0 -#endif /* __MINGW32__ */ - void Win32SetCurrentLocaleName(const char *iso_code); int OTTDStringCompare(const char *s1, const char *s2); From 2df48a78ccf617da3c1b4304353a59adbe51b431 Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 13 May 2021 23:47:08 +0200 Subject: [PATCH 341/800] Fix: [MinGW32] Can't convert lambda to stdcall --- src/video/win32_v.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 7dfc0034a5..9c5714786c 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -914,24 +914,27 @@ void VideoDriver_Win32Base::EditBoxLostFocus() SetCandidatePos(this->main_wnd); } +static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data) +{ + auto &list = *reinterpret_cast*>(data); + + MONITORINFOEX monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monitorInfo); + + DEVMODE devMode = {}; + devMode.dmSize = sizeof(DEVMODE); + devMode.dmDriverExtra = 0; + EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode); + + if (devMode.dmDisplayFrequency != 0) list.push_back(devMode.dmDisplayFrequency); + return true; +} + std::vector VideoDriver_Win32Base::GetListOfMonitorRefreshRates() { std::vector rates = {}; - EnumDisplayMonitors(nullptr, nullptr, [](HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data) -> BOOL { - auto &list = *reinterpret_cast*>(data); - - MONITORINFOEX monitorInfo = {}; - monitorInfo.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(hMonitor, &monitorInfo); - - DEVMODE devMode = {}; - devMode.dmSize = sizeof(DEVMODE); - devMode.dmDriverExtra = 0; - EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode); - - if (devMode.dmDisplayFrequency != 0) list.push_back(devMode.dmDisplayFrequency); - return true; - }, reinterpret_cast(&rates)); + EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, reinterpret_cast(&rates)); return rates; } From b7250a42e1e069b77bf52e76da20e7efea441b05 Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 13 May 2021 23:48:28 +0200 Subject: [PATCH 342/800] Fix: [MinGW32] Linking error --- src/os/windows/crashlog_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 0e1d2f8ccd..1d3ed5193e 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -633,7 +633,7 @@ static void CDECL CustomAbort(int signal) mov safe_esp, esp } # else - asm("movl %esp, _safe_esp"); + asm("movl %%esp, %0" : "=rm" (safe_esp)); # endif _safe_esp = safe_esp; #endif From 00e3fddd0cdff727b7a1c263e86a7238eb3f4780 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 14 May 2021 01:07:18 +0200 Subject: [PATCH 343/800] Fix: [MinGW] Unused squirrel code triggering a warning --- src/3rdparty/squirrel/squirrel/sqfuncstate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp b/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp index c8548bac36..2baca100e0 100644 --- a/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp @@ -79,7 +79,7 @@ SQInstructionDesc g_InstrDesc[]={ {"_OP_NEWSLOTA"}, {"_OP_SCOPE_END"} }; -#endif + void DumpLiteral(SQObjectPtr &o) { switch(type(o)){ @@ -90,6 +90,7 @@ void DumpLiteral(SQObjectPtr &o) default: printf("(%s %p)",GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler } } +#endif SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed) { From 15f66329c28cb0aa3107dbb8da71281b1501be6b Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 14 May 2021 02:15:26 +0200 Subject: [PATCH 344/800] Fix: [MinGW] Silence 2 cast warnings --- src/os/windows/string_uniscribe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index 6c0a9366e9..7c70557b61 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -144,7 +144,7 @@ void UniscribeResetScriptCache(FontSize size) /** Load the matching native Windows font. */ static HFONT HFontFromFont(Font *font) { - if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect((const PLOGFONT)font->fc->GetOSHandle()); + if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect(reinterpret_cast(const_cast(font->fc->GetOSHandle()))); LOGFONT logfont; ZeroMemory(&logfont, sizeof(LOGFONT)); From 744a9e474575af90935807620bff860c02559d76 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 14 May 2021 15:26:03 +0200 Subject: [PATCH 345/800] Codechange: [WIN32] Add a wrapper around GetProcAddress() --- src/os/windows/crashlog_win.cpp | 38 ++++++++++++----------------- src/os/windows/font_win32.cpp | 3 ++- src/os/windows/win32.cpp | 27 ++------------------- src/os/windows/win32.h | 43 +++++++++++++++++++++++++++++++-- src/video/win32_v.cpp | 9 ++++--- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 1d3ed5193e..5ce04e52ed 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -368,22 +368,7 @@ static const uint MAX_FRAMES = 64; char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) const { -#define M(x) x "\0" - static const char dbg_import[] = - M("dbghelp.dll") - M("SymInitialize") - M("SymSetOptions") - M("SymCleanup") - M("StackWalk64") - M("SymFunctionTableAccess64") - M("SymGetModuleBase64") - M("SymGetModuleInfo64") - M("SymGetSymFromAddr64") - M("SymGetLineFromAddr64") - M("") - ; -#undef M - + DllLoader dbghelp(L"dbghelp.dll"); struct ProcPtrs { BOOL (WINAPI * pSymInitialize)(HANDLE, PCSTR, BOOL); BOOL (WINAPI * pSymSetOptions)(DWORD); @@ -394,12 +379,22 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c BOOL (WINAPI * pSymGetModuleInfo64)(HANDLE, DWORD64, PIMAGEHLP_MODULE64); BOOL (WINAPI * pSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); BOOL (WINAPI * pSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); - } proc; + } proc = { + dbghelp.GetProcAddress("SymInitialize"), + dbghelp.GetProcAddress("SymSetOptions"), + dbghelp.GetProcAddress("SymCleanup"), + dbghelp.GetProcAddress("StackWalk64"), + dbghelp.GetProcAddress("SymFunctionTableAccess64"), + dbghelp.GetProcAddress("SymGetModuleBase64"), + dbghelp.GetProcAddress("SymGetModuleInfo64"), + dbghelp.GetProcAddress("SymGetSymFromAddr64"), + dbghelp.GetProcAddress("SymGetLineFromAddr64"), + }; buffer += seprintf(buffer, last, "\nDecoded stack trace:\n"); /* Try to load the functions from the DLL, if that fails because of a too old dbghelp.dll, just skip it. */ - if (LoadLibraryList((Function*)&proc, dbg_import)) { + if (dbghelp.Success()) { /* Initialize symbol handler. */ HANDLE hCur = GetCurrentProcess(); proc.pSymInitialize(hCur, nullptr, TRUE); @@ -486,14 +481,14 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c /* virtual */ int CrashLogWindows::WriteCrashDump(char *filename, const char *filename_last) const { int ret = 0; - HMODULE dbghelp = LoadLibrary(L"dbghelp.dll"); - if (dbghelp != nullptr) { + DllLoader dbghelp(L"dbghelp.dll"); + if (dbghelp.Success()) { typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, CONST PMINIDUMP_EXCEPTION_INFORMATION, CONST PMINIDUMP_USER_STREAM_INFORMATION, CONST PMINIDUMP_CALLBACK_INFORMATION); - MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); + MiniDumpWriteDump_t funcMiniDumpWriteDump = dbghelp.GetProcAddress("MiniDumpWriteDump"); if (funcMiniDumpWriteDump != nullptr) { seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str()); HANDLE file = CreateFile(OTTD2FS(filename).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); @@ -519,7 +514,6 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c } else { ret = -1; } - FreeLibrary(dbghelp); } return ret; } diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 6c4e67deb0..956e4a85c0 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -620,8 +620,9 @@ void LoadWin32Font(FontSize fs) if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { /* Try a nice little undocumented function first for getting the internal font name. * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ + static DllLoader _gdi32(L"gdi32.dll"); typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); - static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(L"Gdi32"), "GetFontResourceInfoW"); + static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetProcAddress("GetFontResourceInfoW"); if (GetFontResourceInfo != nullptr) { /* Try to query an array of LOGFONTs that describe the file. */ diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 4478caa650..7880210087 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -50,30 +50,6 @@ bool MyShowCursor(bool show, bool toggle) return !show; } -/** - * Helper function needed by dynamically loading libraries - */ -bool LoadLibraryList(Function proc[], const char *dll) -{ - while (*dll != '\0') { - HMODULE lib; - lib = LoadLibrary(OTTD2FS(dll).c_str()); - - if (lib == nullptr) return false; - for (;;) { - FARPROC p; - - while (*dll++ != '\0') { /* Nothing */ } - if (*dll == '\0') break; - p = GetProcAddress(lib, dll); - if (p == nullptr) return false; - *proc++ = (Function)p; - } - dll++; - } - return true; -} - void ShowOSErrorBox(const char *buf, bool system) { MyShowCursor(true); @@ -679,7 +655,8 @@ int OTTDStringCompare(const char *s1, const char *s2) #endif if (first_time) { - _CompareStringEx = (PFNCOMPARESTRINGEX)GetProcAddress(GetModuleHandle(L"Kernel32"), "CompareStringEx"); + static DllLoader _kernel32(L"Kernel32.dll"); + _CompareStringEx = _kernel32.GetProcAddress("CompareStringEx"); first_time = false; } diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index bf88e312a7..1d31273308 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -13,8 +13,47 @@ #include bool MyShowCursor(bool show, bool toggle = false); -typedef void (*Function)(int); -bool LoadLibraryList(Function proc[], const char *dll); +class DllLoader { +public: + explicit DllLoader(LPCTSTR filename) + { + this->hmodule = ::LoadLibrary(filename); + if (this->hmodule == nullptr) this->success = false; + } + + + ~DllLoader() + { + ::FreeLibrary(this->hmodule); + } + + bool Success() { return this->success; } + + class ProcAddress { + public: + explicit ProcAddress(void *p) : p(p) {} + + template >> + operator T *() const + { + return reinterpret_cast(this->p); + } + + private: + void *p; + }; + + ProcAddress GetProcAddress(const char *proc_name) + { + void *p = reinterpret_cast(::GetProcAddress(this->hmodule, proc_name)); + if (p == nullptr) this->success = false; + return ProcAddress(p); + } + +private: + HMODULE hmodule = nullptr; + bool success = true; +}; char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 9c5714786c..35a995b99d 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -956,10 +956,11 @@ float VideoDriver_Win32Base::GetDPIScale() static bool init_done = false; if (!init_done) { init_done = true; - - _GetDpiForWindow = (PFNGETDPIFORWINDOW)GetProcAddress(GetModuleHandle(L"User32"), "GetDpiForWindow"); - _GetDpiForSystem = (PFNGETDPIFORSYSTEM)GetProcAddress(GetModuleHandle(L"User32"), "GetDpiForSystem"); - _GetDpiForMonitor = (PFNGETDPIFORMONITOR)GetProcAddress(LoadLibrary(L"Shcore.dll"), "GetDpiForMonitor"); + static DllLoader _user32(L"user32.dll"); + static DllLoader _shcore(L"shcore.dll"); + _GetDpiForWindow = _user32.GetProcAddress("GetDpiForWindow"); + _GetDpiForSystem = _user32.GetProcAddress("GetDpiForSystem"); + _GetDpiForMonitor = _shcore.GetProcAddress("GetDpiForMonitor"); } UINT cur_dpi = 0; From d485b50813f3be6ba0c5ea74e9c7d97f0ef1f5d5 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 14 May 2021 15:41:00 +0200 Subject: [PATCH 346/800] Fix: [MinGW] Ignore wglGetProcAddress() cast warnings --- src/video/win32_v.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 35a995b99d..4afc751afa 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -1265,6 +1265,12 @@ static void LoadWGLExtensions() if (rc != nullptr) { wglMakeCurrent(dc, rc); +#ifdef __MINGW32__ + /* GCC doesn't understand the expected usage of wglGetProcAddress(). */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif /* __MINGW32__ */ + /* Get list of WGL extensions. */ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtensionsStringARB != nullptr) { @@ -1279,6 +1285,9 @@ static void LoadWGLExtensions() } } +#ifdef __MINGW32__ +#pragma GCC diagnostic pop +#endif wglMakeCurrent(nullptr, nullptr); wglDeleteContext(rc); } From c2db408d5d947cd4f3df42754a598226818c519f Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 20 May 2021 19:48:45 +0200 Subject: [PATCH 347/800] Fix aa5a8fe28: [MinGW] Wrong define tested (WIN32 vs _WIN32) --- src/walltime_func.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/walltime_func.h b/src/walltime_func.h index 219a8907de..f070d8e2b9 100644 --- a/src/walltime_func.h +++ b/src/walltime_func.h @@ -17,7 +17,7 @@ struct LocalTimeToStruct { static inline std::tm ToTimeStruct(std::time_t time_since_epoch) { std::tm time = {}; -#ifdef WIN32 +#ifdef _WIN32 /* Windows has swapped the parameters around for localtime_s. */ localtime_s(&time, &time_since_epoch); #else @@ -32,7 +32,7 @@ struct UTCTimeToStruct { static inline std::tm ToTimeStruct(std::time_t time_since_epoch) { std::tm time = {}; -#ifdef WIN32 +#ifdef _WIN32 /* Windows has swapped the parameters around for gmtime_s. */ gmtime_s(&time, &time_since_epoch); #else From d09210e1c6a446ec5a97de4e171aa101d047765a Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Thu, 22 Apr 2021 13:54:32 -0400 Subject: [PATCH 348/800] Feature: Configurable subsidy duration --- src/date_type.h | 1 + src/lang/english.txt | 14 +++++++++----- src/saveload/saveload.h | 1 + src/saveload/subsidy_sl.cpp | 17 +++++++++-------- src/settings_gui.cpp | 1 + src/settings_type.h | 3 ++- src/subsidy.cpp | 30 +++++++++++++++++++++--------- src/subsidy_base.h | 11 +++++++++-- src/subsidy_func.h | 3 ++- src/subsidy_gui.cpp | 4 ++-- src/table/settings/settings.ini | 13 +++++++++++++ 11 files changed, 70 insertions(+), 28 deletions(-) diff --git a/src/date_type.h b/src/date_type.h index 4cbcfac4ed..c0f005734e 100644 --- a/src/date_type.h +++ b/src/date_type.h @@ -28,6 +28,7 @@ typedef uint8 Day; ///< Type for the day of the month, note: 1 based, first d static const int DAY_TICKS = 74; ///< ticks per day static const int DAYS_IN_YEAR = 365; ///< days per year static const int DAYS_IN_LEAP_YEAR = 366; ///< sometimes, you need one day more... +static const int MONTHS_IN_YEAR = 12; ///< months per year static const int STATION_RATING_TICKS = 185; ///< cycle duration for updating station rating static const int STATION_ACCEPTANCE_TICKS = 250; ///< cycle duration for updating station acceptance diff --git a/src/lang/english.txt b/src/lang/english.txt index 4a92eba893..206cc212f7 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -883,11 +883,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING2} to {STRING2} will now not attract a subsidy STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING2} to {STRING2} is no longer subsidised -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING2} to {STRING2} will attract a year's subsidy from the local authority! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay 50% extra for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay double rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay triple rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay quadruple rates for the next year! +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING2} to {STRING2} will attract a {NUM} year subsidy from the local authority! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay 50% extra for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay double rates for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay triple rates for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay quadruple rates for the next {NUM} year{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 months of misery to motorists! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopoly! @@ -1203,6 +1203,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Vehicle breakdo STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Control how often inadequately serviced vehicles may break down STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsidy multiplier: {STRING2} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Set how much is paid for subsidised connections +STR_CONFIG_SETTING_SUBSIDY_DURATION :Subsidy duration: {STRING2} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Set the number of years for which a subsidy is awarded +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} year{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :No subsidies STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Construction costs: {STRING2} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Set level of construction and purchase costs STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING2} diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 3a2427c933..28af1fd37d 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -328,6 +328,7 @@ enum SaveLoadVersion : uint16 { SLV_INDUSTRY_TEXT, ///< 289 PR#8576 v1.11.0-RC1 Additional GS text for industries. SLV_MAPGEN_SETTINGS_REVAMP, ///< 290 PR#8891 v1.11 Revamp of some mapgen settings (snow coverage, desert coverage, heightmap height, custom terrain type). SLV_GROUP_REPLACE_WAGON_REMOVAL, ///< 291 PR#7441 Per-group wagon removal flag. + SLV_CUSTOM_SUBSIDY_DURATION, ///< 292 PR#9081 Configurable subsidy duration. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index b17ae1f252..9ed65a04ec 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -16,14 +16,15 @@ static const SaveLoad _subsidies_desc[] = { SLE_VAR(Subsidy, cargo_type, SLE_UINT8), - SLE_VAR(Subsidy, remaining, SLE_UINT8), - SLE_CONDVAR(Subsidy, awarded, SLE_UINT8, SLV_125, SL_MAX_VERSION), - SLE_CONDVAR(Subsidy, src_type, SLE_UINT8, SLV_125, SL_MAX_VERSION), - SLE_CONDVAR(Subsidy, dst_type, SLE_UINT8, SLV_125, SL_MAX_VERSION), - SLE_CONDVAR(Subsidy, src, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5), - SLE_CONDVAR(Subsidy, src, SLE_UINT16, SLV_5, SL_MAX_VERSION), - SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5), - SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, remaining, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_CUSTOM_SUBSIDY_DURATION), + SLE_CONDVAR(Subsidy, remaining, SLE_UINT16, SLV_CUSTOM_SUBSIDY_DURATION, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, awarded, SLE_UINT8, SLV_125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, src_type, SLE_UINT8, SLV_125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, dst_type, SLE_UINT8, SLV_125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, src, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5), + SLE_CONDVAR(Subsidy, src, SLE_UINT16, SLV_5, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5), + SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION), }; static void Save_SUBS() diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 1bd58c13b9..b17b343c79 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1691,6 +1691,7 @@ static SettingsContainer &GetSettingsTree() accounting->Add(new SettingEntry("difficulty.initial_interest")); accounting->Add(new SettingEntry("difficulty.max_loan")); accounting->Add(new SettingEntry("difficulty.subsidy_multiplier")); + accounting->Add(new SettingEntry("difficulty.subsidy_duration")); accounting->Add(new SettingEntry("economy.feeder_payment_share")); accounting->Add(new SettingEntry("economy.infrastructure_maintenance")); accounting->Add(new SettingEntry("difficulty.vehicle_costs")); diff --git a/src/settings_type.h b/src/settings_type.h index 8023683848..05efc11e55 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -72,7 +72,8 @@ struct DifficultySettings { byte vehicle_costs; ///< amount of money spent on vehicle running cost byte competitor_speed; ///< the speed at which the AI builds byte vehicle_breakdowns; ///< likelihood of vehicles breaking down - byte subsidy_multiplier; ///< amount of subsidy + byte subsidy_multiplier; ///< payment multiplier for subsidized deliveries + uint16 subsidy_duration; ///< duration of subsidies byte construction_cost; ///< how expensive is building byte terrain_type; ///< the mountainousness of the landscape byte quantity_sea_lakes; ///< the amount of seas/lakes diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 14679e4dc0..8800da1bd0 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -41,7 +41,7 @@ void Subsidy::AwardTo(CompanyID company) assert(!this->IsAwarded()); this->awarded = company; - this->remaining = SUBSIDY_CONTRACT_MONTHS; + this->remaining = _settings_game.difficulty.subsidy_duration * MONTHS_IN_YEAR; char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, company); @@ -50,7 +50,7 @@ void Subsidy::AwardTo(CompanyID company) char *cn = stredup(company_name); /* Add a news item */ - std::pair reftype = SetupSubsidyDecodeParam(this, false); + std::pair reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded); InjectDParam(1); SetDParamStr(0, cn); @@ -69,17 +69,21 @@ void Subsidy::AwardTo(CompanyID company) /** * Setup the string parameters for printing the subsidy at the screen, and compute the news reference for the subsidy. * @param s %Subsidy being printed. - * @param mode Unit of cargo used, \c true means general name, \c false means singular form. + * @param mode Type of subsidy news message to decide on parameter format. * @return Reference of the subsidy in the news system. */ -std::pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) +std::pair SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode) { NewsReferenceType reftype1 = NR_NONE; NewsReferenceType reftype2 = NR_NONE; - /* if mode is false, use the singular form */ + /* Choose whether to use the singular or plural form of the cargo name based on how we're printing the subsidy */ const CargoSpec *cs = CargoSpec::Get(s->cargo_type); - SetDParam(0, mode ? cs->name : cs->name_single); + if (mode == SubsidyDecodeParamType::Gui || mode == SubsidyDecodeParamType::NewsWithdrawn) { + SetDParam(0, cs->name); + } else { + SetDParam(0, cs->name_single); + } switch (s->src_type) { case ST_INDUSTRY: @@ -107,6 +111,11 @@ std::pair SetupSubsidyDecodeParam(const Su } SetDParam(5, s->dst); + /* If the subsidy is being offered or awarded, the news item mentions the subsidy duration. */ + if (mode == SubsidyDecodeParamType::NewsOffered || mode == SubsidyDecodeParamType::NewsAwarded) { + SetDParam(7, _settings_game.difficulty.subsidy_duration); + } + return std::pair(reftype1, reftype2); } @@ -216,7 +225,7 @@ void CreateSubsidy(CargoID cid, SourceType src_type, SourceID src, SourceType ds s->remaining = SUBSIDY_OFFER_MONTHS; s->awarded = INVALID_COMPANY; - std::pair reftype = SetupSubsidyDecodeParam(s, false); + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered); AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC); SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST); @@ -491,13 +500,13 @@ void SubsidyMonthlyLoop() for (Subsidy *s : Subsidy::Iterate()) { if (--s->remaining == 0) { if (!s->IsAwarded()) { - std::pair reftype = SetupSubsidyDecodeParam(s, true); + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index)); Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index)); } else { if (s->awarded == _local_company) { - std::pair reftype = SetupSubsidyDecodeParam(s, true); + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); } AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index)); @@ -510,6 +519,9 @@ void SubsidyMonthlyLoop() if (modified) { RebuildSubsidisedSourceAndDestinationCache(); + } else if (_settings_game.difficulty.subsidy_duration == 0) { + /* If subsidy duration is set to 0, subsidies are disabled, so bail out. */ + return; } else if (_settings_game.linkgraph.distribution_pax != DT_MANUAL && _settings_game.linkgraph.distribution_mail != DT_MANUAL && _settings_game.linkgraph.distribution_armoured != DT_MANUAL && diff --git a/src/subsidy_base.h b/src/subsidy_base.h index ef9276433f..120c5cecef 100644 --- a/src/subsidy_base.h +++ b/src/subsidy_base.h @@ -21,7 +21,7 @@ extern SubsidyPool _subsidy_pool; /** Struct about subsidies, offered and awarded */ struct Subsidy : SubsidyPool::PoolItem<&_subsidy_pool> { CargoID cargo_type; ///< Cargo type involved in this subsidy, CT_INVALID for invalid subsidy - byte remaining; ///< Remaining months when this subsidy is valid + uint16 remaining; ///< Remaining months when this subsidy is valid CompanyID awarded; ///< Subsidy is awarded to this company; INVALID_COMPANY if it's not awarded to anyone SourceType src_type; ///< Source of subsidised path (ST_INDUSTRY or ST_TOWN) SourceType dst_type; ///< Destination of subsidised path (ST_INDUSTRY or ST_TOWN) @@ -52,11 +52,18 @@ struct Subsidy : SubsidyPool::PoolItem<&_subsidy_pool> { /** Constants related to subsidies */ static const uint SUBSIDY_OFFER_MONTHS = 12; ///< Duration of subsidy offer -static const uint SUBSIDY_CONTRACT_MONTHS = 12; ///< Duration of subsidy after awarding static const uint SUBSIDY_PAX_MIN_POPULATION = 400; ///< Min. population of towns for subsidised pax route static const uint SUBSIDY_CARGO_MIN_POPULATION = 900; ///< Min. population of destination town for cargo route static const uint SUBSIDY_MAX_PCT_TRANSPORTED = 42; ///< Subsidy will be created only for towns/industries with less % transported static const uint SUBSIDY_MAX_DISTANCE = 70; ///< Max. length of subsidised route (DistanceManhattan) static const uint SUBSIDY_TOWN_CARGO_RADIUS = 6; ///< Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~= min catchmement + min station / 2) +/** Types of subsidy news messages, which determine how the date is printed and whether to use singular or plural cargo names */ +enum class SubsidyDecodeParamType { + NewsOffered = 0, ///< News item for an offered subsidy + NewsAwarded = 1, ///< News item for an awarded subsidy + NewsWithdrawn = 2, ///< News item for a subsidy offer withdrawn, or expired subsidy + Gui = 3, ///< Subsidies listed in the Subsidy GUI +}; + #endif /* SUBSIDY_BASE_H */ diff --git a/src/subsidy_func.h b/src/subsidy_func.h index cc63577d33..5cd7a31181 100644 --- a/src/subsidy_func.h +++ b/src/subsidy_func.h @@ -15,8 +15,9 @@ #include "company_type.h" #include "cargo_type.h" #include "news_type.h" +#include "subsidy_base.h" -std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, bool mode); +std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode); void DeleteSubsidyWith(SourceType type, SourceID index); bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st); void RebuildSubsidisedSourceAndDestinationCache(); diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index fe3c55c111..b46ca4da29 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -161,7 +161,7 @@ struct SubsidyListWindow : Window { if (!s->IsAwarded()) { if (IsInsideMM(pos, 0, cap)) { /* Displays the two offered towns */ - SetupSubsidyDecodeParam(s, true); + SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui); SetDParam(7, _date - ymd.day + s->remaining * 32); DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_OFFERED_FROM_TO); } @@ -184,7 +184,7 @@ struct SubsidyListWindow : Window { for (const Subsidy *s : Subsidy::Iterate()) { if (s->IsAwarded()) { if (IsInsideMM(pos, 0, cap)) { - SetupSubsidyDecodeParam(s, true); + SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui); SetDParam(7, s->awarded); SetDParam(8, _date - ymd.day + s->remaining * 32); diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index f9f1cb87b7..17a4b30258 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -231,6 +231,19 @@ str = STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER strhelp = STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT strval = STR_SUBSIDY_X1_5 +[SDT_VAR] +var = difficulty.subsidy_duration +type = SLE_UINT16 +from = SLV_CUSTOM_SUBSIDY_DURATION +flags = SF_GUI_0_IS_SPECIAL +def = 1 +min = 0 +max = 5000 +interval = 1 +str = STR_CONFIG_SETTING_SUBSIDY_DURATION +strhelp = STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT +strval = STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE + [SDT_VAR] var = difficulty.construction_cost type = SLE_UINT8 From acb6348ba62337d7580397d8f858e4a0bd1b0cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Thu, 10 Jun 2021 23:54:52 +0200 Subject: [PATCH 349/800] Add: [Actions] msys2/MinGW CI (#8698) --- .github/workflows/ci-build.yml | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 4dea7350c7..8f1d1e1956 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -316,6 +316,78 @@ jobs: cd ${GITHUB_WORKSPACE}/build ctest --timeout 120 + + msys2: + name: msys2 + + strategy: + fail-fast: false + matrix: + include: + - msystem: MINGW64 + arch: x86_64 + - msystem: MINGW32 + arch: i686 + + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.msystem }} + update: true + install: >- + git + make + mingw-w64-${{ matrix.arch }}-cmake + mingw-w64-${{ matrix.arch }}-gcc + mingw-w64-${{ matrix.arch }}-lzo2 + mingw-w64-${{ matrix.arch }}-libpng + + - name: Install OpenGFX + shell: bash + run: | + mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset" + cd "C:/Users/Public/Documents/OpenTTD/baseset" + + echo "::group::Download OpenGFX" + curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip opengfx-all.zip + echo "::endgroup::" + + rm -f opengfx-all.zip + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build + shell: msys2 {0} + run: | + mkdir build + cd build + + echo "::group::CMake" + cmake .. -G"MSYS Makefiles" + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + cmake --build . -j $(nproc) + echo "::endgroup::" + + - name: Test + shell: msys2 {0} + run: | + cd build + ctest -j $(nproc) --timeout 120 + check_annotations: name: Check Annotations needs: @@ -323,6 +395,7 @@ jobs: - linux - macos - windows + - msys2 if: always() && github.event_name == 'pull_request' From ef25afd55ab868a4322d0c241b5c4898966ac919 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 11 Jun 2021 00:18:20 +0200 Subject: [PATCH 350/800] Fix #9348, 4d74e51: don't try to sell shares of spectators (#9349) "new_owner" can be INVALID_OWNER, and as INVALID_OWNER == COMPANY_SPECTATORS, we could end up trying to sell shares of nobody. --- src/company_cmd.cpp | 2 +- src/economy.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index e58d29b2b5..1c79c4b8a5 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -67,7 +67,7 @@ Company::Company(uint16 name_1, bool is_ai) this->clear_limit = (uint32)_settings_game.construction.clear_frame_burst << 16; this->tree_limit = (uint32)_settings_game.construction.tree_frame_burst << 16; - for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR; + for (uint j = 0; j < 4; j++) this->share_owners[j] = INVALID_OWNER; InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY); } diff --git a/src/economy.cpp b/src/economy.cpp index efea96806f..7f14bed8ad 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -324,10 +324,12 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) Backup cur_company2(_current_company, FILE_LINE); const Company *c = Company::Get(old_owner); for (i = 0; i < 4; i++) { + if (c->share_owners[i] == INVALID_OWNER) continue; + if (c->bankrupt_value == 0 && c->share_owners[i] == new_owner) { /* You are the one buying the company; so don't sell the shares back to you. */ - Company::Get(new_owner)->share_owners[i] = COMPANY_SPECTATOR; - } else if (c->share_owners[i] != INVALID_OWNER) { + Company::Get(new_owner)->share_owners[i] = INVALID_OWNER; + } else { cur_company2.Change(c->share_owners[i]); /* Sell the shares */ CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC | DC_BANKRUPT, CMD_SELL_SHARE_IN_COMPANY); From ee5f23382d551bedcc998ba7aaf92333885c21d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Fri, 11 Jun 2021 16:40:04 +0200 Subject: [PATCH 351/800] Fix: [Script] doxygen_filter is very strict about DOXYGEN_API usage (#9351) --- src/script/api/script_priorityqueue.hpp | 2 +- src/script/api/script_text.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/api/script_priorityqueue.hpp b/src/script/api/script_priorityqueue.hpp index 5f8718e424..517f6ab0bd 100644 --- a/src/script/api/script_priorityqueue.hpp +++ b/src/script/api/script_priorityqueue.hpp @@ -76,7 +76,7 @@ public: SQInteger Peek(HSQUIRRELVM vm); SQInteger Exists(HSQUIRRELVM vm); SQInteger Clear(HSQUIRRELVM vm); -#endif +#endif /* DOXYGEN_API */ /** * Check if the queue is empty. diff --git a/src/script/api/script_text.hpp b/src/script/api/script_text.hpp index 2553695377..64cf2e7993 100644 --- a/src/script/api/script_text.hpp +++ b/src/script/api/script_text.hpp @@ -88,7 +88,7 @@ public: * @param ... Optional arguments for this string. */ ScriptText(StringID string, ...); -#endif +#endif /* DOXYGEN_API */ ~ScriptText(); #ifndef DOXYGEN_API From 16ebf7861f2b8fce6f1c44b0666bb8794a39abbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Fri, 11 Jun 2021 16:59:19 +0200 Subject: [PATCH 352/800] Fix 4079c47: Missed a file when removing generated .sq files from the repo (#9350) --- .../template/template_priorityqueue.hpp.sq | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/script/api/template/template_priorityqueue.hpp.sq diff --git a/src/script/api/template/template_priorityqueue.hpp.sq b/src/script/api/template/template_priorityqueue.hpp.sq deleted file mode 100644 index 14c63324fb..0000000000 --- a/src/script/api/template/template_priorityqueue.hpp.sq +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ - -#include "../script_priorityqueue.hpp" - -namespace SQConvert { - /* Allow ScriptPriorityQueue to be used as Squirrel parameter */ - template <> inline ScriptPriorityQueue *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; } - template <> inline ScriptPriorityQueue &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; } - template <> inline const ScriptPriorityQueue *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; } - template <> inline const ScriptPriorityQueue &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; } - template <> inline int Return(HSQUIRRELVM vm, ScriptPriorityQueue *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "PriorityQueue", res, nullptr, DefSQDestructorCallback, true); return 1; } -} // namespace SQConvert From c562b4c52754ea51418f5b4ecc46a36e14f849f0 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 11 Jun 2021 18:54:52 +0000 Subject: [PATCH 353/800] Update: Translations from eints hindi: 67 changes by ritwikraghav14 --- src/lang/afrikaans.txt | 5 --- src/lang/arabic_egypt.txt | 5 --- src/lang/basque.txt | 5 --- src/lang/belarusian.txt | 5 --- src/lang/brazilian_portuguese.txt | 5 --- src/lang/bulgarian.txt | 5 --- src/lang/catalan.txt | 5 --- src/lang/croatian.txt | 5 --- src/lang/czech.txt | 5 --- src/lang/danish.txt | 5 --- src/lang/dutch.txt | 5 --- src/lang/english_AU.txt | 5 --- src/lang/english_US.txt | 5 --- src/lang/esperanto.txt | 5 --- src/lang/estonian.txt | 5 --- src/lang/faroese.txt | 5 --- src/lang/finnish.txt | 5 --- src/lang/french.txt | 5 --- src/lang/frisian.txt | 5 --- src/lang/gaelic.txt | 5 --- src/lang/galician.txt | 5 --- src/lang/german.txt | 5 --- src/lang/greek.txt | 5 --- src/lang/hebrew.txt | 5 --- src/lang/hindi.txt | 67 +++++++++++++++++++++++++++++++ src/lang/hungarian.txt | 5 --- src/lang/icelandic.txt | 5 --- src/lang/indonesian.txt | 5 --- src/lang/irish.txt | 5 --- src/lang/italian.txt | 5 --- src/lang/japanese.txt | 5 --- src/lang/korean.txt | 5 --- src/lang/latin.txt | 5 --- src/lang/latvian.txt | 5 --- src/lang/lithuanian.txt | 5 --- src/lang/luxembourgish.txt | 5 --- src/lang/malay.txt | 5 --- src/lang/norwegian_bokmal.txt | 5 --- src/lang/norwegian_nynorsk.txt | 5 --- src/lang/persian.txt | 5 --- src/lang/polish.txt | 5 --- src/lang/portuguese.txt | 5 --- src/lang/romanian.txt | 5 --- src/lang/russian.txt | 5 --- src/lang/serbian.txt | 5 --- src/lang/simplified_chinese.txt | 5 --- src/lang/slovak.txt | 5 --- src/lang/slovenian.txt | 5 --- src/lang/spanish.txt | 5 --- src/lang/spanish_MX.txt | 5 --- src/lang/swedish.txt | 5 --- src/lang/tamil.txt | 2 - src/lang/thai.txt | 5 --- src/lang/traditional_chinese.txt | 5 --- src/lang/turkish.txt | 5 --- src/lang/ukrainian.txt | 5 --- src/lang/urdu.txt | 5 --- src/lang/vietnamese.txt | 5 --- src/lang/welsh.txt | 5 --- 59 files changed, 67 insertions(+), 287 deletions(-) diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index a3ef0aac4a..cb3052a1bd 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -874,11 +874,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidie-aanbod het verval:{}{}{STRING} van {STRING} tot {STRING} sal nou nie 'n subsidie aantrek nie. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie onttrek:{}{}{STRING} diens van {STRING} tot {STRING} is nie meer gesubsideieer nie. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Diens subsidie aanbod:{}{}Eerste {STRING} diens van {STRING} tot {STRING} sal 'n jaar se subsidie van die plaaslike raad kry! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Diens subsidie toeken aan {STRING}!{}{}{STRING} Diens van {STRING} tot {STRING} sal nou 50% extra vir die volgende jaar betaal! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Diens subsidie toeken aan {STRING}!{}{}{STRING} diens van {STRING} tot {STRING} sal nou dubbel pryse vir die volgende jaar betaal! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Diens subsidie toeken aan {STRING}!{}{}{STRING} diens van {STRING} tot {STRING} sal nou driemaal pryse vir die volgende jaar betaal! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Diens subsidie toeken aan {STRING}!{}{}{STRING} diens van {STRING} tot {STRING} sal nou viervoud pryse vir die volgende jaar betaal! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Verkeer warboel in {TOWN}!{}{}Pad heropbou program befonds deur {STRING} bring 6 maande van ellende na motoriste! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Vervoer monopoly! diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index f17f8c4084..ea1634a0a9 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -853,11 +853,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK} اعلان عن انتهاء عرض{}{} نقل {STRING} من {STRING} الى {STRING} لن يعطي ارباح اضافية بعد الآن . STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK} تم سحب العرض{}{} نقل {STRING} من {STRING} الى {STRING} لم يعد معروض -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}اعلان عن عرض{}{} نقل اول {STRING} من {STRING} الى {STRING} سوف يعطي زيادة ارباح في السنة القادمة. -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK} العرض قد اعطي لـ {STRING}!{}{} نقل {STRING} من {STRING} الى {STRING} سوف يعطي زيادة 50% ارباح للسنة القادمة -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}العرض قد اعطي لـ {STRING}!{}{} نقل {STRING}من {STRING}الى {STRING} سوف يعطي ضعف الدخل للسنة القادمة -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}شركة {STRING} فازت بالعرض{}{} نقل {STRING} من {STRING} الى {STRING} سوف يعطي 3 اضعاف الدخل للسنة القادمة -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK} شركة {STRING} فازت بالعرض !{}{} نقل {STRING} من {STRING} الى {STRING} سوف يعطي اربعة اضعاف الدخل للسنة القادمة STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK} فوضى طرق عارمة في مدينة {TOWN}!{}{}اعادة ترميم الطرق مولت من قبل شركة {STRING}{} تجلي ستة أشهر من الشقاء لعربات الطريق. diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 00570926f6..fc3e35f1a3 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -850,11 +850,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidio eskaintza agortu egin da:{}{}{STRING} {STRING}tik {STRING}ra doanarentzat ez dago subsidiorik orain. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidioa kenduta:{}{}{STRING} Ez dago subsidiorik {STRING}(e)tik {STRING}(e)ra garraiatzeagatik. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Diru-laguntza eskaintza:{}{} {STRING} {STRING}tik {STRING}ra doan lehenengoari bertako udalak diru-laguntza emango dio urte batetan zehar! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Diru-laguntza{STRING}entzako!{}{}{STRING} {STRING}tik {STRING}ra egindako serbitzuak %50-a gehiago irabaziko dute hurrengo urtean zehar! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Diru-laguntza {STRING}entzako da!{}{}{STRING} {STRING}tik {STRING}ra egiten duen serbitzuak bikoitza irabaziko du hurrengo urtean zehar! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Diru-laguntza {STRING}entzako da!{}{}{STRING} {STRING}tik {STRING}ra doan serbitzuak hirukoitza irabaziko du hurrengo urtean zehar! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Diru-laguntza {STRING}entzako da!{}{}{STRING} {STRING}tik {STRING}ra doan zerbitzuak laukoitza irabaziko du hurrengo urtean zehar! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK} Trafiko nahaste-borrastea {TOWN}en!{}{} {STRING}k ordaindutako errepideen konponketa plana sei hilabeterako arazoak esanguratzen die gidariei! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Garraio monopolia!! diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 4d6856f6a4..8ec4fbd9cd 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -1183,11 +1183,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Прапанова субсыдыі мінула:{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} субсыдыявацца больш ня будзе. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Тэрмін субсыдыі сышоў:{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} больш не субсыдуецца. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Прапанова субсыдыі:{}{}Першая кампанія, якая павязе {STRING.acc} па маршруце {STRING} — {STRING}, атрымае гадавую субсыдыю ад мясцовых уладаў! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Кампанія «{STRING}» атрымала субсыдыю!{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} будзе аплочана ў паўтарачным памеры на працягу года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Кампанія «{STRING}» атрымала субсыдыю!{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} будзе аплочана ў падвоеным памеры на працягу года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Кампанія «{STRING}» атрымала субсыдыю!{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} будзе аплочана ў патроеным памеры на працягу года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Кампанія «{STRING}» атрымала субсыдыю!{}{}Перавозка {STRING.gen} па маршруце {STRING} — {STRING} будзе аплочана ў чатырохразовым памеры на працягу года! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Хаос на дарогах г. {NBSP}{TOWN}!{}{}Рэканструкцыя дарогаў, прафінансаваная {STRING}, прынясе кіроўцам 6 месяцаў пакут! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Транспартная манаполія! diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 4dd815985b..48388ac9fc 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}A oferta do subsídio expirou:{}{}{STRING} de {STRING} para {STRING} agora não irá atrair um subsídio STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsídio removido:{}{} Serviço de {STRING} de {STRING} para {STRING} não é mais subsidiado -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsídio de serviço oferecido:{}{} Primeiro serviço de {STRING} de {STRING} para {STRING} atrairá subsídio de um ano da prefeitura local! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsídio de serviço concedido á {STRING}!{}{}{STRING} serviço de {STRING} para {STRING} pagará 50% extra durante o próximo ano ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido á {STRING}!{}{}{STRING} serviço de {STRING} para {STRING} pagará o dobro de tarifas durante o próximo ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido á {STRING}!{}{}{STRING} serviço de {STRING} para {STRING} pagará o triplo de tarifas durante o próximo ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido á {STRING}!{}{}{STRING} serviço de {STRING} para {STRING} pagará o quadruplo de tarifas durante o próximo ano! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Tráfego caótico em {TOWN}!{}{} Programa de reconstrução rodoviária financiado por {STRING} provoca 6 meses de miséria aos condutores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopólio dos transportes! diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 533ca83adc..1fad584e6b 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -856,11 +856,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Предложението за субсидия изтече:{}{}Превозът на {STRING} от {STRING} до {STRING} повече няма да получава субсидия. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Анулирана субсидия:{}{}Превозът на {STRING} от {STRING} до {STRING} вече не се субсидира. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Предложена субсидия:{}{}Първият превоз на {STRING} от {STRING} до {STRING} ще спечели едногодишна субсидия от местните власти! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} спечели субсидия!{}{}Превозът на {STRING} от {STRING} до {STRING} ще се заплаща с 50% повече през следващата година! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} спечели субсидия!!{}{}Превозът на {STRING} от {STRING} до {STRING} ще се заплаща двойно през следващата година! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{STRING} спечели субсидия!!{}{}Превозът на {STRING} от {STRING} до {STRING} ще се заплаща тройно през следващата година! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} спечели субсидия!!{}{}Превозът на {STRING} от {STRING} до {STRING} ще се заплаща четворно през следващата година! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Хаос на трафика в {TOWN}!{}{}Програмата за пътна реконструкция, финансирана от {STRING}, доведе до 6 месеца мизерия за мотористите! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Монополист на транспорта! diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 2d9b85ffa8..bbb399eb55 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvenció caducada:{}{}El transport de {STRING} des de {STRING} fins a {STRING} no tindrà subvenció STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvenció retirada:{}{}El transport de {STRING} des de {STRING} fins a {STRING} ja no està subvencionat -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Oferta de subvenció per a un servei:{}{}La primera companyia en transportar {STRING} des de {STRING} fins a {STRING} tindrà una subvenció d'un any per part de l'autoritat local -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} rebrà uns ingressos addicionals del 50% durant el pròxim any -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el doble de la tarifa habitual durant el pròxim any -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el triple de la tarifa habitual durant el pròxim any -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el quàdruple de la tarifa habitual durant el pròxim any STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trànsit caòtic a {TOWN}{}{}El programa de reconstrucció dels carrers patrocinat per {STRING} porta 6 mesos de misèria als automobilistes STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoli de transports diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index 1dbf6d265a..0e9dec5382 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -969,11 +969,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Istekla je ponuda za poticaje:{}{}prijevoz {STRING.gen} od {STRING} do {STRING} više neće biti potican STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvencija je povučena:{}{}prijevoz {STRING.gen} od {STRING} do {STRING} više nije subvencioniran -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ponuđen je poticaj:{}{}Prvi koji preveze {STRING.aku} od {STRING} do {STRING} primat će jednogodišnji poticaj lokalne samouprave! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvencija je dodijeljena tvrtki {STRING}!{}{}Prijevoz {STRING.gen} od postaje {STRING} do postaje {STRING} plaćat će se 50% više sljedećih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvencija je dodijeljena tvrtki {STRING}!{}{}Prijevoz {STRING.gen} od postaje {STRING} do postaje {STRING} plaćat će se dvostruko sljedećih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Poticaj je dodijeljen tvrtki {STRING}!{}{}Prijevoz {STRING.gen} od postaje {STRING} do postaje {STRING} plaćat će se trostruko sljedećih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Poticaj je dodijeljen tvrtki {STRING}!{}{}Prijevoz {STRING.gen} od postaje {STRING} do postaje {STRING} plaćat će se četverostruko sljedećih godinu dana! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Grad {TOWN} zahvatio je prometni kaos!{}{}Program rekonstrukcije cesta koji financira tvrtka {STRING} sljedećih će 6 mjeseci zadavati glavobolje motoriziranima! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopol transporta! diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 96bcc65df5..f88eb3f0ba 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -970,11 +970,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Nabídka dotace přepravy vypršela:{}{}Dotace dopravy {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} nebude dále nabízena STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Ukončení dotování dopravy:{}{}Dotace pro {STRING} z{NBSP}{STRING.gen} do {STRING.gen} již nebude dále poskytována -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Nabídka dotace:{}{}Doprava {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} bude jeden rok dotována místní správou! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Dotace přidělena společnosti {STRING}.{}{}Doprava {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} bude po jeden rok vynášet 150{NBSP}% normální ceny -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Dotace přidělena společnosti {STRING}.{}{}Doprava {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} bude po jeden rok vynášet dvojnásobek normální ceny! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Dotace přidělena společnosti {STRING}.{}{}Doprava {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} bude po jeden rok vynášet trojnásobek normální ceny! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Dotace přidělena společnosti {STRING}.{}{}Doprava {STRING.gen} z{NBSP}{STRING.gen} do {STRING.gen} bude po jeden rok vynášet čtyřnásobek normální ceny! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN} zažívá dopravní chaos!{}{}Program přestavby ulic sponzorovaný {STRING} přináší motoristům 6 měsíců utrpení! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportní monopol! diff --git a/src/lang/danish.txt b/src/lang/danish.txt index f2b4987183..a3cad4ff5a 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -873,11 +873,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Licitation af tilskudsordning udløbet:{}{}{STRING} fra {STRING} til {STRING} vil ikke længere udløse tilskud. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Tilskudsordning tilbagetrukket:{}{}{STRING} fragt fra {STRING} til {STRING} modtager ikke længere tilskud. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Tilskudsordning i licitation:{}{}Første {STRING} fragt fra {STRING} til {STRING} vil udløse et års tilskud fra de lokale myndigheder! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Tilskudsordning tildelt {STRING}!{}{}{STRING} fragt fra {STRING} til {STRING} vil give 50% mere i de næste 12 måneder! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Tilskudsordning tildelt {STRING}!{}{}{STRING} fragt fra {STRING} til {STRING} vil give dobbelt udbytte i de næste 12 måneder! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Tilskudsordning tildelt {STRING}!{}{}{STRING} fragt fra {STRING} til {STRING} vil give tredobbelt udbytte i de næste 12 måneder! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Tilskudsordning tildelt {STRING}!{}{}{STRING} fragt fra {STRING} til {STRING} vil give firedobbelt udbytte i de næste 12 måneder! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i byen {TOWN}!{}{}Vejfornyelse betalt af {STRING} forårsager 6 måneders kaos i trafikken! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index aa8ad733de..4deb9d1df2 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidieaanbod is verlopen:{}{}{STRING} van {STRING} naar {STRING} wordt nu niet meer gesubsidieerd STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie ingetrokken:{}{}{STRING}route van {STRING} naar {STRING} wordt nu niet meer gesubsidieerd -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidie aangeboden:{}{}Eerste {STRING}route van {STRING} naar {STRING} krijgt een jaar lang subsidie van de gemeente! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt volgend jaar 50% extra betaald! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt volgend jaar dubbel betaald! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt volgend jaar driedubbel betaald! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt volgend jaar vierdubbel betaald! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Verkeerschaos in {TOWN}!{}{}Wegreconstructie betaald door {STRING} zorgt voor 6 maanden van misère bij weggebruikers! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopolie! diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index d645ee56e1..e2faa0e819 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -849,11 +849,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING} to {STRING} will now not attract a subsidy STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING} to {STRING} is no longer subsidised -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING} to {STRING} will attract a year's subsidy from the local authority! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay 50% extra for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay double rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay triple rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay quadruple rates for the next year! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {STRING} brings 6 months of misery to motorists! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopoly! diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 6155a1f84e..f62da4cf90 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING} to {STRING} will now not attract a subsidy STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING} to {STRING} is no longer subsidized -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING} to {STRING} will attract a year's subsidy from the local authority! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay 50% extra for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay double rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay triple rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay quadruple rates for the next year! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding program funded by {STRING} brings 6 months of misery to motorists! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopoly! diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index ae6d42ada0..0505e59c3b 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -846,11 +846,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subvencia oferto ne plu validas:{}{}{STRING} de {STRING} al {STRING} ne estos subvenciata. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvencio retiriĝis:{}{}Servo de {STRING} de {STRING} al {STRING} ne plu estas subvenciata. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subvencia oferto:{}{}Unua servo de {STRING} de {STRING} al {STRING} ricevos subvencion de jaro de la lokaj estroj! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvencio doniĝis al {STRING}!{}{}Servo de {STRING} de {STRING} al {STRING} ricevis pliaĵon de 50% por la sekva jaro! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvencio doniĝis al {STRING}!{}{}Servo de {STRING} de {STRING} al {STRING} ricevis duoblajn pagojn por la sekva jaro! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvencio doniĝis al {STRING}!{}{}Servo de {STRING} de {STRING} al {STRING} ricevis trioblajn pagojn por la sekva jaro! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvencio doniĝis al {STRING}!{}{}Servo de {STRING} de {STRING} al {STRING} ricevis kvaroblajn pagojn por la sekva jaro! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafika ĥaoso en {TOWN}!{}{}Vojrekonstruada programo komencita de {STRING} alportas 6-monatan mizeron al vojuzantoj! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transporta monopolo! diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index b30da7c16d..e36ed2a9b8 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -940,11 +940,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Jaam {ST STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Toetuse pakkumine lõppes:{}{}{STRING.g} kohast {STRING} kohta {STRING} veoste eest ei maksta enam toetusi STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Toetuse maksmise aeg sai läbi:{}{}{STRING}kohast {STRING} kohta {STRING} eest ei maksta enam edaspidi toetust -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Veoteenusele pakutakse toetust:{}{}{STRING.g}veo eest asustusest {STRING} asustusse {STRING}. Esimesele teenusepakkujale makstakse aasta läbi toetusi! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal 50% rohkem! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal kahekordselt! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal kolmekordselt! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal neljakordselt! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Liikluskaos asustuses {TOWN}!{}{}Ettevõtte {STRING} poolt rahastatud teede ümberehitus tekitab 6 kuu jooksul maanteedel liiklushäireid! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transpordimonopol! diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index 4508d9723f..678326311f 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -830,11 +830,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tilboð um stuðul útgingi:{}{}{STRING} frá {STRING} til {STRING} fær nú ongan stuðul STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Stuðul tikin aftur:{}{}{STRING} flutningur frá {STRING} til {STRING} er ikki stuðla longur -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Tilboð um flutnings stuðul:{}{}Fyrsti {STRING} flutningur frá {STRING} til {STRING} fær stuðul í eitt ár frá mynduleikanum á staðnum! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Flutnings stuðul handaður {STRING}!{}{}{STRING} flutningur frá {STRING} til {STRING} gevur 50% eyka úrtøku í eitt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Flutnings stuðul handaður {STRING}!{}{}{STRING} flutningur frá {STRING} til {STRING} hevur tvífaldaða úrtøku í eitt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Flutnings stuðul handaður {STRING}!{}{}{STRING} flutningur frá {STRING} til {STRING} hevur trýfaldaða úrtøku í eitt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Flutnings stuðul handaður {STRING}!{}{}{STRING} flutningur frá {STRING} til {STRING} hevur ferfaldaða úrtøku í eitt ár! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Ferðslu ruðuleiki í {TOWN}!{}{}Umvæling av vega kervi fíggja av {STRING} førir við sær 6 mánaðir av neyð fyri bilførarar! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Flutnings einahandil! diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index ee4acaf91f..158b4e079a 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tukitarjous päättynyt:{}{}{STRING} välillä {STRING} - {STRING} ei voi enää saada tukea STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Tuki vedetty pois:{}{}{STRING} kuljetuspalvelu välille {STRING}-{STRING} ei ole enää tuettu -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Tuki tarjottu:{}{}Ensimmäinen {STRING}kuljetus välillä {STRING} – {STRING} saa vuoden mittaisen tuen paikallisviranomaisilta! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING}-{STRING} tuottaa 50{NBSP}% enemmän seuraavan vuoden ajan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING}-{STRING} tuottaa tuplaten seuraavan vuoden ajan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING}-{STRING} tuottaa kolminkertaisesti seuraavan vuoden ajan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING}-{STRING} tuottaa nelinkertaisesti seuraavan vuoden ajan! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}: liikennekaaos!{}{}{STRING} rahoittaa katujen kunnostuksen; autoilijoille odotettavissa kuusi kuukautta kurjuutta! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Kuljetusmonopoli! diff --git a/src/lang/french.txt b/src/lang/french.txt index bafaed87a8..b1e3c04cf0 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offre de subvention expirée{NBSP}:{}{}Le transport de {STRING} entre {STRING} et {STRING} n'est désormais plus subventionné STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Abandon de la subvention{NBSP}:{}{}Le transport de {STRING} entre {STRING} et {STRING} n'est plus subventionné -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Offre de subvention{NBSP}:{}{}Le premier service de {STRING} entre {STRING} et {STRING} sera subventionné pendant un an{NBSP}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera 50{NBSP}% de plus pendant un an{NBSP}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera double pendant un an{NBSP}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera triple pendant un an{NBSP}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera quadruple pendant un an{NBSP}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Problèmes de trafic à {TOWN}{NBSP}!{}{}La reconstruction des routes financée par {STRING} provoque 6 mois de problèmes aux automobilistes{NBSP}! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopole des transports{NBSP}! diff --git a/src/lang/frisian.txt b/src/lang/frisian.txt index 6bceed5a1a..a882028ebe 100644 --- a/src/lang/frisian.txt +++ b/src/lang/frisian.txt @@ -858,11 +858,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsydzje oanbieding ferrûn:{}{}{STRING} fan {STRING} nei {STRING} sil no net in subsydzje krije. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsydzje ôfrûn:{}{}{STRING} tsjinst fan {STRING} nei {STRING} krijt gjin subsydzje mear. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsydzje oanbean:{}{}Earste{STRING} tsjinst fan {STRING} nei {STRING} krijt in jier subsydzje fan 'e gemeente! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsydzje tawezen oan {STRING}!{}{}{STRING} tsjinst fan {STRING} nei {STRING} krijt 50% ekstra betelle foar it kommende jier! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsydzje tawezen oan {STRING}!{}{}{STRING} tsjinst fan {STRING} nei {STRING} krijt dûbel betelle foar it kommende jier! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsydzje tawezen oan {STRING}!{}{}{STRING} tsjinst fan {STRING} nei {STRING} krijt trijedûbel betelle foar it kommende jier! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsydzje tawezen oan {STRING}!{}{}{STRING} tsjinst fan {STRING} nei {STRING} krijt fjouwerdûbel betelle foar it kommende jier! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Ferkearsgaos yn {TOWN}!{}{}Dykreparaasje betelle troch {STRING} bringt 6 moannen oan ellinde foar ferkearsdielnimmers! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopoalje! diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index 1f8bdda035..2fa9fb0ec9 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -1063,11 +1063,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Gabhaidh STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Dh'fhalbh an ùine air tairgse tarrail:{}{}Chan fhaighear tarrail airson {STRING} a thoirt bho {STRING} gu {STRING} a-nis STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Chaidh tarrail a tharraing:{}{}Chan fhaigh seirbheis {STRING} bho {STRING} gu {STRING} tarrail a-nis -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Chaidh tarrail seirbheise a thairgsinn:{}{}Gheibh a' chiad seirbheis {STRING} bho {STRING} gu {STRING} tarrail fad bliadhna bhon ùghdarras ionadail! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Bhuannaich {STRING} tarrail seirbheise!{}{}Pàighidh seirbheis {STRING} bho {STRING} gu {STRING} 50% a bharrachd fad bliadhna! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Bhuannaich {STRING} tarrail seirbheise!{}{}Pàighidh seirbheis {STRING} bho {STRING} gu {STRING} reataichean dà-fhillte fad bliadhna! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Bhuannaich {STRING} tarrail seirbheise!{}{}Pàighidh seirbheis {STRING} bho {STRING} gu {STRING} reataichean trì-fillte fad bliadhna! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Bhuannaich {STRING} tarrail seirbheise!{}{}Pàighidh seirbheis {STRING} bho {STRING} gu {STRING} reataichean ceithir-fillte fad bliadhna! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Bùrach trafaig ann am baile {TOWN}!{}{}Bheir prògram leasachadh rathaidean maoinichte le {STRING} dòlam dha dhraibhearan fad 6 mìosan! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Aon-mhargadh giùlain! diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 7d53f3328c..35d97a0691 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -873,11 +873,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvención expirada:{}{}{STRING} dende {STRING} ata {STRING} non será subvencionada. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvención reitrada:{}{}O servizo de transporte de {STRING} dende {STRING} ata {STRING} xa non ten subvención. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Oferta de subvención:{}{}O primeiro servizo de transporte de {STRING} dende {STRING} ata {STRING} será subvencionado durante un ano pola autoridade local! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvención concedida a {STRING}!{}{}Polo servizo de transporte de {STRING} dende {STRING} ata {STRING} pagarase un 50% máis durante o vindeiro ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvención concedida a {STRING}!{}{}Polo servizo de transporte de {STRING} dende {STRING} ata {STRING} pagarase o dobre durante o vindeiro ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvención concedida a {STRING}!{}{}Polo servizo de transporte de {STRING} dende {STRING} ata {STRING} pagarase o triplo durante o vindeiro ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvención concedida a {STRING}!{}{}Polo servizo de transporte de {STRING} dende {STRING} ata {STRING} pagaráse o cuádruplo durante o vindeiro ano! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Caos no tráfico de {TOWN}!{}{}O programa de reconstrución de estradas financiado por {STRING} trae 6 meses de miseria para os condutores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopolio de transportes! diff --git a/src/lang/german.txt b/src/lang/german.txt index 64d2f71bcb..014ecbf7fd 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionsangebot abgelaufen:{}{}{STRING}transport von {STRING} nach {STRING} wird nicht mehr subventioniert STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionsende:{}{}{STRING}transport von {STRING} nach {STRING} wird nicht mehr subventioniert -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subventionsangebot:{}{}Erster {STRING}transport von {STRING} nach {STRING} wird ein Jahr von den örtlichen Behörden subventioniert! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält im nächsten Jahr einen 50% höheren Preis! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält im nächsten Jahr den doppelten Preis! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält im nächsten Jahr den dreifachen Preis! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält im nächsten Jahr den vierfachen Preis! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Verkehrschaos in {TOWN}!{}{}Straßensanierungsprogramm finanziert durch {STRING} wird 6 Monate lang Verzögerungen im Verkehr bewirken! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! diff --git a/src/lang/greek.txt b/src/lang/greek.txt index 9c42988eef..f28c2b20b0 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -985,11 +985,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Ο στ STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Έληξε η προσφορά επιδότησης:{}{}{STRING} από {G τον τη το} {STRING} πρός {G τον τη το} {STRING} δεν θα επιδοτείται πλέον. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Η επιδότηση αποσύρθηκε:{}{}Η υπηρεσια για {STRING.subs} απο το {STRING} προς το {STRING} δεν επιδοτείται πλέον. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Προσφορά χρηματοδότησης υπηρεσίας:{}{}Η πρώτη υπηρεσία για {STRING.subs} από {G τον τη το} {STRING} προς {G τον τη το} {STRING} επιχορηγείται για ένα έτος από την τοπική αρχή! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Η χρηματοδότηση της υπηρεσίας απονεμήθη στην εταιρία {STRING}!{}{}Η υπηρεσία για {STRING.subs} από τον σταθμό {STRING} προς το σταθμό {STRING} θα χρεώνεται 50% παραπάνω για ένα έτος! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Η επιχορήγηση υπηρεσίας απονεμήθη στην εταιρία {STRING}!{}{}Η υπηρεσία για {STRING.subs} από τον σταθμό {STRING} προς το σταθμό {STRING} θα χρεώνεται διπλά για το επόμενο έτος! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Η επιχορήγηση υπηρεσίας απονεμήθη στην εταιρία {STRING}!{}{}Η υπηρεσία για {STRING.subs} από το σταθμό {STRING} προς το σταθμό {STRING} θα χρεώνεται τριπλά για το επόμενο έτος! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Η επιχορήγηση υπηρεσίας απονεμήθη στην εταιρία {STRING}!{}{}Η υπηρεσία για {STRING.subs} από τον σταθμό {STRING} προς τον σταθμό {STRING} θα χρεώνεται τετραπλά για το επόμενο έτος! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Χαώδης κίνηση στην πόλη {TOWN}!{}{}Χρηματοδοτήθηκε πρόγραμμα ανακατασκευής των δρόμων από την εταιρία {STRING} και προκαλεί 6 μήνες μιζέριας στους οδηγούς! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Μονοπώλιο μεταφορών! diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index 9822890e8e..5882c1490b 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -876,11 +876,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}פג תוקף הצעת סובסידיה:{}{}סובסידיה של הובלת {STRING.plural} מ{STRING} אל {STRING} לא תזכה עוד בסיבסוד. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}סובסידיה הוסרה:{}{}שירות הובלת {STRING.plural} מ{STRING} אל {STRING} אינו מסובסד יותר. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}הצעה למתן סובסידיה:{}{}שירות הובלת {STRING.plural} ראשון מ{STRING} אל {STRING} יזכה לסובסידיה בת שנה מהרשות המקומית! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}סובסידיה לשירות ניתנה לחברת {STRING}!{}{}שירות הובלת {STRING.plural} מ{STRING} אל {STRING} יזכה לשיעור תשלום גדול ב-50% לשנה הקרובה -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}סובסידיה לשירות ניתנה לחברת {STRING}!{}{}שירות הובלת {STRING.plural} מ{STRING} אל {STRING} יזכה לשיעור תשלום כפול לשנה הקרובה! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}סובסידיה לשירות ניתנה לחברת {STRING}!{}{}שירות הובלת {STRING.plural} מ{STRING} אל {STRING} יזכה לשיעור תשלום משולש לשנה הקרובה! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}סובסידיה לשירות ניתנה לחברת {STRING}!{}{}שירות הובלת {STRING.plural} מ{STRING} אל {STRING} יזכה לשיעור תשלום מוכפל פי 4 לשנה הקרובה! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}פקקי תנועה ענקיים ב{TOWN}!{}{} תכנית לשיפוץ מקיף של הכבישים במימון {STRING} מביאה לקטסטרופת תנועה לשישה חודשים STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}מונופול תחבורה! diff --git a/src/lang/hindi.txt b/src/lang/hindi.txt index 220e584b4c..b993e19477 100644 --- a/src/lang/hindi.txt +++ b/src/lang/hindi.txt @@ -29,17 +29,21 @@ STR_CARGO_PLURAL_COAL :कोयला STR_CARGO_SINGULAR_NOTHING : STR_CARGO_SINGULAR_MAIZE :मक्का STR_CARGO_SINGULAR_SWEETS :मिठाई +STR_CARGO_SINGULAR_TOFFEE :टॉफी # Quantity of cargo STR_QUANTITY_NOTHING : +STR_QUANTITY_VALUABLES :{COMMA}{NBSP}मूल्यवान वस्तुओं {P "का थैला" "के थैले"} # Two letter abbreviation of cargo name STR_ABBREV_NOTHING : +STR_ABBREV_COAL :{TINY_FONT}कोयला # 'Mode' of transport for cargoes # Colours, do not shuffle STR_COLOUR_PINK :गुलाबी +STR_COLOUR_RED :लाल # Units used in OpenTTD @@ -62,6 +66,7 @@ STR_COLOUR_PINK :गुलाब # On screen keyboard window # Measurement tooltip +STR_MEASURE_LENGTH_HEIGHTDIFF :{BLACK}लंबाई : {NUM}{}ऊंचाई का अंतर : {HEIGHT} # These are used in buttons @@ -75,6 +80,7 @@ STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :पिछले # Group by options for vehicle list # Tooltips for the main toolbar +STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW :{BLACK}ध्वनि/संगीत विकल्प # Extra tooltips for the scenario editor toolbar @@ -104,6 +110,7 @@ STR_FILE_MENU_SEPARATOR : ############ range ends here ############ range for industry menu starts +STR_INDUSTRY_MENU_INDUSTRY_CHAIN :औद्योगिक शृंखला ############ range ends here ############ range for railway construction menu starts @@ -136,6 +143,7 @@ STR_ORDINAL_NUMBER_2ND :द्वित ############ range for ordinal numbers ends ############ range for days starts +STR_DAY_NUMBER_15TH :१५वीं ############ range for days ends ############ range for months starts @@ -156,6 +164,7 @@ STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLA # Graph key window # Company league window +STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} '{STRING}' # Performance detail window ############ Those following lines need to be in this order!! @@ -168,16 +177,20 @@ STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKG # Playlist window # Highscore window +STR_HIGHSCORE_PRESIDENT_OF_COMPANY_ACHIEVES_STATUS :{BIG_FONT}{WHITE}{1:COMPANY} के {0:PRESIDENT_NAME} ने '{2:STRING}' की स्थिति प्राप्त की! # Smallmap window +STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}रिक्त भूमि +STR_SMALLMAP_LEGENDA_TOWNS :{TINY_FONT}{BLACK}नगर STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} STR_SMALLMAP_COMPANY :{TINY_FONT}{COMPANY} STR_SMALLMAP_TOWN :{TINY_FONT}{WHITE}{TOWN} # Status bar messages +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * ठहरा हुआ (संपर्क चित्र अद्यतन के लिये प्रतीक्षारत) * * # News message history @@ -186,6 +199,7 @@ STR_NEWS_CUSTOM_ITEM :{BIG_FONT}{BLAC +STR_NEWS_COMPANY_LAUNCH_DESCRIPTION :{BIG_FONT}{BLACK}{STRING} ने {TOWN} के पास निर्माण शुरु किया! @@ -208,6 +222,7 @@ STR_NEWS_NEW_VEHICLE_TYPE :{BIG_FONT}{BLAC # Game options window ############ start of currency region +STR_GAME_OPTIONS_CURRENCY_FIM :मार्का, फिनलैंड (FIM) STR_GAME_OPTIONS_CURRENCY_HKD :हाँग काँग डॉलर (एचकेडी) ############ end of currency region @@ -226,12 +241,14 @@ STR_GAME_OPTIONS_TOWN_NAME_ITALIAN :इटैलि STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH :प्रत्येक माह ############ end of autosave dropdown +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% पूर्ण) +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :सामान्य @@ -243,6 +260,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH :प्रत् # Custom currency window +STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP :{BLACK}एक पाउंड (£) की तुलना में अपनी मुद्रा का अवमूल्यन करें @@ -270,13 +288,23 @@ STR_CONFIG_SETTING_COMPANIES_OFF :बन्द +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :मानचित्र के भूभाग की अधिकतम ऊंचाई निर्धारित करें। "(स्वतः)" चुनने पर भूभाग जनन के बाद एक उपयुक्त संख्या चुन ली जायेगी। STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} +STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :ट्रेन के लिये ढलान की तेजी की स्थापना। ऊँची संख्या से चढ़ान पर चढ़ना अधिक कठिन हो जाता है। +STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :निर्दिष्ट करें कि ट्रेनों को स्टेशन पर कहाँ रुकना चाहिये। स्टेशन में प्रवेश के पास 'समीप का छोर', स्टेशन के बीच में 'मध्य', और प्रवेश की उलटी ओर 'दूर का छोर' है। ध्यान दें कि यह विन्यास केवल नये निर्देशों के लिये मानक स्थापित करता है। प्रत्येक निर्देश को अलग से किसी अन्य व्यवहार के लिये स्थापित किया जा सकता है। +STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :समीप का छोर +STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :मध्य +STR_CONFIG_SETTING_STOP_LOCATION_FAR_END :दूर का छोर +STR_CONFIG_SETTING_BRIBE_HELPTEXT :कंपनियों को स्थानीय नगर प्रशासन को रिश्वत देने की अनुमति दें। यदि रिश्वत पर किसी निरीक्षक की दृष्टि पड़ती है तो कंपनी छः महीने के लिये नगर में काम नहीं कर पायेगी। +STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :सक्षम होने पर वाहनों के निर्देशों की आवधिक जाँच की जाती है, और कुछ सुस्पष्ट मामलों को पता चलते ही एक संदेश द्वारा बताया जाता है। STR_CONFIG_SETTING_ORDER_REVIEW_OFF :नहीं +STR_CONFIG_SETTING_STATION_SPREAD_HELPTEXT :एक स्टेशन के हिस्सों के विस्तार हेतु अधिकतम क्षेत्र निर्धारित करें। ऊंची संख्या खेल को धीमा कर सकती है। +STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :बैंगनी @@ -290,6 +318,7 @@ STR_CONFIG_SETTING_SOUND_NEWS :समाचा +STR_CONFIG_SETTING_NEWS_ACCIDENTS_DISASTERS :दुर्घटनायें / आपदायें : {STRING} STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} @@ -306,6 +335,7 @@ STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_IN_2X :२x +STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}सामान्य @@ -316,8 +346,10 @@ STR_CONFIG_SETTING_SPRITE_ZOOM_LVL_IN_2X :२x # Intro window +STR_INTRO_PLAY_HEIGHTMAP :{BLACK}उभार-मानचित्र खेलें +STR_INTRO_TOOLTIP_SCENARIO_EDITOR :{BLACK}अपनी इच्छानुसार एक क्रीड़ा-विश्व/परिदृश्य बनायें @@ -335,6 +367,7 @@ STR_QUIT_YES :{BLACK}हा # Face selection window +STR_FACE_LOAD_DONE :{WHITE}ओपनटीटीडी प्रारूप पत्र से आपका प्रिय चेहरा भर लिया गया है # Network server list @@ -390,14 +423,18 @@ STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}उद ############ Leave those lines in this order!! STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :खेल अभी भी ठहरा हुआ है ({STRING}, {STRING}, {STRING}) ############ End of leave-in-this-order +STR_NETWORK_MESSAGE_CLIENT_LEAVING :छोड़ रहा है # Content downloading window +STR_CONTENT_DETAIL_SUBTITLE_ALREADY_HERE :{SILVER}यह आपके पास पहले से मौजूद है +STR_CONTENT_DETAIL_SUBTITLE_DOES_NOT_EXIST :{SILVER}यह सामग्री अज्ञात है और इसे ओपनटीटीडी में प्राप्त नहीं किया जा सकता है # Order of these is important! # Content downloading progress window # Content downloading error messages +STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD :{WHITE}डाउनलोड असफल हुआ... @@ -425,6 +462,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :खेल अ # Rail station construction window +STR_STATION_CLASS_DFLT :मानक स्टेशन # Signal window @@ -439,6 +477,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :खेल अ # Road vehicle station construction window # Waterways toolbar (last two for SE only) +STR_WATERWAYS_TOOLBAR_BUILD_CANALS_TOOLTIP :{BLACK}नहर बनायें। अनुमानित मूल्य जानने के लिये Shift दबायें # Ship depot construction window @@ -449,6 +488,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :खेल अ # Airport construction window +STR_AIRPORT_CLASS_SMALL :लघु विमानतल # Landscaping toolbar @@ -481,11 +521,13 @@ STR_FOUND_TOWN_CITY :{BLACK}शह # Houses come directly from their building names +STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION :रेलवे स्टेशन # Industries come directly from their industry names +STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL :इस्पात का रेल झूला पुल @@ -493,6 +535,7 @@ STR_FOUND_TOWN_CITY :{BLACK}शह # About OpenTTD window # Framerate display window +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL} ms STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} STR_FRAMERATE_BYTES_WARN :{YELLOW}{BYTES} STR_FRAMERATE_BYTES_BAD :{RED}{BYTES} @@ -509,6 +552,7 @@ STR_FRAMERATE_BYTES_BAD :{RED}{BYTES} # Strings for map borders at game generation STR_MAPGEN_BORDER_WATER :{BLACK}जल +STR_MAPGEN_BORDER_RANDOM :{BLACK}यादृच्छिक @@ -562,6 +606,8 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING # Town view window STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} +STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{GREEN} (पहुंचाया गया) +STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}स्थानीय प्रशासन STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}स्थानीय प्राधिकारी के बारे में जानकारी दिखाएँ STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}फैलाएँ @@ -588,6 +634,7 @@ STR_STORY_BOOK_TITLE :{YELLOW}{STRING STR_STORY_BOOK_NEXT_PAGE_TOOLTIP :{BLACK}अगले पृष्ठ पर जाएँ # Station list window +STR_STATION_LIST_TOOLTIP :{BLACK}स्टेशनों के नाम - मुख्य दृश्य को स्टेशन पर केंद्रित करने के लिये स्टेशन के नाम पर क्लिक करें। Ctrl+क्लिक करने पर एक नया दृश्य-द्वार खुलता है। STR_STATION_LIST_STATION :{YELLOW}{STATION} {STATION_FEATURES} STR_STATION_LIST_WAYPOINT :{YELLOW}{WAYPOINT} @@ -598,6 +645,7 @@ STR_STATION_VIEW_WAITING_CARGO :{WHITE}{CARGO_L +STR_STATION_VIEW_VIA :{YELLOW}{CARGO_SHORT} {STATION} द्वारा ############ range for rating starts @@ -623,6 +671,7 @@ STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE :{WHITE}{PRESIDE +STR_COMPANY_VIEW_COMPANY_NAME_BUTTON :{BLACK}कंपनी का नाम @@ -633,6 +682,7 @@ STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE :{WHITE}{PRESIDE STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}उद्योग STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PROD3 :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} # Industry view STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY} @@ -665,6 +715,8 @@ STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING ############ range for vehicle availability starts ############ range for vehicle availability ends +STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}मूल्य : {GOLD}{CURRENCY_LONG}{BLACK} भार : {GOLD}{WEIGHT_SHORT} +STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}भार : {GOLD}{WEIGHT_SHORT} ({WEIGHT_SHORT}) @@ -673,6 +725,7 @@ STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING +STR_BUY_VEHICLE_ROAD_VEHICLE_HIDE_TOGGLE_BUTTON :{BLACK}छिपायें @@ -764,6 +817,7 @@ STR_ORDER_TEXT :{STRING} {STRIN +STR_ORDER_REFIT_TOOLTIP :{BLACK}इस मार्ग पर ढोये जा रहे नौभार को बदलने के लिये नये प्रकार का नौभार चुनें। Ctrl+क्लिक करने पर परिवर्तन का आदेश निरस्त हो जायेगा। @@ -779,6 +833,7 @@ STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS :के बर # String parts to build the order string +STR_ORDER_NEAREST_DEPOT :निकटतम STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT :{STRING} {STRING} {STRING} STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT} @@ -799,6 +854,7 @@ STR_ORDER_GO_TO_STATION :{STRING} {STATI +STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}इस समयसारिणी के लिये एक आरंभिक दिनांक चुनें। Ctrl+क्लिक इस समयसारिणी की प्रारंभिक तिथि निर्धारित करता है और यदि निर्देश पूर्णतः समयसारिणी-बद्ध है तो इस निर्देश को साझा करने वाले सभी वाहनों को उनके परस्पर निर्देशों के आधार पर समानता से वितरित करता है। @@ -838,8 +894,10 @@ STR_AI_CONFIG_CHANGE_NONE : # Income 'floats' STR_INCOME_FLOAT_COST :{RED}मूल्य: {CURRENCY_LONG} +STR_FEEDER_COST :{YELLOW}हस्तांतरण : {CURRENCY_LONG}{WHITE} / {RED}मूल्य : {CURRENCY_LONG} # Saveload messages +STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :फाइल लिखने में असमर्थ # Map generation messages @@ -866,8 +924,10 @@ STR_ERROR_TOO_HIGH :{WHITE}... ब # Town related errors +STR_ERROR_CAN_T_RENAME_TOWN :{WHITE}नगर का नाम नहीं बदला जा सकता है... # Industry related errors +STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... वन केवल बर्फ की सीमा के ऊपर ही लगाये जा सकते हैं। # Station construction related errors @@ -888,6 +948,7 @@ STR_ERROR_TOO_HIGH :{WHITE}... ब # Autoreplace related errors +STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}स्वतः नवीनीकरण/बदलाव का कोई भी नियम लागू नहीं किया गया # Rail construction errors @@ -934,6 +995,7 @@ STR_ERROR_CAN_T_RENAME_SHIP :{WHITE}जह # Translatable comment for OpenTTD's desktop shortcut # Translatable descriptions in media/baseset/*.ob* files +STR_BASESOUNDS_WIN_DESCRIPTION :ट्रांस्पोर्ट टायिकून डीलक्स के विंडोज संस्करण की मूल ध्वनियां। ##id 0x2000 # Town building names @@ -949,6 +1011,7 @@ STR_INDUSTRY_NAME_BANK_TROPIC_ARCTIC :बैंक STR_SV_EMPTY : STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} उत्तर STR_SV_STNAME_AIRPORT :{STRING} हवाई अड्डा STR_SV_STNAME_BUOY :{STRING} STR_SV_STNAME_WAYPOINT :{STRING} @@ -959,13 +1022,16 @@ STR_SV_STNAME_WAYPOINT :{STRING} # Vehicle names STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_COAL_CAR :कोयला वाहन STR_VEHICLE_NAME_TRAIN_WAGON_RAIL_FRUIT_TRUCK :फल वाहन +STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_TOY_VAN :खिलौनों का डब्बा STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_BUBBLE_VAN :बबल वैन STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKIII_BUS :प्लॉडीपीहट एमके३ बस +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_ARMORED_TRUCK :फोस्टर कवचयुक्त ट्रक STR_VEHICLE_NAME_AIRCRAFT_BAKEWELL_COTSWALD_LB_3 :बेकवेल कॉट्सवॉल्ड एलबी-३ STR_VEHICLE_NAME_AIRCRAFT_BAKEWELL_LUCKETT_LB_9 :बेकवेल लकेट एलबी-९ STR_VEHICLE_NAME_AIRCRAFT_BAKEWELL_LUCKETT_LB80 :बेकवेल लकेट एलबी८० STR_VEHICLE_NAME_AIRCRAFT_BAKEWELL_LUCKETT_LB_11 :बेकवेल लकेट एलबी-११ STR_VEHICLE_NAME_AIRCRAFT_DARWIN_600 :डार्विन ‌६०० +STR_VEHICLE_NAME_AIRCRAFT_AIRTAXI_A34_1000 :एयरटैक्सी ए३४-१००० ##id 0x8800 # Formatting of some strings @@ -978,6 +1044,7 @@ STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING} # Viewport strings +STR_VIEWPORT_TOWN_POP :{WHITE}{TOWN} ({COMMA}) STR_VIEWPORT_TOWN :{WHITE}{TOWN} STR_VIEWPORT_TOWN_TINY_BLACK :{TINY_FONT}{BLACK}{TOWN} STR_VIEWPORT_TOWN_TINY_WHITE :{TINY_FONT}{WHITE}{TOWN} diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 37eb09b1f4..f5d41f3dcd 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -947,11 +947,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}A támogatás határideje lejárt:{}{}{STRING} szállításáért {STRING} és {STRING} között már nem jár támogatás STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Támogatás visszavonva:{}{}{STRING} szállítása {STRING} és {STRING} között már nem támogatott -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Támogatási ajánlat:{}{}Az első {STRING} szállító {STRING} és {STRING} között egy éves támogatást kap a helyi önkormányzattól! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STRING} és {STRING} között másfélszeres hasznot hoz neki! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STRING} és {STRING} között kétszeres hasznot hoz neki! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STRING} és {STRING} között háromszoros hasznot hoz neki! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STRING} és {STRING} között négyszeres hasznot hoz neki! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Közlekedési zűrzavar {TOWN} városában!{}{}{STRING} által indított útfelújítás keseríti meg hat hónapig az autóvezetők életét! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Szállítási monopólium! diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 43735cbc36..9e2bc79cfb 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -829,11 +829,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tilboð til samstarfssamnings runnið út:{}{}{STRING} frá {STRING} til {STRING} mun ekki vera samningsbundið. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Samsarfssamningur gerður ógildur:{}{} {STRING}flutningur frá {STRING} til {STRING} er ekki lengur samningsbundinn. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Nýtt tilboð til samstarfssamnings:{}{}Fyrsti {STRING}flutningur frá {STRING} til {STRING} mun stofna til eins árs samstarfssamnings við bæjaryfirvöld! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Samstarfssamningur gerður við {STRING}!{}{}{STRING}flutningur frá {STRING} til {STRING} mun borga 50% aukalega í heilt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Samstarfssamningur gerður við {STRING}!{}{}{STRING}flutningur frá {STRING} til {STRING} mun borga tvöfalt í heilt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Samstarfssamningur gerður við {STRING}!{}{}{STRING}flutningur frá {STRING} til {STRING} mun borga þrefalt í heilt ár! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Samstarfssamningur gerður við {STRING}!{}{}{STRING}flutningur frá {STRING} til {STRING} mun borga fjórfalt í heilt ár! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Glundroði í umferð {TOWN}!{}{}Uppbygging vega kostuð af {STRING} veldur 6 mánaða vesæld meðal ökumanna! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Flutninga einokun! diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 895775d2ca..a6e167c03b 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Penawaran subsidi berakhir:{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} mulai sekarang tidak lagi mendapat subsidi STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidi berakhir:{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} tidak lagi mendapat subsidi -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Penawaran subsidi:{}{}Jasa transportasi {STRING} pertama dari {STRING} ke {STRING} akan mendapat subsidi selama setahun dari pemkot setempat! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidi diberikan kepada {STRING}!{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} akan dibayar 50% lebih banyak hingga tahun depan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidi diberikan kepada {STRING}!{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} akan dibayar dua kali lipat hingga tahun depan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidi diberikan kepada {STRING}!{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} akan dibayar tiga kali lipat hingga tahun depan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidi diberikan kepada {STRING}!{}{}Jasa transportasi {STRING} dari {STRING} ke {STRING} akan dibayar empat kali lipat hingga tahun depan! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Kekacauan lalu lintas di {TOWN}!{}{}Program perbaikan jalan yang dibiayai oleh {STRING} mengakibat kesengsaraan bagi pengendara selama 6 bulan! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoli transportasi! diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 562a258671..665bdf8fcb 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -858,11 +858,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Glacann STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Fóirdheontas a tairiscíodh imithe as dáta:{}{}Ní thabharfar fóirdheontas ar {STRING} ó {STRING} go {STRING} anois. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Fóirdheontas tarraingte siar:{}{}Ní thabharfar fóirdheontas ar sheirbhís {STRING} ó {STRING} go {STRING} a thuilleadh. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Déantar fóirdheontas seirbhíse a thairiscint:{}{}Tabharfaidh an t-údarás aitiúil fóirdheontas bliana don chéad seirbhís {STRING} ó {STRING} go {STRING}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Bronnadh fóirdheontas seirbhíse ar {STRING}!{}{}Tabharfar 50% breise ar feadh bliana don tseirbhís {STRING} ó {STRING} go {STRING}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Bronnadh fóirdheontas seirbhíse ar {STRING}!{}{}Íocfar rátaí dúbailte ar feadh bliana don tseirbhís {STRING} ó {STRING} go {STRING}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Bronnadh fóirdheontas seirbhíse ar {STRING}!{}{}Íocfar rátaí faoi thrí ar feadh bliana don tseirbhís {STRING} ó {STRING} go {STRING}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Bronnadh fóirdheontas seirbhíse ar {STRING}!{}{}Íocfar rátaí faoi cheathair ar feadh bliana don tseirbhís {STRING} ó {STRING} go {STRING}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Anord tráchta in {TOWN}!{}{}Beidh 6 mhí de chrá croí do thiománaithe de bharr clár atógáil bóithre arna maoiniú ag {STRING}! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monaplacht ar iompar! diff --git a/src/lang/italian.txt b/src/lang/italian.txt index d1d635ae4a..6f32a248e1 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -885,11 +885,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offerta di sussidio scaduta:{}{}Il trasporto di {STRING} da {STRING} a {STRING} non darà più diritto a sovvenzioni STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Sussidio terminato:{}{}Il trasporto di {STRING} da {STRING} a {STRING} non è più sovvenzionato -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Offerta di sussidio:{}{}Il primo servizio {STRING} da {STRING} a {STRING} riceverà un anno di sovvenzioni dall'autorità locale! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Sussidio aggiudicato alla {STRING}!{}{}Il trasporto di {STRING} da {STRING} a {STRING} verrà pagato il 50% in più per il prossimo anno! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Sussidio aggiudicato alla {STRING}!{}{}Il trasporto di {STRING} da {STRING} a {STRING} verrà pagato il doppio per il prossimo anno! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Sussidio aggiudicato alla {STRING}!{}{}Il trasporto di {STRING} da {STRING} a {STRING} verrà pagato il triplo per il prossimo anno! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Sussidio aggiudicato alla {STRING}!{}{}Il trasporto di {STRING} da {STRING} a {STRING} verrà pagato il quadruplo per il prossimo anno! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffico nel caos a {TOWN}!{}{}La ricostruzione delle strade finanziata dalla {STRING} porterà 6 mesi di disagio agli automobilisti! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopolio dei trasporti! diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index f265987604..ddb3ceb50b 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}助成金交付案失効:{}{1:STRING}から{2:STRING}に{0:STRING}を運ぶ便の{}助成金交付案は失効しました STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}助成金支払満了:{}{1:STRING}から{2:STRING}に{0:STRING}を運ぶ便の{}助成金は終了しました -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}助成金交付案:{}最初に{1:STRING}から{2:STRING}へ{0:STRING}を運んだ{}会社に地元当局より1年間助成金を交付されます! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{0:STRING}が助成金を獲得!{}今後一年間{2:STRING}から{3:STRING}へ{1:STRING}を運ぶ便の{}収入は1.5倍になります! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{0:STRING}が助成金を獲得!{}今後一年間{2:STRING}から{3:STRING}へ{1:STRING}を運ぶ便の{}収入は2倍になります! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{0:STRING}が助成金を獲得!{}今後一年間{2:STRING}から{3:STRING}へ{1:STRING}を運ぶ便の{}収入は3倍になります! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{0:STRING}が助成金を獲得!{}今後一年間{2:STRING}から{3:STRING}へ{1:STRING}を運ぶ便の{}収入は4倍になります! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}混乱する道路交通!{}{}{1:STRING}が{0:TOWN}の街路補修に出資{}地元ドライバーには悪夢の半年に! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}輸送独占! diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 552ec2612c..7160293678 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}보조금 지급 계약 파기:{}{}{1:STRING}에서 {2:STRING}까지의 {0:STRING} 수송은{}더 이상 보조금을 지급하지 않습니다. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}보조금 지급 만료:{}{}{1:STRING}에서 {2:STRING}까지의{}{0:STRING} 수송 보조금은 더 이상 지급되지 않습니다. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}보조금 지급 안내:{}{}처음으로 {1:STRING}에서 {2:STRING}까지{}{0:STRING}{G 0 "을" "를"} 수송하는 회사는{}지역 당국으로부터 보조금을 받게 될 것입니다! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지의 {1:STRING} 수송에 대해 50%의 추가 보조금을 내년까지 받게 됩니다! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지의 {1:STRING} 수송에 대해 2배의 추가 보조금을 내년까지 받게 됩니다! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지의 {1:STRING} 수송에 대해 3배의 추가 보조금을 내년까지 받게 됩니다! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지의 {1:STRING} 수송에 대해 4배의 추가 보조금을 내년까지 받게 됩니다! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}의 교통 혼잡!{}{}{STRING}에 의해 실시된 도로 보수공사 프로그램으로 인해 6개월 동안 운전자들이 불편을 겪을 것입니다! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}독점 수송! diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 4322ae03b8..7985a6b4e5 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -1054,11 +1054,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Condicio subsidii discedit:{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} non diutius subveniatur STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidium retractum:{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} non diutius subvenietur -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidium oblatum:{}{}Prima vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} unum annum subveniatur ab auctoritate vicinale! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} assignatur subsidium!{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} merebit reditum sesquiplicem anno secundo! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} assignatur subsidium!{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} merebit reditum duplicem anno secundo! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{STRING} assignatur subsidium!{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} merebit reditum triplicem anno secundo! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} assignatur subsidium!{}{}Vectura {STRING.gen} a {STRING.abl} ad {STRING.acc} merebit reditum quadruplicem anno secundo! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Chaos vehicularium in {TOWN}!{}{}Reconstructio viarum, expensis a {STRING} compartis, affert miseriam autoraedariis 6 menses! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopolium Vecturae! diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index 1de03dded7..2b5bf6ed4f 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -885,11 +885,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsīdijas piedāvājums beidzies:{}{}{STRING} no {STRING} uz {STRING} subsidēšana ir atcelta STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidēšana atcelta:{}{}{STRING} pārvadājumi no {STRING} uz {STRING} turpmāk vairs netiek subsidēti -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsīdijas piedāvājums:{}{}Pirmais {STRING} pārvadātājs no {STRING} uz {STRING} vienu gadu saņems pašvaldības subsīdijas! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Pārvadājumu subsīdija piešķirta {STRING}!{}{}{STRING} pārvadājumi no {STRING} uz {STRING} saņems 50% piemaksu vienu gadu! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Pārvadājumu subsīdija piešķirta {STRING}!{}{}{STRING} pārvadājumi no {STRING} uz {STRING} saņems divkāršu samaksu vienu gadu! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Pārvadājumu subsīdija piešķirta {STRING}!{}{}{STRING} pārvadājumi no {STRING} uz {STRING} saņems trīskāršu samaksu vienu gadu! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Pārvadājumu subsīdija piešķirta {STRING}!{}{}{STRING} pārvadājumi no {STRING} uz {STRING} saņems četrkāršu samaksu vienu gadu! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Satiksmes haoss {TOWN}!{}{}{STRING} apmaksātie ielu pārbūves darbi rada vājprātu uz ielām pusgada garumā! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Pārvadājumu monopols! diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index 3df9612fb3..f4225ae5ed 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -1088,11 +1088,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidijų pasiūlymas baigėsi:{}{}{STRING.ko} pervežimas iš {STRING.ko} į {STRING.ka} daugiau nebesubsidijuojamas. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidijų laikas baigėsi:{}{}{STRING.ko} transportavimas iš {STRING} į {STRING} daugiau nebesubsidijuojamas. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidijų pasiūlymas:{}{}Pirmasis pervežęs {STRING.ka} iš {STRING} į {STRING} gaus metinę vietinės valdžios subsidiją! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidijos suteiktos {STRING}!{}{}{STRING} pervežimas iš {STRING} į {STRING} visus metus bus apmokamas 50% daugiau! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidijos suteiktos {STRING}!{}{}{STRING} pervežimas iš {STRING} į {STRING} visus metus bus apmokamas dvigubai! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidijos suteiktos {STRING}!{}{}{STRING} pervežimas iš {STRING} į {STRING} visus metus bus apmokamas trigubai! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidijos suteiktos {STRING}!{}{}{STRING} pervežimas iš {STRING} į {STRING} bus metus apmokamas keturgubai! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}: Sutriko susisiekimas keliais!{}{}Kelių rekonstrukcija, finansuojama {STRING}, sutrigdė susisiekimą keliais 6 mėnesiams! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transporto monopolija! diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index 2d642a2cba..9009431cf4 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventioun ofgelaaf:{}{}{STRING} vun {STRING} op {STRING} gëtt net méi subventionéiert STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventioun entzunn:{}{}{STRING} Service vun {STRING} op {STRING} gëtt net méi subventionéiert -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subventioun offréiert:{}{}Eischten {STRING} Service vun {STRING} op {STRING} gëtt mat énger Subventioun vun 1 Joer belount.! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subventioun geet un {STRING}!{}{}{STRING} Service vun {STRING} op {STRING} gëtt nächst Joer mat 50% Bonus bezuelt! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subventioun geet un {STRING}!{}{}{STRING} Service vun {STRING} op {STRING} gëtt nächst Joer duebel bezuelt! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subventioun geet un {STRING}!{}{}{STRING} Service vun {STRING} op {STRING} gëtt nächst Joer dräifach bezuelt! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subventioun geet un {STRING}!{}{}{STRING} Service vun {STRING} op {STRING} gëtt nächst Joer mat 400% bezuelt! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafficchaos an {TOWN}!{}{}Stroossenneibau deen vun {STRING} finanzéiert ginn ass bréngt 6 Méint Misère fir d'Autosfuerer! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 96c4382319..729c88fc41 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -834,11 +834,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tempoh tawaran subsidi tamat:{}{}{STRING} dari {STRING} ke {STRING} tidak akan diberi subsidi. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidi ditarik:{}{}Servis {STRING} dari {STRING} ke {STRING} tidak akan diberi subsidi. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidi perkhidmatan ditawarkan:{}{}Perkhidmatan {STRING} pertama dari {STRING} ke {STRING} akan mendapat subsidi selama setahun daripada pihak berkuasa tempatan! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidi perkhidmatan dianugerahkan kepada {STRING}!{}{}Perkhidmatan {STRING} dari {STRING} ke {STRING} akan ditambah bayaran 50% untuk tahun berikutnya! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidi perkhidmatan dianugerahkan kepada {STRING}!{}{}Perkhidmatan {STRING} dari {STRING} ke {STRING} akan dibayar kadar dua kali ganda untuk tahun berikutnya! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidi perkhidmatan dianugerahkan kepada {STRING}!{}{}Perkhidmatan {STRING} dari {STRING} ke {STRING} akan dibayar kadar tiga kali ganda untuk tahun berikutnya! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidi perkhidmatan dianugerahkan kepada {STRING}!{}{}Perkhidmatan {STRING} dari {STRING} ke {STRING} akan dibayar kadar empat kali ganda untuk tahun berikutnya! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Kesesakan lalulintas di {TOWN}!{}{}Rancangan pembinaan semula jalanraya dibiayai oleh {STRING} akan menyeksa pemandu kenderaan selama 6 bulan! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoly pengangkutan! diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 34a55d0c87..4dc6dd145a 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -885,11 +885,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidietilbud har gått ut:{}{}{STRING} fra {STRING} til {STRING} vil ikke subsidieres. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie er trukket tilbake:{}{}Transport av {STRING} fra {STRING} til {STRING} subsidieres ikke lenger. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidietilbud:{}{}Første transport av {STRING} fra {STRING} til {STRING} vil subsidieres av bystyret i ett år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi 50{NBSP}% ekstra fortjeneste det neste året! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi dobbel fortjeneste det neste året! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi trippel fortjeneste det neste året! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi firedobbel fortjeneste det neste året! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffikkaos i {TOWN}!{}{}Veiarbeid finansiert av {STRING} medfører 6 måneders irritasjon for bilistene! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopol! diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index f1cef4c1fc..17c7ffbb0a 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -860,11 +860,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tilbod om subsidie har gått ut:{}{}{STRING} frå {STRING} til {STRING} får ikkje lenger subsidiar STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie trekt attende:{}{}{STRING} teneste frå {STRING} til {STRING} får ikkje lenger subsidiar -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidie-tilbod:{}{}Første transport av {STRING} frå {STRING} til {STRING} vil vere subsidiert i eit år av bystyret! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidie gjeve til {STRING}!{}{}Transport av {STRING} frå {STRING} til {STRING} vil gje 50{NBSP}% ekstra forteneste det neste året! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidie gjeve til {STRING}!{}{}Transport av {STRING} frå {STRING} til {STRING} vil gje dobbel inntekt i eit år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidie gjeve til {STRING}!{}{}Transport av {STRING} frå {STRING} til {STRING} vil gje trippel inntekt i eit år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidie gjeve til {STRING}!{}{}Transport av {STRING} frå {STRING} til {STRING} vil gje firedobbel inntekt i eit år! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Ombyggjing av vegen, finansiert av {STRING}, medførar 6 månaders irritasjon for bilistane! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! diff --git a/src/lang/persian.txt b/src/lang/persian.txt index a6c6a03bcd..be0d60a541 100644 --- a/src/lang/persian.txt +++ b/src/lang/persian.txt @@ -850,11 +850,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}پیشنهاد یارانه باطل شد:{}{}{STRING} از {STRING} به {STRING} دیگر یارانه ای به همراه نخواهد داشت STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}یارانه بازپس گرفته شد:{}{}{STRING} خدمات از {STRING} به {STRING} دیگر شامل یارانه نمی باشند -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}پیشنهاد پرداخت یارانه:{}{}نخستین {STRING} خدمات از {STRING} به {STRING} توسط فرماندار محلی به مدت یک سال شامل یارانه می گردد! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} برنده یارانه خدمات گردید!{}{}{STRING} خدمات از {STRING} به {STRING} به مدت یک سال شامل ۵۰ درصد اضافه می گردد! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} برنده یارانه خدمات گردید!{}{}{STRING} خدمات از {STRING} به {STRING} به مدت یک سال دوبرابر پرداخت میشود! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK} {STRING}برنده یارانه خدمات گردید!{}{}{STRING} دستمزد خدمات از {STRING} به {STRING} به مدت یک سال سه برابر پرداخت می شود! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}یارانه خدمات به {STRING}هدیه داده شد!{}{}{STRING} خدمات ترابری از {STRING} به {STRING} تا یک سال آینده چهار برابر پرداخت خواهد شد! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}ترافیک شدید در {TOWN}!{}{}هزینه روکش کردن آسفالت توسط {STRING} پرداخت گردیده و باعث 6 ماه بدبختی و دردسر برای رانندگان شده است! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}حمل و نقل انحصاری! diff --git a/src/lang/polish.txt b/src/lang/polish.txt index 2bf694bc02..98e0c30364 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -1263,11 +1263,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsydiowanie wygasło:{}{}{STRING} z {STRING} do {STRING} nie będzie już dotowane STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Koniec dotacji:{}{}Przewóz {STRING.d} z {STRING} do {STRING} nie jest już subsydiowany -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Oferta usługi dotowanej:{}{}Pierwszy przewóz {STRING.d} z {STRING} do {STRING} będzie dotowany przez rok przez lokalne władze! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Przyznano subsydia dla {STRING}!{}{}Przewóz {STRING.d} z {STRING} do {STRING} będzie opłacany o 50% więcej przez następny rok! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Przyznano subsydia dla {STRING}!{}{}Przewóz {STRING.d} z {STRING} do {STRING} będzie opłacany podwójnie przez następny rok! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Przyznano subsydia dla {STRING}!{}{}Przewóz {STRING.d} z {STRING} do {STRING} będzie opłacany potrójnie przez następny rok! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Przyznano subsydia dla {STRING}!{}{}Przewóz {STRING.d} z {STRING} do {STRING} będzie opłacany poczwórnie przez następny rok! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Chaos na drogach w {TOWN}!{}{}Program przebudowy dróg ufundowany przez {STRING} przynosi 6 miesięcy męki dla kierowców! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopol transportowy! diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index b716c04719..536535ad0d 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subsídio expirou:{}{}Ligação de {STRING} d{G 1 e o a os as} {STRING} para{G 2 "" " o" " a" " os" " as"} {STRING} já não será subsidiada. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsídio retirado:{}{}Ligação de {STRING} d{G 1 e o a os as} {STRING} para{G 2 "" " o" " a" " os" " as"} {STRING} já não é subsidiada. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsídio de ligação oferecido:{}{}Primeiro serviço de {STRING} de {STRING} para {STRING} atrairá o subsídio de um ano da autoridade local! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Ligação de {STRING} d{G 2 e o a os as} {STRING} para{G 3 "" " o" " a" " os" " as"} {STRING} pagará 50% extra durante o próximo ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Ligação de {STRING} d{G 2 e o a os as} {STRING} para{G 3 "" " o" " a" " os" " as"} {STRING} pagará a dobrar durante o próximo ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Ligação de {STRING} d{G 2 e o a os as} {STRING} para{G 3 "" " o" " a" " os" " as"} {STRING} pagará a triplicar durante o próximo ano! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Ligação de {STRING} d{G 2 e o a os as} {STRING} para{G 3 "" " o" " a" " os" " as"} {STRING} pagará a quadruplicar durante o próximo ano! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Tráfego caótico em {TOWN}!{}{}Programa de reconstrução de estradas financiado por {STRING} provoca 6 meses de miséria aos condutores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopólio de Transporte! diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 87cfb6c7c9..6e6f5a68ba 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -860,11 +860,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Ofertă expirată:{}{}Transportul de {STRING} de la {STRING} la {STRING} nu va mai fi subvenţionat STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Ofertă retrasă:{}{}Transportul de {STRING} de la {STRING} la {STRING} nu va mai fi subvenţionat -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subvenţie oferită:{}{}Primul transport de {STRING} de la {STRING} la {STRING} va primi o subvenţie pe un an din partea autorităţilor locale! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvenţie acordată companiei {STRING}!{}{}Transportul de {STRING} de la {STRING} la {STRING} va aduce încasări cu 50% mai mari timp de un an! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvenţie acordată companiei {STRING}!{}{}Transportul de {STRING} de la {STRING} la {STRING} va aduce încasări duble timp de un an! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvenţie acordată companiei {STRING}!{}{}Transportul de {STRING} de la {STRING} la {STRING} va aduce încasări triple timp de un an! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvenţie acordată companiei {STRING}!{}{}Transportul de {STRING} de la {STRING} la {STRING} va aduce încasări de patru ori mai mari timp de un an! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Haos pe străzile din {TOWN}!{}{}Programul finanțat de {STRING} pentru reconstrucția străzilor aduce 6 luni de haos participanților la trafic! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopol de transport! diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 1752a0cf8a..1576a4a867 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -1028,11 +1028,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Предложение субсидии истекло:{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} субсидироваться не будет. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Срок субсидии истёк:{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} больше не субсидируется. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Предложена субсидия:{}{}Первая компания, которая повезёт {STRING.acc} по маршруту {STRING} - {STRING}, получит годовую субсидию от местных властей! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в полуторном размере в течение года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в двойном размере в течение года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в тройном размере в течение года! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в четырёхкратном размере в течение года! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Хаос на дорогах города{NBSP}{TOWN}!{}{}Профинансированная {STRING} реконструкция дорог на 6 месяцев парализовала работу автотранспорта! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Транспортный монополист! diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 19c3d6e9fb..a4ff5b0c36 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -1078,11 +1078,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Ponuda subvencije istekla:{}{}Prevoz {STRING.gen} iz {STRING} u {STRING} se više neće stimulisati STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvencija povučena:{}{}Usluga prevoza {STRING.gen} između stanica {STRING} i {STRING} više nije u opticaju -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ponuda subvencije:{}{}Preduzimač koji prvi preveze {STRING.aku} od {STRING} do {STRING} stiče pravo na dodatnu zaradu tokom sledeća 24 meseca! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvencija odobrena preduzeću {STRING}!{}{}Za prevoz {STRING.gen} između stanica {STRING} i {STRING} zarada će vredeti 50% više u narednih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvencija odobrena preduzeću {STRING}!{}{}Za prevoz {STRING.gen} između stanica {STRING} i {STRING} zarada će vredeti duplo više u narednih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvencija odobrena preduzeću {STRING}!{}{}Za prevoz {STRING.gen} između stanica {STRING} i {STRING} zarada će vredeti trostruko više u narednih godinu dana! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvencija odobrena preduzeću {STRING}!{}{}Za prevoz {STRING.gen} između stanica {STRING} i {STRING} zarada će vredeti četvorostruko više u narednih godinu dana! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN} - haos na ulicama!{}{}Program rekonstrukcije puteva sponzorisan od strane preduzeća {STRING} donosi vozačima 6 meseci agonije! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Prevoznički monopol! diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index ca97a96c4f..38d2891127 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}财政补贴项目到期:{}{}将 {STRING} 从 {STRING} 运送到 {STRING} 将不再获得财政补贴。 STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}财政补贴项目流标:{}{}将 {STRING} 从 {STRING} 运送到 {STRING} 将不是财政补贴项目。 -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}财政补贴项目招标:{}{}第一个将 {STRING} 从 {STRING} 运送到 {STRING} 的公司将获得地方政府为期一年的财政补贴! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} 获得财政补贴!{}{}今后一年中将 {STRING} 从 {STRING} 运送到 {STRING} 将获得 50% 的额外报酬! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} 获得财政补贴!{}{}今后一年中将 {STRING} 从 {STRING} 运送到 {STRING} 将获得双倍的报酬! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{STRING} 获得财政补贴!{}{}今后一年中将 {STRING} 从 {STRING} 运送到 {STRING} 将获得三倍的报酬! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} 获得财政补贴!{}{}今后一年中将 {STRING} 从 {STRING} 运送到 {STRING} 将获得四倍的报酬! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}的交通陷入混乱!{}{}由 {STRING} 资助的市政道路重建导致市内交通瘫痪 6 个月! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}垄断运输! diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index f9eb2453b9..473bf35647 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -951,11 +951,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Ponuka dotácie skončila:{}{}Preprava {STRING.g} z {STRING} do {STRING} už nebude dotovaná STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Dotácie stiahnuté:{}{}Preprava {STRING.g} z {STRING} do {STRING} už nie je dotovaná -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ponuka dotácie:{}{}Prvá preprava {STRING.g} z {STRING} do {STRING} bude dotovaná miestnou správou! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} do {STRING} bude budúci rok o 50% výnosnejšia! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} to {STRING} bude budúci rok 2x výnosnejšia! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} do {STRING} bude budúci rok 3x výnosnejšia! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Dotácia udelená spoločnosti {STRING}!{}{}Preprava {STRING.g} z {STRING} do {STRING} bude budúci rok 4x výnosnejšia! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}V meste {TOWN} zavládol dopravný chaos!{}{}Rekonštrukcia ciest financovaná {STRING} prinesie 6 mesiacov utrpenia pre motoristov! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Prepravné monopoly! diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index 885bcd3587..1931220d70 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -1012,11 +1012,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Ponudba subvencije potekla:{}{}Prevoz {STRING.r} od {STRING} do {STRING} ni več subvencioniran STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvencija zaključena:{}{}Prevoz {STRING.r} od {STRING} do {STRING} ni več subvencioniran -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Nova ponujena subvencija:{}{}Prvi prevoz {STRING.r} od {STRING.r} do {STRING.r} bo{}subvencioniran s strani mestnega sveta! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvencija podeljena podjetju {STRING}!{}{}Prevoz {STRING.r} od {STRING} do {STRING} bo prinesel 50% večji prihodek{}za naslednje leto! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Podjetje {STRING} je prejelo subvencijo!{}{}Prevoz {STRING.r} od {STRING} do {STRING} bo prinesel dvakratni prihodek{}za naslednje leto! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvencija odobrena podjetju {STRING}!{}{}Prevoz {STRING.r} od {STRING} do {STRING} bo prinesel trikratni prihodek{}za naslednje leto! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvencija podeljena podjetju{STRING}!{}{}Prevoz {STRING.r} od {STRING} do {STRING} bo prinesel štirikratni prihodek{}za naslednje leto! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Prometni kaos v mestu {TOWN}!{}{}Obnovitvena dela, ki jih financira podjetje {STRING},{}bodo prinesla 6 mesecev nevšečnosti{}voznikom motornih vozil! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportni monopol! diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index e69260ca03..2292a69a11 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvención terminada:{}{}{STRING} de {STRING} a {STRING} ya no conlleva una subvención STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvención retirada:{}{}El servicio de {STRING} desde {STRING} a {STRING} ya no está subvencionado -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Se ofrece subvención:{}{}¡Al primer servicio de {STRING} que cubra la línea desde {STRING} a {STRING} se le otorgará una subvención durante un año por parte de las autoridades locales! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará un 50% más caro durante un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa doble durante un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa triple durante un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa cuádruple durante un año! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}¡Colapso circulatorio en {TOWN}!{}{}¡El programa de reconstrucción de carreteras patrocinado por {STRING} causa 6 meses de problemas a los conductores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}¡Monopolio de transportes! diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index c74c5685ab..b3a24afe5f 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subsidio vencida:{}{}{STRING} de {STRING} a {STRING} ya no está subsidiado STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidio retirado:{}{}El servicio de {STRING} de {STRING} hacia {STRING} ya no está subsidiado -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Se ofrece subsidio.{}{}¡El primer servicio de {STRING} desde {STRING} a {STRING} tendrá subsidio durante un año por parte del ayuntamiento local! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará un 50% extra por un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa doble durante un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa triple durante un año! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa cuádruple por un año! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}¡Caos por el tráfico en {TOWN}!{}{}¡Obras de reconstrucción de caminos por parte de {STRING} provocan 6 meses de dolores de cabeza a conductores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}¡Monopolio de transportes! diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 98ac033fae..20f40e8d9c 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionen har gått ut:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionen gäller inte längre:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ny subvention:{}{}Första transporten av {STRING} från {STRING} till {STRING} får ett års subvention från kommunen! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger 50% extra nästa år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger dubbelt så mycket nästa år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger tre gånger så mycket nästa år! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger fyra gånger så mycket nästa år! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index d267768f00..bef67c06c8 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -851,8 +851,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO :{WHITE}{STATION STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION} இப்போது {STRING} {STRING} ஆகியவற்றை ஏற்றுக்கொள்கிறது STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}மானியம் இனிமேல் தரப்படாது:{}{}{STRING} இருந்து {STRING} {STRING} வரை போக்குவரத்திற்கு மானியம் வழங்கப்படாது -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} இற்கு சேவை மானியம் வழங்கப்படுகிறது!{}{} {STRING} முதல் {STRING} வரையிலான {STRING} சேவை அடுத்த ஆண்டுக்கு 50% கூடுதல் கட்டணம் செலுத்தும்! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} இற்கு சேவை மானியம் வழங்கப்படுகிறது!{}{}{STRING} முதல் {STRING} வரையிலான {STRING} சேவை அடுத்த ஆண்டுக்கு 4 மடங்கு கட்டணம் செலுத்தும்! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}இல் சாலை போக்குவரத்து பாதிப்பு!{}{}Road rebuilding programme funded by {STRING} brings 6 months of misery to motorists! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}போக்குவரத்து தனியுரிமை! diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 2cd77a140e..72772f5291 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -849,11 +849,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}ข้อเสนอสำหรับการอุดหนุนสิ้นสุด:{}{}{STRING} จาก {STRING} ถึง {STRING} จะไม่ได้รับการอุดหนุนอีกต่อไป. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}การอุดหนุนถูกถอดถอน:{}{}บริการ {STRING} จาก {STRING} ถึง {STRING} จะไม่ได้รับการสนับสนุนอีกต่อไป. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}มีการสนับสนุนในการทำโครงการ:{}{} ขนส่ง {STRING} เที่ยวปฐมฤกษ์ จาก {STRING} ถึง {STRING} หากดำเนินการจะได้รับเงินอุดหนุนพิเศษรายปีจากเจ้าหน้าที่ในท้องถิ่น! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}เงินสนับสนุนโครงการถูกมอบให้กับ {STRING}!{}{} โดยการขนส่ง {STRING} จาก {STRING} ถึง {STRING} จะได้รับเงินอุดหนุนเพิ่มขึ้น 50% สำหรับปีหน้า! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}การอุดหนุนบริการถูกมอบแก่ {STRING}!{}{}บริการ {STRING} จาก {STRING} ถึง {STRING} จะได้รับเงินสองเท่าในปีหน้า! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}การอุดหนุนบริการถูกมอบแก่ {STRING}!{}{}บริการ {STRING} จาก {STRING} ถึง {STRING} จะได้รับเงินสามเท่าในปีหน้า! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}การอุดหนุนบริการถูกมอบแก่ {STRING}!{}{} บริการ {STRING} จาก {STRING} ถึง {STRING} จะได้รับเงินสี่เท่าในปีหน้า! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}การจราจรยุ่งเหยิงใน {TOWN}!{}{}การสร้างถนนใหม่ที่ได้รับการสนับสนุนโดย {STRING} นำมาซึ่งหกเดือนแห่งความสงสัยแก่ผู้ใช้ถนน! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}เจ้าพ่อวงการขนส่ง! diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 1441c0f474..90f18e8ba2 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -863,11 +863,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}補助過期:{}{}將 {STRING} 從 {STRING} 運到 {STRING} 現在起不再提供補助 STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}補助結束:{}{}將 {STRING} 從 {STRING} 運到 {STRING} 的服務不再提供補助 -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}提供補助:{}{}首先將 {STRING} 從 {STRING} 運到 {STRING} 的公司將得到地方政府補助一年! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{STRING} 獲得補助!{}{}將 {STRING} 從 {STRING} 運到 {STRING} 的服務可在往後一年收到額外 50% 的運費補助! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{STRING} 獲得補助!{}{}將 {STRING} 從 {STRING} 運到 {STRING} 的服務可在往後一年收到雙倍運費補助! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{STRING} 獲得補助!{}{}將 {STRING} 從 {STRING} 運到 {STRING} 的服務可在往後一年收到三倍運費補助! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{STRING} 獲得補助!{}{}將 {STRING} 從 {STRING} 運到 {STRING} 的服務可在往後一年收到四倍運費補助! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN} 交通大亂!{}{}{STRING} 出資的道路重建計劃為用路人帶來六個月的惡夢! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}運輸大亨! diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index 5bdb533ff2..d047e8ea6e 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -884,11 +884,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Teşvik önerisinin süresi doldu:{}{}{1:STRING} ile {2:STRING} arasındaki {0:STRING} taşıma hizmeti artık teşvik almayacak STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Teşvik geri çekildi:{}{}{1:STRING} ile {2:STRING} arasındaki {0:STRING} taşıma hizmeti artık teşvik almayacak -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Hizmet teşviği önerildi:{}{} {1:STRING} -> {2:STRING} arası ilk {0:STRING} taşıma hizmeti belediyeden teşvik alacak! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Hizmet teşviği {0:STRING} şirketine verildi!{}{}{2:STRING} -> {3:STRING} arasındaki {1:STRING} taşıma hizmeti bir yıl boyunca %50 fazla gelir sağlayacak! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Hizmet teşviği {0:STRING} şirketine verildi!{}{}{2:STRING} -> {3:STRING} arasındaki {1:STRING} taşıma hizmeti bir yıl boyunca iki kat fazla gelir sağlayacak! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Hizmet teşviği {0:STRING} şirketine verildi!{}{}{2:STRING} -> {3:STRING} arasındaki {1:STRING} taşıma hizmeti bir yıl boyunca üç kat fazla gelir sağlayacak! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Hizmet teşviği {0:STRING} şirketine verildi!{}{}{2:STRING} -> {3:STRING} arasındaki {1:STRING} taşıma hizmeti bir yıl boyunca dört kat fazla gelir sağlayacak! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK} {TOWN} şehrinde trafik durdu!{}{} {STRING} şirketinin yol yapım çalışmaları başladı! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Taşımacılıkta tekel! diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index 740fa37aa7..4ea3356a40 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -1011,11 +1011,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Субсидія більше не пропонується:{}{}Перевезення {STRING.r} з {STRING} до {STRING} STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Субсидію скасовано:{}{}Перевезення {STRING.r} з {STRING.r} до {STRING.r} -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Пропонується річна субсидія{}{}компанії, яка першою привезе {STRING.z} з {STRING} до {STRING}! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Субсидію надано {STRING}!{}{}Перевезення {STRING.r} з {STRING} до {STRING} принесе додатково 50% протягом наступного року! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Субсидію надано {STRING}!{}{}Перевезення {STRING.r} з {STRING} до {STRING} принесе вдвічі більше прибутків наступного року! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Субсидію надано {STRING}!{}{}Перевезення {STRING.r} з {STRING} до {STRING} принесе втричі більше прибутків наступного року! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Субсидію надано {STRING}!{}{}Перевезення {STRING.r} з {STRING} до {STRING} принесе вчетверо більше прибутків наступного року! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Транспортний безлад у місті {TOWN}!{}{}Реконструкція доріг, фінансована компанією {STRING} принесе транспорту незручності протягом 6 місяців! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Транспортна монополія! diff --git a/src/lang/urdu.txt b/src/lang/urdu.txt index 330cf32824..df5005cdba 100644 --- a/src/lang/urdu.txt +++ b/src/lang/urdu.txt @@ -829,11 +829,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}امداد کی پیشکش کی معیاد ختم:{}{}{STRING} {STRING} سے {STRING} تک اب کوئی امداد نہیں ملے گی STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}امداد ختم:{}{}{STRING} {STRING} سے {STRING} تک کئی گئی خدمت کی اب کوئی امداد نہیں ملے گی -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}خدمات پر امداد کی پیشکش:{}{}پہلی خدمت {STRING} جو {STRING} سے {STRING} تک ہو، پر ایک سال تک امدام ملے گی -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}خدمات پر{STRING} کو امداد دے دی گئی!{}{}{STRING} {STRING} سے {STRING} تک دی جانے والی خدمات پر اگلے سال 50٪ زیادہ ملیں گے -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}خدمات پر{STRING} کو امداد دے دی گئی!{}{}{STRING} {STRING} سے {STRING} تک دی جانے والی خدمات پر اگلے سال دُگنے پیسے ملیں گے -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}خدمات پر{STRING} کو امداد دے دی گئی!{}{}{STRING} {STRING} سے {STRING} تک دی جانے والی خدمات پر اگلے سال تین گُنا پیسے ملیں گے -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}خدمات پر{STRING} کو امداد دے دی گئی!{}{}{STRING} {STRING} سے {STRING} تک دی جانے والی خدمات پر اگلے سال چار گُنا پیسے ملیں گے STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN} میں ٹریفک کا بُرا حال!{}{}سڑکیں دوبارہ بنوانے کے پیسے {STRING} نے دئیے۔ اس کی وجہ سے اگلے 6 ماہ مشکل رہے گی diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 0f60717951..d525de771f 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -883,11 +883,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Lời đề nghị trợ cấp đã hết hạn:{}{}{STRING} từ {STRING} đến {STRING} bây giờ sẽ không có trợ cấp. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Trợ cấp đã hết:{}{}Dịch vụ vận chuyển {STRING} từ {STRING} đến {STRING} sẽ không được trợ cấp nữa. -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Đề nghị trợ cấp:{}{}Dịch vụ vận tải {STRING} đầu tiên từ {STRING} đến {STRING} sẽ nhận được tiền trợ cấp trong một năm của chính quyền địa phương! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Trợ cấp dịch vụ được trao cho {STRING}!{}{}Dịch vụ {STRING} từ {STRING} đến {STRING} sẽ thu lợi cao hơn 50% đến năm sau! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Trợ cấp dịch vụ được trao cho {STRING}!{}{}Dịch vụ {STRING} từ {STRING} đến {STRING} sẽ thu lợi gấp đôi đến năm sau! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Trợ cấp dịch vụ được trao cho {STRING}!{}{}Dịch vụ {STRING} từ {STRING} đến {STRING} sẽ thu lợi gấp ba đến năm sau! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Trợ cấp dịch vụ được trao cho {STRING}!{}{}Dịch vụ {STRING} từ {STRING} đến {STRING} sẽ thu lợi gấp tư đến năm sau! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Giao thông hỗn loạn tại {TOWN}!{}{}Chương trình sửa đường đầu tư bởi {STRING} mang 6 tháng khốn đốn cho người chạy mô tô! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Độc quyền vận tải! diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index c2ef7f65c9..695c08f651 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -859,11 +859,6 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Mae {STA STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Cynnig cymhorthdal ar ben:{}{}Ni fydd cludo {STRING} o {STRING} i {STRING} yn derbyn cymhorthdal bellach STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Cymhorthdal wedi'i dynnu'n ôl:{}{}Ni fydd gwasanaeth {STRING} o {STRING} i {STRING} yn derbyn cymhorthdal bellach -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Cynnig cymhorthdal:{}{}Bydd y gwasanaeth {STRING} cyntaf o {STRING} i {STRING} yn derbyn blwyddyn o gymhorthdal gan yr awdurdod lleol! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu 50% yn fwy am y flwyddyn nesaf! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu dwywaith yn fwy am y flwyddyn nesaf! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu teirgwaith yn fwy am y flwyddyn nesaf! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu pedair gwaith yn fwy am y flwyddyn nesaf! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Anrhefn traffig yn {TOWN}!{}{}Daw gwaith ffordd a ariannwyd gan {STRING} â 6 mis o boen i deithwyr ffordd y dref! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoli cludiant! From f1328db063fe0808a55e7ed76304491b84916146 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 4 Jun 2021 12:52:00 +0100 Subject: [PATCH 354/800] Codechange: Deduplicate ResolveReal() for resolvers that don't use real sprite groups. This may change behaviour when multiple loading/loaded stages are provided, as the various copies checked in different orders, however only one result is expected in these cases anyway. --- src/newgrf_airport.cpp | 12 ------------ src/newgrf_canal.cpp | 10 ---------- src/newgrf_cargo.cpp | 12 ------------ src/newgrf_generic.cpp | 10 ---------- src/newgrf_railtype.cpp | 7 ------- src/newgrf_railtype.h | 2 -- src/newgrf_roadtype.cpp | 7 ------- src/newgrf_roadtype.h | 2 -- src/newgrf_spritegroup.cpp | 3 +++ 9 files changed, 3 insertions(+), 62 deletions(-) diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 86b65fd0e3..df400145d5 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -57,8 +57,6 @@ struct AirportResolverObject : public ResolverObject { } } - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override; uint32 GetDebugID() const override; }; @@ -219,16 +217,6 @@ void AirportOverrideManager::SetEntitySpec(AirportSpec *as) return this->st->GetNewGRFVariable(this->ro, variable, parameter, available); } -/* virtual */ const SpriteGroup *AirportResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - /* Airport action 2s should always have only 1 "loaded" state, but some - * times things don't follow the spec... */ - if (!group->loaded.empty()) return group->loaded[0]; - if (!group->loading.empty()) return group->loading[0]; - - return nullptr; -} - GrfSpecFeature AirportResolverObject::GetFeature() const { return GSF_AIRPORTS; diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 6b3c9b3d42..2977c96a82 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -49,8 +49,6 @@ struct CanalResolverObject : public ResolverObject { } } - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override; uint32 GetDebugID() const override; }; @@ -108,14 +106,6 @@ struct CanalResolverObject : public ResolverObject { return UINT_MAX; } - -/* virtual */ const SpriteGroup *CanalResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - if (group->loaded.empty()) return nullptr; - - return group->loaded[0]; -} - GrfSpecFeature CanalResolverObject::GetFeature() const { return GSF_CANALS; diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index 105a2b2524..70b1a18d94 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -19,22 +19,10 @@ struct CargoResolverObject : public ResolverObject { CargoResolverObject(const CargoSpec *cs, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0); - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override; uint32 GetDebugID() const override; }; -/* virtual */ const SpriteGroup *CargoResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - /* Cargo action 2s should always have only 1 "loaded" state, but some - * times things don't follow the spec... */ - if (!group->loaded.empty()) return group->loaded[0]; - if (!group->loading.empty()) return group->loading[0]; - - return nullptr; -} - GrfSpecFeature CargoResolverObject::GetFeature() const { return GSF_CARGOES; diff --git a/src/newgrf_generic.cpp b/src/newgrf_generic.cpp index 0a138f1d64..c59964714d 100644 --- a/src/newgrf_generic.cpp +++ b/src/newgrf_generic.cpp @@ -63,8 +63,6 @@ struct GenericResolverObject : public ResolverObject { } } - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override { return (GrfSpecFeature)this->generic_scope.feature; @@ -147,14 +145,6 @@ void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *g return UINT_MAX; } - -/* virtual */ const SpriteGroup *GenericResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - if (group->loaded.empty()) return nullptr; - - return group->loaded[0]; -} - /** * Generic resolver. * @param ai_callback Callback comes from the AI. diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 407acc9844..95d891f246 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -58,13 +58,6 @@ return UINT_MAX; } -/* virtual */ const SpriteGroup *RailTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - if (!group->loading.empty()) return group->loading[0]; - if (!group->loaded.empty()) return group->loaded[0]; - return nullptr; -} - GrfSpecFeature RailTypeResolverObject::GetFeature() const { return GSF_RAILTYPES; diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index c382117385..d33504e364 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -49,8 +49,6 @@ struct RailTypeResolverObject : public ResolverObject { } } - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override; uint32 GetDebugID() const override; }; diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 9243bf77e3..4f3b612908 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -58,13 +58,6 @@ return UINT_MAX; } -/* virtual */ const SpriteGroup *RoadTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const -{ - if (!group->loading.empty()) return group->loading[0]; - if (!group->loaded.empty()) return group->loaded[0]; - return nullptr; -} - GrfSpecFeature RoadTypeResolverObject::GetFeature() const { RoadType rt = GetRoadTypeByLabel(this->roadtype_scope.rti->label, false); diff --git a/src/newgrf_roadtype.h b/src/newgrf_roadtype.h index 0e08697932..748d62e82c 100644 --- a/src/newgrf_roadtype.h +++ b/src/newgrf_roadtype.h @@ -40,8 +40,6 @@ struct RoadTypeResolverObject : public ResolverObject { } } - const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; - GrfSpecFeature GetFeature() const override; uint32 GetDebugID() const override; }; diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 29080894ec..d5376116e1 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -124,6 +124,9 @@ static inline uint32 GetVariable(const ResolverObject &object, ScopeResolver *sc */ /* virtual */ const SpriteGroup *ResolverObject::ResolveReal(const RealSpriteGroup *group) const { + if (!group->loaded.empty()) return group->loaded[0]; + if (!group->loading.empty()) return group->loading[0]; + return nullptr; } From 40cec34836a694e7388a4421d746e5238a57b608 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 4 Jun 2021 12:31:00 +0100 Subject: [PATCH 355/800] Change: Skip creating a RealSpriteGroup when there is only one result. This avoids checking RSG for empty sets every time they are evaluated. This might alter behaviour in cases of a malformed NewGRF file. --- src/newgrf.cpp | 55 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 318c5e8ea8..1432c0660e 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -109,7 +109,7 @@ public: int skip_sprites; ///< Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file) /* Currently referenceable spritegroups */ - SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1]; + const SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1]; /** Clear temporary data before processing the next file in the current loading stage */ void ClearDataForNextFile() @@ -4982,7 +4982,7 @@ static void NewSpriteGroup(ByteReader *buf) * otherwise it specifies a number of entries, the exact * meaning depends on the feature * V feature-specific-data (huge mess, don't even look it up --pasky) */ - SpriteGroup *act_group = nullptr; + const SpriteGroup *act_group = nullptr; uint8 feature = buf->ReadByte(); if (feature >= GSF_END) { @@ -5163,24 +5163,53 @@ static void NewSpriteGroup(ByteReader *buf) return; } + grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading", + setid, num_loaded, num_loading); + + if (num_loaded + num_loading == 1) { + /* Avoid creating 'Real' sprite group if only one option. */ + uint16 spriteid = buf->ReadWord(); + act_group = CreateGroupFromGroupID(feature, setid, type, spriteid); + grfmsg(8, "NewSpriteGroup: one result, skipping RealSpriteGroup = subset %u", spriteid); + break; + } + + std::vector loaded; + std::vector loading; + + for (uint i = 0; i < num_loaded; i++) { + loaded.push_back(buf->ReadWord()); + grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, loaded[i]); + } + + for (uint i = 0; i < num_loading; i++) { + loading.push_back(buf->ReadWord()); + grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, loading[i]); + } + + if (std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end() && + std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end() && + loaded[0] == loading[0]) + { + /* Both lists only contain the same value, so don't create 'Real' sprite group */ + act_group = CreateGroupFromGroupID(feature, setid, type, loaded[0]); + grfmsg(8, "NewSpriteGroup: same result, skipping RealSpriteGroup = subset %u", loaded[0]); + break; + } + assert(RealSpriteGroup::CanAllocateItem()); RealSpriteGroup *group = new RealSpriteGroup(); group->nfo_line = _cur.nfo_line; act_group = group; - grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading", - setid, num_loaded, num_loading); - - for (uint i = 0; i < num_loaded; i++) { - uint16 spriteid = buf->ReadWord(); - group->loaded.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); - grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid); + for (uint16 spriteid : loaded) { + const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loaded.push_back(t); } - for (uint i = 0; i < num_loading; i++) { - uint16 spriteid = buf->ReadWord(); - group->loading.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); - grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid); + for (uint16 spriteid : loading) { + const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loading.push_back(t); } break; From 71f3c35288e0b7a357918b285d9fbfa0bc8060dc Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 12 Jun 2021 16:45:26 +0200 Subject: [PATCH 356/800] Fix #9353: [Script] Garbage collecting on priority queues could crash the game --- src/script/script_instance.cpp | 7 +++++-- src/script/script_instance.hpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index 7c2fa43d67..c354126ca7 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -254,9 +254,12 @@ void ScriptInstance::GameLoop() } } -void ScriptInstance::CollectGarbage() const +void ScriptInstance::CollectGarbage() { - if (this->is_started && !this->IsDead()) this->engine->CollectGarbage(); + if (this->is_started && !this->IsDead()) { + ScriptObject::ActiveInstance active(this); + this->engine->CollectGarbage(); + } } /* static */ void ScriptInstance::DoCommandReturn(ScriptInstance *instance) diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp index 4709c44e2f..7db4f5ea8f 100644 --- a/src/script/script_instance.hpp +++ b/src/script/script_instance.hpp @@ -68,7 +68,7 @@ public: /** * Let the VM collect any garbage. */ - void CollectGarbage() const; + void CollectGarbage(); /** * Get the storage of this script. From 8dd846bad42eebc9bf37d62d635b9c3f19e72016 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 12 Jun 2021 18:56:05 +0000 Subject: [PATCH 357/800] Update: Translations from eints norwegian (bokmal): 10 changes by Anolitt korean: 9 changes by telk5093 russian: 9 changes by Ln-Wolf finnish: 10 changes by hpiirai spanish: 8 changes by MontyMontana french: 9 changes by glx22 --- src/lang/finnish.txt | 11 ++++++++++- src/lang/french.txt | 9 +++++++++ src/lang/korean.txt | 9 +++++++++ src/lang/norwegian_bokmal.txt | 10 ++++++++++ src/lang/russian.txt | 9 +++++++++ src/lang/spanish.txt | 10 ++++++++-- 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 158b4e079a..99082055bb 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -883,6 +883,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tukitarjous päättynyt:{}{}{STRING} välillä {STRING} - {STRING} ei voi enää saada tukea STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Tuki vedetty pois:{}{}{STRING} kuljetuspalvelu välille {STRING}-{STRING} ei ole enää tuettu +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Tuki tarjottu:{}{}Ensimmäinen {STRING}kuljetus välillä {STRING} – {STRING} saa {NUM} vuoden mittaisen tuen paikallisviranomaisilta! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING} – {STRING} tuottaa 50{NBSP}% enemmän seuraavan {NUM} vuoden ajan! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING} – {STRING} tuottaa kaksinkertaisesti seuraavan {NUM} vuoden ajan! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING} – {STRING} tuottaa kolminkertaisesti seuraavan {NUM} vuoden ajan! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING} – {STRING} tuottaa nelinkertaisesti seuraavan {NUM} vuoden ajan! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}: liikennekaaos!{}{}{STRING} rahoittaa katujen kunnostuksen; autoilijoille odotettavissa kuusi kuukautta kurjuutta! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Kuljetusmonopoli! @@ -1198,6 +1203,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Kulkuneuvojen h STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Määritä, kuinka usein puutteellisesti huolletut ajoneuvot voivat hajota STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Tukikerroin: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Määritä kuinka paljon tuetuista yhteyksistä maksetaan +STR_CONFIG_SETTING_SUBSIDY_DURATION :Tuen kesto: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Aseta myönnetyn tuen kesto vuosina. +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} vuo{P "si" "tta"} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Ei tukia STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Rakennuskustannukset: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Määritä rakennus- ja ostokustannusten taso STR_CONFIG_SETTING_RECESSIONS :Lamat: {STRING} @@ -3930,7 +3939,7 @@ STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE :{LTBLUE}{ENGINE STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE :{LTBLUE}{ENGINE}{BLACK} Arvo: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT :{BLACK}Kokonaisrahtikapasiteetti: -STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY :{LTBLUE}- {CARGO_LONG} ({CARGO_SHORT}) +STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY :{LTBLUE}– {CARGO_LONG} ({CARGO_SHORT}) STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_MULT :{LTBLUE}– {CARGO_LONG} ({CARGO_SHORT}) (×{NUM}) STR_VEHICLE_DETAILS_CARGO_EMPTY :{LTBLUE}Tyhjä diff --git a/src/lang/french.txt b/src/lang/french.txt index b1e3c04cf0..105c4c5600 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -884,6 +884,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offre de subvention expirée{NBSP}:{}{}Le transport de {STRING} entre {STRING} et {STRING} n'est désormais plus subventionné STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Abandon de la subvention{NBSP}:{}{}Le transport de {STRING} entre {STRING} et {STRING} n'est plus subventionné +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Offre de subvention{NBSP}:{}{}Le premier service de {STRING} entre {STRING} et {STRING} sera subventionné pendant {P 3 la les} {NUM} prochaine{P "" s} année{P "" s}{NBSP}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera 50{NBSP}% de plus pendant {P 4 la les} {NUM} prochaine{P "" s} année{P "" s}{NBSP}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera double pendant {P 4 la les} {NUM} prochaine{P "" s} année{P "" s}{NBSP}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera triple pendant {P 4 la les} {NUM} prochaine{P "" s} année{P "" s}{NBSP}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention accordée à {STRING}{NBSP}!{}{}Le transport de {STRING} entre {STRING} et {STRING} rapportera quadruple pendant {P 4 la les} {NUM} prochaine{P "" s} année{P "" s}{NBSP}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Problèmes de trafic à {TOWN}{NBSP}!{}{}La reconstruction des routes financée par {STRING} provoque 6 mois de problèmes aux automobilistes{NBSP}! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopole des transports{NBSP}! @@ -1199,6 +1204,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Pannes des véh STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Contrôle la fréquence des pannes des véhicule incorrectement entretenus STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicateur de subvention{NBSP}: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Définit combien rapportent les lignes subventionnées +STR_CONFIG_SETTING_SUBSIDY_DURATION :Durée de subvention{NBSP}: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Définir le nombre d'années pour lesquelles une subvention est accordée +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} an{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Pas de subventions STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Coûts de construction{NBSP}: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Définit le niveau des coûts de construction et d'achat STR_CONFIG_SETTING_RECESSIONS :Récessions{NBSP}: {STRING} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 7160293678..d9adccf79b 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -884,6 +884,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}보조금 지급 계약 파기:{}{}{1:STRING}에서 {2:STRING}까지의 {0:STRING} 수송은{}더 이상 보조금을 지급하지 않습니다. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}보조금 지급 만료:{}{}{1:STRING}에서 {2:STRING}까지의{}{0:STRING} 수송 보조금은 더 이상 지급되지 않습니다. +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}보조금 지급 안내{}{}처음으로 {1:STRING}에서 {2:STRING}까지{}{0:STRING}{G 0 "을" "를"} 수송하는 회사는{}지역 당국으로부터 {3:NUM}년간 보조금을 받게 될 것입니다! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지 {1:STRING}{G 1 "을" "를"} 수송에 대해 {4:NUM}년간 50%의 추가 보조금을 받게 됩니다! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지 {1:STRING}{G 1 "을" "를"} 수송에 대해 {4:NUM}년간 2배의 추가 보조금을 받게 됩니다! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지 {1:STRING}{G 1 "을" "를"} 수송에 대해 {4:NUM}년간 3배의 추가 보조금을 받게 됩니다! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}{0:STRING}에게 보조금 지급!{}{}{2:STRING}에서 {3:STRING}까지 {1:STRING}{G 1 "을" "를"} 수송에 대해 {4:NUM}년간 4배의 추가 보조금을 받게 됩니다! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}{TOWN}의 교통 혼잡!{}{}{STRING}에 의해 실시된 도로 보수공사 프로그램으로 인해 6개월 동안 운전자들이 불편을 겪을 것입니다! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}독점 수송! @@ -1199,6 +1204,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :차량 고장 STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :점검을 제대로 받지 않은 차량이 얼마나 자주 고장나도록 할지를 조절하십시오. STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :보조금 배수: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :보조금을 얼마나 지급할지 설정하십시오. +STR_CONFIG_SETTING_SUBSIDY_DURATION :보조금 기간: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :보조금이 몇 년 동안 지급될 지 설정할 수 있습니다. +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM}년 +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :보조금 없음 STR_CONFIG_SETTING_CONSTRUCTION_COSTS :건설 가격: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :건설 및 구매 가격의 수준을 설정하십시오. STR_CONFIG_SETTING_RECESSIONS :경제 불황: {STRING} diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 4dc6dd145a..2d14178c1f 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -885,6 +885,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidietilbud har gått ut:{}{}{STRING} fra {STRING} til {STRING} vil ikke subsidieres. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie er trukket tilbake:{}{}Transport av {STRING} fra {STRING} til {STRING} subsidieres ikke lenger. +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidietilbud:{}{}Første transport av {STRING} fra {STRING} til {STRING} vil subsidieres av bystyret i {NUM} år! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi 50{NBSP}% ekstra fortjeneste det neste {NUM} året{P "" s}!! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi dobbel fortjeneste det neste {NUM} året{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi trippel fortjeneste det neste {NUM} året{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidie gitt til {STRING}!{}{}Transport av {STRING} fra {STRING} til {STRING} vil gi firedobbel fortjeneste det neste {NUM} året{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffikkaos i {TOWN}!{}{}Veiarbeid finansiert av {STRING} medfører 6 måneders irritasjon for bilistene! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopol! @@ -1200,6 +1205,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Havarerte kjør STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Kontrollér hvor ofte mangelfullt vedlikeholdte kjøretøy kan bryte sammen STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplikator for subsidier: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Angi hvor mye som betales for subsidierte forbindelser +STR_CONFIG_SETTING_SUBSIDY_DURATION :Subsidiens varighet: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Angi antall år som subsidiet tildeles for +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} år{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Ingen subsidier STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Byggekostnader: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Still kostnadsnivå for bygging og kjøp STR_CONFIG_SETTING_RECESSIONS :Resesjoner: {STRING} @@ -2203,6 +2212,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kunne ik STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tilkobling #{NUM} ble tidsavbrutt STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Forbindelsen ble brutt pga. en protokollfeil STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Spillernavnet ditt er ikke angitt. Navnet kan angis øverst i flerspillervinduet +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Du har ikke valgt servernavn. Navnet kan velges øverst i flerspillervinduet STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Klientversjonen er ikke den samme som tjenerversjonen STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Feil passord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Tjeneren er full diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 1576a4a867..f2356d6856 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -1028,6 +1028,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Предложение субсидии истекло:{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} субсидироваться не будет. STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Срок субсидии истёк:{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} больше не субсидируется. +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Предложена субсидия:{}{}Первая компания, которая повезёт {STRING.acc} по маршруту {STRING} - {STRING}, будет получать субсидию от местных властей в течение {NUM} {P года лет лет}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в полуторном размере в течение {NUM} {P года лет лет}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в двойном размере в течение {NUM} {P года лет лет}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в тройном размере в течение {NUM} {P года лет лет}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Компания «{STRING}» получает субсидию!{}{}Перевозка {STRING.gen} по маршруту {STRING} - {STRING} будет оплачиваться в четырёхкратном размере в течение {NUM} {P года лет лет}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Хаос на дорогах города{NBSP}{TOWN}!{}{}Профинансированная {STRING} реконструкция дорог на 6 месяцев парализовала работу автотранспорта! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Транспортный монополист! @@ -1349,6 +1354,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Вероятн STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Частота поломок недостаточно качественно обслуживаемого транспорта STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Множитель субсидий: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Установите множитель оплаты за субсидируемые перевозки +STR_CONFIG_SETTING_SUBSIDY_DURATION :Длительность субсидий: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Время, в течение которого выплачиваются субсидии. +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} {P год года лет} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :субсидии отключены STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Затраты на строительство: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Установите уровень затрат на строительство и приобретение STR_CONFIG_SETTING_RECESSIONS :Спады: {STRING} diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 2292a69a11..7bbb2507b2 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -884,6 +884,8 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvención terminada:{}{}{STRING} de {STRING} a {STRING} ya no conlleva una subvención STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvención retirada:{}{}El servicio de {STRING} desde {STRING} a {STRING} ya no está subvencionado +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Se ofrece subvención:{}{}¡Al primer servicio de {STRING} que cubra la línea desde {STRING} a {STRING} se le otorgará una subvención durante {NUM} año{P "" s} por parte de las autoridades locales! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa doble durante los próximos {NUM} año{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}¡Colapso circulatorio en {TOWN}!{}{}¡El programa de reconstrucción de carreteras patrocinado por {STRING} causa 6 meses de problemas a los conductores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}¡Monopolio de transportes! @@ -1197,8 +1199,12 @@ STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Velocidad de co STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Limita la velocidad de las acciones de construcción para las IA STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Averías de vehículos: {STRING} STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controla la frecuencia con la que los vehículos con mantenimiento inadecuado se averían -STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador por subsidio: {STRING} +STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador de la subvención: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Permite fijar a cuanto se pagan las conexiones con subsidio +STR_CONFIG_SETTING_SUBSIDY_DURATION :Duración de las subvenciones: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Establece el número de años para los cuales se conceden las subvenciones +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} año{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sin subvenciones STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costes de construcción: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Fija el nivel de los costes de construcción y compra STR_CONFIG_SETTING_RECESSIONS :Recesiones: {STRING} @@ -2200,7 +2206,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pu STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se ha producido un error de protocolo y la conexión ha sido cerrada STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No se ha establecido tu nombre de jugador. El nombre se puede establecer en la parte superior de la ventana de Multijugador -STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}El nombre de tu servidor no se ha definido. El nombre puede definirse al principio de la ventana de Multijugador +STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}No se ha establecido el nombre de tu servidor. El nombre se puede establecer en la parte superior de la ventana de Multijugador STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo From 418e0ea85f69196845c16193954dedee33191cb5 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 12 Jun 2021 19:13:22 +0200 Subject: [PATCH 358/800] Codechange: Use dynamic string list for contents of land info window. --- src/gfx.cpp | 15 ++++++ src/gfx_func.h | 1 + src/misc_gui.cpp | 117 +++++++++++++++++++---------------------------- 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index a4bac6e13f..e44cb708c2 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -889,6 +889,21 @@ Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize) return layout.GetBounds(); } +/** + * Return the string dimension in pixels. The height and width are returned + * in a single Dimension value. TINYFONT, BIGFONT modifiers are only + * supported as the first character of the string. The returned dimensions + * are therefore a rough estimation correct for all the current strings + * but not every possible combination + * @param str string to calculate pixel-width + * @param start_fontsize Fontsize to start the text with + * @return string width and height in pixels + */ +Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize) +{ + return GetStringBoundingBox(str.c_str(), start_fontsize); +} + /** * Get bounding box of a string. Uses parameters set by #SetDParam if needed. * Has the same restrictions as #GetStringBoundingBox(const char *str, FontSize start_fontsize). diff --git a/src/gfx_func.h b/src/gfx_func.h index 6363a699d9..1d138f3d5e 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -106,6 +106,7 @@ void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL); +Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize = FS_NORMAL); Dimension GetStringBoundingBox(StringID strid); int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL); int GetStringHeight(StringID str, int maxw); diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 6ba65c703e..0663d30e3a 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -32,6 +32,9 @@ #include "table/strings.h" +#include +#include + #include "safeguards.h" /** Method to open the OSK. */ @@ -61,16 +64,10 @@ static WindowDesc _land_info_desc( ); class LandInfoWindow : public Window { - enum LandInfoLines { - LAND_INFO_CENTERED_LINES = 32, ///< Up to 32 centered lines (arbitrary limit) - LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line - LAND_INFO_LINE_END, - }; - - static const uint LAND_INFO_LINE_BUFF_SIZE = 512; + StringList landinfo_data; ///< Info lines to show. + std::string cargo_acceptance; ///< Centered multi-line string for cargo acceptance. public: - char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE]; TileIndex tile; void DrawWidget(const Rect &r, int widget) const override @@ -78,16 +75,14 @@ public: if (widget != WID_LI_BACKGROUND) return; uint y = r.top + WD_TEXTPANEL_TOP; - for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) { - if (StrEmpty(this->landinfo_data[i])) break; - + for (size_t i = 0; i < this->landinfo_data.size(); i++) { DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER); y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL; if (i == 0) y += 4; } - if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) { - SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]); + if (!this->cargo_acceptance.empty()) { + SetDParamStr(0, this->cargo_acceptance); DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_TEXTPANEL_BOTTOM, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER); } } @@ -97,9 +92,7 @@ public: if (widget != WID_LI_BACKGROUND) return; size->height = WD_TEXTPANEL_TOP + WD_TEXTPANEL_BOTTOM; - for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) { - if (StrEmpty(this->landinfo_data[i])) break; - + for (size_t i = 0; i < this->landinfo_data.size(); i++) { uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT; size->width = std::max(size->width, width); @@ -107,10 +100,10 @@ public: if (i == 0) size->height += 4; } - if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) { - uint width = GetStringBoundingBox(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT; + if (!this->cargo_acceptance.empty()) { + uint width = GetStringBoundingBox(this->cargo_acceptance).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT; size->width = std::max(size->width, std::min(300u, width)); - SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]); + SetDParamStr(0, cargo_acceptance); size->height += GetStringHeight(STR_JUST_RAW_STRING, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT); } } @@ -178,12 +171,11 @@ public: AddAcceptedCargo(tile, acceptance, nullptr); GetTileDesc(tile, &td); - uint line_nr = 0; + this->landinfo_data.clear(); /* Tiletype */ SetDParam(0, td.dparam[0]); - GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(td.str)); /* Up to four owners */ for (uint i = 0; i < 4; i++) { @@ -191,8 +183,7 @@ public: SetDParam(0, STR_LAND_AREA_INFORMATION_OWNER_N_A); if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile); - GetString(this->landinfo_data[line_nr], td.owner_type[i], lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(td.owner_type[i])); } /* Cost to clear/revenue when cleared */ @@ -212,18 +203,18 @@ public: SetDParam(0, cost); } } - GetString(this->landinfo_data[line_nr], str, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(str)); /* Location */ - char tmp[16]; - seprintf(tmp, lastof(tmp), "0x%.4X", tile); + std::stringstream tile_ss; + tile_ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << tile; // 0x%.4X + std::string tile_str = tile_ss.str(); // Can't pass it directly to SetDParamStr as the string is only a temporary and would be destructed before the GetString call. + SetDParam(0, TileX(tile)); SetDParam(1, TileY(tile)); SetDParam(2, GetTileZ(tile)); - SetDParamStr(3, tmp); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr])); - line_nr++; + SetDParamStr(3, tile_str); + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LANDINFO_COORDS)); /* Local authority */ SetDParam(0, STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE); @@ -231,126 +222,112 @@ public: SetDParam(0, STR_TOWN_NAME); SetDParam(1, t->index); } - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY)); /* Build date */ if (td.build_date != INVALID_DATE) { SetDParam(0, td.build_date); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_BUILD_DATE, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE)); } /* Station class */ if (td.station_class != STR_NULL) { SetDParam(0, td.station_class); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_CLASS, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_CLASS)); } /* Station type name */ if (td.station_name != STR_NULL) { SetDParam(0, td.station_name); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_TYPE, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_TYPE)); } /* Airport class */ if (td.airport_class != STR_NULL) { SetDParam(0, td.airport_class); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_CLASS, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_CLASS)); } /* Airport name */ if (td.airport_name != STR_NULL) { SetDParam(0, td.airport_name); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_NAME, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_NAME)); } /* Airport tile name */ if (td.airport_tile_name != STR_NULL) { SetDParam(0, td.airport_tile_name); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME)); } /* Rail type name */ if (td.railtype != STR_NULL) { SetDParam(0, td.railtype); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_TYPE, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_TYPE)); } /* Rail speed limit */ if (td.rail_speed != 0) { SetDParam(0, td.rail_speed); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT)); } /* Road type name */ if (td.roadtype != STR_NULL) { SetDParam(0, td.roadtype); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_TYPE, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_TYPE)); } /* Road speed limit */ if (td.road_speed != 0) { SetDParam(0, td.road_speed); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT)); } /* Tram type name */ if (td.tramtype != STR_NULL) { SetDParam(0, td.tramtype); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_TYPE, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_TYPE)); } /* Tram speed limit */ if (td.tram_speed != 0) { SetDParam(0, td.tram_speed); - GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT)); } /* NewGRF name */ if (td.grf != nullptr) { SetDParamStr(0, td.grf); - GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_NEWGRF_NAME, lastof(this->landinfo_data[line_nr])); - line_nr++; + this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_NEWGRF_NAME)); } - assert(line_nr < LAND_INFO_CENTERED_LINES); - - /* Mark last line empty */ - this->landinfo_data[line_nr][0] = '\0'; - /* Cargo acceptance is displayed in a extra multiline */ - char *strp = GetString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE], STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); - bool found = false; + std::stringstream line; + line << GetString(STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED); + bool found = false; for (CargoID i = 0; i < NUM_CARGO; ++i) { if (acceptance[i] > 0) { /* Add a comma between each item. */ - if (found) strp = strecpy(strp, ", ", lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); + if (found) line << ", "; found = true; /* If the accepted value is less than 8, show it in 1/8:ths */ if (acceptance[i] < 8) { SetDParam(0, acceptance[i]); SetDParam(1, CargoSpec::Get(i)->name); - strp = GetString(strp, STR_LAND_AREA_INFORMATION_CARGO_EIGHTS, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); + line << GetString(STR_LAND_AREA_INFORMATION_CARGO_EIGHTS); } else { - strp = GetString(strp, CargoSpec::Get(i)->name, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); + line << GetString(CargoSpec::Get(i)->name); } } } - if (!found) this->landinfo_data[LAND_INFO_MULTICENTER_LINE][0] = '\0'; + if (found) { + this->cargo_acceptance = line.str(); + } else { + this->cargo_acceptance.clear(); + } } bool IsNewGRFInspectable() const override From 2d0abf5a7643afb2b37ca8902d13f1df5c14f5ee Mon Sep 17 00:00:00 2001 From: TELK Date: Sun, 13 Jun 2021 17:06:50 +0900 Subject: [PATCH 359/800] Fix #9362: Hover in online players window was slightly too big (#9364) This causes graphical glitches at the bottom of the window. --- src/network/network_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 9048ad8549..3cdece77c5 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2349,7 +2349,7 @@ public: if (this->hover_index >= 0) { uint offset = this->hover_index * this->line_height; - GfxFillRect(r.left + 2, r.top + offset, r.right - 1, r.top + offset + this->line_height - 1, GREY_SCALE(9)); + GfxFillRect(r.left + 2, r.top + offset, r.right - 1, r.top + offset + this->line_height - 2, GREY_SCALE(9)); } NetworkClientInfo *own_ci = NetworkClientInfo::GetByClientID(_network_own_client_id); From fed3e3305f6437a0d3ccf231585595838369b907 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 11:20:00 +0200 Subject: [PATCH 360/800] Codechange: add function to determine whether are string starts or ends with a given other string --- src/string.cpp | 27 +++++++++++++++++++++++++++ src/string_func.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/src/string.cpp b/src/string.cpp index e9a619c400..fbb447ee90 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -358,6 +358,33 @@ void StrTrimInPlace(std::string &str) StrRightTrimInPlace(str); } +/** + * Check whether the given string starts with the given prefix. + * @param str The string to look at. + * @param prefix The prefix to look for. + * @return True iff the begin of the string is the same as the prefix. + */ +bool StrStartsWith(const std::string_view str, const std::string_view prefix) +{ + size_t prefix_len = prefix.size(); + if (str.size() < prefix_len) return false; + return str.compare(0, prefix_len, prefix, 0, prefix_len) == 0; +} + +/** + * Check whether the given string ends with the given suffix. + * @param str The string to look at. + * @param suffix The suffix to look for. + * @return True iff the end of the string is the same as the suffix. + */ +bool StrEndsWith(const std::string_view str, const std::string_view suffix) +{ + size_t suffix_len = suffix.size(); + if (str.size() < suffix_len) return false; + return str.compare(str.size() - suffix_len, suffix_len, suffix, 0, suffix_len) == 0; +} + + /** Scans the string for colour codes and strips them */ void str_strip_colours(char *str) { diff --git a/src/string_func.h b/src/string_func.h index 2e258fbd20..0cbf26d6b2 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -51,6 +51,9 @@ bool strtolower(std::string &str, std::string::size_type offs = 0); bool StrValid(const char *str, const char *last) NOACCESS(2); void StrTrimInPlace(std::string &str); +bool StrStartsWith(const std::string_view str, const std::string_view prefix); +bool StrEndsWith(const std::string_view str, const std::string_view suffix); + /** * Check if a string buffer is empty. * From ca9c50607eeca1657f7da4a06fe4486574e97139 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 11:30:03 +0200 Subject: [PATCH 361/800] Codechange: use StrStartsWith/StrEndsWith when finding settings --- src/settings.cpp | 28 ++++++++++++---------------- src/settings_internal.h | 4 ++-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 24039c564a..26f6d8fd2c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1235,7 +1235,7 @@ static void HandleOldDiffCustom(bool savegame) if (has_no_town_council_tolerance && name == "town_council_tolerance") continue; std::string fullname = "difficulty." + name; - const SettingDesc *sd = GetSettingFromName(fullname.c_str()); + const SettingDesc *sd = GetSettingFromName(fullname); /* Some settings are no longer in use; skip reading those. */ if (sd == nullptr) { @@ -1705,22 +1705,19 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const * @return Pointer to the setting description of setting \a name if it can be found, * \c nullptr indicates failure to obtain the description. */ -static const SettingDesc *GetSettingFromName(const char *name, const SettingTable &settings) +static const SettingDesc *GetSettingFromName(const std::string_view name, const SettingTable &settings) { /* First check all full names */ for (auto &sd : settings) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strcmp(sd->name, name) == 0) return sd.get(); + if (sd->name == name) return sd.get(); } /* Then check the shortcut variant of the name. */ + std::string short_name_suffix = std::string{ "." }.append(name); for (auto &sd : settings) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - const char *short_name = strchr(sd->name, '.'); - if (short_name != nullptr) { - short_name++; - if (strcmp(short_name, name) == 0) return sd.get(); - } + if (StrEndsWith(sd->name, short_name_suffix)) return sd.get(); } return nullptr; @@ -1731,13 +1728,11 @@ static const SettingDesc *GetSettingFromName(const char *name, const SettingTabl * @param prefix The prefix to look for. * @param saveloads A vector to store the result in. */ -void GetSettingSaveLoadByPrefix(const char *prefix, std::vector &saveloads) +void GetSettingSaveLoadByPrefix(std::string_view prefix, std::vector &saveloads) { - size_t prefixlen = strlen(prefix); - for (auto &sd : _settings) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (strncmp(sd->name, prefix, prefixlen) == 0) saveloads.push_back(sd->save); + if (StrStartsWith(sd->name, prefix)) saveloads.push_back(sd->save); } } @@ -1747,9 +1742,10 @@ void GetSettingSaveLoadByPrefix(const char *prefix, std::vector &savel * @return Pointer to the setting description of setting \a name if it can be found, * \c nullptr indicates failure to obtain the description. */ -static const SettingDesc *GetCompanySettingFromName(const char *name) +static const SettingDesc *GetCompanySettingFromName(std::string_view name) { - if (strncmp(name, "company.", 8) == 0) name += 8; + static const std::string_view company_prefix = "company."; + if (StrStartsWith(name, company_prefix)) name.remove_prefix(company_prefix.size()); return GetSettingFromName(name, _company_settings); } @@ -1759,7 +1755,7 @@ static const SettingDesc *GetCompanySettingFromName(const char *name) * @return Pointer to the setting description of setting \a name if it can be found, * \c nullptr indicates failure to obtain the description. */ -const SettingDesc *GetSettingFromName(const char *name) +const SettingDesc *GetSettingFromName(const std::string_view name) { auto sd = GetSettingFromName(name, _settings); if (sd != nullptr) return sd; @@ -1781,7 +1777,7 @@ const SettingDesc *GetSettingFromName(const char *name) CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text) { if (text.empty()) return CMD_ERROR; - const SettingDesc *sd = GetSettingFromName(text.c_str()); + const SettingDesc *sd = GetSettingFromName(text); if (sd == nullptr) return CMD_ERROR; if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR; diff --git a/src/settings_internal.h b/src/settings_internal.h index a625f576c2..e1b3b75a7e 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -301,8 +301,8 @@ struct NullSettingDesc : SettingDesc { typedef std::initializer_list> SettingTable; -const SettingDesc *GetSettingFromName(const char *name); -void GetSettingSaveLoadByPrefix(const char *prefix, std::vector &saveloads); +const SettingDesc *GetSettingFromName(const std::string_view name); +void GetSettingSaveLoadByPrefix(const std::string_view prefix, std::vector &saveloads); bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame = false); bool SetSettingValue(const StringSettingDesc *sd, const std::string value, bool force_newgame = false); From e588923bff12e0c46aaab72fdca3e8b5cb211081 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 11:40:54 +0200 Subject: [PATCH 362/800] Codechange: add std::string accepting SetDParamStr to ErrorMessageData --- src/error.h | 1 + src/error_gui.cpp | 10 ++++++++++ src/newgrf_debug_gui.cpp | 2 +- src/openttd.cpp | 6 +++--- src/spriteloader/grf.cpp | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/error.h b/src/error.h index 9c445fc48e..06440c127c 100644 --- a/src/error.h +++ b/src/error.h @@ -52,6 +52,7 @@ public: void SetDParam(uint n, uint64 v); void SetDParamStr(uint n, const char *str); + void SetDParamStr(uint n, const std::string &str); void CopyOutDParams(); }; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 70b403a683..06c0c44e05 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -164,6 +164,16 @@ void ErrorMessageData::SetDParamStr(uint n, const char *str) this->strings[n] = stredup(str); } +/** + * Set a rawstring parameter. + * @param n Parameter index + * @param str Raw string + */ +void ErrorMessageData::SetDParamStr(uint n, const std::string &str) +{ + this->SetDParamStr(n, str.c_str()); +} + /** Define a queue with errors. */ typedef std::list ErrorList; /** The actual queue with errors. */ diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 9453f5de91..ec221e2f33 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -828,7 +828,7 @@ struct SpriteAlignerWindow : Window { switch (widget) { case WID_SA_CAPTION: SetDParam(0, this->current_sprite); - SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename().c_str()); + SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename()); break; case WID_SA_OFFSETS_ABS: diff --git a/src/openttd.cpp b/src/openttd.cpp index fcd8fcd34b..7800fba840 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -707,7 +707,7 @@ int openttd_main(int argc, char *argv[]) BaseGraphics::SetSet({}); ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND); - msg.SetDParamStr(0, graphics_set.c_str()); + msg.SetDParamStr(0, graphics_set); ScheduleErrorMessage(msg); } } @@ -766,7 +766,7 @@ int openttd_main(int argc, char *argv[]) usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 1.4 of README.md."); } else { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND); - msg.SetDParamStr(0, sounds_set.c_str()); + msg.SetDParamStr(0, sounds_set); ScheduleErrorMessage(msg); } } @@ -778,7 +778,7 @@ int openttd_main(int argc, char *argv[]) usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 1.4 of README.md."); } else { ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND); - msg.SetDParamStr(0, music_set.c_str()); + msg.SetDParamStr(0, music_set); ScheduleErrorMessage(msg); } } diff --git a/src/spriteloader/grf.cpp b/src/spriteloader/grf.cpp index fae87b87fc..5a49a0c8ab 100644 --- a/src/spriteloader/grf.cpp +++ b/src/spriteloader/grf.cpp @@ -35,7 +35,7 @@ static bool WarnCorruptSprite(const SpriteFile &file, size_t file_pos, int line) { static byte warning_level = 0; if (warning_level == 0) { - SetDParamStr(0, file.GetSimplifiedFilename().c_str()); + SetDParamStr(0, file.GetSimplifiedFilename()); ShowErrorMessage(STR_NEWGRF_ERROR_CORRUPT_SPRITE, INVALID_STRING_ID, WL_ERROR); } DEBUG(sprite, warning_level, "[%i] Loading corrupted sprite from %s at position %i", line, file.GetSimplifiedFilename().c_str(), (int)file_pos); From bf500c39c9b6c7359204c5454aefa0dc7f51dae5 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 30 May 2021 11:51:21 +0200 Subject: [PATCH 363/800] Codechange: make the name of SettingDesc a std::string --- src/gamelog.cpp | 4 ++-- src/gamelog.h | 2 +- src/script/api/script_gamesettings.cpp | 2 +- src/settings.cpp | 8 ++++---- src/settings_internal.h | 18 +++++++++--------- src/table/settings/settings.ini | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/gamelog.cpp b/src/gamelog.cpp index 1a4998e40e..8965ea55fb 100644 --- a/src/gamelog.cpp +++ b/src/gamelog.cpp @@ -483,14 +483,14 @@ void GamelogOldver() * @param oldval old setting value * @param newval new setting value */ -void GamelogSetting(const char *name, int32 oldval, int32 newval) +void GamelogSetting(const std::string &name, int32 oldval, int32 newval) { assert(_gamelog_action_type == GLAT_SETTING); LoggedChange *lc = GamelogChange(GLCT_SETTING); if (lc == nullptr) return; - lc->setting.name = stredup(name); + lc->setting.name = stredup(name.c_str()); lc->setting.oldval = oldval; lc->setting.newval = newval; } diff --git a/src/gamelog.h b/src/gamelog.h index e7951c50c7..d9e0dd529e 100644 --- a/src/gamelog.h +++ b/src/gamelog.h @@ -48,7 +48,7 @@ bool GamelogTestEmergency(); void GamelogRevision(); void GamelogMode(); void GamelogOldver(); -void GamelogSetting(const char *name, int32 oldval, int32 newval); +void GamelogSetting(const std::string &name, int32 oldval, int32 newval); void GamelogGRFUpdate(const GRFConfig *oldg, const GRFConfig *newg); void GamelogGRFAddList(const GRFConfig *newg); diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 458545226f..35277e3036 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -37,7 +37,7 @@ if ((sd->flags & SF_NO_NETWORK_SYNC) != 0) return false; - return ScriptObject::DoCommand(0, 0, value, CMD_CHANGE_SETTING, sd->name); + return ScriptObject::DoCommand(0, 0, value, CMD_CHANGE_SETTING, sd->name.c_str()); } /* static */ bool ScriptGameSettings::IsDisabledVehicleType(ScriptVehicle::VehicleType vehicle_type) diff --git a/src/settings.cpp b/src/settings.cpp index 26f6d8fd2c..7ec5112fd7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1980,13 +1980,13 @@ void IConsoleGetSetting(const char *name, bool force_newgame) const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game; if (sd->IsStringSetting()) { - IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, sd->AsStringSetting()->Read(object).c_str()); + IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", sd->name.c_str(), sd->AsStringSetting()->Read(object).c_str()); } else if (sd->IsIntSetting()) { char value[20]; sd->FormatValue(value, lastof(value), object); const IntSettingDesc *int_setting = sd->AsIntSetting(); IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)", - name, value, (sd->flags & SF_GUI_0_IS_SPECIAL) ? "(0) " : "", int_setting->min, int_setting->max); + sd->name.c_str(), value, (sd->flags & SF_GUI_0_IS_SPECIAL) ? "(0) " : "", int_setting->min, int_setting->max); } } @@ -2001,10 +2001,10 @@ void IConsoleListSettings(const char *prefilter) for (auto &sd : _settings) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (prefilter != nullptr && strstr(sd->name, prefilter) == nullptr) continue; + if (prefilter != nullptr && sd->name.find(prefilter) == std::string::npos) continue; char value[80]; sd->FormatValue(value, lastof(value), &GetGameSettings()); - IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name, value); + IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name.c_str(), value); } IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); diff --git a/src/settings_internal.h b/src/settings_internal.h index e1b3b75a7e..5ba7ca454a 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -69,11 +69,11 @@ struct IniItem; /** Properties of config file settings. */ struct SettingDesc { - SettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup) : + SettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup) : name(name), flags(flags), startup(startup), save(save) {} virtual ~SettingDesc() {} - const char *name; ///< Name of the setting. Used in configuration file and for console. + std::string name; ///< Name of the setting. Used in configuration file and for console. SettingFlag flags; ///< Handles how a setting would show up in the GUI (text/currency, etc.). bool startup; ///< Setting has to be loaded directly at startup?. SaveLoad save; ///< Internal structure (going to savegame, parts to config). @@ -140,7 +140,7 @@ struct IntSettingDesc : SettingDesc { */ typedef void PostChangeCallback(int32 value); - IntSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, + IntSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def), min(min), max(max), interval(interval), @@ -182,7 +182,7 @@ private: /** Boolean setting. */ struct BoolSettingDesc : IntSettingDesc { - BoolSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, bool def, + BoolSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, bool def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, @@ -198,7 +198,7 @@ struct BoolSettingDesc : IntSettingDesc { struct OneOfManySettingDesc : IntSettingDesc { typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error - OneOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, + OneOfManySettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -222,7 +222,7 @@ struct OneOfManySettingDesc : IntSettingDesc { /** Many of many setting. */ struct ManyOfManySettingDesc : OneOfManySettingDesc { - ManyOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, + ManyOfManySettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -251,7 +251,7 @@ struct StringSettingDesc : SettingDesc { */ typedef void PostChangeCallback(const std::string &value); - StringSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def, + StringSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, const char *def, uint32 max_length, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def == nullptr ? "" : def), max_length(max_length), pre_check(pre_check), post_callback(post_callback) {} @@ -277,7 +277,7 @@ private: /** List/array settings. */ struct ListSettingDesc : SettingDesc { - ListSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def) : + ListSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, const char *def) : SettingDesc(save, name, flags, startup), def(def) {} virtual ~ListSettingDesc() {} @@ -291,7 +291,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, "", SF_NOT_IN_CONFIG, false) {} + SettingDesc(save, {}, SF_NOT_IN_CONFIG, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 17a4b30258..7c5cac8869 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -1002,14 +1002,14 @@ post_cb = MaxVehiclesChanged cat = SC_BASIC [SDTG_BOOL] -name = nullptr +name = {} flags = SF_NO_NETWORK var = _old_vds.servint_ispercent def = false to = SLV_120 [SDTG_VAR] -name = nullptr +name = {} type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_trains @@ -1019,7 +1019,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = nullptr +name = {} type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_roadveh @@ -1029,7 +1029,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = nullptr +name = {} type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_ships @@ -1039,7 +1039,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = nullptr +name = {} type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_aircraft From 845fded2a08a62fa2afd8a041d168c6774f113df Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 13 Jun 2021 10:07:44 +0200 Subject: [PATCH 364/800] Fix #9361, a2051ba: [Network] Off by one in CanWriteToPacket Previously it did not allow writing a byte to a packet that was of size limit - 1 anymore. --- src/network/core/packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 737b4624c9..e106d5787f 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -98,7 +98,7 @@ void Packet::PrepareToSend() */ bool Packet::CanWriteToPacket(size_t bytes_to_write) { - return this->Size() + bytes_to_write < this->limit; + return this->Size() + bytes_to_write <= this->limit; } /* From 662d8dfc309d5c5312049a93002fd39176e96baf Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 12 Jun 2021 09:34:09 +0200 Subject: [PATCH 365/800] Add: minimal set of headers from {fmt} 7.1.3 to 3rdparty --- README.md | 3 + src/3rdparty/CMakeLists.txt | 1 + src/3rdparty/fmt/CMakeLists.txt | 5 + src/3rdparty/fmt/LICENSE.rst | 27 + src/3rdparty/fmt/core.h | 2122 +++++++++++++++++ src/3rdparty/fmt/format-inl.h | 2801 ++++++++++++++++++++++ src/3rdparty/fmt/format.h | 3960 +++++++++++++++++++++++++++++++ 7 files changed, 8919 insertions(+) create mode 100644 src/3rdparty/fmt/CMakeLists.txt create mode 100644 src/3rdparty/fmt/LICENSE.rst create mode 100644 src/3rdparty/fmt/core.h create mode 100644 src/3rdparty/fmt/format-inl.h create mode 100644 src/3rdparty/fmt/format.h diff --git a/README.md b/README.md index a5142ffecb..ab51479e1b 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,9 @@ See the comments in the source files in `src/3rdparty/md5` for the complete lice The implementations of Posix `getaddrinfo` and `getnameinfo` for OS/2 in `src/3rdparty/os2` are distributed partly under the GNU Lesser General Public License 2.1, and partly under the (3-clause) BSD license. The exact licensing terms can be found in `src/3rdparty/os2/getaddrinfo.c` resp. `src/3rdparty/os2/getnameinfo.c`. +The fmt implementation in `src/3rdparty/fmt` is licensed under the MIT license. +See `src/3rdparty/fmt/LICENSE.rst` for the complete license text. + ## 4.0 Credits diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index ca082cf785..50fa6922f4 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(fmt) add_subdirectory(md5) add_subdirectory(squirrel) add_subdirectory(opengl) diff --git a/src/3rdparty/fmt/CMakeLists.txt b/src/3rdparty/fmt/CMakeLists.txt new file mode 100644 index 0000000000..22a02416c3 --- /dev/null +++ b/src/3rdparty/fmt/CMakeLists.txt @@ -0,0 +1,5 @@ +add_files( + core.h + format.h + format-inl.h +) diff --git a/src/3rdparty/fmt/LICENSE.rst b/src/3rdparty/fmt/LICENSE.rst new file mode 100644 index 0000000000..f0ec3db4d2 --- /dev/null +++ b/src/3rdparty/fmt/LICENSE.rst @@ -0,0 +1,27 @@ +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. diff --git a/src/3rdparty/fmt/core.h b/src/3rdparty/fmt/core.h new file mode 100644 index 0000000000..0a81e0ccd9 --- /dev/null +++ b/src/3rdparty/fmt/core.h @@ -0,0 +1,2122 @@ +// Formatting library for C++ - the core API +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CORE_H_ +#define FMT_CORE_H_ + +#include // std::FILE +#include +#include +#include +#include +#include +#include +#include + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 70103 + +#ifdef __clang__ +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif + +#if defined(__GNUC__) && !defined(__clang__) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif + +#if defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION +#else +# define FMT_HAS_GXX_CXX11 0 +#endif + +#ifdef __NVCC__ +# define FMT_NVCC __NVCC__ +#else +# define FMT_NVCC 0 +#endif + +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +# define FMT_SUPPRESS_MSC_WARNING(n) __pragma(warning(suppress : n)) +#else +# define FMT_MSC_VER 0 +# define FMT_SUPPRESS_MSC_WARNING(n) +#endif + +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif + +#if defined(__has_include) && !defined(__INTELLISENSE__) && \ + (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600) +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif + +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ + (__cplusplus >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ + (__cplusplus >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +// Check if relaxed C++14 constexpr is supported. +// GCC doesn't allow throw in constexpr until version 6 (bug 67371). +#ifndef FMT_USE_CONSTEXPR +# define FMT_USE_CONSTEXPR \ + (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \ + (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \ + !FMT_NVCC && !FMT_ICC_VERSION +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +# define FMT_CONSTEXPR_DECL constexpr +#else +# define FMT_CONSTEXPR inline +# define FMT_CONSTEXPR_DECL +#endif + +#ifndef FMT_OVERRIDE +# if FMT_HAS_FEATURE(cxx_override_control) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 +# define FMT_OVERRIDE override +# else +# define FMT_OVERRIDE +# endif +#endif + +// Check if exceptions are disabled. +#ifndef FMT_EXCEPTIONS +# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ + FMT_MSC_VER && !_HAS_EXCEPTIONS +# define FMT_EXCEPTIONS 0 +# else +# define FMT_EXCEPTIONS 1 +# endif +#endif + +// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). +#ifndef FMT_USE_NOEXCEPT +# define FMT_USE_NOEXCEPT 0 +#endif + +#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 +# define FMT_DETECTED_NOEXCEPT noexcept +# define FMT_HAS_CXX11_NOEXCEPT 1 +#else +# define FMT_DETECTED_NOEXCEPT throw() +# define FMT_HAS_CXX11_NOEXCEPT 0 +#endif + +#ifndef FMT_NOEXCEPT +# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT +# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT +# else +# define FMT_NOEXCEPT +# endif +#endif + +// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code +// warnings. +#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \ + !FMT_NVCC +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#ifndef FMT_DEPRECATED +# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900 +# define FMT_DEPRECATED [[deprecated]] +# else +# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__) +# define FMT_DEPRECATED __attribute__((deprecated)) +# elif FMT_MSC_VER +# define FMT_DEPRECATED __declspec(deprecated) +# else +# define FMT_DEPRECATED /* deprecated */ +# endif +# endif +#endif + +// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers. +#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC +# define FMT_DEPRECATED_ALIAS +#else +# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED +#endif + +#ifndef FMT_INLINE +# if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_INLINE inline __attribute__((always_inline)) +# else +# define FMT_INLINE inline +# endif +#endif + +#ifndef FMT_USE_INLINE_NAMESPACES +# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ + (FMT_MSC_VER >= 1900 && !_MANAGED) +# define FMT_USE_INLINE_NAMESPACES 1 +# else +# define FMT_USE_INLINE_NAMESPACES 0 +# endif +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# if FMT_USE_INLINE_NAMESPACES +# define FMT_INLINE_NAMESPACE inline namespace +# define FMT_END_NAMESPACE \ + } \ + } +# else +# define FMT_INLINE_NAMESPACE namespace +# define FMT_END_NAMESPACE \ + } \ + using namespace v7; \ + } +# endif +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + FMT_INLINE_NAMESPACE v7 { +#endif + +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# define FMT_CLASS_API FMT_SUPPRESS_MSC_WARNING(4275) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# define FMT_EXTERN_TEMPLATE_API FMT_API +# define FMT_EXPORTED +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# define FMT_EXTERN_TEMPLATE_API FMT_API +# endif +#else +# define FMT_CLASS_API +#endif +#ifndef FMT_API +# define FMT_API +#endif +#ifndef FMT_EXTERN_TEMPLATE_API +# define FMT_EXTERN_TEMPLATE_API +#endif +#ifndef FMT_INSTANTIATION_DEF_API +# define FMT_INSTANTIATION_DEF_API FMT_API +#endif + +#ifndef FMT_HEADER_ONLY +# define FMT_EXTERN extern +#else +# define FMT_EXTERN +#endif + +// libc++ supports string_view in pre-c++17. +#if (FMT_HAS_INCLUDE() && \ + (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +# include +# define FMT_USE_STRING_VIEW +#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L +# include +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + +#ifndef FMT_UNICODE +# define FMT_UNICODE !FMT_MSC_VER +#endif +#if FMT_UNICODE && FMT_MSC_VER +# pragma execution_character_set("utf-8") +#endif + +FMT_BEGIN_NAMESPACE + +// Implementations of enable_if_t and other metafunctions for older systems. +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; +template using bool_constant = std::integral_constant; +template +using remove_reference_t = typename std::remove_reference::type; +template +using remove_const_t = typename std::remove_const::type; +template +using remove_cvref_t = typename std::remove_cv>::type; +template struct type_identity { using type = T; }; +template using type_identity_t = typename type_identity::type; + +struct monostate {}; + +// An enable_if helper to be used in template parameters which results in much +// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed +// to workaround a bug in MSVC 2019 (see #1140 and #1186). +#define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 + +namespace detail { + +// A helper function to suppress "conditional expression is constant" warnings. +template constexpr T const_check(T value) { return value; } + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#ifndef FMT_ASSERT +# ifdef NDEBUG +// FMT_ASSERT is not empty to avoid -Werror=empty-body. +# define FMT_ASSERT(condition, message) ((void)0) +# else +# define FMT_ASSERT(condition, message) \ + ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ + ? (void)0 \ + : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message))) +# endif +#endif + +#if defined(FMT_USE_STRING_VIEW) +template using std_string_view = std::basic_string_view; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) +template +using std_string_view = std::experimental::basic_string_view; +#else +template struct std_string_view {}; +#endif + +#ifdef FMT_USE_INT128 +// Do nothing. +#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \ + !(FMT_CLANG_VERSION && FMT_MSC_VER) +# define FMT_USE_INT128 1 +using int128_t = __int128_t; +using uint128_t = __uint128_t; +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +struct int128_t {}; +struct uint128_t {}; +#endif + +// Casts a nonnegative integer to unsigned. +template +FMT_CONSTEXPR typename std::make_unsigned::type to_unsigned(Int value) { + FMT_ASSERT(value >= 0, "negative value"); + return static_cast::type>(value); +} + +FMT_SUPPRESS_MSC_WARNING(4566) constexpr unsigned char micro[] = "\u00B5"; + +template constexpr bool is_unicode() { + return FMT_UNICODE || sizeof(Char) != 1 || + (sizeof(micro) == 3 && micro[0] == 0xC2 && micro[1] == 0xB5); +} + +#ifdef __cpp_char8_t +using char8_type = char8_t; +#else +enum char8_type : unsigned char {}; +#endif +} // namespace detail + +#ifdef FMT_USE_INTERNAL +namespace internal = detail; // DEPRECATED +#endif + +/** + An implementation of ``std::basic_string_view`` for pre-C++17. It provides a + subset of the API. ``fmt::basic_string_view`` is used for format strings even + if ``std::string_view`` is available to prevent issues when a library is + compiled with a different ``-std`` option than the client code (which is not + recommended). + */ +template class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {} + + /** Constructs a string reference object from a C string and a size. */ + constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT + : data_(s), + size_(count) {} + + /** + \rst + Constructs a string reference object from a C string computing + the size with ``std::char_traits::length``. + \endrst + */ +#if __cplusplus >= 201703L // C++17's char_traits::length() is constexpr. + FMT_CONSTEXPR +#endif + basic_string_view(const Char* s) + : data_(s), size_(std::char_traits::length(s)) {} + + /** Constructs a string reference from a ``std::basic_string`` object. */ + template + FMT_CONSTEXPR basic_string_view( + const std::basic_string& s) FMT_NOEXCEPT + : data_(s.data()), + size_(s.size()) {} + + template >::value)> + FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()), + size_(s.size()) {} + + /** Returns a pointer to the string data. */ + constexpr const Char* data() const { return data_; } + + /** Returns the string size. */ + constexpr size_t size() const { return size_; } + + constexpr iterator begin() const { return data_; } + constexpr iterator end() const { return data_ + size_; } + + constexpr const Char& operator[](size_t pos) const { return data_[pos]; } + + FMT_CONSTEXPR void remove_prefix(size_t n) { + data_ += n; + size_ -= n; + } + + // Lexicographically compare this string reference to other. + int compare(basic_string_view other) const { + size_t str_size = size_ < other.size_ ? size_ : other.size_; + int result = std::char_traits::compare(data_, other.data_, str_size); + if (result == 0) + result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + return result; + } + + friend bool operator==(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) == 0; + } + friend bool operator!=(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) != 0; + } + friend bool operator<(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) < 0; + } + friend bool operator<=(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) <= 0; + } + friend bool operator>(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) > 0; + } + friend bool operator>=(basic_string_view lhs, basic_string_view rhs) { + return lhs.compare(rhs) >= 0; + } +}; + +using string_view = basic_string_view; +using wstring_view = basic_string_view; + +/** Specifies if ``T`` is a character type. Can be specialized by users. */ +template struct is_char : std::false_type {}; +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; + +/** + \rst + Returns a string view of `s`. In order to add custom string type support to + {fmt} provide an overload of `to_string_view` for it in the same namespace as + the type for the argument-dependent lookup to work. + + **Example**:: + + namespace my_ns { + inline string_view to_string_view(const my_string& s) { + return {s.data(), s.length()}; + } + } + std::string message = fmt::format(my_string("The answer is {}"), 42); + \endrst + */ +template ::value)> +inline basic_string_view to_string_view(const Char* s) { + return s; +} + +template +inline basic_string_view to_string_view( + const std::basic_string& s) { + return s; +} + +template +inline basic_string_view to_string_view(basic_string_view s) { + return s; +} + +template >::value)> +inline basic_string_view to_string_view(detail::std_string_view s) { + return s; +} + +// A base class for compile-time strings. It is defined in the fmt namespace to +// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42). +struct compile_string {}; + +template +struct is_compile_string : std::is_base_of {}; + +template ::value)> +constexpr basic_string_view to_string_view(const S& s) { + return s; +} + +namespace detail { +void to_string_view(...); +using fmt::v7::to_string_view; + +// Specifies whether S is a string type convertible to fmt::basic_string_view. +// It should be a constexpr function but MSVC 2017 fails to compile it in +// enable_if and MSVC 2015 fails to compile it as an alias template. +template +struct is_string : std::is_class()))> { +}; + +template struct char_t_impl {}; +template struct char_t_impl::value>> { + using result = decltype(to_string_view(std::declval())); + using type = typename result::value_type; +}; + +// Reports a compile-time error if S is not a valid format string. +template ::value)> +FMT_INLINE void check_format_string(const S&) { +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert(is_compile_string::value, + "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " + "FMT_STRING."); +#endif +} +template ::value)> +void check_format_string(S); + +struct error_handler { + constexpr error_handler() = default; + constexpr error_handler(const error_handler&) = default; + + // This function is intentionally not constexpr to give a compile-time error. + FMT_NORETURN FMT_API void on_error(const char* message); +}; +} // namespace detail + +/** String's character type. */ +template using char_t = typename detail::char_t_impl::type; + +/** + \rst + Parsing context consisting of a format string range being parsed and an + argument counter for automatic indexing. + + You can use one of the following type aliases for common character types: + + +-----------------------+-------------------------------------+ + | Type | Definition | + +=======================+=====================================+ + | format_parse_context | basic_format_parse_context | + +-----------------------+-------------------------------------+ + | wformat_parse_context | basic_format_parse_context | + +-----------------------+-------------------------------------+ + \endrst + */ +template +class basic_format_parse_context : private ErrorHandler { + private: + basic_string_view format_str_; + int next_arg_id_; + + public: + using char_type = Char; + using iterator = typename basic_string_view::iterator; + + explicit constexpr basic_format_parse_context( + basic_string_view format_str, ErrorHandler eh = {}, + int next_arg_id = 0) + : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {} + + /** + Returns an iterator to the beginning of the format string range being + parsed. + */ + constexpr iterator begin() const FMT_NOEXCEPT { return format_str_.begin(); } + + /** + Returns an iterator past the end of the format string range being parsed. + */ + constexpr iterator end() const FMT_NOEXCEPT { return format_str_.end(); } + + /** Advances the begin iterator to ``it``. */ + FMT_CONSTEXPR void advance_to(iterator it) { + format_str_.remove_prefix(detail::to_unsigned(it - begin())); + } + + /** + Reports an error if using the manual argument indexing; otherwise returns + the next argument index and switches to the automatic indexing. + */ + FMT_CONSTEXPR int next_arg_id() { + // Don't check if the argument id is valid to avoid overhead and because it + // will be checked during formatting anyway. + if (next_arg_id_ >= 0) return next_arg_id_++; + on_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + + /** + Reports an error if using the automatic argument indexing; otherwise + switches to the manual indexing. + */ + FMT_CONSTEXPR void check_arg_id(int) { + if (next_arg_id_ > 0) + on_error("cannot switch from automatic to manual argument indexing"); + else + next_arg_id_ = -1; + } + + FMT_CONSTEXPR void check_arg_id(basic_string_view) {} + + FMT_CONSTEXPR void on_error(const char* message) { + ErrorHandler::on_error(message); + } + + constexpr ErrorHandler error_handler() const { return *this; } +}; + +using format_parse_context = basic_format_parse_context; +using wformat_parse_context = basic_format_parse_context; + +template class basic_format_arg; +template class basic_format_args; +template class dynamic_format_arg_store; + +// A formatter for objects of type T. +template +struct formatter { + // A deleted default constructor indicates a disabled formatter. + formatter() = delete; +}; + +// Specifies if T has an enabled formatter specialization. A type can be +// formattable even if it doesn't have a formatter e.g. via a conversion. +template +using has_formatter = + std::is_constructible>; + +// Checks whether T is a container with contiguous storage. +template struct is_contiguous : std::false_type {}; +template +struct is_contiguous> : std::true_type {}; + +namespace detail { + +// Extracts a reference to the container from back_insert_iterator. +template +inline Container& get_container(std::back_insert_iterator it) { + using bi_iterator = std::back_insert_iterator; + struct accessor : bi_iterator { + accessor(bi_iterator iter) : bi_iterator(iter) {} + using bi_iterator::container; + }; + return *accessor(it).container; +} + +/** + \rst + A contiguous memory buffer with an optional growing ability. It is an internal + class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. + \endrst + */ +template class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_SUPPRESS_MSC_WARNING(26495) + buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} + + buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) FMT_NOEXCEPT + : ptr_(p), + size_(sz), + capacity_(cap) {} + + ~buffer() = default; + + /** Sets the buffer data and capacity. */ + void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + /** Increases the buffer capacity to hold at least *capacity* elements. */ + virtual void grow(size_t capacity) = 0; + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + T* begin() FMT_NOEXCEPT { return ptr_; } + T* end() FMT_NOEXCEPT { return ptr_ + size_; } + + const T* begin() const FMT_NOEXCEPT { return ptr_; } + const T* end() const FMT_NOEXCEPT { return ptr_ + size_; } + + /** Returns the size of this buffer. */ + size_t size() const FMT_NOEXCEPT { return size_; } + + /** Returns the capacity of this buffer. */ + size_t capacity() const FMT_NOEXCEPT { return capacity_; } + + /** Returns a pointer to the buffer data. */ + T* data() FMT_NOEXCEPT { return ptr_; } + + /** Returns a pointer to the buffer data. */ + const T* data() const FMT_NOEXCEPT { return ptr_; } + + /** Clears this buffer. */ + void clear() { size_ = 0; } + + // Tries resizing the buffer to contain *count* elements. If T is a POD type + // the new elements may not be initialized. + void try_resize(size_t count) { + try_reserve(count); + size_ = count <= capacity_ ? count : capacity_; + } + + // Tries increasing the buffer capacity to *new_capacity*. It can increase the + // capacity by a smaller amount than requested but guarantees there is space + // for at least one additional element either by increasing the capacity or by + // flushing the buffer if it is full. + void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow(new_capacity); + } + + void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /** Appends data to the end of the buffer. */ + template void append(const U* begin, const U* end); + + template T& operator[](I index) { return ptr_[index]; } + template const T& operator[](I index) const { + return ptr_[index]; + } +}; + +struct buffer_traits { + explicit buffer_traits(size_t) {} + size_t count() const { return 0; } + size_t limit(size_t size) { return size; } +}; + +class fixed_buffer_traits { + private: + size_t count_ = 0; + size_t limit_; + + public: + explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} + size_t count() const { return count_; } + size_t limit(size_t size) { + size_t n = limit_ > count_ ? limit_ - count_ : 0; + count_ += size; + return size < n ? size : n; + } +}; + +// A buffer that writes to an output iterator when flushed. +template +class iterator_buffer final : public Traits, public buffer { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + void grow(size_t) final FMT_OVERRIDE { + if (this->size() == buffer_size) flush(); + } + void flush(); + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), + buffer(data_, 0, buffer_size), + out_(out) {} + ~iterator_buffer() { flush(); } + + OutputIt out() { + flush(); + return out_; + } + size_t count() const { return Traits::count() + this->size(); } +}; + +template class iterator_buffer final : public buffer { + protected: + void grow(size_t) final FMT_OVERRIDE {} + + public: + explicit iterator_buffer(T* out, size_t = 0) : buffer(out, 0, ~size_t()) {} + + T* out() { return &*this->end(); } +}; + +// A buffer that writes to a container with the contiguous storage. +template +class iterator_buffer, + enable_if_t::value, + typename Container::value_type>> + final : public buffer { + private: + Container& container_; + + protected: + void grow(size_t capacity) final FMT_OVERRIDE { + container_.resize(capacity); + this->set(&container_[0], capacity); + } + + public: + explicit iterator_buffer(Container& c) + : buffer(c.size()), container_(c) {} + explicit iterator_buffer(std::back_insert_iterator out, size_t = 0) + : iterator_buffer(get_container(out)) {} + std::back_insert_iterator out() { + return std::back_inserter(container_); + } +}; + +// A buffer that counts the number of code units written discarding the output. +template class counting_buffer final : public buffer { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + protected: + void grow(size_t) final FMT_OVERRIDE { + if (this->size() != buffer_size) return; + count_ += this->size(); + this->clear(); + } + + public: + counting_buffer() : buffer(data_, 0, buffer_size) {} + + size_t count() { return count_ + this->size(); } +}; + +// An output iterator that appends to the buffer. +// It is used to reduce symbol sizes for the common case. +template +class buffer_appender : public std::back_insert_iterator> { + using base = std::back_insert_iterator>; + + public: + explicit buffer_appender(buffer& buf) : base(buf) {} + buffer_appender(base it) : base(it) {} + + buffer_appender& operator++() { + base::operator++(); + return *this; + } + + buffer_appender operator++(int) { + buffer_appender tmp = *this; + ++*this; + return tmp; + } +}; + +// Maps an output iterator into a buffer. +template +iterator_buffer get_buffer(OutputIt); +template buffer& get_buffer(buffer_appender); + +template OutputIt get_buffer_init(OutputIt out) { + return out; +} +template buffer& get_buffer_init(buffer_appender out) { + return get_container(out); +} + +template +auto get_iterator(Buffer& buf) -> decltype(buf.out()) { + return buf.out(); +} +template buffer_appender get_iterator(buffer& buf) { + return buffer_appender(buf); +} + +template +struct fallback_formatter { + fallback_formatter() = delete; +}; + +// Specifies if T has an enabled fallback_formatter specialization. +template +using has_fallback_formatter = + std::is_constructible>; + +struct view {}; + +template struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template struct named_arg_info { + const Char* name; + int id; +}; + +template +struct arg_data { + // args_[0].named_args points to named_args_ to avoid bloating format_args. + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; + named_arg_info named_args_[NUM_NAMED_ARGS]; + + template + arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {} + arg_data(const arg_data& other) = delete; + const T* args() const { return args_ + 1; } + named_arg_info* named_args() { return named_args_; } +}; + +template +struct arg_data { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; + + template + FMT_INLINE arg_data(const U&... init) : args_{init...} {} + FMT_INLINE const T* args() const { return args_; } + FMT_INLINE std::nullptr_t named_args() { return nullptr; } +}; + +template +inline void init_named_args(named_arg_info*, int, int) {} + +template +void init_named_args(named_arg_info* named_args, int arg_count, + int named_arg_count, const T&, const Tail&... args) { + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template +void init_named_args(named_arg_info* named_args, int arg_count, + int named_arg_count, const named_arg& arg, + const Tail&... args) { + named_args[named_arg_count++] = {arg.name, arg_count}; + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template +FMT_INLINE void init_named_args(std::nullptr_t, int, int, const Args&...) {} + +template struct is_named_arg : std::false_type {}; + +template +struct is_named_arg> : std::true_type {}; + +template constexpr size_t count() { return B ? 1 : 0; } +template constexpr size_t count() { + return (B1 ? 1 : 0) + count(); +} + +template constexpr size_t count_named_args() { + return count::value...>(); +} + +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template +struct type_constant : std::integral_constant {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template \ + struct type_constant \ + : std::integral_constant {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_t, int128_type); +FMT_TYPE_CONSTANT(uint128_t, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr bool is_integral_type(type t) { + return t > type::none_type && t <= type::last_integer_type; +} + +constexpr bool is_arithmetic_type(type t) { + return t > type::none_type && t <= type::last_numeric_type; +} + +template struct string_value { + const Char* data; + size_t size; +}; + +template struct named_arg_value { + const named_arg_info* data; + size_t size; +}; + +template struct custom_value { + using parse_context = typename Context::parse_context_type; + const void* value; + void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx); +}; + +// A formatting argument value. +template class value { + public: + using char_type = typename Context::char_type; + + union { + int int_value; + unsigned uint_value; + long long long_long_value; + unsigned long long ulong_long_value; + int128_t int128_value; + uint128_t uint128_value; + bool bool_value; + char_type char_value; + float float_value; + double double_value; + long double long_double_value; + const void* pointer; + string_value string; + custom_value custom; + named_arg_value named_args; + }; + + constexpr FMT_INLINE value(int val = 0) : int_value(val) {} + constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} + FMT_INLINE value(long long val) : long_long_value(val) {} + FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} + FMT_INLINE value(int128_t val) : int128_value(val) {} + FMT_INLINE value(uint128_t val) : uint128_value(val) {} + FMT_INLINE value(float val) : float_value(val) {} + FMT_INLINE value(double val) : double_value(val) {} + FMT_INLINE value(long double val) : long_double_value(val) {} + FMT_INLINE value(bool val) : bool_value(val) {} + FMT_INLINE value(char_type val) : char_value(val) {} + FMT_INLINE value(const char_type* val) { string.data = val; } + FMT_INLINE value(basic_string_view val) { + string.data = val.data(); + string.size = val.size(); + } + FMT_INLINE value(const void* val) : pointer(val) {} + FMT_INLINE value(const named_arg_info* args, size_t size) + : named_args{args, size} {} + + template FMT_INLINE value(const T& val) { + custom.value = &val; + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter` for `format` and + // `printf_formatter` for `printf`. + custom.format = format_custom_arg< + T, conditional_t::value, + typename Context::template formatter_type, + fallback_formatter>>; + } + + private: + // Formats an argument of a custom type, such as a user-defined class. + template + static void format_custom_arg(const void* arg, + typename Context::parse_context_type& parse_ctx, + Context& ctx) { + Formatter f; + parse_ctx.advance_to(f.parse(parse_ctx)); + ctx.advance_to(f.format(*static_cast(arg), ctx)); + } +}; + +template +FMT_CONSTEXPR basic_format_arg make_arg(const T& value); + +// To minimize the number of types we need to deal with, long is translated +// either to int or to long long depending on its size. +enum { long_short = sizeof(long) == sizeof(int) }; +using long_type = conditional_t; +using ulong_type = conditional_t; + +struct unformattable {}; + +// Maps formatting arguments to core types. +template struct arg_mapper { + using char_type = typename Context::char_type; + + FMT_CONSTEXPR int map(signed char val) { return val; } + FMT_CONSTEXPR unsigned map(unsigned char val) { return val; } + FMT_CONSTEXPR int map(short val) { return val; } + FMT_CONSTEXPR unsigned map(unsigned short val) { return val; } + FMT_CONSTEXPR int map(int val) { return val; } + FMT_CONSTEXPR unsigned map(unsigned val) { return val; } + FMT_CONSTEXPR long_type map(long val) { return val; } + FMT_CONSTEXPR ulong_type map(unsigned long val) { return val; } + FMT_CONSTEXPR long long map(long long val) { return val; } + FMT_CONSTEXPR unsigned long long map(unsigned long long val) { return val; } + FMT_CONSTEXPR int128_t map(int128_t val) { return val; } + FMT_CONSTEXPR uint128_t map(uint128_t val) { return val; } + FMT_CONSTEXPR bool map(bool val) { return val; } + + template ::value)> + FMT_CONSTEXPR char_type map(T val) { + static_assert( + std::is_same::value || std::is_same::value, + "mixing character types is disallowed"); + return val; + } + + FMT_CONSTEXPR float map(float val) { return val; } + FMT_CONSTEXPR double map(double val) { return val; } + FMT_CONSTEXPR long double map(long double val) { return val; } + + FMT_CONSTEXPR const char_type* map(char_type* val) { return val; } + FMT_CONSTEXPR const char_type* map(const char_type* val) { return val; } + template ::value)> + FMT_CONSTEXPR basic_string_view map(const T& val) { + static_assert(std::is_same>::value, + "mixing character types is disallowed"); + return to_string_view(val); + } + template , T>::value && + !is_string::value && !has_formatter::value && + !has_fallback_formatter::value)> + FMT_CONSTEXPR basic_string_view map(const T& val) { + return basic_string_view(val); + } + template < + typename T, + FMT_ENABLE_IF( + std::is_constructible, T>::value && + !std::is_constructible, T>::value && + !is_string::value && !has_formatter::value && + !has_fallback_formatter::value)> + FMT_CONSTEXPR basic_string_view map(const T& val) { + return std_string_view(val); + } + FMT_CONSTEXPR const char* map(const signed char* val) { + static_assert(std::is_same::value, "invalid string type"); + return reinterpret_cast(val); + } + FMT_CONSTEXPR const char* map(const unsigned char* val) { + static_assert(std::is_same::value, "invalid string type"); + return reinterpret_cast(val); + } + FMT_CONSTEXPR const char* map(signed char* val) { + const auto* const_val = val; + return map(const_val); + } + FMT_CONSTEXPR const char* map(unsigned char* val) { + const auto* const_val = val; + return map(const_val); + } + + FMT_CONSTEXPR const void* map(void* val) { return val; } + FMT_CONSTEXPR const void* map(const void* val) { return val; } + FMT_CONSTEXPR const void* map(std::nullptr_t val) { return val; } + template FMT_CONSTEXPR int map(const T*) { + // Formatting of arbitrary pointers is disallowed. If you want to output + // a pointer cast it to "void *" or "const void *". In particular, this + // forbids formatting of "[const] volatile char *" which is printed as bool + // by iostreams. + static_assert(!sizeof(T), "formatting of non-void pointers is disallowed"); + return 0; + } + + template ::value && + !has_formatter::value && + !has_fallback_formatter::value)> + FMT_CONSTEXPR auto map(const T& val) + -> decltype(std::declval().map( + static_cast::type>(val))) { + return map(static_cast::type>(val)); + } + template ::value && !is_char::value && + (has_formatter::value || + has_fallback_formatter::value))> + FMT_CONSTEXPR const T& map(const T& val) { + return val; + } + + template + FMT_CONSTEXPR auto map(const named_arg& val) + -> decltype(std::declval().map(val.value)) { + return map(val.value); + } + + unformattable map(...) { return {}; } +}; + +// A type constant after applying arg_mapper. +template +using mapped_type_constant = + type_constant().map(std::declval())), + typename Context::char_type>; + +enum { packed_arg_bits = 4 }; +// Maximum number of arguments with packed types. +enum { max_packed_args = 62 / packed_arg_bits }; +enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; +enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; +} // namespace detail + +// A formatting argument. It is a trivially copyable/constructible type to +// allow storage in basic_memory_buffer. +template class basic_format_arg { + private: + detail::value value_; + detail::type type_; + + template + friend FMT_CONSTEXPR basic_format_arg detail::make_arg( + const T& value); + + template + friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, + const basic_format_arg& arg) + -> decltype(vis(0)); + + friend class basic_format_args; + friend class dynamic_format_arg_store; + + using char_type = typename Context::char_type; + + template + friend struct detail::arg_data; + + basic_format_arg(const detail::named_arg_info* args, size_t size) + : value_(args, size) {} + + public: + class handle { + public: + explicit handle(detail::custom_value custom) : custom_(custom) {} + + void format(typename Context::parse_context_type& parse_ctx, + Context& ctx) const { + custom_.format(custom_.value, parse_ctx, ctx); + } + + private: + detail::custom_value custom_; + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + + constexpr explicit operator bool() const FMT_NOEXCEPT { + return type_ != detail::type::none_type; + } + + detail::type type() const { return type_; } + + bool is_integral() const { return detail::is_integral_type(type_); } + bool is_arithmetic() const { return detail::is_arithmetic_type(type_); } +}; + +/** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + ``vis(value)`` will be called with the value of type ``double``. + \endrst + */ +template +FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg( + Visitor&& vis, const basic_format_arg& arg) -> decltype(vis(0)) { + using char_type = typename Context::char_type; + switch (arg.type_) { + case detail::type::none_type: + break; + case detail::type::int_type: + return vis(arg.value_.int_value); + case detail::type::uint_type: + return vis(arg.value_.uint_value); + case detail::type::long_long_type: + return vis(arg.value_.long_long_value); + case detail::type::ulong_long_type: + return vis(arg.value_.ulong_long_value); +#if FMT_USE_INT128 + case detail::type::int128_type: + return vis(arg.value_.int128_value); + case detail::type::uint128_type: + return vis(arg.value_.uint128_value); +#else + case detail::type::int128_type: + case detail::type::uint128_type: + break; +#endif + case detail::type::bool_type: + return vis(arg.value_.bool_value); + case detail::type::char_type: + return vis(arg.value_.char_value); + case detail::type::float_type: + return vis(arg.value_.float_value); + case detail::type::double_type: + return vis(arg.value_.double_value); + case detail::type::long_double_type: + return vis(arg.value_.long_double_value); + case detail::type::cstring_type: + return vis(arg.value_.string.data); + case detail::type::string_type: + return vis(basic_string_view(arg.value_.string.data, + arg.value_.string.size)); + case detail::type::pointer_type: + return vis(arg.value_.pointer); + case detail::type::custom_type: + return vis(typename basic_format_arg::handle(arg.value_.custom)); + } + return vis(monostate()); +} + +template struct formattable : std::false_type {}; + +namespace detail { + +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template struct void_t_impl { using type = void; }; +template +using void_t = typename detail::void_t_impl::type; + +template +struct is_output_iterator : std::false_type {}; + +template +struct is_output_iterator< + It, T, + void_t::iterator_category, + decltype(*std::declval() = std::declval())>> + : std::true_type {}; + +template +struct is_back_insert_iterator : std::false_type {}; +template +struct is_back_insert_iterator> + : std::true_type {}; + +template +struct is_contiguous_back_insert_iterator : std::false_type {}; +template +struct is_contiguous_back_insert_iterator> + : is_contiguous {}; +template +struct is_contiguous_back_insert_iterator> + : std::true_type {}; + +// A type-erased reference to an std::locale to avoid heavy include. +class locale_ref { + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + locale_ref() : locale_(nullptr) {} + template explicit locale_ref(const Locale& loc); + + explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; } + + template Locale get() const; +}; + +template constexpr unsigned long long encode_types() { return 0; } + +template +constexpr unsigned long long encode_types() { + return static_cast(mapped_type_constant::value) | + (encode_types() << packed_arg_bits); +} + +template +FMT_CONSTEXPR basic_format_arg make_arg(const T& value) { + basic_format_arg arg; + arg.type_ = mapped_type_constant::value; + arg.value_ = arg_mapper().map(value); + return arg; +} + +template int check(unformattable) { + static_assert( + formattable(), + "Cannot format an argument. To make type T formattable provide a " + "formatter specialization: https://fmt.dev/latest/api.html#udt"); + return 0; +} +template inline const U& check(const U& val) { + return val; +} + +// The type template parameter is there to avoid an ODR violation when using +// a fallback formatter in one translation unit and an implicit conversion in +// another (not recommended). +template +inline value make_arg(const T& val) { + return check(arg_mapper().map(val)); +} + +template +inline basic_format_arg make_arg(const T& value) { + return make_arg(value); +} + +template struct is_reference_wrapper : std::false_type {}; +template +struct is_reference_wrapper> : std::true_type {}; + +template const T& unwrap(const T& v) { return v; } +template const T& unwrap(const std::reference_wrapper& v) { + return static_cast(v); +} + +class dynamic_arg_list { + // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for + // templates it doesn't complain about inability to deduce single translation + // unit for placing vtable. So storage_node_base is made a fake template. + template struct node { + virtual ~node() = default; + std::unique_ptr> next; + }; + + template struct typed_node : node<> { + T value; + + template + FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} + + template + FMT_CONSTEXPR typed_node(const basic_string_view& arg) + : value(arg.data(), arg.size()) {} + }; + + std::unique_ptr> head_; + + public: + template const T& push(const Arg& arg) { + auto new_node = std::unique_ptr>(new typed_node(arg)); + auto& value = new_node->value; + new_node->next = std::move(head_); + head_ = std::move(new_node); + return value; + } +}; +} // namespace detail + +// Formatting context. +template class basic_format_context { + public: + /** The character type for the output. */ + using char_type = Char; + + private: + OutputIt out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + using iterator = OutputIt; + using format_arg = basic_format_arg; + using parse_context_type = basic_format_parse_context; + template using formatter_type = formatter; + + basic_format_context(const basic_format_context&) = delete; + void operator=(const basic_format_context&) = delete; + /** + Constructs a ``basic_format_context`` object. References to the arguments are + stored in the object so make sure they have appropriate lifetimes. + */ + basic_format_context(OutputIt out, + basic_format_args ctx_args, + detail::locale_ref loc = detail::locale_ref()) + : out_(out), args_(ctx_args), loc_(loc) {} + + format_arg arg(int id) const { return args_.get(id); } + format_arg arg(basic_string_view name) { return args_.get(name); } + int arg_id(basic_string_view name) { return args_.get_id(name); } + const basic_format_args& args() const { return args_; } + + detail::error_handler error_handler() { return {}; } + void on_error(const char* message) { error_handler().on_error(message); } + + // Returns an iterator to the beginning of the output range. + iterator out() { return out_; } + + // Advances the begin iterator to ``it``. + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator()) out_ = it; + } + + detail::locale_ref locale() { return loc_; } +}; + +template +using buffer_context = + basic_format_context, Char>; +using format_context = buffer_context; +using wformat_context = buffer_context; + +// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164. +#define FMT_BUFFER_CONTEXT(Char) \ + basic_format_context, Char> + +/** + \rst + An array of references to arguments. It can be implicitly converted into + `~fmt::basic_format_args` for passing into type-erased formatting functions + such as `~fmt::vformat`. + \endrst + */ +template +class format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args +#endif +{ + private: + static const size_t num_args = sizeof...(Args); + static const size_t num_named_args = detail::count_named_args(); + static const bool is_packed = num_args <= detail::max_packed_args; + + using value_type = conditional_t, + basic_format_arg>; + + detail::arg_data + data_; + + friend class basic_format_args; + + static constexpr unsigned long long desc = + (is_packed ? detail::encode_types() + : detail::is_unpacked_bit | num_args) | + (num_named_args != 0 + ? static_cast(detail::has_named_args_bit) + : 0); + + public: + format_arg_store(const Args&... args) + : +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + basic_format_args(*this), +#endif + data_{detail::make_arg< + is_packed, Context, + detail::mapped_type_constant::value>(args)...} { + detail::init_named_args(data_.named_args(), 0, 0, args...); + } +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::format_args`. `Context` + can be omitted in which case it defaults to `~fmt::context`. + See `~fmt::arg` for lifetime considerations. + \endrst + */ +template +inline format_arg_store make_format_args( + const Args&... args) { + return {args...}; +} + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references + to arguments and can be implicitly converted to `~fmt::format_args`. + If ``format_str`` is a compile-time string then `make_args_checked` checks + its validity at compile time. + \endrst + */ +template > +inline auto make_args_checked(const S& format_str, + const remove_reference_t&... args) + -> format_arg_store, remove_reference_t...> { + static_assert( + detail::count<( + std::is_base_of>::value && + std::is_reference::value)...>() == 0, + "passing views as lvalues is disallowed"); + detail::check_format_string(format_str); + return {args...}; +} + +/** + \rst + Returns a named argument to be used in a formatting function. It should only + be used in a call to a formatting function. + + **Example**:: + + fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); + \endrst + */ +template +inline detail::named_arg arg(const Char* name, const T& arg) { + static_assert(!detail::is_named_arg(), "nested named arguments"); + return {name, arg}; +} + +/** + \rst + A dynamic version of `fmt::format_arg_store`. + It's equipped with a storage to potentially temporary objects which lifetimes + could be shorter than the format arguments object. + + It can be implicitly converted into `~fmt::basic_format_args` for passing + into type-erased formatting functions such as `~fmt::vformat`. + \endrst + */ +template +class dynamic_format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args +#endif +{ + private: + using char_type = typename Context::char_type; + + template struct need_copy { + static constexpr detail::type mapped_type = + detail::mapped_type_constant::value; + + enum { + value = !(detail::is_reference_wrapper::value || + std::is_same>::value || + std::is_same>::value || + (mapped_type != detail::type::cstring_type && + mapped_type != detail::type::string_type && + mapped_type != detail::type::custom_type)) + }; + }; + + template + using stored_type = conditional_t::value, + std::basic_string, T>; + + // Storage of basic_format_arg must be contiguous. + std::vector> data_; + std::vector> named_info_; + + // Storage of arguments not fitting into basic_format_arg must grow + // without relocation because items in data_ refer to it. + detail::dynamic_arg_list dynamic_args_; + + friend class basic_format_args; + + unsigned long long get_types() const { + return detail::is_unpacked_bit | data_.size() | + (named_info_.empty() + ? 0ULL + : static_cast(detail::has_named_args_bit)); + } + + const basic_format_arg* data() const { + return named_info_.empty() ? data_.data() : data_.data() + 1; + } + + template void emplace_arg(const T& arg) { + data_.emplace_back(detail::make_arg(arg)); + } + + template + void emplace_arg(const detail::named_arg& arg) { + if (named_info_.empty()) { + constexpr const detail::named_arg_info* zero_ptr{nullptr}; + data_.insert(data_.begin(), {zero_ptr, 0}); + } + data_.emplace_back(detail::make_arg(detail::unwrap(arg.value))); + auto pop_one = [](std::vector>* data) { + data->pop_back(); + }; + std::unique_ptr>, decltype(pop_one)> + guard{&data_, pop_one}; + named_info_.push_back({arg.name, static_cast(data_.size() - 2u)}); + data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; + guard.release(); + } + + public: + /** + \rst + Adds an argument into the dynamic store for later passing to a formatting + function. + + Note that custom types and string types (but not string views) are copied + into the store dynamically allocating memory if necessary. + + **Example**:: + + fmt::dynamic_format_arg_store store; + store.push_back(42); + store.push_back("abc"); + store.push_back(1.5f); + std::string result = fmt::vformat("{} and {} and {}", store); + \endrst + */ + template void push_back(const T& arg) { + if (detail::const_check(need_copy::value)) + emplace_arg(dynamic_args_.push>(arg)); + else + emplace_arg(detail::unwrap(arg)); + } + + /** + \rst + Adds a reference to the argument into the dynamic store for later passing to + a formatting function. Supports named arguments wrapped in + ``std::reference_wrapper`` via ``std::ref()``/``std::cref()``. + + **Example**:: + + fmt::dynamic_format_arg_store store; + char str[] = "1234567890"; + store.push_back(std::cref(str)); + int a1_val{42}; + auto a1 = fmt::arg("a1_", a1_val); + store.push_back(std::cref(a1)); + + // Changing str affects the output but only for string and custom types. + str[0] = 'X'; + + std::string result = fmt::vformat("{} and {a1_}"); + assert(result == "X234567890 and 42"); + \endrst + */ + template void push_back(std::reference_wrapper arg) { + static_assert( + detail::is_named_arg::type>::value || + need_copy::value, + "objects of built-in types and string views are always copied"); + emplace_arg(arg.get()); + } + + /** + Adds named argument into the dynamic store for later passing to a formatting + function. ``std::reference_wrapper`` is supported to avoid copying of the + argument. + */ + template + void push_back(const detail::named_arg& arg) { + const char_type* arg_name = + dynamic_args_.push>(arg.name).c_str(); + if (detail::const_check(need_copy::value)) { + emplace_arg( + fmt::arg(arg_name, dynamic_args_.push>(arg.value))); + } else { + emplace_arg(fmt::arg(arg_name, arg.value)); + } + } + + /** Erase all elements from the store */ + void clear() { + data_.clear(); + named_info_.clear(); + dynamic_args_ = detail::dynamic_arg_list(); + } + + /** + \rst + Reserves space to store at least *new_cap* arguments including + *new_cap_named* named arguments. + \endrst + */ + void reserve(size_t new_cap, size_t new_cap_named) { + FMT_ASSERT(new_cap >= new_cap_named, + "Set of arguments includes set of named arguments"); + data_.reserve(new_cap); + named_info_.reserve(new_cap_named); + } +}; + +/** + \rst + A view of a collection of formatting arguments. To avoid lifetime issues it + should only be used as a parameter type in type-erased functions such as + ``vformat``:: + + void vlog(string_view format_str, format_args args); // OK + format_args args = make_format_args(42); // Error: dangling reference + \endrst + */ +template class basic_format_args { + public: + using size_type = int; + using format_arg = basic_format_arg; + + private: + // A descriptor that contains information about formatting arguments. + // If the number of arguments is less or equal to max_packed_args then + // argument types are passed in the descriptor. This reduces binary code size + // per formatting function call. + unsigned long long desc_; + union { + // If is_packed() returns true then argument values are stored in values_; + // otherwise they are stored in args_. This is done to improve cache + // locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const detail::value* values_; + const format_arg* args_; + }; + + bool is_packed() const { return (desc_ & detail::is_unpacked_bit) == 0; } + bool has_named_args() const { + return (desc_ & detail::has_named_args_bit) != 0; + } + + detail::type type(int index) const { + int shift = index * detail::packed_arg_bits; + unsigned int mask = (1 << detail::packed_arg_bits) - 1; + return static_cast((desc_ >> shift) & mask); + } + + basic_format_args(unsigned long long desc, + const detail::value* values) + : desc_(desc), values_(values) {} + basic_format_args(unsigned long long desc, const format_arg* args) + : desc_(desc), args_(args) {} + + public: + basic_format_args() : desc_(0) {} + + /** + \rst + Constructs a `basic_format_args` object from `~fmt::format_arg_store`. + \endrst + */ + template + FMT_INLINE basic_format_args(const format_arg_store& store) + : basic_format_args(store.desc, store.data_.args()) {} + + /** + \rst + Constructs a `basic_format_args` object from + `~fmt::dynamic_format_arg_store`. + \endrst + */ + FMT_INLINE basic_format_args(const dynamic_format_arg_store& store) + : basic_format_args(store.get_types(), store.data()) {} + + /** + \rst + Constructs a `basic_format_args` object from a dynamic set of arguments. + \endrst + */ + basic_format_args(const format_arg* args, int count) + : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), + args) {} + + /** Returns the argument with the specified id. */ + format_arg get(int id) const { + format_arg arg; + if (!is_packed()) { + if (id < max_size()) arg = args_[id]; + return arg; + } + if (id >= detail::max_packed_args) return arg; + arg.type_ = type(id); + if (arg.type_ == detail::type::none_type) return arg; + arg.value_ = values_[id]; + return arg; + } + + template format_arg get(basic_string_view name) const { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template int get_id(basic_string_view name) const { + if (!has_named_args()) return -1; + const auto& named_args = + (is_packed() ? values_[-1] : args_[-1].value_).named_args; + for (size_t i = 0; i < named_args.size; ++i) { + if (named_args.data[i].name == name) return named_args.data[i].id; + } + return -1; + } + + int max_size() const { + unsigned long long max_packed = detail::max_packed_args; + return static_cast(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +#ifdef FMT_ARM_ABI_COMPATIBILITY +/** An alias to ``basic_format_args``. */ +// Separate types would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args; +using wformat_args = basic_format_args; +#else +// DEPRECATED! These are kept for ABI compatibility. +// It is a separate type rather than an alias to make symbols readable. +struct format_args : basic_format_args { + template + FMT_INLINE format_args(const Args&... args) : basic_format_args(args...) {} +}; +struct wformat_args : basic_format_args { + using basic_format_args::basic_format_args; +}; +#endif + +namespace detail { + +template ::value)> +std::basic_string vformat( + basic_string_view format_str, + basic_format_args>> args); + +FMT_API std::string vformat(string_view format_str, format_args args); + +template +void vformat_to( + buffer& buf, basic_string_view format_str, + basic_format_args)> args, + detail::locale_ref loc = {}); + +template ::value)> +inline void vprint_mojibake(std::FILE*, basic_string_view, const Args&) {} + +FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); +#ifndef _WIN32 +inline void vprint_mojibake(std::FILE*, string_view, format_args) {} +#endif +} // namespace detail + +/** Formats a string and writes the output to ``out``. */ +// GCC 8 and earlier cannot handle std::back_insert_iterator with +// vformat_to(...) overload, so SFINAE on iterator type instead. +template , + bool enable = detail::is_output_iterator::value> +auto vformat_to(OutputIt out, const S& format_str, + basic_format_args>> args) + -> typename std::enable_if::type { + decltype(detail::get_buffer(out)) buf(detail::get_buffer_init(out)); + detail::vformat_to(buf, to_string_view(format_str), args); + return detail::get_iterator(buf); +} + +/** + \rst + Formats arguments, writes the result to the output iterator ``out`` and returns + the iterator past the end of the output range. + + **Example**:: + + std::vector out; + fmt::format_to(std::back_inserter(out), "{}", 42); + \endrst + */ +// We cannot use FMT_ENABLE_IF because of a bug in gcc 8.3. +template >::value> +inline auto format_to(OutputIt out, const S& format_str, Args&&... args) -> + typename std::enable_if::type { + const auto& vargs = fmt::make_args_checked(format_str, args...); + return vformat_to(out, to_string_view(format_str), vargs); +} + +template struct format_to_n_result { + /** Iterator past the end of the output range. */ + OutputIt out; + /** Total (not truncated) output size. */ + size_t size; +}; + +template ::value)> +inline format_to_n_result vformat_to_n( + OutputIt out, size_t n, basic_string_view format_str, + basic_format_args>> args) { + detail::iterator_buffer buf(out, + n); + detail::vformat_to(buf, format_str, args); + return {buf.out(), buf.count()}; +} + +/** + \rst + Formats arguments, writes up to ``n`` characters of the result to the output + iterator ``out`` and returns the total output size and the iterator past the + end of the output range. + \endrst + */ +template >::value> +inline auto format_to_n(OutputIt out, size_t n, const S& format_str, + const Args&... args) -> + typename std::enable_if>::type { + const auto& vargs = fmt::make_args_checked(format_str, args...); + return vformat_to_n(out, n, to_string_view(format_str), vargs); +} + +/** + Returns the number of characters in the output of + ``format(format_str, args...)``. + */ +template +inline size_t formatted_size(string_view format_str, Args&&... args) { + const auto& vargs = fmt::make_args_checked(format_str, args...); + detail::counting_buffer<> buf; + detail::vformat_to(buf, format_str, vargs); + return buf.count(); +} + +template > +FMT_INLINE std::basic_string vformat( + const S& format_str, + basic_format_args>> args) { + return detail::vformat(to_string_view(format_str), args); +} + +/** + \rst + Formats arguments and returns the result as a string. + + **Example**:: + + #include + std::string message = fmt::format("The answer is {}", 42); + \endrst +*/ +// Pass char_t as a default template parameter instead of using +// std::basic_string> to reduce the symbol size. +template > +FMT_INLINE std::basic_string format(const S& format_str, Args&&... args) { + const auto& vargs = fmt::make_args_checked(format_str, args...); + return detail::vformat(to_string_view(format_str), vargs); +} + +FMT_API void vprint(string_view, format_args); +FMT_API void vprint(std::FILE*, string_view, format_args); + +/** + \rst + Formats ``args`` according to specifications in ``format_str`` and writes the + output to the file ``f``. Strings are assumed to be Unicode-encoded unless the + ``FMT_UNICODE`` macro is set to 0. + + **Example**:: + + fmt::print(stderr, "Don't {}!", "panic"); + \endrst + */ +template > +inline void print(std::FILE* f, const S& format_str, Args&&... args) { + const auto& vargs = fmt::make_args_checked(format_str, args...); + return detail::is_unicode() + ? vprint(f, to_string_view(format_str), vargs) + : detail::vprint_mojibake(f, to_string_view(format_str), vargs); +} + +/** + \rst + Formats ``args`` according to specifications in ``format_str`` and writes + the output to ``stdout``. Strings are assumed to be Unicode-encoded unless + the ``FMT_UNICODE`` macro is set to 0. + + **Example**:: + + fmt::print("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template > +inline void print(const S& format_str, Args&&... args) { + const auto& vargs = fmt::make_args_checked(format_str, args...); + return detail::is_unicode() + ? vprint(to_string_view(format_str), vargs) + : detail::vprint_mojibake(stdout, to_string_view(format_str), + vargs); +} +FMT_END_NAMESPACE + +#endif // FMT_CORE_H_ diff --git a/src/3rdparty/fmt/format-inl.h b/src/3rdparty/fmt/format-inl.h new file mode 100644 index 0000000000..8f2fe7354a --- /dev/null +++ b/src/3rdparty/fmt/format-inl.h @@ -0,0 +1,2801 @@ +// Formatting library for C++ - implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_FORMAT_INL_H_ +#define FMT_FORMAT_INL_H_ + +#include +#include +#include +#include +#include +#include // std::memmove +#include +#include + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +# include +#endif + +#ifdef _WIN32 +# include // _isatty +#endif + +#include "format.h" + +// Dummy implementations of strerror_r and strerror_s called if corresponding +// system functions are not available. +inline fmt::detail::null<> strerror_r(int, char*, ...) { return {}; } +inline fmt::detail::null<> strerror_s(char*, size_t, ...) { return {}; } + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_FUNC void assert_fail(const char* file, int line, const char* message) { + // Use unchecked std::fprintf to avoid triggering another assertion when + // writing to stderr fails + std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); + // Chosen instead of std::abort to satisfy Clang in CUDA mode during device + // code pass. + std::terminate(); +} + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else // _MSC_VER +inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); + va_end(args); + return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +// A portable thread-safe version of strerror. +// Sets buffer to point to a string describing the error code. +// This can be either a pointer to a string stored in buffer, +// or a pointer to some static immutable string. +// Returns one of the following values: +// 0 - success +// ERANGE - buffer is not large enough to store the error message +// other - failure +// Buffer should be at least of size 1. +inline int safe_strerror(int error_code, char*& buffer, + size_t buffer_size) FMT_NOEXCEPT { + FMT_ASSERT(buffer != nullptr && buffer_size != 0, "invalid buffer"); + + class dispatcher { + private: + int error_code_; + char*& buffer_; + size_t buffer_size_; + + // A noop assignment operator to avoid bogus warnings. + void operator=(const dispatcher&) {} + + // Handle the result of XSI-compliant version of strerror_r. + int handle(int result) { + // glibc versions before 2.13 return result in errno. + return result == -1 ? errno : result; + } + + // Handle the result of GNU-specific version of strerror_r. + FMT_MAYBE_UNUSED + int handle(char* message) { + // If the buffer is full then the message is probably truncated. + if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1) + return ERANGE; + buffer_ = message; + return 0; + } + + // Handle the case when strerror_r is not available. + FMT_MAYBE_UNUSED + int handle(detail::null<>) { + return fallback(strerror_s(buffer_, buffer_size_, error_code_)); + } + + // Fallback to strerror_s when strerror_r is not available. + FMT_MAYBE_UNUSED + int fallback(int result) { + // If the buffer is full then the message is probably truncated. + return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? ERANGE + : result; + } + +#if !FMT_MSC_VER + // Fallback to strerror if strerror_r and strerror_s are not available. + int fallback(detail::null<>) { + errno = 0; + buffer_ = strerror(error_code_); + return errno; + } +#endif + + public: + dispatcher(int err_code, char*& buf, size_t buf_size) + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} + + int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); } + }; + return dispatcher(error_code, buffer, buffer_size).run(); +} + +FMT_FUNC void format_error_code(detail::buffer& out, int error_code, + string_view message) FMT_NOEXCEPT { + // Report error code making sure that the output fits into + // inline_buffer_size to avoid dynamic memory allocation and potential + // bad_alloc. + out.try_resize(0); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + auto abs_value = static_cast>(error_code); + if (detail::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); + auto it = buffer_appender(out); + if (message.size() <= inline_buffer_size - error_code_size) + format_to(it, "{}{}", message, SEP); + format_to(it, "{}{}", ERROR_STR, error_code); + assert(out.size() <= inline_buffer_size); +} + +FMT_FUNC void report_error(format_func func, int error_code, + string_view message) FMT_NOEXCEPT { + memory_buffer full_message; + func(full_message, error_code, message); + // Don't use fwrite_fully because the latter may throw. + (void)std::fwrite(full_message.data(), full_message.size(), 1, stderr); + std::fputc('\n', stderr); +} + +// A wrapper around fwrite that throws on error. +inline void fwrite_fully(const void* ptr, size_t size, size_t count, + FILE* stream) { + size_t written = std::fwrite(ptr, size, count, stream); + if (written < count) FMT_THROW(system_error(errno, "cannot write to file")); +} +} // namespace detail + +#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) +namespace detail { + +template +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same::value, ""); +} + +template Locale locale_ref::get() const { + static_assert(std::is_same::value, ""); + return locale_ ? *static_cast(locale_) : std::locale(); +} + +template FMT_FUNC std::string grouping_impl(locale_ref loc) { + return std::use_facet>(loc.get()).grouping(); +} +template FMT_FUNC Char thousands_sep_impl(locale_ref loc) { + return std::use_facet>(loc.get()) + .thousands_sep(); +} +template FMT_FUNC Char decimal_point_impl(locale_ref loc) { + return std::use_facet>(loc.get()) + .decimal_point(); +} +} // namespace detail +#else +template +FMT_FUNC std::string detail::grouping_impl(locale_ref) { + return "\03"; +} +template FMT_FUNC Char detail::thousands_sep_impl(locale_ref) { + return FMT_STATIC_THOUSANDS_SEPARATOR; +} +template FMT_FUNC Char detail::decimal_point_impl(locale_ref) { + return '.'; +} +#endif + +FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default; +FMT_API FMT_FUNC system_error::~system_error() FMT_NOEXCEPT = default; + +FMT_FUNC void system_error::init(int err_code, string_view format_str, + format_args args) { + error_code_ = err_code; + memory_buffer buffer; + format_system_error(buffer, err_code, vformat(format_str, args)); + std::runtime_error& base = *this; + base = std::runtime_error(to_string(buffer)); +} + +namespace detail { + +template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) { + // fallback_uintptr is always stored in little endian. + int i = static_cast(sizeof(void*)) - 1; + while (i > 0 && n.value[i] == 0) --i; + auto char_digits = std::numeric_limits::digits / 4; + return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1; +} + +template +const typename basic_data::digit_pair basic_data::digits[] = { + {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, + {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'}, + {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, + {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, + {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'}, + {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, + {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'}, + {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, + {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, + {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'}, + {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, + {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'}, + {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, + {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, + {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'}, + {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, + {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}}; + +template +const char basic_data::hex_digits[] = "0123456789abcdef"; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ + (factor)*1000000, (factor)*10000000, (factor)*100000000, \ + (factor)*1000000000 + +template +const uint64_t basic_data::powers_of_10_64[] = { + 1, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + +template +const uint32_t basic_data::zero_or_powers_of_10_32[] = {0, + FMT_POWERS_OF_10(1)}; +template +const uint64_t basic_data::zero_or_powers_of_10_64[] = { + 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + +template +const uint32_t basic_data::zero_or_powers_of_10_32_new[] = { + 0, 0, FMT_POWERS_OF_10(1)}; + +template +const uint64_t basic_data::zero_or_powers_of_10_64_new[] = { + 0, 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + +// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340. +// These are generated by support/compute-powers.py. +template +const uint64_t basic_data::grisu_pow10_significands[] = { + 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, + 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, + 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, + 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, + 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, + 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, + 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, + 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, + 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, + 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, + 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, + 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, + 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, + 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, + 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, + 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, + 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, + 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, + 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, + 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, + 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, + 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, + 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, + 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, + 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, + 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, + 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, + 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, + 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, +}; + +// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding +// to significands above. +template +const int16_t basic_data::grisu_pow10_exponents[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, + -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, + -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, + -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, + -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, + 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, + 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, + 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; + +template +const divtest_table_entry basic_data::divtest_table_for_pow5_32[] = + {{0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333}, + {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba}, + {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5}, + {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf}, + {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897}, + {0x3ed61f49, 0x000001b7}}; + +template +const divtest_table_entry basic_data::divtest_table_for_pow5_64[] = + {{0x0000000000000001, 0xffffffffffffffff}, + {0xcccccccccccccccd, 0x3333333333333333}, + {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70}, + {0x1cac083126e978d5, 0x020c49ba5e353f7c}, + {0xd288ce703afb7e91, 0x0068db8bac710cb2}, + {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0}, + {0x790fb65668c26139, 0x000431bde82d7b63}, + {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a}, + {0xc767074b22e90e21, 0x00002af31dc46118}, + {0x8e47ce423a2e9c6d, 0x0000089705f4136b}, + {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b}, + {0x0fee64690c913975, 0x00000057f5ff85e5}, + {0x3662e0e1cf503eb1, 0x000000119799812d}, + {0xa47a2cf9f6433fbd, 0x0000000384b84d09}, + {0x54186f653140a659, 0x00000000b424dc35}, + {0x7738164770402145, 0x0000000024075f3d}, + {0xe4a4d1417cd9a041, 0x000000000734aca5}, + {0xc75429d9e5c5200d, 0x000000000170ef54}, + {0xc1773b91fac10669, 0x000000000049c977}, + {0x26b172506559ce15, 0x00000000000ec1e4}, + {0xd489e3a9addec2d1, 0x000000000002f394}, + {0x90e860bb892c8d5d, 0x000000000000971d}, + {0x502e79bf1b6f4f79, 0x0000000000001e39}, + {0xdcd618596be30fe5, 0x000000000000060b}}; + +template +const uint64_t basic_data::dragonbox_pow10_significands_64[] = { + 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, + 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb, + 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28, + 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, + 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, + 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810, + 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, + 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, + 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, + 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000, + 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, + 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, + 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, + 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000, + 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, + 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, + 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0, + 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984, + 0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296, + 0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6, + 0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20, + 0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd, + 0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719, + 0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e}; + +template +const uint128_wrapper basic_data::dragonbox_pow10_significands_128[] = { +#if FMT_USE_FULL_CACHE_DRAGONBOX + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0x9faacf3df73609b1, 0x77b191618c54e9ad}, + {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, + {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e}, + {0x9becce62836ac577, 0x4ee367f9430aec33}, + {0xc2e801fb244576d5, 0x229c41f793cda740}, + {0xf3a20279ed56d48a, 0x6b43527578c11110}, + {0x9845418c345644d6, 0x830a13896b78aaaa}, + {0xbe5691ef416bd60c, 0x23cc986bc656d554}, + {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9}, + {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, + {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54}, + {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, + {0x91376c36d99995be, 0x23100809b9c21fa2}, + {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, + {0xe2e69915b3fff9f9, 0x16c90c8f323f516d}, + {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, + {0xb1442798f49ffb4a, 0x99cd11cfdf41779d}, + {0xdd95317f31c7fa1d, 0x40405643d711d584}, + {0x8a7d3eef7f1cfc52, 0x482835ea666b2573}, + {0xad1c8eab5ee43b66, 0xda3243650005eed0}, + {0xd863b256369d4a40, 0x90bed43e40076a83}, + {0x873e4f75e2224e68, 0x5a7744a6e804a292}, + {0xa90de3535aaae202, 0x711515d0a205cb37}, + {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, + {0x8412d9991ed58091, 0xe858790afe9486c3}, + {0xa5178fff668ae0b6, 0x626e974dbe39a873}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, + {0xa139029f6a239f72, 0x1c1fffc1ebc44e81}, + {0xc987434744ac874e, 0xa327ffb266b56221}, + {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9}, + {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, + {0xc4ce17b399107c22, 0xcb550fb4384d21d4}, + {0xf6019da07f549b2b, 0x7e2a53a146606a49}, + {0x99c102844f94e0fb, 0x2eda7444cbfc426e}, + {0xc0314325637a1939, 0xfa911155fefb5309}, + {0xf03d93eebc589f88, 0x793555ab7eba27cb}, + {0x96267c7535b763b5, 0x4bc1558b2f3458df}, + {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17}, + {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, + {0x92a1958a7675175f, 0x0bfacd89ec191eca}, + {0xb749faed14125d36, 0xcef980ec671f667c}, + {0xe51c79a85916f484, 0x82b7e12780e7401b}, + {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, + {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16}, + {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, + {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1}, + {0xaecc49914078536d, 0x58fae9f773886e19}, + {0xda7f5bf590966848, 0xaf39a475506a899f}, + {0x888f99797a5e012d, 0x6d8406c952429604}, + {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84}, + {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, + {0x855c3be0a17fcd26, 0x5cf2eea09a550680}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0xd0601d8efc57b08b, 0xf13b94daf124da27}, + {0x823c12795db6ce57, 0x76c53d08d6b70859}, + {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f}, + {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, + {0xfe5d54150b090b02, 0xd3f93b35435d7c4d}, + {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, + {0xc6b8e9b0709f109a, 0x359ab6419ca1091c}, + {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, + {0x9b407691d7fc44f8, 0x79e0de63425dcf1e}, + {0xc21094364dfb5636, 0x985915fc12f542e5}, + {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e}, + {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, + {0xbd8430bd08277231, 0x50c6ff782a838354}, + {0xece53cec4a314ebd, 0xa4f8bf5635246429}, + {0x940f4613ae5ed136, 0x871b7795e136be9a}, + {0xb913179899f68584, 0x28e2557b59846e40}, + {0xe757dd7ec07426e5, 0x331aeada2fe589d0}, + {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, + {0xb4bca50b065abe63, 0x0fed077a756b53aa}, + {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, + {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d}, + {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, + {0xdca04777f541c567, 0xecf0d7a0fc5583a1}, + {0x89e42caaf9491b60, 0xf41686c49db57245}, + {0xac5d37d5b79b6239, 0x311c2875c522ced6}, + {0xd77485cb25823ac7, 0x7d633293366b828c}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, + {0xd267caa862a12d66, 0xd072df63c324fd7c}, + {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, + {0xa46116538d0deb78, 0x52d9be85f074e609}, + {0xcd795be870516656, 0x67902e276c921f8c}, + {0x806bd9714632dff6, 0x00ba1cd8a3db53b7}, + {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, + {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce}, + {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, + {0x9cc3a6eec6311a63, 0xcbe3303674053bb1}, + {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, + {0xf4f1b4d515acb93b, 0xee92fb5515482d45}, + {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, + {0xbf5cd54678eef0b6, 0xd262d45a78a0635e}, + {0xef340a98172aace4, 0x86fb897116c87c35}, + {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1}, + {0xbae0a846d2195712, 0x8974836059cca10a}, + {0xe998d258869facd7, 0x2bd1a438703fc94c}, + {0x91ff83775423cc06, 0x7b6306a34627ddd0}, + {0xb67f6455292cbf08, 0x1a3bc84c17b1d543}, + {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, + {0x8e938662882af53e, 0x547eb47b7282ee9d}, + {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, + {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5}, + {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, + {0xae0b158b4738705e, 0x9624ab50b148d446}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7}, + {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, + {0xd47487cc8470652b, 0x7647c32000696720}, + {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, + {0xa5fb0a17c777cf09, 0xf468107100525891}, + {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, + {0x81ac1fe293d599bf, 0xc6f14cd848405531}, + {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, + {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d}, + {0xfd442e4688bd304a, 0x908f4a166d1da664}, + {0x9e4a9cec15763e2e, 0x9a598e4e043287ff}, + {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, + {0xf7549530e188c128, 0xd12bee59e68ef47d}, + {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, + {0xc13a148e3032d6e7, 0xe36a52363c1faf02}, + {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, + {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba}, + {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, + {0xebdf661791d60f56, 0x111b495b3464ad22}, + {0x936b9fcebb25c995, 0xcab10dd900beec35}, + {0xb84687c269ef3bfb, 0x3d5d514f40eea743}, + {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, + {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac}, + {0xb3f4e093db73a093, 0x59ed216765690f57}, + {0xe0f218b8d25088b8, 0x306869c13ec3532d}, + {0x8c974f7383725573, 0x1e414218c73a13fc}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, + {0x894bc396ce5da772, 0x6b8bba8c328eb784}, + {0xab9eb47c81f5114f, 0x066ea92f3f326565}, + {0xd686619ba27255a2, 0xc80a537b0efefebe}, + {0x8613fd0145877585, 0xbd06742ce95f5f37}, + {0xa798fc4196e952e7, 0x2c48113823b73705}, + {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, + {0x82ef85133de648c4, 0x9a984d73dbe722fc}, + {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, + {0xcc963fee10b7d1b3, 0x318df905079926a9}, + {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, + {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634}, + {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, + {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1}, + {0x9c1661a651213e2d, 0x06bea10ca65c084f}, + {0xc31bfa0fe5698db8, 0x486e494fcff30a63}, + {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, + {0x986ddb5c6b3a76b7, 0xf89629465a75e01d}, + {0xbe89523386091465, 0xf6bbb397f1135824}, + {0xee2ba6c0678b597f, 0x746aa07ded582e2d}, + {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, + {0xba121a4650e4ddeb, 0x92f34d62616ce414}, + {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, + {0x915e2486ef32cd60, 0x0ace1474dc1d122f}, + {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, + {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3}, + {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, + {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c}, + {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, + {0xd89d64d57a607744, 0xe871c7bf077ba8b8}, + {0x87625f056c7c4a8b, 0x11471cd764ad4973}, + {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0}, + {0xd389b47879823479, 0x4aff1d108d4ec2c4}, + {0x843610cb4bf160cb, 0xcedf722a585139bb}, + {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, + {0xce947a3da6a9273e, 0x733d226229feea33}, + {0x811ccc668829b887, 0x0806357d5a3f5260}, + {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8}, + {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, + {0xfc2c3f3841f17c67, 0xbbac2078d443ace3}, + {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, + {0xc5029163f384a931, 0x0a9e795e65d4df12}, + {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, + {0x99ea0196163fa42e, 0x504bced1bf8e4e46}, + {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, + {0xf07da27a82c37088, 0x5d767327bb4e5a4d}, + {0x964e858c91ba2655, 0x3a6a07f8d510f870}, + {0xbbe226efb628afea, 0x890489f70a55368c}, + {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, + {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e}, + {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, + {0xb32df8e9f3546564, 0x47939822dc96abfa}, + {0xdff9772470297ebd, 0x59787e2b93bc56f8}, + {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b}, + {0xaefae51477a06b03, 0xede622920b6b23f2}, + {0xdab99e59958885c4, 0xe95fab368e45ecee}, + {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, + {0xaae103b5fcd2a881, 0xd652bdc29f26a11a}, + {0xd59944a37c0752a2, 0x4be76d3346f04960}, + {0x857fcae62d8493a5, 0x6f70a4400c562ddc}, + {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, + {0xd097ad07a71f26b2, 0x7e2000a41346a7a8}, + {0x825ecc24c873782f, 0x8ed400668c0c28c9}, + {0xa2f67f2dfa90563b, 0x728900802f0f32fb}, + {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, + {0xfea126b7d78186bc, 0xe2f610c84987bfa9}, + {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, + {0xc6ede63fa05d3143, 0x91503d1c79720dbc}, + {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, + {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb}, + {0xc24452da229b021b, 0xfbe85badce996169}, + {0xf2d56790ab41c2a2, 0xfae27299423fb9c4}, + {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, + {0xbdb6b8e905cb600f, 0x5400e987bbc1c921}, + {0xed246723473e3813, 0x290123e9aab23b69}, + {0x9436c0760c86e30b, 0xf9a0b6720aaf6522}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0xe7958cb87392c2c2, 0xb60b1d1230b20e05}, + {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, + {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4}, + {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, + {0x8d590723948a535f, 0x579c487e5a38ad0f}, + {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, + {0xdcdb1b2798182244, 0xf8e431456cf88e66}, + {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, + {0xac8b2d36eed2dac5, 0xe272467e3d222f40}, + {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, + {0x86ccbb52ea94baea, 0x98e947129fc2b4ea}, + {0xa87fea27a539e9a5, 0x3f2398d747b36225}, + {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae}, + {0x83a3eeeef9153e89, 0x1953cf68300424ad}, + {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8}, + {0xcdb02555653131b6, 0x3792f412cb06794e}, + {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1}, + {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, + {0xc8de047564d20a8b, 0xf245825a5a445276}, + {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, + {0x9ced737bb6c4183d, 0x55464dd69685606c}, + {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, + {0xf53304714d9265df, 0xd53dd99f4b3066a9}, + {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, + {0xbf8fdb78849a5f96, 0xde98520472bdd034}, + {0xef73d256a5c0f77c, 0x963e66858f6d4441}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xbb127c53b17ec159, 0x5560c018580d5d53}, + {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7}, + {0x9226712162ab070d, 0xcab3961304ca70e9}, + {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23}, + {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, + {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243}, + {0xb267ed1940f1c61c, 0x55f038b237591ed4}, + {0xdf01e85f912e37a3, 0x6b6c46dec52f6689}, + {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, + {0xae397d8aa96c1b77, 0xabec975e0a0d081b}, + {0xd9c7dced53c72255, 0x96e7bd358c904a22}, + {0x881cea14545c7575, 0x7e50d64177da2e55}, + {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, + {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865}, + {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, + {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f}, + {0xcfb11ead453994ba, 0x67de18eda5814af3}, + {0x81ceb32c4b43fcf4, 0x80eacf948770ced8}, + {0xa2425ff75e14fc31, 0xa1258379a94d028e}, + {0xcad2f7f5359a3b3e, 0x096ee45813a04331}, + {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, + {0x9e74d1b791e07e48, 0x775ea264cf55347e}, + {0xc612062576589dda, 0x95364afe032a819e}, + {0xf79687aed3eec551, 0x3a83ddbd83f52205}, + {0x9abe14cd44753b52, 0xc4926a9672793543}, + {0xc16d9a0095928a27, 0x75b7053c0f178294}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0x971da05074da7bee, 0xd3f6fc16ebca5e04}, + {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, + {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6}, + {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, + {0xb877aa3236a4b449, 0x09befeb9fad487c3}, + {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, + {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11}, + {0xb424dc35095cd80f, 0x538484c19ef38c95}, + {0xe12e13424bb40e13, 0x2865a5f206b06fba}, + {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, + {0xafebff0bcb24aafe, 0xf78f69a51539d749}, + {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, + {0x89705f4136b4a597, 0x31680a88f8953031}, + {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, + {0xd6bf94d5e57a42bc, 0x3d32907604691b4d}, + {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, + {0xa7c5ac471b478423, 0x0fcf80dc33721d54}, + {0xd1b71758e219652b, 0xd3c36113404ea4a9}, + {0x83126e978d4fdf3b, 0x645a1cac083126ea}, + {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, + {0xcccccccccccccccc, 0xcccccccccccccccd}, + {0x8000000000000000, 0x0000000000000000}, + {0xa000000000000000, 0x0000000000000000}, + {0xc800000000000000, 0x0000000000000000}, + {0xfa00000000000000, 0x0000000000000000}, + {0x9c40000000000000, 0x0000000000000000}, + {0xc350000000000000, 0x0000000000000000}, + {0xf424000000000000, 0x0000000000000000}, + {0x9896800000000000, 0x0000000000000000}, + {0xbebc200000000000, 0x0000000000000000}, + {0xee6b280000000000, 0x0000000000000000}, + {0x9502f90000000000, 0x0000000000000000}, + {0xba43b74000000000, 0x0000000000000000}, + {0xe8d4a51000000000, 0x0000000000000000}, + {0x9184e72a00000000, 0x0000000000000000}, + {0xb5e620f480000000, 0x0000000000000000}, + {0xe35fa931a0000000, 0x0000000000000000}, + {0x8e1bc9bf04000000, 0x0000000000000000}, + {0xb1a2bc2ec5000000, 0x0000000000000000}, + {0xde0b6b3a76400000, 0x0000000000000000}, + {0x8ac7230489e80000, 0x0000000000000000}, + {0xad78ebc5ac620000, 0x0000000000000000}, + {0xd8d726b7177a8000, 0x0000000000000000}, + {0x878678326eac9000, 0x0000000000000000}, + {0xa968163f0a57b400, 0x0000000000000000}, + {0xd3c21bcecceda100, 0x0000000000000000}, + {0x84595161401484a0, 0x0000000000000000}, + {0xa56fa5b99019a5c8, 0x0000000000000000}, + {0xcecb8f27f4200f3a, 0x0000000000000000}, + {0x813f3978f8940984, 0x4000000000000000}, + {0xa18f07d736b90be5, 0x5000000000000000}, + {0xc9f2c9cd04674ede, 0xa400000000000000}, + {0xfc6f7c4045812296, 0x4d00000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xc5371912364ce305, 0x6c28000000000000}, + {0xf684df56c3e01bc6, 0xc732000000000000}, + {0x9a130b963a6c115c, 0x3c7f400000000000}, + {0xc097ce7bc90715b3, 0x4b9f100000000000}, + {0xf0bdc21abb48db20, 0x1e86d40000000000}, + {0x96769950b50d88f4, 0x1314448000000000}, + {0xbc143fa4e250eb31, 0x17d955a000000000}, + {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, + {0x92efd1b8d0cf37be, 0x5aa1cae500000000}, + {0xb7abc627050305ad, 0xf14a3d9e40000000}, + {0xe596b7b0c643c719, 0x6d9ccd05d0000000}, + {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, + {0xb35dbf821ae4f38b, 0xdda2802c8a800000}, + {0xe0352f62a19e306e, 0xd50b2037ad200000}, + {0x8c213d9da502de45, 0x4526f422cc340000}, + {0xaf298d050e4395d6, 0x9670b12b7f410000}, + {0xdaf3f04651d47b4c, 0x3c0cdd765f114000}, + {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, + {0xab0e93b6efee0053, 0x8eea0d047a457a00}, + {0xd5d238a4abe98068, 0x72a4904598d6d880}, + {0x85a36366eb71f041, 0x47a6da2b7f864750}, + {0xa70c3c40a64e6c51, 0x999090b65f67d924}, + {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d}, + {0x82818f1281ed449f, 0xbff8f10e7a8921a4}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0d}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490}, + {0xfee50b7025c36a08, 0x02f236d04753d5b4}, + {0x9f4f2726179a2245, 0x01d762422c946590}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb2f}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7a}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b44}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b616}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe41}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd1}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcb}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebe}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784337}, + {0xacb92ed9397bf996, 0x49c2c37f07965404}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be906}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30190}, + {0x83c7088e1aab65db, 0x792667c6da79e0fa}, + {0xa4b8cab1a1563f52, 0x577001b891185938}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0x80b05e5ac60b6178, 0x544f8158315b05b4}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c721}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38e9}, + {0xfb5878494ace3a5f, 0x04ab48a04065c723}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8394}, + {0xf5746577930d6500, 0xca8f44ec7ee36479}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a12}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97}, + {0xea1575143cf97226, 0xf52d09d71a3293bd}, + {0x924d692ca61be758, 0x593c2626705f9c56}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956447}, + {0x8edf98b59a373fec, 0x4724bd4189bd5eac}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb657}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed}, + {0x8b865b215899f46c, 0xbd79e0d20082ee74}, + {0xae67f1e9aec07187, 0xecd8590680a3aa11}, + {0xda01ee641a708de9, 0xe80e6f4820cc9495}, + {0x884134fe908658b2, 0x3109058d147fdcdd}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd415}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb0}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0xcfe87f7cef46ff16, 0xe612641865679a63}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e}, + {0xa26da3999aef7749, 0xe3be5e330f38f09d}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa}, + {0xc646d63501a1511d, 0xb281e1fd541501b8}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4226}, + {0x9ae757596946075f, 0x3375788de9b06958}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83ae}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49a}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e0}, + {0xbd176620a501fbff, 0xb650e5a93bc3d898}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe}, + {0x93ba47c980e98cdf, 0xc66f336c36b10137}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4184}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e5}, + {0x9043ea1ac7e41392, 0x87c89837ad68db2f}, + {0xb454e4a179dd1877, 0x29babe4598c311fb}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660c}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f}, + {0xdc21a1171d42645d, 0x76707543f4fa1f73}, + {0x899504ae72497eba, 0x6a06494a791c53a8}, + {0xabfa45da0edbde69, 0x0487db9d17636892}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b6}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xa7f26836f282b732, 0x8e6cac7768d7141e}, + {0xd1ef0244af2364ff, 0x3207d795430cd926}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b8}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6}, + {0xcd036837130890a1, 0x36dba887c37a8c0f}, + {0x802221226be55a64, 0xc2494954da2c9789}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc7}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9}, + {0x9c69a97284b578d7, 0xff2a760414536efb}, + {0xc38413cf25e2d70d, 0xfef5138519684aba}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a61}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fa}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26183}, + {0xba756174393d88df, 0x94f971119aeef9e4}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85d}, + {0x91abb422ccb812ee, 0xac62e055c10ab33a}, + {0xb616a12b7fe617aa, 0x577b986b314d6009}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b}, + {0x8e41ade9fbebc27d, 0x14588f13be847307}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb}, + {0x8aec23d680043bee, 0x25de7bb9480d5854}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6a}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0x87aa9aff79042286, 0x90fb44d2f05d0842}, + {0xa99541bf57452b28, 0x353a1607ac744a53}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce8}, + {0x847c9b5d7c2e09b7, 0x69956135febada11}, + {0xa59bc234db398c25, 0x43fab9837e699095}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f5}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731732}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43e}, + {0x9defbf01b061adab, 0x3a0888136afa64a7}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd0}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d45}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864b}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b325}, + {0xbc4665b596706114, 0x873d5d9f0dde1fee}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f2}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa}, + {0x8fa475791a569d10, 0xf96e017d694487bc}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ac}, + {0xe070f78d3927556a, 0x85bbe253f47b1417}, + {0x8c469ab843b89562, 0x93956d7478ccec8e}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e}, + {0x88fcf317f22241e2, 0x441fece3bdf81f03}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c3}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074}, + {0x85c7056562757456, 0xf6872d5667844e49}, + {0xa738c6bebb12d16c, 0xb428f8ac016561db}, + {0xd106f86e69d785c7, 0xe13336d701beba52}, + {0x82a45b450226b39c, 0xecc0024661173473}, + {0xa34d721642b06084, 0x27f002d7f95d0190}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4}, + {0xff290242c83396ce, 0x7e67047175a15271}, + {0x9f79a169bd203e41, 0x0f0062c6e984d386}, + {0xc75809c42c684dd1, 0x52c07b78a3e60868}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a82}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb691}, + {0xc2abf989935ddbfe, 0x6acff893d00ea435}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d43}, + {0x98165af37b2153de, 0xc3727a337a8b704a}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c}, + {0xeda2ee1c7064130c, 0x1162def06f79df73}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a2}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xb10d8e1456105dad, 0x7425a83e872c5f47}, + {0xdd50f1996b947518, 0xd12f124e28f77719}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550b}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4e}, + {0x8714a775e3e95c78, 0x65acfaec34810a71}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d}, + {0xd31045a8341ca07c, 0x1ede48111209a050}, + {0x83ea2b892091e44d, 0x934aed0aab460432}, + {0xa4e4b66b68b65d60, 0xf81da84d5617853f}, + {0xce1de40642e3f4b9, 0x36251260ab9d668e}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019}, + {0xa1075a24e4421730, 0xb24cf65b8612f81f}, + {0xc94930ae1d529cfc, 0xdee033f26797b627}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864e}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1db}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af3}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1}, + {0xea53df5fd18d5513, 0x84c86189216dc5ed}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511012}, + {0xdf78e4b2bd342cf6, 0x914da9246b255416}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e}, + {0xae9672aba3d0c320, 0xa184ac2473b529b1}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e}, + {0x8865899617fb1871, 0x7e2fa67c7a658892}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7}, + {0xd51ea6fa85785631, 0x552a74227f3ea565}, + {0x8533285c936b35de, 0xd53a88958f87275f}, + {0xa67ff273b8460356, 0x8a892abaf368f137}, + {0xd01fef10a657842c, 0x2d2b7569b0432d85}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc73}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b8f}, + {0xcb3f2f7642717713, 0x241c70a936219a73}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0110}, + {0x9ec95d1463e8a506, 0xf4363804324a40aa}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050a}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8326}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8cec}, + {0x976e41088617ca01, 0xd5be0503e085d813}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219e}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b503}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad4}, + {0x906a617d450187e2, 0x27fb2b80668b24c5}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf6}, + {0xe1a63853bbd26451, 0x5e7873f8a0396973}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e8}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fb}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d}, + {0xac2820d9623bf429, 0x546345fa9fbdcd44}, + {0xd732290fbacaf133, 0xa97c177947ad4095}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a74}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3111}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3}, + {0xa0555e361951c366, 0xd7e105bcc332621f}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7}, + {0xfa856334878fc150, 0xb14f98f6f0feb951}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c8}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fa}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3}, + {0xeeea5d5004981478, 0x1858ccfce06cac74}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc8}, + {0xbaa718e68396cffd, 0xd30560258f54e6ba}, + {0xe950df20247c83fd, 0x47c6b82ef32a2069}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5441}, + {0xb6472e511c81471d, 0xe0133fe4adf8e952}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a6}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648}, + {0xb201833b35d63f73, 0x2cd2cc6551e513da}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1}, + {0x8b112e86420f6191, 0xfb04afaf27faf782}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b563}, + {0xd94ad8b1c7380874, 0x18375281ae7822bc}, + {0x87cec76f1c830548, 0x8f2293910d0b15b5}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22}, + {0xd433179d9c8cb841, 0x5fa60692a46151eb}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd333}, + {0xa5c7ea73224deff3, 0x12b9b522906c0800}, + {0xcf39e50feae16bef, 0xd768226b34870a00}, + {0x81842f29f2cce375, 0xe6a1158300d46640}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd0}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc4}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1}, + {0xc5a05277621be293, 0xc7098b7305241885}, + {0xf70867153aa2db38, 0xb8cbee4fc66d1ea7} +#else + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0xc350000000000000, 0x0000000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xfee50b7025c36a08, 0x02f236d04753d5b4}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc8} +#endif +}; + +#if !FMT_USE_FULL_CACHE_DRAGONBOX +template +const uint64_t basic_data::powers_of_5_64[] = { + 0x0000000000000001, 0x0000000000000005, 0x0000000000000019, + 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35, + 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1, + 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd, + 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9, + 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5, + 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631, + 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed, + 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9}; + +template +const uint32_t basic_data::dragonbox_pow10_recovery_errors[] = { + 0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001, + 0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555, + 0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110, + 0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454, + 0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014, + 0x69514555, 0x05151109, 0x00155555}; +#endif + +template +const char basic_data::foreground_color[] = "\x1b[38;2;"; +template +const char basic_data::background_color[] = "\x1b[48;2;"; +template const char basic_data::reset_color[] = "\x1b[0m"; +template const wchar_t basic_data::wreset_color[] = L"\x1b[0m"; +template const char basic_data::signs[] = {0, '-', '+', ' '}; +template +const char basic_data::left_padding_shifts[] = {31, 31, 0, 1, 0}; +template +const char basic_data::right_padding_shifts[] = {0, 31, 0, 1, 0}; + +template struct bits { + static FMT_CONSTEXPR_DECL const int value = + static_cast(sizeof(T) * std::numeric_limits::digits); +}; + +class fp; +template fp normalize(fp value); + +// Lower (upper) boundary is a value half way between a floating-point value +// and its predecessor (successor). Boundaries have the same exponent as the +// value so only significands are stored. +struct boundaries { + uint64_t lower; + uint64_t upper; +}; + +// A handmade floating-point number f * pow(2, e). +class fp { + private: + using significand_type = uint64_t; + + template + using is_supported_float = bool_constant; + + public: + significand_type f; + int e; + + // All sizes are in bits. + // Subtract 1 to account for an implicit most significant bit in the + // normalized form. + static FMT_CONSTEXPR_DECL const int double_significand_size = + std::numeric_limits::digits - 1; + static FMT_CONSTEXPR_DECL const uint64_t implicit_bit = + 1ULL << double_significand_size; + static FMT_CONSTEXPR_DECL const int significand_size = + bits::value; + + fp() : f(0), e(0) {} + fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 double. It is a template to prevent compile + // errors on platforms where double is not IEEE754. + template explicit fp(Double d) { assign(d); } + + // Assigns d to this and return true iff predecessor is closer than successor. + template ::value)> + bool assign(Float d) { + // Assume float is in the format [sign][exponent][significand]. + using limits = std::numeric_limits; + const int float_significand_size = limits::digits - 1; + const int exponent_size = + bits::value - float_significand_size - 1; // -1 for sign + const uint64_t float_implicit_bit = 1ULL << float_significand_size; + const uint64_t significand_mask = float_implicit_bit - 1; + const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask; + const int exponent_bias = (1 << exponent_size) - limits::max_exponent - 1; + constexpr bool is_double = sizeof(Float) == sizeof(uint64_t); + auto u = bit_cast>(d); + f = u & significand_mask; + int biased_e = + static_cast((u & exponent_mask) >> float_significand_size); + // Predecessor is closer if d is a normalized power of 2 (f == 0) other than + // the smallest normalized number (biased_e > 1). + bool is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e != 0) + f += float_implicit_bit; + else + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + e = biased_e - exponent_bias - float_significand_size; + return is_predecessor_closer; + } + + template ::value)> + bool assign(Float) { + *this = fp(); + return false; + } +}; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template fp normalize(fp value) { + // Handle subnormals. + const auto shifted_implicit_bit = fp::implicit_bit << SHIFT; + while ((value.f & shifted_implicit_bit) == 0) { + value.f <<= 1; + --value.e; + } + // Subtract 1 to account for hidden bit. + const auto offset = + fp::significand_size - fp::double_significand_size - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; } + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +inline uint64_t multiply(uint64_t lhs, uint64_t rhs) { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast(product >> 64); + return (static_cast(product) & (1ULL << 63)) != 0 ? f + 1 : f; +#else + // Multiply 32-bit parts of significands. + uint64_t mask = (1ULL << 32) - 1; + uint64_t a = lhs >> 32, b = lhs & mask; + uint64_t c = rhs >> 32, d = rhs & mask; + uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; + // Compute mid 64-bit of result and round. + uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); + return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); +#endif +} + +inline fp operator*(fp x, fp y) { return {multiply(x.f, y.f), x.e + y.e + 64}; } + +// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its +// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`. +inline fp get_cached_power(int min_exponent, int& pow10_exponent) { + const int shift = 32; + const auto significand = static_cast(data::log10_2_significand); + int index = static_cast( + ((min_exponent + fp::significand_size - 1) * (significand >> shift) + + ((int64_t(1) << shift) - 1)) // ceil + >> 32 // arithmetic shift + ); + // Decimal exponent of the first (smallest) cached power of 10. + const int first_dec_exp = -348; + // Difference between 2 consecutive decimal exponents in cached powers of 10. + const int dec_exp_step = 8; + index = (index - first_dec_exp - 1) / dec_exp_step + 1; + pow10_exponent = first_dec_exp + index * dec_exp_step; + return {data::grisu_pow10_significands[index], + data::grisu_pow10_exponents[index]}; +} + +// A simple accumulator to hold the sums of terms in bigint::square if uint128_t +// is not available. +struct accumulator { + uint64_t lower; + uint64_t upper; + + accumulator() : lower(0), upper(0) {} + explicit operator uint32_t() const { return static_cast(lower); } + + void operator+=(uint64_t n) { + lower += n; + if (lower < n) ++upper; + } + void operator>>=(int shift) { + assert(shift == 32); + (void)shift; + lower = (upper << 32) | (lower >> 32); + upper >>= 32; + } +}; + +class bigint { + private: + // A bigint is stored as an array of bigits (big digits), with bigit at index + // 0 being the least significant one. + using bigit = uint32_t; + using double_bigit = uint64_t; + enum { bigits_capacity = 32 }; + basic_memory_buffer bigits_; + int exp_; + + bigit operator[](int index) const { return bigits_[to_unsigned(index)]; } + bigit& operator[](int index) { return bigits_[to_unsigned(index)]; } + + static FMT_CONSTEXPR_DECL const int bigit_bits = bits::value; + + friend struct formatter; + + void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = static_cast((*this)[index]) - other - borrow; + (*this)[index] = static_cast(result); + borrow = static_cast(result >> (bigit_bits * 2 - 1)); + } + + void remove_leading_zeros() { + int num_bigits = static_cast(bigits_.size()) - 1; + while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; + bigits_.resize(to_unsigned(num_bigits + 1)); + } + + // Computes *this -= other assuming aligned bigints and *this >= other. + void subtract_aligned(const bigint& other) { + FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); + FMT_ASSERT(compare(*this, other) >= 0, ""); + bigit borrow = 0; + int i = other.exp_ - exp_; + for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) + subtract_bigits(i, other.bigits_[j], borrow); + while (borrow > 0) subtract_bigits(i, 0, borrow); + remove_leading_zeros(); + } + + void multiply(uint32_t value) { + const double_bigit wide_value = value; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * wide_value + carry; + bigits_[i] = static_cast(result); + carry = static_cast(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + void multiply(uint64_t value) { + const bigit mask = ~bigit(0); + const double_bigit lower = value & mask; + const double_bigit upper = value >> bigit_bits; + double_bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * lower + (carry & mask); + carry = + bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits); + bigits_[i] = static_cast(result); + } + while (carry != 0) { + bigits_.push_back(carry & mask); + carry >>= bigit_bits; + } + } + + public: + bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + ~bigint() { assert(bigits_.capacity() <= bigits_capacity); } + + bigint(const bigint&) = delete; + void operator=(const bigint&) = delete; + + void assign(const bigint& other) { + auto size = other.bigits_.size(); + bigits_.resize(size); + auto data = other.bigits_.data(); + std::copy(data, data + size, make_checked(bigits_.data(), size)); + exp_ = other.exp_; + } + + void assign(uint64_t n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = n & ~bigit(0); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + int num_bigits() const { return static_cast(bigits_.size()) + exp_; } + + FMT_NOINLINE bigint& operator<<=(int shift) { + assert(shift >= 0); + exp_ += shift / bigit_bits; + shift %= bigit_bits; + if (shift == 0) return *this; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + bigit c = bigits_[i] >> (bigit_bits - shift); + bigits_[i] = (bigits_[i] << shift) + carry; + carry = c; + } + if (carry != 0) bigits_.push_back(carry); + return *this; + } + + template bigint& operator*=(Int value) { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t(value)); + return *this; + } + + friend int compare(const bigint& lhs, const bigint& rhs) { + int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); + if (num_lhs_bigits != num_rhs_bigits) + return num_lhs_bigits > num_rhs_bigits ? 1 : -1; + int i = static_cast(lhs.bigits_.size()) - 1; + int j = static_cast(rhs.bigits_.size()) - 1; + int end = i - j; + if (end < 0) end = 0; + for (; i >= end; --i, --j) { + bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j]; + if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1; + } + if (i != j) return i > j ? 1 : -1; + return 0; + } + + // Returns compare(lhs1 + lhs2, rhs). + friend int add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) { + int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits()); + int num_rhs_bigits = rhs.num_bigits(); + if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; + if (max_lhs_bigits > num_rhs_bigits) return 1; + auto get_bigit = [](const bigint& n, int i) -> bigit { + return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; + }; + double_bigit borrow = 0; + int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = + static_cast(get_bigit(lhs1, i)) + get_bigit(lhs2, i); + bigit rhs_bigit = get_bigit(rhs, i); + if (sum > rhs_bigit + borrow) return 1; + borrow = rhs_bigit + borrow - sum; + if (borrow > 1) return -1; + borrow <<= bigit_bits; + } + return borrow != 0 ? -1 : 0; + } + + // Assigns pow(10, exp) to this bigint. + void assign_pow10(int exp) { + assert(exp >= 0); + if (exp == 0) return assign(1); + // Find the top bit. + int bitmask = 1; + while (exp >= bitmask) bitmask <<= 1; + bitmask >>= 1; + // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by + // repeated squaring and multiplication. + assign(5); + bitmask >>= 1; + while (bitmask != 0) { + square(); + if ((exp & bitmask) != 0) *this *= 5; + bitmask >>= 1; + } + *this <<= exp; // Multiply by pow(2, exp) by shifting. + } + + void square() { + basic_memory_buffer n(std::move(bigits_)); + int num_bigits = static_cast(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + bigits_.resize(to_unsigned(num_result_bigits)); + using accumulator_t = conditional_t; + auto sum = accumulator_t(); + for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { + // Compute bigit at position bigit_index of the result by adding + // cross-product terms n[i] * n[j] such that i + j == bigit_index. + for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { + // Most terms are multiplied twice which can be optimized in the future. + sum += static_cast(n[i]) * n[j]; + } + (*this)[bigit_index] = static_cast(sum); + sum >>= bits::value; // Compute the carry. + } + // Do the same for the top half. + for (int bigit_index = num_bigits; bigit_index < num_result_bigits; + ++bigit_index) { + for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) + sum += static_cast(n[i++]) * n[j--]; + (*this)[bigit_index] = static_cast(sum); + sum >>= bits::value; + } + --num_result_bigits; + remove_leading_zeros(); + exp_ *= 2; + } + + // If this bigint has a bigger exponent than other, adds trailing zero to make + // exponents equal. This simplifies some operations such as subtraction. + void align(const bigint& other) { + int exp_difference = exp_ - other.exp_; + if (exp_difference <= 0) return; + int num_bigits = static_cast(bigits_.size()); + bigits_.resize(to_unsigned(num_bigits + exp_difference)); + for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) + bigits_[j] = bigits_[i]; + std::uninitialized_fill_n(bigits_.data(), exp_difference, 0); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + int divmod_assign(const bigint& divisor) { + FMT_ASSERT(this != &divisor, ""); + if (compare(*this, divisor) < 0) return 0; + FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); + align(divisor); + int quotient = 0; + do { + subtract_aligned(divisor); + ++quotient; + } while (compare(*this, divisor) >= 0); + return quotient; + } +}; + +enum class round_direction { unknown, up, down }; + +// Given the divisor (normally a power of 10), the remainder = v % divisor for +// some number v and the error, returns whether v should be rounded up, down, or +// whether the rounding direction can't be determined due to error. +// error should be less than divisor / 2. +inline round_direction get_round_direction(uint64_t divisor, uint64_t remainder, + uint64_t error) { + FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow. + FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow. + FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow. + // Round down if (remainder + error) * 2 <= divisor. + if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2) + return round_direction::down; + // Round up if (remainder - error) * 2 >= divisor. + if (remainder >= error && + remainder - error >= divisor - (remainder - error)) { + return round_direction::up; + } + return round_direction::unknown; +} + +namespace digits { +enum result { + more, // Generate more digits. + done, // Done generating digits. + error // Digit generation cancelled due to an error. +}; +} + +// Generates output using the Grisu digit-gen algorithm. +// error: the size of the region (lower, upper) outside of which numbers +// definitely do not round to value (Delta in Grisu3). +template +FMT_ALWAYS_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, + int& exp, Handler& handler) { + const fp one(1ULL << -value.e, value.e); + // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be + // zero because it contains a product of two 64-bit numbers with MSB set (due + // to normalization) - 1, shifted right by at most 60 bits. + auto integral = static_cast(value.f >> -one.e); + FMT_ASSERT(integral != 0, ""); + FMT_ASSERT(integral == value.f >> -one.e, ""); + // The fractional part of scaled value (p2 in Grisu) c = value % one. + uint64_t fractional = value.f & (one.f - 1); + exp = count_digits(integral); // kappa in Grisu. + // Divide by 10 to prevent overflow. + auto result = handler.on_start(data::powers_of_10_64[exp - 1] << -one.e, + value.f / 10, error * 10, exp); + if (result != digits::more) return result; + // Generate digits for the integral part. This can produce up to 10 digits. + do { + uint32_t digit = 0; + auto divmod_integral = [&](uint32_t divisor) { + digit = integral / divisor; + integral %= divisor; + }; + // This optimization by Milo Yip reduces the number of integer divisions by + // one per iteration. + switch (exp) { + case 10: + divmod_integral(1000000000); + break; + case 9: + divmod_integral(100000000); + break; + case 8: + divmod_integral(10000000); + break; + case 7: + divmod_integral(1000000); + break; + case 6: + divmod_integral(100000); + break; + case 5: + divmod_integral(10000); + break; + case 4: + divmod_integral(1000); + break; + case 3: + divmod_integral(100); + break; + case 2: + divmod_integral(10); + break; + case 1: + digit = integral; + integral = 0; + break; + default: + FMT_ASSERT(false, "invalid number of digits"); + } + --exp; + auto remainder = (static_cast(integral) << -one.e) + fractional; + result = handler.on_digit(static_cast('0' + digit), + data::powers_of_10_64[exp] << -one.e, remainder, + error, exp, true); + if (result != digits::more) return result; + } while (exp > 0); + // Generate digits for the fractional part. + for (;;) { + fractional *= 10; + error *= 10; + char digit = static_cast('0' + (fractional >> -one.e)); + fractional &= one.f - 1; + --exp; + result = handler.on_digit(digit, one.f, fractional, error, exp, false); + if (result != digits::more) return result; + } +} + +// The fixed precision digit handler. +struct fixed_handler { + char* buf; + int size; + int precision; + int exp10; + bool fixed; + + digits::result on_start(uint64_t divisor, uint64_t remainder, uint64_t error, + int& exp) { + // Non-fixed formats require at least one digit and no precision adjustment. + if (!fixed) return digits::more; + // Adjust fixed precision by exponent because it is relative to decimal + // point. + precision += exp + exp10; + // Check if precision is satisfied just by leading zeros, e.g. + // format("{:.2f}", 0.001) gives "0.00" without generating any digits. + if (precision > 0) return digits::more; + if (precision < 0) return digits::done; + auto dir = get_round_direction(divisor, remainder, error); + if (dir == round_direction::unknown) return digits::error; + buf[size++] = dir == round_direction::up ? '1' : '0'; + return digits::done; + } + + digits::result on_digit(char digit, uint64_t divisor, uint64_t remainder, + uint64_t error, int, bool integral) { + FMT_ASSERT(remainder < divisor, ""); + buf[size++] = digit; + if (!integral && error >= remainder) return digits::error; + if (size < precision) return digits::more; + if (!integral) { + // Check if error * 2 < divisor with overflow prevention. + // The check is not needed for the integral part because error = 1 + // and divisor > (1 << 32) there. + if (error >= divisor || error >= divisor - error) return digits::error; + } else { + FMT_ASSERT(error == 1 && divisor > 2, ""); + } + auto dir = get_round_direction(divisor, remainder, error); + if (dir != round_direction::up) + return dir == round_direction::down ? digits::done : digits::error; + ++buf[size - 1]; + for (int i = size - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[size++] = '0'; + else + ++exp10; + } + return digits::done; + } +}; + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +FMT_SAFEBUFFERS inline uint128_wrapper umul128(uint64_t x, + uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + return static_cast(x) * static_cast(y); +#elif defined(_MSC_VER) && defined(_M_X64) + uint128_wrapper result; + result.low_ = _umul128(x, y, &result.high_); + return result; +#else + const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1); + + uint64_t a = x >> 32; + uint64_t b = x & mask; + uint64_t c = y >> 32; + uint64_t d = y & mask; + + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + + uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); + + return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), + (intermediate << 32) + (bd & mask)}; +#endif +} + +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x, + uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return static_cast(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +FMT_SAFEBUFFERS inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) + FMT_NOEXCEPT { + uint128_wrapper g0 = umul128(x, y.high()); + g0 += umul128_upper64(x, y.low()); + return g0.high(); +} + +// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return static_cast(umul128_upper64(x, y)); +} + +// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +FMT_SAFEBUFFERS inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) + FMT_NOEXCEPT { + uint64_t g01 = x * y.high(); + uint64_t g10 = umul128_upper64(x, y.low()); + return g01 + g10; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return x * y; +} + +// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from +// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4. +inline int floor_log10_pow2(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const int shift = 22; + return (e * static_cast(data::log10_2_significand >> (64 - shift))) >> + shift; +} + +// Various fast log computations. +inline int floor_log2_pow10(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + const uint64_t log2_10_integer_part = 3; + const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9; + const int shift_amount = 19; + return (e * static_cast( + (log2_10_integer_part << shift_amount) | + (log2_10_fractional_digits >> (64 - shift_amount)))) >> + shift_amount; +} +inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375; + const int shift_amount = 22; + return (e * static_cast(data::log10_2_significand >> + (64 - shift_amount)) - + static_cast(log10_4_over_3_fractional_digits >> + (64 - shift_amount))) >> + shift_amount; +} + +// Returns true iff x is divisible by pow(2, exp). +inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZ + return FMT_BUILTIN_CTZ(x) >= exp; +#else + return exp < num_bits() && x == ((x >> exp) << exp); +#endif +} +inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZLL + return FMT_BUILTIN_CTZLL(x) >= exp; +#else + return exp < num_bits() && x == ((x >> exp) << exp); +#endif +} + +// Returns true iff x is divisible by pow(5, exp). +inline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 10, "too large exponent"); + return x * data::divtest_table_for_pow5_32[exp].mod_inv <= + data::divtest_table_for_pow5_32[exp].max_quotient; +} +inline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 23, "too large exponent"); + return x * data::divtest_table_for_pow5_64[exp].mod_inv <= + data::divtest_table_for_pow5_64[exp].max_quotient; +} + +// Replaces n by floor(n / pow(5, N)) returning true if and only if n is +// divisible by pow(5, N). +// Precondition: n <= 2 * pow(5, N + 1). +template +bool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int bits_for_comparison; + uint32_t threshold; + int shift_amount; + } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}}; + constexpr auto info = infos[N - 1]; + n *= info.magic_number; + const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1; + bool result = (n & comparison_mask) <= info.threshold; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int shift_amount; + uint32_t divisor_times_10; + } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}}; + constexpr auto info = infos[N - 1]; + FMT_ASSERT(n <= info.divisor_times_10, "n is too large"); + return n * info.magic_number >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT { + return n / float_info::big_divisor; +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT { + return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9; +} + +// Various subroutines using pow10 cache +template struct cache_accessor; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint64_t; + + static uint64_t get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + return data::dragonbox_pow10_significands_64[k - float_info::min_k]; + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul96_upper32(u, cache); + } + + static uint32_t compute_delta(const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast(cache >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast( + (cache - (cache >> (float_info::significand_bits + 2))) >> + (64 - float_info::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast( + (cache + (cache >> (float_info::significand_bits + 1))) >> + (64 - float_info::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (static_cast( + cache >> + (64 - float_info::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint128_wrapper; + + static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return data::dragonbox_pow10_significands_128[k - + float_info::min_k]; +#else + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info::min_k; + int offset = k - kb; + + // Get base cache. + uint128_wrapper base_cache = + data::dragonbox_pow10_significands_128[cache_index]; + if (offset == 0) return base_cache; + + // Compute the required amount of bit-shift. + int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; + FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); + + // Try to recover the real cache. + uint64_t pow5 = data::powers_of_5_64[offset]; + uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5); + uint128_wrapper middle_low = + umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5); + + recovered_cache += middle_low.high(); + + uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); + uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); + + recovered_cache = + uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + + if (kb < 0) recovered_cache += 1; + + // Get error. + int error_idx = (k - float_info::min_k) / 16; + uint32_t error = (data::dragonbox_pow10_recovery_errors[error_idx] >> + ((k - float_info::min_k) % 16) * 2) & + 0x3; + + // Add the error back. + FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), ""); + return {recovered_cache.high(), recovered_cache.low() + error}; +#endif + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul192_upper64(u, cache); + } + + static uint32_t compute_delta(cache_entry_type const& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast(cache.high() >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() - + (cache.high() >> (float_info::significand_bits + 2))) >> + (64 - float_info::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() + + (cache.high() >> (float_info::significand_bits + 1))) >> + (64 - float_info::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return ((cache.high() >> + (64 - float_info::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +// Various integer checks +template +bool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT { + return exponent >= + float_info< + T>::case_shorter_interval_left_endpoint_lower_threshold && + exponent <= + float_info::case_shorter_interval_left_endpoint_upper_threshold; +} +template +bool is_endpoint_integer(typename float_info::carrier_uint two_f, + int exponent, int minus_k) FMT_NOEXCEPT { + if (exponent < float_info::case_fc_pm_half_lower_threshold) return false; + // For k >= 0. + if (exponent <= float_info::case_fc_pm_half_upper_threshold) return true; + // For k < 0. + if (exponent > float_info::divisibility_check_by_5_threshold) return false; + return divisible_by_power_of_5(two_f, minus_k); +} + +template +bool is_center_integer(typename float_info::carrier_uint two_f, int exponent, + int minus_k) FMT_NOEXCEPT { + // Exponent for 5 is negative. + if (exponent > float_info::divisibility_check_by_5_threshold) return false; + if (exponent > float_info::case_fc_upper_threshold) + return divisible_by_power_of_5(two_f, minus_k); + // Both exponents are nonnegative. + if (exponent >= float_info::case_fc_lower_threshold) return true; + // Exponent for 2 is negative. + return divisible_by_power_of_2(two_f, minus_k - exponent + 1); +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_ALWAYS_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZ + int t = FMT_BUILTIN_CTZ(n); +#else + int t = ctz(n); +#endif + if (t > float_info::max_trailing_zeros) + t = float_info::max_trailing_zeros; + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint32_t mod_inv2 = 0xc28f5c29; + const uint32_t max_quotient2 = 0x0a3d70a3; + + int s = 0; + for (; s < t - 1; s += 2) { + if (n * mod_inv2 > max_quotient2) break; + n *= mod_inv2; + } + if (s < t && n * mod_inv1 <= max_quotient1) { + n *= mod_inv1; + ++s; + } + n >>= s; + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZLL + int t = FMT_BUILTIN_CTZLL(n); +#else + int t = ctzll(n); +#endif + if (t > float_info::max_trailing_zeros) + t = float_info::max_trailing_zeros; + // Divide by 10^8 and reduce to 32-bits + // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17, + // both of the quotient and the r should fit in 32-bits + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint64_t mod_inv8 = 0xc767074b22e90e21; + const uint64_t max_quotient8 = 0x00002af31dc46118; + + // If the number is divisible by 1'0000'0000, work with the quotient + if (t >= 8) { + auto quotient_candidate = n * mod_inv8; + + if (quotient_candidate <= max_quotient8) { + auto quotient = static_cast(quotient_candidate >> 8); + + int s = 8; + for (; s < t; ++s) { + if (quotient * mod_inv1 > max_quotient1) break; + quotient *= mod_inv1; + } + quotient >>= (s - 8); + n = quotient; + return s; + } + } + + // Otherwise, work with the remainder + auto quotient = static_cast(n / 100000000); + auto remainder = static_cast(n - 100000000 * quotient); + + if (t == 0 || remainder * mod_inv1 > max_quotient1) { + return 0; + } + remainder *= mod_inv1; + + if (t == 1 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 1) + quotient * 10000000ull; + return 1; + } + remainder *= mod_inv1; + + if (t == 2 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 2) + quotient * 1000000ull; + return 2; + } + remainder *= mod_inv1; + + if (t == 3 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 3) + quotient * 100000ull; + return 3; + } + remainder *= mod_inv1; + + if (t == 4 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 4) + quotient * 10000ull; + return 4; + } + remainder *= mod_inv1; + + if (t == 5 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 5) + quotient * 1000ull; + return 5; + } + remainder *= mod_inv1; + + if (t == 6 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 6) + quotient * 100ull; + return 6; + } + remainder *= mod_inv1; + + n = (remainder >> 7) + quotient * 10ull; + return 7; +} + +// The main algorithm for shorter interval case +template +FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp shorter_interval_case( + int exponent) FMT_NOEXCEPT { + decimal_fp ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor::cache_entry_type; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + + auto xi = cache_accessor::compute_left_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + auto zi = cache_accessor::compute_right_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval(exponent)) ++xi; + + // Try bigger divisor + ret_value.significand = zi / 10; + + // If succeed, remove trailing zeros if necessary and return + if (ret_value.significand * 10 >= xi) { + ret_value.exponent = minus_k + 1; + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + } + + // Otherwise, compute the round-up of y + ret_value.significand = + cache_accessor::compute_round_up_for_shorter_interval_case( + cache, beta_minus_1); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info::shorter_interval_tie_lower_threshold && + exponent <= float_info::shorter_interval_tie_upper_threshold) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } else if (ret_value.significand < xi) { + ++ret_value.significand; + } + return ret_value; +} + +template +FMT_SAFEBUFFERS decimal_fp to_decimal(T x) FMT_NOEXCEPT { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info::carrier_uint; + using cache_entry_type = typename cache_accessor::cache_entry_type; + auto br = bit_cast(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast(1) << float_info::significand_bits) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = static_cast((br & exponent_mask()) >> + float_info::significand_bits); + + if (exponent != 0) { // Check if normal. + exponent += float_info::exponent_bias - float_info::significand_bits; + + // Shorter interval case; proceed like Schubfach. + if (significand == 0) return shorter_interval_case(exponent); + + significand |= + (static_cast(1) << float_info::significand_bits); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = float_info::min_exponent - float_info::significand_bits; + } + + const bool include_left_endpoint = (significand % 2 == 0); + const bool include_right_endpoint = include_left_endpoint; + + // Compute k and beta. + const int minus_k = floor_log10_pow2(exponent) - float_info::kappa; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor::compute_delta(cache, beta_minus_1); + const carrier_uint two_fc = significand << 1; + const carrier_uint two_fr = two_fc | 1; + const carrier_uint zi = + cache_accessor::compute_mul(two_fr << beta_minus_1, cache); + + // Step 2: Try larger divisor; remove trailing zeros if necessary + + // Using an upper bound on zi, we might be able to optimize the division + // better than the compiler; we are computing zi / big_divisor here + decimal_fp ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(zi); + uint32_t r = static_cast(zi - float_info::big_divisor * + ret_value.significand); + + if (r > deltai) { + goto small_divisor_case_label; + } else if (r < deltai) { + // Exclude the right endpoint if necessary + if (r == 0 && !include_right_endpoint && + is_endpoint_integer(two_fr, exponent, minus_k)) { + --ret_value.significand; + r = float_info::big_divisor; + goto small_divisor_case_label; + } + } else { + // r == deltai; compare fractional parts + // Check conditions in the order different from the paper + // to take advantage of short-circuiting + const carrier_uint two_fl = two_fc - 1; + if ((!include_left_endpoint || + !is_endpoint_integer(two_fl, exponent, minus_k)) && + !cache_accessor::compute_mul_parity(two_fl, cache, beta_minus_1)) { + goto small_divisor_case_label; + } + } + ret_value.exponent = minus_k + float_info::kappa + 1; + + // We may need to remove trailing zeros + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + + // Step 3: Find the significand with the smaller divisor + +small_divisor_case_label: + ret_value.significand *= 10; + ret_value.exponent = minus_k + float_info::kappa; + + const uint32_t mask = (1u << float_info::kappa) - 1; + auto dist = r - (deltai / 2) + (float_info::small_divisor / 2); + + // Is dist divisible by 2^kappa? + if ((dist & mask) == 0) { + const bool approx_y_parity = + ((dist ^ (float_info::small_divisor / 2)) & 1) != 0; + dist >>= float_info::kappa; + + // Is dist divisible by 5^kappa? + if (check_divisibility_and_divide_by_pow5::kappa>(dist)) { + ret_value.significand += dist; + + // Check z^(f) >= epsilon^(f) + // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, + // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f) + // Since there are only 2 possibilities, we only need to care about the + // parity. Also, zi and r should have the same parity since the divisor + // is an even number + if (cache_accessor::compute_mul_parity(two_fc, cache, beta_minus_1) != + approx_y_parity) { + --ret_value.significand; + } else { + // If z^(f) >= epsilon^(f), we might have a tie + // when z^(f) == epsilon^(f), or equivalently, when y is an integer + if (is_center_integer(two_fc, exponent, minus_k)) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } + } + } + // Is dist not divisible by 5^kappa? + else { + ret_value.significand += dist; + } + } + // Is dist not divisible by 2^kappa? + else { + // Since we know dist is small, we might be able to optimize the division + // better than the compiler; we are computing dist / small_divisor here + ret_value.significand += + small_division_by_pow10::kappa>(dist); + } + return ret_value; +} +} // namespace dragonbox + +// Formats value using a variation of the Fixed-Precision Positive +// Floating-Point Printout ((FPP)^2) algorithm by Steele & White: +// https://fmt.dev/p372-steele.pdf. +template +void fallback_format(Double d, int num_digits, bool binary32, buffer& buf, + int& exp10) { + bigint numerator; // 2 * R in (FPP)^2. + bigint denominator; // 2 * S in (FPP)^2. + // lower and upper are differences between value and corresponding boundaries. + bigint lower; // (M^- in (FPP)^2). + bigint upper_store; // upper's value if different from lower. + bigint* upper = nullptr; // (M^+ in (FPP)^2). + fp value; + // Shift numerator and denominator by an extra bit or two (if lower boundary + // is closer) to make lower and upper integers. This eliminates multiplication + // by 2 during later computations. + const bool is_predecessor_closer = + binary32 ? value.assign(static_cast(d)) : value.assign(d); + int shift = is_predecessor_closer ? 2 : 1; + uint64_t significand = value.f << shift; + if (value.e >= 0) { + numerator.assign(significand); + numerator <<= value.e; + lower.assign(1); + lower <<= value.e; + if (shift != 1) { + upper_store.assign(1); + upper_store <<= value.e + 1; + upper = &upper_store; + } + denominator.assign_pow10(exp10); + denominator <<= shift; + } else if (exp10 < 0) { + numerator.assign_pow10(-exp10); + lower.assign(numerator); + if (shift != 1) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= significand; + denominator.assign(1); + denominator <<= shift - value.e; + } else { + numerator.assign(significand); + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower.assign(1); + if (shift != 1) { + upper_store.assign(1ULL << 1); + upper = &upper_store; + } + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (num_digits < 0) { + // Generate the shortest representation. + if (!upper) upper = &lower; + bool even = (value.f & 1) == 0; + num_digits = 0; + char* data = buf.data(); + for (;;) { + int digit = numerator.divmod_assign(denominator); + bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. + // numerator + upper >[=] pow10: + bool high = add_compare(numerator, *upper, denominator) + even > 0; + data[num_digits++] = static_cast('0' + digit); + if (low || high) { + if (!low) { + ++data[num_digits - 1]; + } else if (high) { + int result = add_compare(numerator, numerator, denominator); + // Round half to even. + if (result > 0 || (result == 0 && (digit % 2) != 0)) + ++data[num_digits - 1]; + } + buf.try_resize(to_unsigned(num_digits)); + exp10 -= num_digits - 1; + return; + } + numerator *= 10; + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + // Generate the given number of digits. + exp10 -= num_digits - 1; + if (num_digits == 0) { + buf.try_resize(1); + denominator *= 10; + buf[0] = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; + return; + } + buf.try_resize(to_unsigned(num_digits)); + for (int i = 0; i < num_digits - 1; ++i) { + int digit = numerator.divmod_assign(denominator); + buf[i] = static_cast('0' + digit); + numerator *= 10; + } + int digit = numerator.divmod_assign(denominator); + auto result = add_compare(numerator, numerator, denominator); + if (result > 0 || (result == 0 && (digit % 2) != 0)) { + if (digit == 9) { + const auto overflow = '0' + 10; + buf[num_digits - 1] = overflow; + // Propagate the carry. + for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] == overflow) { + buf[0] = '1'; + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast('0' + digit); +} + +template +int format_float(T value, int precision, float_specs specs, buffer& buf) { + static_assert(!std::is_same::value, ""); + FMT_ASSERT(value >= 0, "value is negative"); + + const bool fixed = specs.format == float_format::fixed; + if (value <= 0) { // <= instead of == to silence a warning. + if (precision <= 0 || !fixed) { + buf.push_back('0'); + return 0; + } + buf.try_resize(to_unsigned(precision)); + std::uninitialized_fill_n(buf.data(), precision, '0'); + return -precision; + } + + if (!specs.use_grisu) return snprintf_float(value, precision, specs, buf); + + if (precision < 0) { + // Use Dragonbox for the shortest format. + if (specs.binary32) { + auto dec = dragonbox::to_decimal(static_cast(value)); + write(buffer_appender(buf), dec.significand); + return dec.exponent; + } + auto dec = dragonbox::to_decimal(static_cast(value)); + write(buffer_appender(buf), dec.significand); + return dec.exponent; + } + + // Use Grisu + Dragon4 for the given precision: + // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf. + int exp = 0; + const int min_exp = -60; // alpha in Grisu. + int cached_exp10 = 0; // K in Grisu. + fp normalized = normalize(fp(value)); + const auto cached_pow = get_cached_power( + min_exp - (normalized.e + fp::significand_size), cached_exp10); + normalized = normalized * cached_pow; + // Limit precision to the maximum possible number of significant digits in an + // IEEE754 double because we don't need to generate zeros. + const int max_double_digits = 767; + if (precision > max_double_digits) precision = max_double_digits; + fixed_handler handler{buf.data(), 0, precision, -cached_exp10, fixed}; + if (grisu_gen_digits(normalized, 1, exp, handler) == digits::error) { + exp += handler.size - cached_exp10 - 1; + fallback_format(value, handler.precision, specs.binary32, buf, exp); + } else { + exp += handler.exp10; + buf.try_resize(to_unsigned(handler.size)); + } + if (!fixed && !specs.showpoint) { + // Remove trailing zeros. + auto num_digits = buf.size(); + while (num_digits > 0 && buf[num_digits - 1] == '0') { + --num_digits; + ++exp; + } + buf.try_resize(num_digits); + } + return exp; +} // namespace detail + +template +int snprintf_float(T value, int precision, float_specs specs, + buffer& buf) { + // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. + FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer"); + static_assert(!std::is_same::value, ""); + + // Subtract 1 to account for the difference in precision since we use %e for + // both general and exponent format. + if (specs.format == float_format::general || + specs.format == float_format::exp) + precision = (precision >= 0 ? precision : 6) - 1; + + // Build the format string. + enum { max_format_size = 7 }; // The longest format is "%#.*Le". + char format[max_format_size]; + char* format_ptr = format; + *format_ptr++ = '%'; + if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#'; + if (precision >= 0) { + *format_ptr++ = '.'; + *format_ptr++ = '*'; + } + if (std::is_same()) *format_ptr++ = 'L'; + *format_ptr++ = specs.format != float_format::hex + ? (specs.format == float_format::fixed ? 'f' : 'e') + : (specs.upper ? 'A' : 'a'); + *format_ptr = '\0'; + + // Format using snprintf. + auto offset = buf.size(); + for (;;) { + auto begin = buf.data() + offset; + auto capacity = buf.capacity() - offset; +#ifdef FMT_FUZZ + if (precision > 100000) + throw std::runtime_error( + "fuzz mode - avoid large allocation inside snprintf"); +#endif + // Suppress the warning about a nonliteral format string. + // Cannot use auto because of a bug in MinGW (#1532). + int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; + int result = precision >= 0 + ? snprintf_ptr(begin, capacity, format, precision, value) + : snprintf_ptr(begin, capacity, format, value); + if (result < 0) { + // The buffer will grow exponentially. + buf.try_reserve(buf.capacity() + 1); + continue; + } + auto size = to_unsigned(result); + // Size equal to capacity means that the last character was truncated. + if (size >= capacity) { + buf.try_reserve(size + offset + 1); // Add 1 for the terminating '\0'. + continue; + } + auto is_digit = [](char c) { return c >= '0' && c <= '9'; }; + if (specs.format == float_format::fixed) { + if (precision == 0) { + buf.try_resize(size); + return 0; + } + // Find and remove the decimal point. + auto end = begin + size, p = end; + do { + --p; + } while (is_digit(*p)); + int fraction_size = static_cast(end - p - 1); + std::memmove(p, p + 1, to_unsigned(fraction_size)); + buf.try_resize(size - 1); + return -fraction_size; + } + if (specs.format == float_format::hex) { + buf.try_resize(size + offset); + return 0; + } + // Find and parse the exponent. + auto end = begin + size, exp_pos = end; + do { + --exp_pos; + } while (*exp_pos != 'e'); + char sign = exp_pos[1]; + assert(sign == '+' || sign == '-'); + int exp = 0; + auto p = exp_pos + 2; // Skip 'e' and sign. + do { + assert(is_digit(*p)); + exp = exp * 10 + (*p++ - '0'); + } while (p != end); + if (sign == '-') exp = -exp; + int fraction_size = 0; + if (exp_pos != begin + 1) { + // Remove trailing zeros. + auto fraction_end = exp_pos - 1; + while (*fraction_end == '0') --fraction_end; + // Move the fractional part left to get rid of the decimal point. + fraction_size = static_cast(fraction_end - begin - 1); + std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size)); + } + buf.try_resize(to_unsigned(fraction_size) + offset + 1); + return exp - fraction_size; + } +} + +// A public domain branchless UTF-8 decoder by Christopher Wellons: +// https://github.com/skeeto/branchless-utf8 +/* Decode the next character, c, from buf, reporting errors in e. + * + * Since this is a branchless decoder, four bytes will be read from the + * buffer regardless of the actual length of the next character. This + * means the buffer _must_ have at least three bytes of zero padding + * following the end of the data stream. + * + * Errors are reported in e, which will be non-zero if the parsed + * character was somehow invalid: invalid byte sequence, non-canonical + * encoding, or a surrogate half. + * + * The function returns a pointer to the next character. When an error + * occurs, this pointer will be a guess that depends on the particular + * error, but it will always advance at least one byte. + */ +inline const char* utf8_decode(const char* buf, uint32_t* c, int* e) { + static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; + static const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; + static const int shiftc[] = {0, 18, 12, 6, 0}; + static const int shifte[] = {0, 6, 4, 2, 0}; + + int len = code_point_length(buf); + const char* next = buf + len; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + auto s = reinterpret_cast(buf); + *c = uint32_t(s[0] & masks[len]) << 18; + *c |= uint32_t(s[1] & 0x3f) << 12; + *c |= uint32_t(s[2] & 0x3f) << 6; + *c |= uint32_t(s[3] & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + *e = (*c < mins[len]) << 6; // non-canonical encoding + *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? + *e |= (*c > 0x10FFFF) << 8; // out of range? + *e |= (s[1] & 0xc0) >> 2; + *e |= (s[2] & 0xc0) >> 4; + *e |= (s[3]) >> 6; + *e ^= 0x2a; // top two bits of each tail byte correct? + *e >>= shifte[len]; + + return next; +} + +struct stringifier { + template FMT_INLINE std::string operator()(T value) const { + return to_string(value); + } + std::string operator()(basic_format_arg::handle h) const { + memory_buffer buf; + format_parse_context parse_ctx({}); + format_context format_ctx(buffer_appender(buf), {}, {}); + h.format(parse_ctx, format_ctx); + return to_string(buf); + } +}; +} // namespace detail + +template <> struct formatter { + format_parse_context::iterator parse(format_parse_context& ctx) { + return ctx.begin(); + } + + format_context::iterator format(const detail::bigint& n, + format_context& ctx) { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = format_to(out, "{:x}", value); + first = false; + continue; + } + out = format_to(out, "{:08x}", value); + } + if (n.exp_ > 0) + out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; + +FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { + auto transcode = [this](const char* p) { + auto cp = uint32_t(); + auto error = 0; + p = utf8_decode(p, &cp, &error); + if (error != 0) FMT_THROW(std::runtime_error("invalid utf8")); + if (cp <= 0xFFFF) { + buffer_.push_back(static_cast(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast(0xDC00 + (cp & 0x3FF))); + } + return p; + }; + auto p = s.data(); + const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. + if (s.size() >= block_size) { + for (auto end = p + s.size() - block_size + 1; p < end;) p = transcode(p); + } + if (auto num_chars_left = s.data() + s.size() - p) { + char buf[2 * block_size - 1] = {}; + memcpy(buf, p, to_unsigned(num_chars_left)); + p = buf; + do { + p = transcode(p); + } while (p - buf < num_chars_left); + } + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer& out, int error_code, + string_view message) FMT_NOEXCEPT { + FMT_TRY { + memory_buffer buf; + buf.resize(inline_buffer_size); + for (;;) { + char* system_message = &buf[0]; + int result = + detail::safe_strerror(error_code, system_message, buf.size()); + if (result == 0) { + format_to(detail::buffer_appender(out), "{}: {}", message, + system_message); + return; + } + if (result != ERANGE) + break; // Can't get error message, report error code instead. + buf.resize(buf.size() * 2); + } + } + FMT_CATCH(...) {} + format_error_code(out, error_code, message); +} + +FMT_FUNC void detail::error_handler::on_error(const char* message) { + FMT_THROW(format_error(message)); +} + +FMT_FUNC void report_system_error(int error_code, + fmt::string_view message) FMT_NOEXCEPT { + report_error(format_system_error, error_code, message); +} + +FMT_FUNC std::string detail::vformat(string_view format_str, format_args args) { + if (format_str.size() == 2 && equal2(format_str.data(), "{}")) { + auto arg = args.get(0); + if (!arg) error_handler().on_error("argument not found"); + return visit_format_arg(stringifier(), arg); + } + memory_buffer buffer; + detail::vformat_to(buffer, format_str, args); + return to_string(buffer); +} + +#ifdef _WIN32 +namespace detail { +using dword = conditional_t; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); +} // namespace detail +#endif + +FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, + basic_format_args>(args)); +#ifdef _WIN32 + auto fd = _fileno(f); + if (_isatty(fd)) { + detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size())); + auto written = detail::dword(); + if (!detail::WriteConsoleW(reinterpret_cast(_get_osfhandle(fd)), + u16.c_str(), static_cast(u16.size()), + &written, nullptr)) { + FMT_THROW(format_error("failed to write to console")); + } + return; + } +#endif + detail::fwrite_fully(buffer.data(), 1, buffer.size(), f); +} + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str, + format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, + basic_format_args>(args)); + fwrite_fully(buffer.data(), 1, buffer.size(), f); +} +#endif + +FMT_FUNC void vprint(string_view format_str, format_args args) { + vprint(stdout, format_str, args); +} + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/src/3rdparty/fmt/format.h b/src/3rdparty/fmt/format.h new file mode 100644 index 0000000000..1a037b02b7 --- /dev/null +++ b/src/3rdparty/fmt/format.h @@ -0,0 +1,3960 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - present, Victor Zverovich + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --- Optional exception to the license --- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into a machine-executable object form of such + source code, you may redistribute such embedded portions in such object form + without including the above copyright and permission notices. + */ + +#ifndef FMT_FORMAT_H_ +#define FMT_FORMAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" + +#ifdef __INTEL_COMPILER +# define FMT_ICC_VERSION __INTEL_COMPILER +#elif defined(__ICL) +# define FMT_ICC_VERSION __ICL +#else +# define FMT_ICC_VERSION 0 +#endif + +#ifdef __NVCC__ +# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__) +#else +# define FMT_CUDA_VERSION 0 +#endif + +#ifdef __has_builtin +# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define FMT_HAS_BUILTIN(x) 0 +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_NOINLINE __attribute__((noinline)) +#else +# define FMT_NOINLINE +#endif + +#if __cplusplus == 201103L || __cplusplus == 201402L +# if defined(__INTEL_COMPILER) || defined(__PGI) +# define FMT_FALLTHROUGH +# elif defined(__clang__) +# define FMT_FALLTHROUGH [[clang::fallthrough]] +# elif FMT_GCC_VERSION >= 700 && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) +# define FMT_FALLTHROUGH [[gnu::fallthrough]] +# else +# define FMT_FALLTHROUGH +# endif +#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) || \ + (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define FMT_FALLTHROUGH [[fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +#ifndef FMT_MAYBE_UNUSED +# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) +# define FMT_MAYBE_UNUSED [[maybe_unused]] +# else +# define FMT_MAYBE_UNUSED +# endif +#endif + +#ifndef FMT_THROW +# if FMT_EXCEPTIONS +# if FMT_MSC_VER || FMT_NVCC +FMT_BEGIN_NAMESPACE +namespace detail { +template inline void do_throw(const Exception& x) { + // Silence unreachable code warnings in MSVC and NVCC because these + // are nearly impossible to fix in a generic code. + volatile bool b = true; + if (b) throw x; +} +} // namespace detail +FMT_END_NAMESPACE +# define FMT_THROW(x) detail::do_throw(x) +# else +# define FMT_THROW(x) throw x +# endif +# else +# define FMT_THROW(x) \ + do { \ + static_cast(sizeof(x)); \ + FMT_ASSERT(false, ""); \ + } while (false) +# endif +#endif + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifndef FMT_USE_USER_DEFINED_LITERALS +// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. +# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \ + FMT_MSC_VER >= 1900) && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) +# define FMT_USE_USER_DEFINED_LITERALS 1 +# else +# define FMT_USE_USER_DEFINED_LITERALS 0 +# endif +#endif + +#ifndef FMT_USE_UDL_TEMPLATE +// EDG frontend based compilers (icc, nvcc, PGI, etc) and GCC < 6.4 do not +// properly support UDL templates and GCC >= 9 warns about them. +# if FMT_USE_USER_DEFINED_LITERALS && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 501) && \ + ((FMT_GCC_VERSION >= 604 && __cplusplus >= 201402L) || \ + FMT_CLANG_VERSION >= 304) && \ + !defined(__PGI) && !defined(__NVCC__) +# define FMT_USE_UDL_TEMPLATE 1 +# else +# define FMT_USE_UDL_TEMPLATE 0 +# endif +#endif + +#ifndef FMT_USE_FLOAT +# define FMT_USE_FLOAT 1 +#endif + +#ifndef FMT_USE_DOUBLE +# define FMT_USE_DOUBLE 1 +#endif + +#ifndef FMT_USE_LONG_DOUBLE +# define FMT_USE_LONG_DOUBLE 1 +#endif + +// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of +// int_writer template instances to just one by only using the largest integer +// type. This results in a reduction in binary size but will cause a decrease in +// integer formatting performance. +#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) +# define FMT_REDUCE_INT_INSTANTIATIONS 0 +#endif + +// __builtin_clz is broken in clang with Microsoft CodeGen: +// https://github.com/fmtlib/fmt/issues/519 +#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +#endif +#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +#endif +#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctz)) +# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) +#endif +#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctzll)) +# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) +#endif + +#if FMT_MSC_VER +# include // _BitScanReverse[64], _BitScanForward[64], _umul128 +#endif + +// Some compilers masquerade as both MSVC and GCC-likes or otherwise support +// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the +// MSVC intrinsics if the clz and clzll builtins are not available. +#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && \ + !defined(FMT_BUILTIN_CTZLL) && !defined(_MANAGED) +FMT_BEGIN_NAMESPACE +namespace detail { +// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. +# ifndef __clang__ +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# endif +# if defined(_WIN64) && !defined(__clang__) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif + +inline int clz(uint32_t x) { + unsigned long r = 0; + _BitScanReverse(&r, x); + FMT_ASSERT(x != 0, ""); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. + FMT_SUPPRESS_MSC_WARNING(6102) + return 31 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZ(n) detail::clz(n) + +inline int clzll(uint64_t x) { + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) return 63 ^ (r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x)); +# endif + FMT_ASSERT(x != 0, ""); + FMT_SUPPRESS_MSC_WARNING(6102) // Suppress a bogus static analysis warning. + return 63 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) + +inline int ctz(uint32_t x) { + unsigned long r = 0; + _BitScanForward(&r, x); + FMT_ASSERT(x != 0, ""); + FMT_SUPPRESS_MSC_WARNING(6102) // Suppress a bogus static analysis warning. + return static_cast(r); +} +# define FMT_BUILTIN_CTZ(n) detail::ctz(n) + +inline int ctzll(uint64_t x) { + unsigned long r = 0; + FMT_ASSERT(x != 0, ""); + FMT_SUPPRESS_MSC_WARNING(6102) // Suppress a bogus static analysis warning. +# ifdef _WIN64 + _BitScanForward64(&r, x); +# else + // Scan the low 32 bits. + if (_BitScanForward(&r, static_cast(x))) return static_cast(r); + // Scan the high 32 bits. + _BitScanForward(&r, static_cast(x >> 32)); + r += 32; +# endif + return static_cast(r); +} +# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) +} // namespace detail +FMT_END_NAMESPACE +#endif + +// Enable the deprecated numeric alignment. +#ifndef FMT_DEPRECATED_NUMERIC_ALIGN +# define FMT_DEPRECATED_NUMERIC_ALIGN 0 +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +// An equivalent of `*reinterpret_cast(&source)` that doesn't have +// undefined behavior (e.g. due to type aliasing). +// Example: uint64_t d = bit_cast(2.718); +template +inline Dest bit_cast(const Source& source) { + static_assert(sizeof(Dest) == sizeof(Source), "size mismatch"); + Dest dest; + std::memcpy(&dest, &source, sizeof(dest)); + return dest; +} + +inline bool is_big_endian() { + const auto u = 1u; + struct bytes { + char data[sizeof(u)]; + }; + return bit_cast(u).data[0] == 0; +} + +// A fallback implementation of uintptr_t for systems that lack it. +struct fallback_uintptr { + unsigned char value[sizeof(void*)]; + + fallback_uintptr() = default; + explicit fallback_uintptr(const void* p) { + *this = bit_cast(p); + if (is_big_endian()) { + for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j) + std::swap(value[i], value[j]); + } + } +}; +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +inline uintptr_t to_uintptr(const void* p) { return bit_cast(p); } +#else +using uintptr_t = fallback_uintptr; +inline fallback_uintptr to_uintptr(const void* p) { + return fallback_uintptr(p); +} +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits::max() but shorter and not affected by the max macro. +template constexpr T max_value() { + return (std::numeric_limits::max)(); +} +template constexpr int num_bits() { + return std::numeric_limits::digits; +} +// std::numeric_limits::digits may return 0 for 128-bit ints. +template <> constexpr int num_bits() { return 128; } +template <> constexpr int num_bits() { return 128; } +template <> constexpr int num_bits() { + return static_cast(sizeof(void*) * + std::numeric_limits::digits); +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) + __builtin_assume(condition); +#endif +} + +// An approximation of iterator_t for pre-C++20 systems. +template +using iterator_t = decltype(std::begin(std::declval())); +template using sentinel_t = decltype(std::end(std::declval())); + +// A workaround for std::string not having mutable data() until C++17. +template inline Char* get_data(std::basic_string& s) { + return &s[0]; +} +template +inline typename Container::value_type* get_data(Container& c) { + return c.data(); +} + +#if defined(_SECURE_SCL) && _SECURE_SCL +// Make a checked iterator to avoid MSVC warnings. +template using checked_ptr = stdext::checked_array_iterator; +template checked_ptr make_checked(T* p, size_t size) { + return {p, size}; +} +#else +template using checked_ptr = T*; +template inline T* make_checked(T* p, size_t) { return p; } +#endif + +template ::value)> +#if FMT_CLANG_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +inline checked_ptr +reserve(std::back_insert_iterator it, size_t n) { + Container& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return make_checked(get_data(c) + size, n); +} + +template +inline buffer_appender reserve(buffer_appender it, size_t n) { + buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template inline Iterator& reserve(Iterator& it, size_t) { + return it; +} + +template +constexpr T* to_pointer(OutputIt, size_t) { + return nullptr; +} +template T* to_pointer(buffer_appender it, size_t n) { + buffer& buf = get_container(it); + auto size = buf.size(); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template ::value)> +inline std::back_insert_iterator base_iterator( + std::back_insert_iterator& it, + checked_ptr) { + return it; +} + +template +inline Iterator base_iterator(Iterator, Iterator it) { + return it; +} + +// An output iterator that counts the number of objects written to it and +// discards them. +class counting_iterator { + private: + size_t count_; + + public: + using iterator_category = std::output_iterator_tag; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; + using _Unchecked_type = counting_iterator; // Mark iterator as checked. + + struct value_type { + template void operator=(const T&) {} + }; + + counting_iterator() : count_(0) {} + + size_t count() const { return count_; } + + counting_iterator& operator++() { + ++count_; + return *this; + } + counting_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + friend counting_iterator operator+(counting_iterator it, difference_type n) { + it.count_ += static_cast(n); + return it; + } + + value_type operator*() const { return {}; } +}; + +template class truncating_iterator_base { + protected: + OutputIt out_; + size_t limit_; + size_t count_; + + truncating_iterator_base(OutputIt out, size_t limit) + : out_(out), limit_(limit), count_(0) {} + + public: + using iterator_category = std::output_iterator_tag; + using value_type = typename std::iterator_traits::value_type; + using difference_type = void; + using pointer = void; + using reference = void; + using _Unchecked_type = + truncating_iterator_base; // Mark iterator as checked. + + OutputIt base() const { return out_; } + size_t count() const { return count_; } +}; + +// An output iterator that truncates the output and counts the number of objects +// written to it. +template ::value_type>::type> +class truncating_iterator; + +template +class truncating_iterator + : public truncating_iterator_base { + mutable typename truncating_iterator_base::value_type blackhole_; + + public: + using value_type = typename truncating_iterator_base::value_type; + + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base(out, limit) {} + + truncating_iterator& operator++() { + if (this->count_++ < this->limit_) ++this->out_; + return *this; + } + + truncating_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + value_type& operator*() const { + return this->count_ < this->limit_ ? *this->out_ : blackhole_; + } +}; + +template +class truncating_iterator + : public truncating_iterator_base { + public: + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base(out, limit) {} + + template truncating_iterator& operator=(T val) { + if (this->count_++ < this->limit_) *this->out_++ = val; + return *this; + } + + truncating_iterator& operator++() { return *this; } + truncating_iterator& operator++(int) { return *this; } + truncating_iterator& operator*() { return *this; } +}; + +template +inline size_t count_code_points(basic_string_view s) { + return s.size(); +} + +// Counts the number of code points in a UTF-8 string. +inline size_t count_code_points(basic_string_view s) { + const char* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80) ++num_code_points; + } + return num_code_points; +} + +inline size_t count_code_points(basic_string_view s) { + return count_code_points(basic_string_view( + reinterpret_cast(s.data()), s.size())); +} + +template +inline size_t code_point_index(basic_string_view s, size_t n) { + size_t size = s.size(); + return n < size ? n : size; +} + +// Calculates the index of the nth code point in a UTF-8 string. +inline size_t code_point_index(basic_string_view s, size_t n) { + const char8_type* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) { + return i; + } + } + return s.size(); +} + +template +using needs_conversion = bool_constant< + std::is_same::value_type, + char>::value && + std::is_same::value>; + +template ::value)> +OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { + return std::copy(begin, end, it); +} + +template ::value)> +OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { + return std::transform(begin, end, it, + [](char c) { return static_cast(c); }); +} + +template +inline counting_iterator copy_str(InputIt begin, InputIt end, + counting_iterator it) { + return it + (end - begin); +} + +template +using is_fast_float = bool_constant::is_iec559 && + sizeof(T) <= sizeof(double)>; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +template +template +void buffer::append(const U* begin, const U* end) { + do { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count)); + size_ += count; + begin += count; + } while (begin != end); +} + +template +void iterator_buffer::flush() { + out_ = std::copy_n(data_, this->limit(this->size()), out_); + this->clear(); +} +} // namespace detail + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic memory allocation. +enum { inline_buffer_size = 500 }; + +/** + \rst + A dynamically growing memory buffer for trivially copyable/constructible types + with the first ``SIZE`` elements stored in the object itself. + + You can use one of the following type aliases for common character types: + + +----------------+------------------------------+ + | Type | Definition | + +================+==============================+ + | memory_buffer | basic_memory_buffer | + +----------------+------------------------------+ + | wmemory_buffer | basic_memory_buffer | + +----------------+------------------------------+ + + **Example**:: + + fmt::memory_buffer out; + format_to(out, "The answer is {}.", 42); + + This will append the following output to the ``out`` object: + + .. code-block:: none + + The answer is 42. + + The output can be converted to an ``std::string`` with ``to_string(out)``. + \endrst + */ +template > +class basic_memory_buffer final : public detail::buffer { + private: + T store_[SIZE]; + + // Don't inherit from Allocator avoid generating type_info for it. + Allocator alloc_; + + // Deallocate memory allocated by the buffer. + void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + protected: + void grow(size_t size) final FMT_OVERRIDE; + + public: + using value_type = T; + using const_reference = const T&; + + explicit basic_memory_buffer(const Allocator& alloc = Allocator()) + : alloc_(alloc) { + this->set(store_, SIZE); + } + ~basic_memory_buffer() { deallocate(); } + + private: + // Move data from other to this buffer. + void move(basic_memory_buffer& other) { + alloc_ = std::move(other.alloc_); + T* data = other.data(); + size_t size = other.size(), capacity = other.capacity(); + if (data == other.store_) { + this->set(store_, capacity); + std::uninitialized_copy(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + } + this->resize(size); + } + + public: + /** + \rst + Constructs a :class:`fmt::basic_memory_buffer` object moving the content + of the other object to it. + \endrst + */ + basic_memory_buffer(basic_memory_buffer&& other) FMT_NOEXCEPT { move(other); } + + /** + \rst + Moves the content of the other ``basic_memory_buffer`` object to this one. + \endrst + */ + basic_memory_buffer& operator=(basic_memory_buffer&& other) FMT_NOEXCEPT { + FMT_ASSERT(this != &other, ""); + deallocate(); + move(other); + return *this; + } + + // Returns a copy of the allocator associated with this buffer. + Allocator get_allocator() const { return alloc_; } + + /** + Resizes the buffer to contain *count* elements. If T is a POD type new + elements may not be initialized. + */ + void resize(size_t count) { this->try_resize(count); } + + /** Increases the buffer capacity to *new_capacity*. */ + void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } + + // Directly append data into the buffer + using detail::buffer::append; + template + void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +template +void basic_memory_buffer::grow(size_t size) { +#ifdef FMT_FUZZ + if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); +#endif + size_t old_capacity = this->capacity(); + size_t new_capacity = old_capacity + old_capacity / 2; + if (size > new_capacity) new_capacity = size; + T* old_data = this->data(); + T* new_data = + std::allocator_traits::allocate(alloc_, new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + std::uninitialized_copy(old_data, old_data + this->size(), + detail::make_checked(new_data, new_capacity)); + this->set(new_data, new_capacity); + // deallocate must not throw according to the standard, but even if it does, + // the buffer already uses the new storage and will deallocate it in + // destructor. + if (old_data != store_) alloc_.deallocate(old_data, old_capacity); +} + +using memory_buffer = basic_memory_buffer; +using wmemory_buffer = basic_memory_buffer; + +template +struct is_contiguous> : std::true_type { +}; + +/** A formatting error such as invalid format string. */ +FMT_CLASS_API +class FMT_API format_error : public std::runtime_error { + public: + explicit format_error(const char* message) : std::runtime_error(message) {} + explicit format_error(const std::string& message) + : std::runtime_error(message) {} + format_error(const format_error&) = default; + format_error& operator=(const format_error&) = default; + format_error(format_error&&) = default; + format_error& operator=(format_error&&) = default; + ~format_error() FMT_NOEXCEPT FMT_OVERRIDE; +}; + +namespace detail { + +template +using is_signed = + std::integral_constant::is_signed || + std::is_same::value>; + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template ::value)> +FMT_CONSTEXPR bool is_negative(T value) { + return value < 0; +} +template ::value)> +FMT_CONSTEXPR bool is_negative(T) { + return false; +} + +template ::value)> +FMT_CONSTEXPR bool is_supported_floating_point(T) { + return (std::is_same::value && FMT_USE_FLOAT) || + (std::is_same::value && FMT_USE_DOUBLE) || + (std::is_same::value && FMT_USE_LONG_DOUBLE); +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template +using uint32_or_64_or_128_t = + conditional_t() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t() <= 64, uint64_t, uint128_t>>; + +// 128-bit integer type used internally +struct FMT_EXTERN_TEMPLATE_API uint128_wrapper { + uint128_wrapper() = default; + +#if FMT_USE_INT128 + uint128_t internal_; + + uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT + : internal_{static_cast(low) | + (static_cast(high) << 64)} {} + + uint128_wrapper(uint128_t u) : internal_{u} {} + + uint64_t high() const FMT_NOEXCEPT { return uint64_t(internal_ >> 64); } + uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { + internal_ += n; + return *this; + } +#else + uint64_t high_; + uint64_t low_; + + uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT : high_{high}, + low_{low} {} + + uint64_t high() const FMT_NOEXCEPT { return high_; } + uint64_t low() const FMT_NOEXCEPT { return low_; } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { +# if defined(_MSC_VER) && defined(_M_X64) + unsigned char carry = _addcarry_u64(0, low_, n, &low_); + _addcarry_u64(carry, high_, 0, &high_); + return *this; +# else + uint64_t sum = low_ + n; + high_ += (sum < low_ ? 1 : 0); + low_ = sum; + return *this; +# endif + } +#endif +}; + +// Table entry type for divisibility test used internally +template struct FMT_EXTERN_TEMPLATE_API divtest_table_entry { + T mod_inv; + T max_quotient; +}; + +// Static data is placed in this class template for the header-only config. +template struct FMT_EXTERN_TEMPLATE_API basic_data { + static const uint64_t powers_of_10_64[]; + static const uint32_t zero_or_powers_of_10_32_new[]; + static const uint64_t zero_or_powers_of_10_64_new[]; + static const uint64_t grisu_pow10_significands[]; + static const int16_t grisu_pow10_exponents[]; + static const divtest_table_entry divtest_table_for_pow5_32[]; + static const divtest_table_entry divtest_table_for_pow5_64[]; + static const uint64_t dragonbox_pow10_significands_64[]; + static const uint128_wrapper dragonbox_pow10_significands_128[]; + // log10(2) = 0x0.4d104d427de7fbcc... + static const uint64_t log10_2_significand = 0x4d104d427de7fbcc; +#if !FMT_USE_FULL_CACHE_DRAGONBOX + static const uint64_t powers_of_5_64[]; + static const uint32_t dragonbox_pow10_recovery_errors[]; +#endif + // GCC generates slightly better code for pairs than chars. + using digit_pair = char[2]; + static const digit_pair digits[]; + static const char hex_digits[]; + static const char foreground_color[]; + static const char background_color[]; + static const char reset_color[5]; + static const wchar_t wreset_color[5]; + static const char signs[]; + static const char left_padding_shifts[5]; + static const char right_padding_shifts[5]; + + // DEPRECATED! These are for ABI compatibility. + static const uint32_t zero_or_powers_of_10_32[]; + static const uint64_t zero_or_powers_of_10_64[]; +}; + +// Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). +// This is a function instead of an array to workaround a bug in GCC10 (#1810). +FMT_INLINE uint16_t bsr2log10(int bsr) { + static constexpr uint16_t data[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + return data[bsr]; +} + +#ifndef FMT_EXPORTED +FMT_EXTERN template struct basic_data; +#endif + +// This is a struct rather than an alias to avoid shadowing warnings in gcc. +struct data : basic_data<> {}; + +#ifdef FMT_BUILTIN_CLZLL +// Returns the number of decimal digits in n. Leading zeros are not counted +// except for n == 0 in which case count_digits returns 1. +inline int count_digits(uint64_t n) { + // https://github.com/fmtlib/format-benchmark/blob/master/digits10 + auto t = bsr2log10(FMT_BUILTIN_CLZLL(n | 1) ^ 63); + return t - (n < data::zero_or_powers_of_10_64_new[t]); +} +#else +// Fallback version of count_digits used when __builtin_clz is not available. +inline int count_digits(uint64_t n) { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} +#endif + +#if FMT_USE_INT128 +inline int count_digits(uint128_t n) { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000U; + count += 4; + } +} +#endif + +// Counts the number of digits in n. BITS = log2(radix). +template inline int count_digits(UInt n) { + int num_digits = 0; + do { + ++num_digits; + } while ((n >>= BITS) != 0); + return num_digits; +} + +template <> int count_digits<4>(detail::fallback_uintptr n); + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_ALWAYS_INLINE inline __attribute__((always_inline)) +#elif FMT_MSC_VER +# define FMT_ALWAYS_INLINE __forceinline +#else +# define FMT_ALWAYS_INLINE inline +#endif + +// To suppress unnecessary security cookie checks +#if FMT_MSC_VER && !FMT_CLANG_VERSION +# define FMT_SAFEBUFFERS __declspec(safebuffers) +#else +# define FMT_SAFEBUFFERS +#endif + +#ifdef FMT_BUILTIN_CLZ +// Optional version of count_digits for better performance on 32-bit platforms. +inline int count_digits(uint32_t n) { + auto t = bsr2log10(FMT_BUILTIN_CLZ(n | 1) ^ 31); + return t - (n < data::zero_or_powers_of_10_32_new[t]); +} +#endif + +template constexpr int digits10() FMT_NOEXCEPT { + return std::numeric_limits::digits10; +} +template <> constexpr int digits10() FMT_NOEXCEPT { return 38; } +template <> constexpr int digits10() FMT_NOEXCEPT { return 38; } + +template FMT_API std::string grouping_impl(locale_ref loc); +template inline std::string grouping(locale_ref loc) { + return grouping_impl(loc); +} +template <> inline std::string grouping(locale_ref loc) { + return grouping_impl(loc); +} + +template FMT_API Char thousands_sep_impl(locale_ref loc); +template inline Char thousands_sep(locale_ref loc) { + return Char(thousands_sep_impl(loc)); +} +template <> inline wchar_t thousands_sep(locale_ref loc) { + return thousands_sep_impl(loc); +} + +template FMT_API Char decimal_point_impl(locale_ref loc); +template inline Char decimal_point(locale_ref loc) { + return Char(decimal_point_impl(loc)); +} +template <> inline wchar_t decimal_point(locale_ref loc) { + return decimal_point_impl(loc); +} + +// Compares two characters for equality. +template bool equal2(const Char* lhs, const char* rhs) { + return lhs[0] == rhs[0] && lhs[1] == rhs[1]; +} +inline bool equal2(const char* lhs, const char* rhs) { + return memcmp(lhs, rhs, 2) == 0; +} + +// Copies two characters from src to dst. +template void copy2(Char* dst, const char* src) { + *dst++ = static_cast(*src++); + *dst = static_cast(*src); +} +FMT_INLINE void copy2(char* dst, const char* src) { memcpy(dst, src, 2); } + +template struct format_decimal_result { + Iterator begin; + Iterator end; +}; + +// Formats a decimal unsigned integer value writing into out pointing to a +// buffer of specified size. The caller must ensure that the buffer is large +// enough. +template +inline format_decimal_result format_decimal(Char* out, UInt value, + int size) { + FMT_ASSERT(size >= count_digits(value), "invalid digit count"); + out += size; + Char* end = out; + while (value >= 100) { + // Integer division is slow so do it for a group of two digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + out -= 2; + copy2(out, data::digits[value % 100]); + value /= 100; + } + if (value < 10) { + *--out = static_cast('0' + value); + return {out, end}; + } + out -= 2; + copy2(out, data::digits[value]); + return {out, end}; +} + +template >::value)> +inline format_decimal_result format_decimal(Iterator out, UInt value, + int size) { + // Buffer is large enough to hold all digits (digits10 + 1). + Char buffer[digits10() + 1]; + auto end = format_decimal(buffer, value, size).end; + return {out, detail::copy_str(buffer, end, out)}; +} + +template +inline Char* format_uint(Char* buffer, UInt value, int num_digits, + bool upper = false) { + buffer += num_digits; + Char* end = buffer; + do { + const char* digits = upper ? "0123456789ABCDEF" : data::hex_digits; + unsigned digit = (value & ((1 << BASE_BITS) - 1)); + *--buffer = static_cast(BASE_BITS < 4 ? static_cast('0' + digit) + : digits[digit]); + } while ((value >>= BASE_BITS) != 0); + return end; +} + +template +Char* format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits, + bool = false) { + auto char_digits = std::numeric_limits::digits / 4; + int start = (num_digits + char_digits - 1) / char_digits - 1; + if (int start_digits = num_digits % char_digits) { + unsigned value = n.value[start--]; + buffer = format_uint(buffer, value, start_digits); + } + for (; start >= 0; --start) { + unsigned value = n.value[start]; + buffer += char_digits; + auto p = buffer; + for (int i = 0; i < char_digits; ++i) { + unsigned digit = (value & ((1 << BASE_BITS) - 1)); + *--p = static_cast(data::hex_digits[digit]); + value >>= BASE_BITS; + } + } + return buffer; +} + +template +inline It format_uint(It out, UInt value, int num_digits, bool upper = false) { + if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { + format_uint(ptr, value, num_digits, upper); + return out; + } + // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). + char buffer[num_bits() / BASE_BITS + 1]; + format_uint(buffer, value, num_digits, upper); + return detail::copy_str(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + wmemory_buffer buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + operator wstring_view() const { return {&buffer_[0], size()}; } + size_t size() const { return buffer_.size() - 1; } + const wchar_t* c_str() const { return &buffer_[0]; } + std::wstring str() const { return {&buffer_[0], size()}; } +}; + +template struct null {}; + +// Workaround an array initialization issue in gcc 4.8. +template struct fill_t { + private: + enum { max_size = 4 }; + Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)}; + unsigned char size_ = 1; + + public: + FMT_CONSTEXPR void operator=(basic_string_view s) { + auto size = s.size(); + if (size > max_size) { + FMT_THROW(format_error("invalid fill")); + return; + } + for (size_t i = 0; i < size; ++i) data_[i] = s[i]; + size_ = static_cast(size); + } + + size_t size() const { return size_; } + const Char* data() const { return data_; } + + FMT_CONSTEXPR Char& operator[](size_t index) { return data_[index]; } + FMT_CONSTEXPR const Char& operator[](size_t index) const { + return data_[index]; + } +}; +} // namespace detail + +// We cannot use enum classes as bit fields because of a gcc bug +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414. +namespace align { +enum type { none, left, right, center, numeric }; +} +using align_t = align::type; + +namespace sign { +enum type { none, minus, plus, space }; +} +using sign_t = sign::type; + +// Format specifiers for built-in and string types. +template struct basic_format_specs { + int width; + int precision; + char type; + align_t align : 4; + sign_t sign : 3; + bool alt : 1; // Alternate form ('#'). + detail::fill_t fill; + + constexpr basic_format_specs() + : width(0), + precision(-1), + type(0), + align(align::none), + sign(sign::none), + alt(false) {} +}; + +using format_specs = basic_format_specs; + +namespace detail { +namespace dragonbox { + +// Type-specific information that Dragonbox uses. +template struct float_info; + +template <> struct float_info { + using carrier_uint = uint32_t; + static const int significand_bits = 23; + static const int exponent_bits = 8; + static const int min_exponent = -126; + static const int max_exponent = 127; + static const int exponent_bias = -127; + static const int decimal_digits = 9; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int cache_bits = 64; + static const int divisibility_check_by_5_threshold = 39; + static const int case_fc_pm_half_lower_threshold = -1; + static const int case_fc_pm_half_upper_threshold = 6; + static const int case_fc_lower_threshold = -2; + static const int case_fc_upper_threshold = 6; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; + static const int max_trailing_zeros = 7; +}; + +template <> struct float_info { + using carrier_uint = uint64_t; + static const int significand_bits = 52; + static const int exponent_bits = 11; + static const int min_exponent = -1022; + static const int max_exponent = 1023; + static const int exponent_bias = -1023; + static const int decimal_digits = 17; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 326; + static const int cache_bits = 128; + static const int divisibility_check_by_5_threshold = 86; + static const int case_fc_pm_half_lower_threshold = -2; + static const int case_fc_pm_half_upper_threshold = 9; + static const int case_fc_lower_threshold = -4; + static const int case_fc_upper_threshold = 9; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; + static const int max_trailing_zeros = 16; +}; + +template struct decimal_fp { + using significand_type = typename float_info::carrier_uint; + significand_type significand; + int exponent; +}; + +template FMT_API decimal_fp to_decimal(T x) FMT_NOEXCEPT; +} // namespace dragonbox + +template +constexpr typename dragonbox::float_info::carrier_uint exponent_mask() { + using uint = typename dragonbox::float_info::carrier_uint; + return ((uint(1) << dragonbox::float_info::exponent_bits) - 1) + << dragonbox::float_info::significand_bits; +} + +// A floating-point presentation format. +enum class float_format : unsigned char { + general, // General: exponent notation or fixed point based on magnitude. + exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. + fixed, // Fixed point with the default precision of 6, e.g. 0.0012. + hex +}; + +struct float_specs { + int precision; + float_format format : 8; + sign_t sign : 8; + bool upper : 1; + bool locale : 1; + bool binary32 : 1; + bool use_grisu : 1; + bool showpoint : 1; +}; + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template It write_exponent(int exp, It it) { + FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); + if (exp < 0) { + *it++ = static_cast('-'); + exp = -exp; + } else { + *it++ = static_cast('+'); + } + if (exp >= 100) { + const char* top = data::digits[exp / 100]; + if (exp >= 1000) *it++ = static_cast(top[0]); + *it++ = static_cast(top[1]); + exp %= 100; + } + const char* d = data::digits[exp]; + *it++ = static_cast(d[0]); + *it++ = static_cast(d[1]); + return it; +} + +template +int format_float(T value, int precision, float_specs specs, buffer& buf); + +// Formats a floating-point number with snprintf. +template +int snprintf_float(T value, int precision, float_specs specs, + buffer& buf); + +template T promote_float(T value) { return value; } +inline double promote_float(float value) { return static_cast(value); } + +template +FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) { + switch (spec) { + case 0: + case 'd': + handler.on_dec(); + break; + case 'x': + case 'X': + handler.on_hex(); + break; + case 'b': + case 'B': + handler.on_bin(); + break; + case 'o': + handler.on_oct(); + break; +#ifdef FMT_DEPRECATED_N_SPECIFIER + case 'n': +#endif + case 'L': + handler.on_num(); + break; + case 'c': + handler.on_chr(); + break; + default: + handler.on_error(); + } +} + +template +FMT_CONSTEXPR float_specs parse_float_type_spec( + const basic_format_specs& specs, ErrorHandler&& eh = {}) { + auto result = float_specs(); + result.showpoint = specs.alt; + switch (specs.type) { + case 0: + result.format = float_format::general; + result.showpoint |= specs.precision > 0; + break; + case 'G': + result.upper = true; + FMT_FALLTHROUGH; + case 'g': + result.format = float_format::general; + break; + case 'E': + result.upper = true; + FMT_FALLTHROUGH; + case 'e': + result.format = float_format::exp; + result.showpoint |= specs.precision != 0; + break; + case 'F': + result.upper = true; + FMT_FALLTHROUGH; + case 'f': + result.format = float_format::fixed; + result.showpoint |= specs.precision != 0; + break; + case 'A': + result.upper = true; + FMT_FALLTHROUGH; + case 'a': + result.format = float_format::hex; + break; +#ifdef FMT_DEPRECATED_N_SPECIFIER + case 'n': +#endif + case 'L': + result.locale = true; + break; + default: + eh.on_error("invalid type specifier"); + break; + } + return result; +} + +template +FMT_CONSTEXPR void handle_char_specs(const basic_format_specs* specs, + Handler&& handler) { + if (!specs) return handler.on_char(); + if (specs->type && specs->type != 'c') return handler.on_int(); + if (specs->align == align::numeric || specs->sign != sign::none || specs->alt) + handler.on_error("invalid format specifier for char"); + handler.on_char(); +} + +template +FMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler&& handler) { + if (spec == 0 || spec == 's') + handler.on_string(); + else if (spec == 'p') + handler.on_pointer(); + else + handler.on_error("invalid type specifier"); +} + +template +FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler&& eh) { + if (spec != 0 && spec != 's') eh.on_error("invalid type specifier"); +} + +template +FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler&& eh) { + if (spec != 0 && spec != 'p') eh.on_error("invalid type specifier"); +} + +template class int_type_checker : private ErrorHandler { + public: + FMT_CONSTEXPR explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {} + + FMT_CONSTEXPR void on_dec() {} + FMT_CONSTEXPR void on_hex() {} + FMT_CONSTEXPR void on_bin() {} + FMT_CONSTEXPR void on_oct() {} + FMT_CONSTEXPR void on_num() {} + FMT_CONSTEXPR void on_chr() {} + + FMT_CONSTEXPR void on_error() { + ErrorHandler::on_error("invalid type specifier"); + } +}; + +template +class char_specs_checker : public ErrorHandler { + private: + char type_; + + public: + FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh) + : ErrorHandler(eh), type_(type) {} + + FMT_CONSTEXPR void on_int() { + handle_int_type_spec(type_, int_type_checker(*this)); + } + FMT_CONSTEXPR void on_char() {} +}; + +template +class cstring_type_checker : public ErrorHandler { + public: + FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh) + : ErrorHandler(eh) {} + + FMT_CONSTEXPR void on_string() {} + FMT_CONSTEXPR void on_pointer() {} +}; + +template +FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t& fill) { + auto fill_size = fill.size(); + if (fill_size == 1) return std::fill_n(it, n, fill[0]); + for (size_t i = 0; i < n; ++i) it = std::copy_n(fill.data(), fill_size, it); + return it; +} + +// Writes the output of f, padded according to format specifications in specs. +// size: output size in code units. +// width: output display width in (terminal) column positions. +template +inline OutputIt write_padded(OutputIt out, + const basic_format_specs& specs, size_t size, + size_t width, F&& f) { + static_assert(align == align::left || align == align::right, ""); + unsigned spec_width = to_unsigned(specs.width); + size_t padding = spec_width > width ? spec_width - width : 0; + auto* shifts = align == align::left ? data::left_padding_shifts + : data::right_padding_shifts; + size_t left_padding = padding >> shifts[specs.align]; + auto it = reserve(out, size + padding * specs.fill.size()); + it = fill(it, left_padding, specs.fill); + it = f(it); + it = fill(it, padding - left_padding, specs.fill); + return base_iterator(out, it); +} + +template +inline OutputIt write_padded(OutputIt out, + const basic_format_specs& specs, size_t size, + F&& f) { + return write_padded(out, specs, size, size, f); +} + +template +OutputIt write_bytes(OutputIt out, string_view bytes, + const basic_format_specs& specs) { + using iterator = remove_reference_t; + return write_padded(out, specs, bytes.size(), [bytes](iterator it) { + const char* data = bytes.data(); + return copy_str(data, data + bytes.size(), it); + }); +} + +// Data for write_int that doesn't depend on output iterator type. It is used to +// avoid template code bloat. +template struct write_int_data { + size_t size; + size_t padding; + + write_int_data(int num_digits, string_view prefix, + const basic_format_specs& specs) + : size(prefix.size() + to_unsigned(num_digits)), padding(0) { + if (specs.align == align::numeric) { + auto width = to_unsigned(specs.width); + if (width > size) { + padding = width - size; + size = width; + } + } else if (specs.precision > num_digits) { + size = prefix.size() + to_unsigned(specs.precision); + padding = to_unsigned(specs.precision - num_digits); + } + } +}; + +// Writes an integer in the format +// +// where are written by f(it). +template +OutputIt write_int(OutputIt out, int num_digits, string_view prefix, + const basic_format_specs& specs, F f) { + auto data = write_int_data(num_digits, prefix, specs); + using iterator = remove_reference_t; + return write_padded(out, specs, data.size, [=](iterator it) { + if (prefix.size() != 0) + it = copy_str(prefix.begin(), prefix.end(), it); + it = std::fill_n(it, data.padding, static_cast('0')); + return f(it); + }); +} + +template +OutputIt write(OutputIt out, basic_string_view s, + const basic_format_specs& specs) { + auto data = s.data(); + auto size = s.size(); + if (specs.precision >= 0 && to_unsigned(specs.precision) < size) + size = code_point_index(s, to_unsigned(specs.precision)); + auto width = specs.width != 0 + ? count_code_points(basic_string_view(data, size)) + : 0; + using iterator = remove_reference_t; + return write_padded(out, specs, size, width, [=](iterator it) { + return copy_str(data, data + size, it); + }); +} + +// The handle_int_type_spec handler that writes an integer. +template struct int_writer { + OutputIt out; + locale_ref locale; + const basic_format_specs& specs; + UInt abs_value; + char prefix[4]; + unsigned prefix_size; + + using iterator = + remove_reference_t(), 0))>; + + string_view get_prefix() const { return string_view(prefix, prefix_size); } + + template + int_writer(OutputIt output, locale_ref loc, Int value, + const basic_format_specs& s) + : out(output), + locale(loc), + specs(s), + abs_value(static_cast(value)), + prefix_size(0) { + static_assert(std::is_same, UInt>::value, ""); + if (is_negative(value)) { + prefix[0] = '-'; + ++prefix_size; + abs_value = 0 - abs_value; + } else if (specs.sign != sign::none && specs.sign != sign::minus) { + prefix[0] = specs.sign == sign::plus ? '+' : ' '; + ++prefix_size; + } + } + + void on_dec() { + auto num_digits = count_digits(abs_value); + out = write_int( + out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) { + return format_decimal(it, abs_value, num_digits).end; + }); + } + + void on_hex() { + if (specs.alt) { + prefix[prefix_size++] = '0'; + prefix[prefix_size++] = specs.type; + } + int num_digits = count_digits<4>(abs_value); + out = write_int(out, num_digits, get_prefix(), specs, + [this, num_digits](iterator it) { + return format_uint<4, Char>(it, abs_value, num_digits, + specs.type != 'x'); + }); + } + + void on_bin() { + if (specs.alt) { + prefix[prefix_size++] = '0'; + prefix[prefix_size++] = static_cast(specs.type); + } + int num_digits = count_digits<1>(abs_value); + out = write_int(out, num_digits, get_prefix(), specs, + [this, num_digits](iterator it) { + return format_uint<1, Char>(it, abs_value, num_digits); + }); + } + + void on_oct() { + int num_digits = count_digits<3>(abs_value); + if (specs.alt && specs.precision <= num_digits && abs_value != 0) { + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + prefix[prefix_size++] = '0'; + } + out = write_int(out, num_digits, get_prefix(), specs, + [this, num_digits](iterator it) { + return format_uint<3, Char>(it, abs_value, num_digits); + }); + } + + enum { sep_size = 1 }; + + void on_num() { + std::string groups = grouping(locale); + if (groups.empty()) return on_dec(); + auto sep = thousands_sep(locale); + if (!sep) return on_dec(); + int num_digits = count_digits(abs_value); + int size = num_digits, n = num_digits; + std::string::const_iterator group = groups.cbegin(); + while (group != groups.cend() && n > *group && *group > 0 && + *group != max_value()) { + size += sep_size; + n -= *group; + ++group; + } + if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back()); + char digits[40]; + format_decimal(digits, abs_value, num_digits); + basic_memory_buffer buffer; + size += static_cast(prefix_size); + const auto usize = to_unsigned(size); + buffer.resize(usize); + basic_string_view s(&sep, sep_size); + // Index of a decimal digit with the least significant digit having index 0. + int digit_index = 0; + group = groups.cbegin(); + auto p = buffer.data() + size - 1; + for (int i = num_digits - 1; i > 0; --i) { + *p-- = static_cast(digits[i]); + if (*group <= 0 || ++digit_index % *group != 0 || + *group == max_value()) + continue; + if (group + 1 != groups.cend()) { + digit_index = 0; + ++group; + } + std::uninitialized_copy(s.data(), s.data() + s.size(), + make_checked(p, s.size())); + p -= s.size(); + } + *p-- = static_cast(*digits); + if (prefix_size != 0) *p = static_cast('-'); + auto data = buffer.data(); + out = write_padded( + out, specs, usize, usize, + [=](iterator it) { return copy_str(data, data + size, it); }); + } + + void on_chr() { *out++ = static_cast(abs_value); } + + FMT_NORETURN void on_error() { + FMT_THROW(format_error("invalid type specifier")); + } +}; + +template +OutputIt write_nonfinite(OutputIt out, bool isinf, + const basic_format_specs& specs, + const float_specs& fspecs) { + auto str = + isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan"); + constexpr size_t str_size = 3; + auto sign = fspecs.sign; + auto size = str_size + (sign ? 1 : 0); + using iterator = remove_reference_t; + return write_padded(out, specs, size, [=](iterator it) { + if (sign) *it++ = static_cast(data::signs[sign]); + return copy_str(str, str + str_size, it); + }); +} + +// A decimal floating-point number significand * pow(10, exp). +struct big_decimal_fp { + const char* significand; + int significand_size; + int exponent; +}; + +inline int get_significand_size(const big_decimal_fp& fp) { + return fp.significand_size; +} +template +inline int get_significand_size(const dragonbox::decimal_fp& fp) { + return count_digits(fp.significand); +} + +template +inline OutputIt write_significand(OutputIt out, const char* significand, + int& significand_size) { + return copy_str(significand, significand + significand_size, out); +} +template +inline OutputIt write_significand(OutputIt out, UInt significand, + int significand_size) { + return format_decimal(out, significand, significand_size).end; +} + +template ::value)> +inline Char* write_significand(Char* out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) { + if (!decimal_point) + return format_decimal(out, significand, significand_size).end; + auto end = format_decimal(out + 1, significand, significand_size).end; + if (integral_size == 1) + out[0] = out[1]; + else + std::copy_n(out + 1, integral_size, out); + out[integral_size] = decimal_point; + return end; +} + +template >::value)> +inline OutputIt write_significand(OutputIt out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) { + // Buffer is large enough to hold digits (digits10 + 1) and a decimal point. + Char buffer[digits10() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_str(buffer, end, out); +} + +template +inline OutputIt write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) { + out = detail::copy_str(significand, significand + integral_size, out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_str(significand + integral_size, + significand + significand_size, out); +} + +template +OutputIt write_float(OutputIt out, const DecimalFP& fp, + const basic_format_specs& specs, float_specs fspecs, + Char decimal_point) { + auto significand = fp.significand; + int significand_size = get_significand_size(fp); + static const Char zero = static_cast('0'); + auto sign = fspecs.sign; + size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); + using iterator = remove_reference_t; + + int output_exp = fp.exponent + significand_size - 1; + auto use_exp_format = [=]() { + if (fspecs.format == float_format::exp) return true; + if (fspecs.format != float_format::general) return false; + // Use the fixed notation if the exponent is in [exp_lower, exp_upper), + // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. + const int exp_lower = -4, exp_upper = 16; + return output_exp < exp_lower || + output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); + }; + if (use_exp_format()) { + int num_zeros = 0; + if (fspecs.showpoint) { + num_zeros = (std::max)(fspecs.precision - significand_size, 0); + size += to_unsigned(num_zeros); + } else if (significand_size == 1) { + decimal_point = Char(); + } + auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; + int exp_digits = 2; + if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; + + size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); + char exp_char = fspecs.upper ? 'E' : 'e'; + auto write = [=](iterator it) { + if (sign) *it++ = static_cast(data::signs[sign]); + // Insert a decimal point after the first digit and add an exponent. + it = write_significand(it, significand, significand_size, 1, + decimal_point); + if (num_zeros > 0) it = std::fill_n(it, num_zeros, zero); + *it++ = static_cast(exp_char); + return write_exponent(output_exp, it); + }; + return specs.width > 0 ? write_padded(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = fp.exponent + significand_size; + if (fp.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(fp.exponent); + int num_zeros = fspecs.precision - exp; +#ifdef FMT_FUZZ + if (num_zeros > 5000) + throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); +#endif + if (fspecs.showpoint) { + if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1; + if (num_zeros > 0) size += to_unsigned(num_zeros); + } + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = static_cast(data::signs[sign]); + it = write_significand(it, significand, significand_size); + it = std::fill_n(it, fp.exponent, zero); + if (!fspecs.showpoint) return it; + *it++ = decimal_point; + return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it; + }); + } else if (exp > 0) { + // 1234e-2 -> 12.34[0+] + int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0; + size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = static_cast(data::signs[sign]); + it = write_significand(it, significand, significand_size, exp, + decimal_point); + return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it; + }); + } + // 1234e-6 -> 0.001234 + int num_zeros = -exp; + if (significand_size == 0 && fspecs.precision >= 0 && + fspecs.precision < num_zeros) { + num_zeros = fspecs.precision; + } + size += 2 + to_unsigned(num_zeros); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = static_cast(data::signs[sign]); + *it++ = zero; + if (num_zeros == 0 && significand_size == 0 && !fspecs.showpoint) return it; + *it++ = decimal_point; + it = std::fill_n(it, num_zeros, zero); + return write_significand(it, significand, significand_size); + }); +} + +template ::value)> +OutputIt write(OutputIt out, T value, basic_format_specs specs, + locale_ref loc = {}) { + if (const_check(!is_supported_floating_point(value))) return out; + float_specs fspecs = parse_float_type_spec(specs); + fspecs.sign = specs.sign; + if (std::signbit(value)) { // value < 0 is false for NaN so use signbit. + fspecs.sign = sign::minus; + value = -value; + } else if (fspecs.sign == sign::minus) { + fspecs.sign = sign::none; + } + + if (!std::isfinite(value)) + return write_nonfinite(out, std::isinf(value), specs, fspecs); + + if (specs.align == align::numeric && fspecs.sign) { + auto it = reserve(out, 1); + *it++ = static_cast(data::signs[fspecs.sign]); + out = base_iterator(out, it); + fspecs.sign = sign::none; + if (specs.width != 0) --specs.width; + } + + memory_buffer buffer; + if (fspecs.format == float_format::hex) { + if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]); + snprintf_float(promote_float(value), specs.precision, fspecs, buffer); + return write_bytes(out, {buffer.data(), buffer.size()}, specs); + } + int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6; + if (fspecs.format == float_format::exp) { + if (precision == max_value()) + FMT_THROW(format_error("number is too big")); + else + ++precision; + } + if (const_check(std::is_same())) fspecs.binary32 = true; + fspecs.use_grisu = is_fast_float(); + int exp = format_float(promote_float(value), precision, fspecs, buffer); + fspecs.precision = precision; + Char point = + fspecs.locale ? decimal_point(loc) : static_cast('.'); + auto fp = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; + return write_float(out, fp, specs, fspecs, point); +} + +template ::value)> +OutputIt write(OutputIt out, T value) { + if (const_check(!is_supported_floating_point(value))) return out; + + using floaty = conditional_t::value, double, T>; + using uint = typename dragonbox::float_info::carrier_uint; + auto bits = bit_cast(value); + + auto fspecs = float_specs(); + auto sign_bit = bits & (uint(1) << (num_bits() - 1)); + if (sign_bit != 0) { + fspecs.sign = sign::minus; + value = -value; + } + + static const auto specs = basic_format_specs(); + uint mask = exponent_mask(); + if ((bits & mask) == mask) + return write_nonfinite(out, std::isinf(value), specs, fspecs); + + auto dec = dragonbox::to_decimal(static_cast(value)); + return write_float(out, dec, specs, fspecs, static_cast('.')); +} + +template ::value && + !is_fast_float::value)> +inline OutputIt write(OutputIt out, T value) { + return write(out, value, basic_format_specs()); +} + +template +OutputIt write_char(OutputIt out, Char value, + const basic_format_specs& specs) { + using iterator = remove_reference_t; + return write_padded(out, specs, 1, [=](iterator it) { + *it++ = value; + return it; + }); +} + +template +OutputIt write_ptr(OutputIt out, UIntPtr value, + const basic_format_specs* specs) { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + using iterator = remove_reference_t; + auto write = [=](iterator it) { + *it++ = static_cast('0'); + *it++ = static_cast('x'); + return format_uint<4, Char>(it, value, num_digits); + }; + return specs ? write_padded(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +template struct is_integral : std::is_integral {}; +template <> struct is_integral : std::true_type {}; +template <> struct is_integral : std::true_type {}; + +template +OutputIt write(OutputIt out, monostate) { + FMT_ASSERT(false, ""); + return out; +} + +template ::value)> +OutputIt write(OutputIt out, string_view value) { + auto it = reserve(out, value.size()); + it = copy_str(value.begin(), value.end(), it); + return base_iterator(out, it); +} + +template +OutputIt write(OutputIt out, basic_string_view value) { + auto it = reserve(out, value.size()); + it = std::copy(value.begin(), value.end(), it); + return base_iterator(out, it); +} + +template +buffer_appender write(buffer_appender out, + basic_string_view value) { + get_container(out).append(value.begin(), value.end()); + return out; +} + +template ::value && + !std::is_same::value && + !std::is_same::value)> +OutputIt write(OutputIt out, T value) { + auto abs_value = static_cast>(value); + bool negative = is_negative(value); + // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. + if (negative) abs_value = ~abs_value + 1; + int num_digits = count_digits(abs_value); + auto size = (negative ? 1 : 0) + static_cast(num_digits); + auto it = reserve(out, size); + if (auto ptr = to_pointer(it, size)) { + if (negative) *ptr++ = static_cast('-'); + format_decimal(ptr, abs_value, num_digits); + return out; + } + if (negative) *it++ = static_cast('-'); + it = format_decimal(it, abs_value, num_digits).end; + return base_iterator(out, it); +} + +template +OutputIt write(OutputIt out, bool value) { + return write(out, string_view(value ? "true" : "false")); +} + +template +OutputIt write(OutputIt out, Char value) { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template +OutputIt write(OutputIt out, const Char* value) { + if (!value) { + FMT_THROW(format_error("string pointer is null")); + } else { + auto length = std::char_traits::length(value); + out = write(out, basic_string_view(value, length)); + } + return out; +} + +template +OutputIt write(OutputIt out, const void* value) { + return write_ptr(out, to_uintptr(value), nullptr); +} + +template +auto write(OutputIt out, const T& value) -> typename std::enable_if< + mapped_type_constant>::value == + type::custom_type, + OutputIt>::type { + using context_type = basic_format_context; + using formatter_type = + conditional_t::value, + typename context_type::template formatter_type, + fallback_formatter>; + context_type ctx(out, {}, {}); + return formatter_type().format(value, ctx); +} + +// An argument visitor that formats the argument and writes it via the output +// iterator. It's a class and not a generic lambda for compatibility with C++11. +template struct default_arg_formatter { + using context = basic_format_context; + + OutputIt out; + basic_format_args args; + locale_ref loc; + + template OutputIt operator()(T value) { + return write(out, value); + } + + OutputIt operator()(typename basic_format_arg::handle handle) { + basic_format_parse_context parse_ctx({}); + basic_format_context format_ctx(out, args, loc); + handle.format(parse_ctx, format_ctx); + return format_ctx.out(); + } +}; + +template +class arg_formatter_base { + public: + using iterator = OutputIt; + using char_type = Char; + using format_specs = basic_format_specs; + + private: + iterator out_; + locale_ref locale_; + format_specs* specs_; + + // Attempts to reserve space for n extra characters in the output range. + // Returns a pointer to the reserved range or a reference to out_. + auto reserve(size_t n) -> decltype(detail::reserve(out_, n)) { + return detail::reserve(out_, n); + } + + using reserve_iterator = remove_reference_t(), 0))>; + + template void write_int(T value, const format_specs& spec) { + using uint_type = uint32_or_64_or_128_t; + int_writer w(out_, locale_, value, spec); + handle_int_type_spec(spec.type, w); + out_ = w.out; + } + + void write(char value) { + auto&& it = reserve(1); + *it++ = value; + } + + template ::value)> + void write(Ch value) { + out_ = detail::write(out_, value); + } + + void write(string_view value) { + auto&& it = reserve(value.size()); + it = copy_str(value.begin(), value.end(), it); + } + void write(wstring_view value) { + static_assert(std::is_same::value, ""); + auto&& it = reserve(value.size()); + it = std::copy(value.begin(), value.end(), it); + } + + template + void write(const Ch* s, size_t size, const format_specs& specs) { + auto width = specs.width != 0 + ? count_code_points(basic_string_view(s, size)) + : 0; + out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) { + return copy_str(s, s + size, it); + }); + } + + template + void write(basic_string_view s, const format_specs& specs = {}) { + out_ = detail::write(out_, s, specs); + } + + void write_pointer(const void* p) { + out_ = write_ptr(out_, to_uintptr(p), specs_); + } + + struct char_spec_handler : ErrorHandler { + arg_formatter_base& formatter; + Char value; + + char_spec_handler(arg_formatter_base& f, Char val) + : formatter(f), value(val) {} + + void on_int() { + // char is only formatted as int if there are specs. + formatter.write_int(static_cast(value), *formatter.specs_); + } + void on_char() { + if (formatter.specs_) + formatter.out_ = write_char(formatter.out_, value, *formatter.specs_); + else + formatter.write(value); + } + }; + + struct cstring_spec_handler : error_handler { + arg_formatter_base& formatter; + const Char* value; + + cstring_spec_handler(arg_formatter_base& f, const Char* val) + : formatter(f), value(val) {} + + void on_string() { formatter.write(value); } + void on_pointer() { formatter.write_pointer(value); } + }; + + protected: + iterator out() { return out_; } + format_specs* specs() { return specs_; } + + void write(bool value) { + if (specs_) + write(string_view(value ? "true" : "false"), *specs_); + else + out_ = detail::write(out_, value); + } + + void write(const Char* value) { + if (!value) { + FMT_THROW(format_error("string pointer is null")); + } else { + auto length = std::char_traits::length(value); + basic_string_view sv(value, length); + specs_ ? write(sv, *specs_) : write(sv); + } + } + + public: + arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc) + : out_(out), locale_(loc), specs_(s) {} + + iterator operator()(monostate) { + FMT_ASSERT(false, "invalid argument type"); + return out_; + } + + template ::value)> + FMT_INLINE iterator operator()(T value) { + if (specs_) + write_int(value, *specs_); + else + out_ = detail::write(out_, value); + return out_; + } + + iterator operator()(Char value) { + handle_char_specs(specs_, + char_spec_handler(*this, static_cast(value))); + return out_; + } + + iterator operator()(bool value) { + if (specs_ && specs_->type) return (*this)(value ? 1 : 0); + write(value != 0); + return out_; + } + + template ::value)> + iterator operator()(T value) { + auto specs = specs_ ? *specs_ : format_specs(); + if (const_check(is_supported_floating_point(value))) + out_ = detail::write(out_, value, specs, locale_); + else + FMT_ASSERT(false, "unsupported float argument type"); + return out_; + } + + iterator operator()(const Char* value) { + if (!specs_) return write(value), out_; + handle_cstring_type_spec(specs_->type, cstring_spec_handler(*this, value)); + return out_; + } + + iterator operator()(basic_string_view value) { + if (specs_) { + check_string_type_spec(specs_->type, error_handler()); + write(value, *specs_); + } else { + write(value); + } + return out_; + } + + iterator operator()(const void* value) { + if (specs_) check_pointer_type_spec(specs_->type, error_handler()); + write_pointer(value); + return out_; + } +}; + +/** The default argument formatter. */ +template +class arg_formatter : public arg_formatter_base { + private: + using char_type = Char; + using base = arg_formatter_base; + using context_type = basic_format_context; + + context_type& ctx_; + basic_format_parse_context* parse_ctx_; + const Char* ptr_; + + public: + using iterator = typename base::iterator; + using format_specs = typename base::format_specs; + + /** + \rst + Constructs an argument formatter object. + *ctx* is a reference to the formatting context, + *specs* contains format specifier information for standard argument types. + \endrst + */ + explicit arg_formatter( + context_type& ctx, + basic_format_parse_context* parse_ctx = nullptr, + format_specs* specs = nullptr, const Char* ptr = nullptr) + : base(ctx.out(), specs, ctx.locale()), + ctx_(ctx), + parse_ctx_(parse_ctx), + ptr_(ptr) {} + + using base::operator(); + + /** Formats an argument of a user-defined type. */ + iterator operator()(typename basic_format_arg::handle handle) { + if (ptr_) advance_to(*parse_ctx_, ptr_); + handle.format(*parse_ctx_, ctx_); + return ctx_.out(); + } +}; + +template FMT_CONSTEXPR bool is_name_start(Char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c; +} + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +template +FMT_CONSTEXPR int parse_nonnegative_int(const Char*& begin, const Char* end, + ErrorHandler&& eh) { + FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); + unsigned value = 0; + // Convert to unsigned to prevent a warning. + constexpr unsigned max_int = max_value(); + unsigned big = max_int / 10; + do { + // Check for overflow. + if (value > big) { + value = max_int + 1; + break; + } + value = value * 10 + unsigned(*begin - '0'); + ++begin; + } while (begin != end && '0' <= *begin && *begin <= '9'); + if (value > max_int) eh.on_error("number is too big"); + return static_cast(value); +} + +template class custom_formatter { + private: + using char_type = typename Context::char_type; + + basic_format_parse_context& parse_ctx_; + Context& ctx_; + + public: + explicit custom_formatter(basic_format_parse_context& parse_ctx, + Context& ctx) + : parse_ctx_(parse_ctx), ctx_(ctx) {} + + void operator()(typename basic_format_arg::handle h) const { + h.format(parse_ctx_, ctx_); + } + + template void operator()(T) const {} +}; + +template +using is_integer = + bool_constant::value && !std::is_same::value && + !std::is_same::value && + !std::is_same::value>; + +template class width_checker { + public: + explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {} + + template ::value)> + FMT_CONSTEXPR unsigned long long operator()(T value) { + if (is_negative(value)) handler_.on_error("negative width"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR unsigned long long operator()(T) { + handler_.on_error("width is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template class precision_checker { + public: + explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {} + + template ::value)> + FMT_CONSTEXPR unsigned long long operator()(T value) { + if (is_negative(value)) handler_.on_error("negative precision"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR unsigned long long operator()(T) { + handler_.on_error("precision is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +// A format specifier handler that sets fields in basic_format_specs. +template class specs_setter { + public: + explicit FMT_CONSTEXPR specs_setter(basic_format_specs& specs) + : specs_(specs) {} + + FMT_CONSTEXPR specs_setter(const specs_setter& other) + : specs_(other.specs_) {} + + FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; } + FMT_CONSTEXPR void on_fill(basic_string_view fill) { + specs_.fill = fill; + } + FMT_CONSTEXPR void on_plus() { specs_.sign = sign::plus; } + FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; } + FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; } + FMT_CONSTEXPR void on_hash() { specs_.alt = true; } + + FMT_CONSTEXPR void on_zero() { + specs_.align = align::numeric; + specs_.fill[0] = Char('0'); + } + + FMT_CONSTEXPR void on_width(int width) { specs_.width = width; } + FMT_CONSTEXPR void on_precision(int precision) { + specs_.precision = precision; + } + FMT_CONSTEXPR void end_precision() {} + + FMT_CONSTEXPR void on_type(Char type) { + specs_.type = static_cast(type); + } + + protected: + basic_format_specs& specs_; +}; + +template class numeric_specs_checker { + public: + FMT_CONSTEXPR numeric_specs_checker(ErrorHandler& eh, detail::type arg_type) + : error_handler_(eh), arg_type_(arg_type) {} + + FMT_CONSTEXPR void require_numeric_argument() { + if (!is_arithmetic_type(arg_type_)) + error_handler_.on_error("format specifier requires numeric argument"); + } + + FMT_CONSTEXPR void check_sign() { + require_numeric_argument(); + if (is_integral_type(arg_type_) && arg_type_ != type::int_type && + arg_type_ != type::long_long_type && arg_type_ != type::char_type) { + error_handler_.on_error("format specifier requires signed argument"); + } + } + + FMT_CONSTEXPR void check_precision() { + if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type) + error_handler_.on_error("precision not allowed for this argument type"); + } + + private: + ErrorHandler& error_handler_; + detail::type arg_type_; +}; + +// A format specifier handler that checks if specifiers are consistent with the +// argument type. +template class specs_checker : public Handler { + private: + numeric_specs_checker checker_; + + // Suppress an MSVC warning about using this in initializer list. + FMT_CONSTEXPR Handler& error_handler() { return *this; } + + public: + FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type) + : Handler(handler), checker_(error_handler(), arg_type) {} + + FMT_CONSTEXPR specs_checker(const specs_checker& other) + : Handler(other), checker_(error_handler(), other.arg_type_) {} + + FMT_CONSTEXPR void on_align(align_t align) { + if (align == align::numeric) checker_.require_numeric_argument(); + Handler::on_align(align); + } + + FMT_CONSTEXPR void on_plus() { + checker_.check_sign(); + Handler::on_plus(); + } + + FMT_CONSTEXPR void on_minus() { + checker_.check_sign(); + Handler::on_minus(); + } + + FMT_CONSTEXPR void on_space() { + checker_.check_sign(); + Handler::on_space(); + } + + FMT_CONSTEXPR void on_hash() { + checker_.require_numeric_argument(); + Handler::on_hash(); + } + + FMT_CONSTEXPR void on_zero() { + checker_.require_numeric_argument(); + Handler::on_zero(); + } + + FMT_CONSTEXPR void end_precision() { checker_.check_precision(); } +}; + +template