Merge branch 'master' into jgrpp-beta

# Conflicts:
#	src/lang/spanish.txt
#	src/network/core/tcp_content_type.h
#	src/network/network_content.cpp
#	src/saveload/cheat_sl.cpp
#	src/saveload/saveload.cpp
#	src/saveload/saveload.h
#	src/saveload/station_sl.cpp
#	src/saveload/vehicle_sl.cpp
#	src/settings.cpp
#	src/settings_internal.h
#	src/table/settings.h.preamble
#	src/table/settings/company_settings.ini
#	src/table/settings/currency_settings.ini
#	src/table/settings/gameopt_settings.ini
#	src/table/settings/misc_settings.ini
#	src/table/settings/settings.ini
#	src/table/settings/win32_settings.ini
#	src/table/settings/window_settings.ini
pull/332/head
Jonathan G Rennison 3 years ago
commit 81290df946

@ -189,8 +189,8 @@ static const CheatEntry _cheats_ui[] = {
{CNM_LOCAL_ONLY, SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat }, {CNM_LOCAL_ONLY, SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat },
{CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat }, {CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat },
{CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_date_ymd.year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, {CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_date_ymd.year, &_cheats.change_date.been_used, &ClickChangeDateCheat },
{CNM_ALL, SLF_NOT_IN_SAVE, STR_CHEAT_INFLATION_COST, &_economy.inflation_prices, &_extra_cheats.inflation_cost.been_used, nullptr }, {CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_COST, &_economy.inflation_prices, &_extra_cheats.inflation_cost.been_used, nullptr },
{CNM_ALL, SLF_NOT_IN_SAVE, STR_CHEAT_INFLATION_INCOME, &_economy.inflation_payment, &_extra_cheats.inflation_income.been_used, nullptr }, {CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_INCOME, &_economy.inflation_payment, &_extra_cheats.inflation_income.been_used, nullptr },
{CNM_ALL, SLE_BOOL, STR_CHEAT_STATION_RATING, &_extra_cheats.station_rating.value, &_extra_cheats.station_rating.been_used, nullptr }, {CNM_ALL, SLE_BOOL, STR_CHEAT_STATION_RATING, &_extra_cheats.station_rating.value, &_extra_cheats.station_rating.been_used, nullptr },
{CNM_ALL, SLE_BOOL, STR_CHEAT_TOWN_RATING, &_extra_cheats.town_rating.value, &_extra_cheats.town_rating.been_used, nullptr }, {CNM_ALL, SLE_BOOL, STR_CHEAT_TOWN_RATING, &_extra_cheats.town_rating.value, &_extra_cheats.town_rating.been_used, nullptr },
}; };
@ -261,7 +261,7 @@ struct CheatWindow : Window {
DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, box_left, y + icon_y_offset + 2); DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, box_left, y + icon_y_offset + 2);
switch (ce->type) { switch (ce->type) {
case SLF_NOT_IN_SAVE: { case SLF_ALLOW_CONTROL: {
/* Change inflation factors */ /* Change inflation factors */
/* Draw [<][>] boxes for settings of an integer-type */ /* Draw [<][>] boxes for settings of an integer-type */
@ -324,7 +324,7 @@ struct CheatWindow : Window {
if (!IsCheatAllowed(ce->mode)) continue; if (!IsCheatAllowed(ce->mode)) continue;
lines++; lines++;
switch (ce->type) { switch (ce->type) {
case SLF_NOT_IN_SAVE: case SLF_ALLOW_CONTROL:
/* Change inflation factors */ /* Change inflation factors */
break; break;
@ -401,7 +401,7 @@ struct CheatWindow : Window {
SetDParam(0, value); SetDParam(0, value);
ShowQueryString(STR_JUST_INT, STR_CHEAT_EDIT_MONEY_QUERY_CAPT, 20, this, CS_NUMERAL_SIGNED, QSF_ACCEPT_UNCHANGED); ShowQueryString(STR_JUST_INT, STR_CHEAT_EDIT_MONEY_QUERY_CAPT, 20, this, CS_NUMERAL_SIGNED, QSF_ACCEPT_UNCHANGED);
return; return;
} else if (ce->type == SLF_NOT_IN_SAVE && x >= 20 + this->box_width + SETTING_BUTTON_WIDTH) { } else if (ce->type == SLF_ALLOW_CONTROL && x >= 20 + this->box_width + SETTING_BUTTON_WIDTH) {
clicked_widget = btn; clicked_widget = btn;
uint64 val = (uint64)ReadValue(ce->variable, SLE_UINT64); uint64 val = (uint64)ReadValue(ce->variable, SLE_UINT64);
SetDParam(0, val * 1000 >> 16); SetDParam(0, val * 1000 >> 16);
@ -420,7 +420,7 @@ struct CheatWindow : Window {
if (!_networking) *ce->been_used = true; if (!_networking) *ce->been_used = true;
switch (ce->type) { switch (ce->type) {
case SLF_NOT_IN_SAVE: { case SLF_ALLOW_CONTROL: {
/* Change inflation factors */ /* Change inflation factors */
uint64 value = (uint64)ReadValue(ce->variable, SLE_UINT64) + (((x >= 10 + this->box_width + SETTING_BUTTON_WIDTH / 2) ? 1 : -1) << 16); uint64 value = (uint64)ReadValue(ce->variable, SLE_UINT64) + (((x >= 10 + this->box_width + SETTING_BUTTON_WIDTH / 2) ? 1 : -1) << 16);
value = Clamp<uint64>(value, 1 << 16, MAX_INFLATION); value = Clamp<uint64>(value, 1 << 16, MAX_INFLATION);
@ -468,7 +468,7 @@ struct CheatWindow : Window {
const CheatEntry *ce = &_cheats_ui[clicked_widget]; const CheatEntry *ce = &_cheats_ui[clicked_widget];
if (ce->type == SLF_NOT_IN_SAVE) { if (ce->type == SLF_ALLOW_CONTROL) {
char tmp_buffer[32]; char tmp_buffer[32];
strecpy(tmp_buffer, str, lastof(tmp_buffer)); strecpy(tmp_buffer, str, lastof(tmp_buffer));
str_replace_wchar(tmp_buffer, lastof(tmp_buffer), GetDecimalSeparatorChar(), '.'); str_replace_wchar(tmp_buffer, lastof(tmp_buffer), GetDecimalSeparatorChar(), '.');

@ -28,12 +28,9 @@ struct Cheats {
Cheat switch_company; ///< change to another company Cheat switch_company; ///< change to another company
Cheat money; ///< get rich or poor Cheat money; ///< get rich or poor
Cheat crossing_tunnels; ///< allow tunnels that cross each other 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 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 change_date; ///< changes date ingame
Cheat setup_prod; ///< setup raw-material production in game 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 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
}; };

@ -1995,7 +1995,7 @@ static void OutputContentState(const ContentInfo *const ci)
char buf[sizeof(ci->md5sum) * 2 + 1]; char buf[sizeof(ci->md5sum) * 2 + 1];
md5sumToString(buf, lastof(buf), ci->md5sum); 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) DEF_CONSOLE_CMD(ConContent)
@ -2065,7 +2065,7 @@ DEF_CONSOLE_CMD(ConContent)
if (strcasecmp(argv[1], "state") == 0) { if (strcasecmp(argv[1], "state") == 0) {
IConsolePrintF(CC_WHITE, "id, type, state, name"); IConsolePrintF(CC_WHITE, "id, type, state, name");
for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) { 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); OutputContentState(*iter);
} }
return true; return true;

@ -2213,7 +2213,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_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_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_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}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_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_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_WRONG_PASSWORD :{WHITE}Contraseña incorrecta
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo

@ -67,6 +67,12 @@ 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_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_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_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 = 64; ///< 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 static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF

@ -373,37 +373,6 @@ uint64 Packet::Recv_uint64()
return n; 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<PacketSize>::max());
this->pos = static_cast<PacketSize>(pos);
StrMakeValidInPlace(bufp, last, settings);
}
/** /**
* Reads characters (bytes) from the packet until it finds a '\0', or reaches a * Reads characters (bytes) from the packet until it finds a '\0', or reaches a
* maximum of \c length characters. * maximum of \c length characters.

@ -87,7 +87,6 @@ public:
uint16 Recv_uint16(); uint16 Recv_uint16();
uint32 Recv_uint32(); uint32 Recv_uint32();
uint64 Recv_uint64(); 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); std::string Recv_string(size_t length, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void Recv_string(std::string &buffer, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void Recv_string(std::string &buffer, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void Recv_binary(char *buffer, size_t size); void Recv_binary(char *buffer, size_t size);

@ -20,50 +20,6 @@
#include "../../safeguards.h" #include "../../safeguards.h"
/** Clear everything in the struct */
ContentInfo::ContentInfo()
{
memset(this, 0, sizeof(*this));
}
/** Free everything allocated */
ContentInfo::~ContentInfo()
{
free(this->dependencies);
free(this->tags);
}
/**
* 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) {
free(this->dependencies);
free(this->tags);
memcpy(this, other, sizeof(ContentInfo));
other->dependencies = nullptr;
other->tags = nullptr;
}
}
/**
* 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? * Is the state either selected or autoselected?
* @return true iff that's the case * @return true iff that's the case

@ -26,6 +26,7 @@ enum ContentType {
CONTENT_TYPE_GAME = 9, ///< The content consists of a game script 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_GAME_LIBRARY = 10, ///< The content consists of a GS library
CONTENT_TYPE_END, ///< Helper to mark the end of the types 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 **/ /** Enum with all types of TCP content packets. The order MUST not be changed **/
@ -57,29 +58,21 @@ struct ContentInfo {
INVALID, ///< The content's invalid INVALID, ///< The content's invalid
}; };
ContentType type; ///< Type of content ContentType type = INVALID_CONTENT_TYPE; ///< Type of content
ContentID id; ///< Unique (server side) ID for the content ContentID id = INVALID_CONTENT_ID; ///< Unique (server side) ID for the content
uint32 filesize; ///< Size of the file uint32 filesize = 0; ///< Size of the file
char filename[48]; ///< Filename (for the .tar.gz; only valid on download) std::string filename; ///< Filename (for the .tar.gz; only valid on download)
char name[64]; ///< Name of the content std::string name; ///< Name of the content
char version[16]; ///< Version of the content std::string version; ///< Version of the content
char url[96]; ///< URL related to the content std::string url; ///< URL related to the content
char description[512]; ///< Description of the content std::string description; ///< Description of the content
uint32 unique_id; ///< Unique ID; either GRF ID or shortname uint32 unique_id = 0; ///< Unique ID; either GRF ID or shortname
byte md5sum[16]; ///< The MD5 checksum byte md5sum[16] = {0}; ///< The MD5 checksum
uint8 dependency_count; ///< Number of dependencies std::vector<ContentID> dependencies; ///< The dependencies (unique server side ids)
ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids) StringList tags; ///< Tags associated with the content
uint8 tag_count; ///< Number of tags State state = State::UNSELECTED; ///< Whether the content info is selected (for download)
char (*tags)[32]; ///< Malloced array of tags (strings) bool upgrade = false; ///< This item is an upgrade
State state; ///< Whether the content info is selected (for download)
bool upgrade; ///< This item is an upgrade
ContentInfo();
~ContentInfo();
void TransferFrom(ContentInfo *other);
size_t Size() const;
bool IsSelected() const; bool IsSelected() const;
bool IsValid() const; bool IsValid() const;
const char *GetTextfile(TextfileType type) const; const char *GetTextfile(TextfileType type) const;

@ -56,26 +56,27 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p)
ci->id = (ContentID)p->Recv_uint32(); ci->id = (ContentID)p->Recv_uint32();
ci->filesize = p->Recv_uint32(); ci->filesize = p->Recv_uint32();
p->Recv_string(ci->name, lengthof(ci->name)); ci->name = p->Recv_string(NETWORK_CONTENT_NAME_LENGTH);
p->Recv_string(ci->version, lengthof(ci->version)); ci->version = p->Recv_string(NETWORK_CONTENT_VERSION_LENGTH);
p->Recv_string(ci->url, lengthof(ci->url)); ci->url = p->Recv_string(NETWORK_CONTENT_URL_LENGTH);
p->Recv_string(ci->description, lengthof(ci->description), SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); ci->description = p->Recv_string(NETWORK_CONTENT_DESC_LENGTH, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
ci->unique_id = p->Recv_uint32(); ci->unique_id = p->Recv_uint32();
for (uint j = 0; j < sizeof(ci->md5sum); j++) { for (uint j = 0; j < sizeof(ci->md5sum); j++) {
ci->md5sum[j] = p->Recv_uint8(); ci->md5sum[j] = p->Recv_uint8();
} }
ci->dependency_count = p->Recv_uint8(); uint dependency_count = p->Recv_uint8();
ci->dependencies = MallocT<ContentID>(ci->dependency_count); ci->dependencies.reserve(dependency_count);
for (uint i = 0; i < ci->dependency_count; i++) { for (uint i = 0; i < dependency_count; i++) {
ci->dependencies[i] = (ContentID)p->Recv_uint32(); ContentID cid = (ContentID)p->Recv_uint32();
this->reverse_dependency_map.insert({ ci->dependencies[i], ci->id }); ci->dependencies.push_back(cid);
this->reverse_dependency_map.insert({ cid, ci->id });
} }
ci->tag_count = p->Recv_uint8(); uint tag_count = p->Recv_uint8();
ci->tags = MallocT<char[32]>(ci->tag_count); ci->tags.reserve(tag_count);
for (uint i = 0; i < ci->tag_count; i++) p->Recv_string(ci->tags[i], lengthof(*ci->tags)); for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p->Recv_string(NETWORK_CONTENT_TAG_LENGTH));
if (!ci->IsValid()) { if (!ci->IsValid()) {
delete ci; delete ci;
@ -146,16 +147,15 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p)
if (ici->type == ci->type && ici->unique_id == ci->unique_id && if (ici->type == ci->type && ici->unique_id == ci->unique_id &&
memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) { memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) {
/* Preserve the name if possible */ /* 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; if (ici->IsSelected()) ci->state = ici->state;
/* /*
* As ici might be selected by the content window we cannot delete that. * 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 * However, we want to keep most of the values of ci, except the values
* we (just) already preserved. * we (just) already preserved.
* So transfer data and ownership of allocated memory from ci to ici.
*/ */
ici->TransferFrom(ci); *ici = *ci;
delete ci; delete ci;
this->OnReceiveContentInfo(ici); this->OnReceiveContentInfo(ici);
@ -509,7 +509,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p)
this->curInfo->type = (ContentType)p->Recv_uint8(); this->curInfo->type = (ContentType)p->Recv_uint8();
this->curInfo->id = (ContentID)p->Recv_uint32(); this->curInfo->id = (ContentID)p->Recv_uint32();
this->curInfo->filesize = 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()) { if (!this->BeforeDownload()) {
this->CloseConnection(); this->CloseConnection();
@ -728,7 +728,7 @@ void ClientNetworkContentSocketHandler::OnReceiveData(const char *data, size_t l
} }
/* Copy the string, without extension, to the filename. */ /* 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. */ /* Request the next file. */
if (!this->BeforeDownload()) { if (!this->BeforeDownload()) {
@ -988,10 +988,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
/* Selection is easy; just walk all children and set the /* Selection is easy; just walk all children and set the
* autoselected state. That way we can see what we automatically * autoselected state. That way we can see what we automatically
* selected and thus can unselect when a dependency is removed. */ * selected and thus can unselect when a dependency is removed. */
for (uint i = 0; i < ci->dependency_count; i++) { for (auto &dependency : ci->dependencies) {
ContentInfo *c = this->GetContent(ci->dependencies[i]); ContentInfo *c = this->GetContent(dependency);
if (c == nullptr) { if (c == nullptr) {
this->DownloadContentInfo(ci->dependencies[i]); this->DownloadContentInfo(dependency);
} else if (c->state == ContentInfo::UNSELECTED) { } else if (c->state == ContentInfo::UNSELECTED) {
c->state = ContentInfo::AUTOSELECTED; c->state = ContentInfo::AUTOSELECTED;
this->CheckDependencyState(c); this->CheckDependencyState(c);
@ -1014,10 +1014,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
this->Unselect(c->id); this->Unselect(c->id);
} }
for (uint i = 0; i < ci->dependency_count; i++) { for (auto &dependency : ci->dependencies) {
const ContentInfo *c = this->GetContent(ci->dependencies[i]); const ContentInfo *c = this->GetContent(dependency);
if (c == nullptr) { if (c == nullptr) {
DownloadContentInfo(ci->dependencies[i]); DownloadContentInfo(dependency);
continue; continue;
} }
if (c->state != ContentInfo::AUTOSELECTED) continue; if (c->state != ContentInfo::AUTOSELECTED) continue;

@ -146,7 +146,7 @@ void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widge
void BaseNetworkContentDownloadStatusWindow::OnDownloadProgress(const ContentInfo *ci, int bytes) void BaseNetworkContentDownloadStatusWindow::OnDownloadProgress(const ContentInfo *ci, int bytes)
{ {
if (ci->id != this->cur_id) { 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->cur_id = ci->id;
this->downloaded_files++; this->downloaded_files++;
} }
@ -406,7 +406,7 @@ class NetworkContentListWindow : public Window, ContentCallback {
/** Sort content by name. */ /** Sort content by name. */
static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b) 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. */ /** Sort content by type. */
@ -441,10 +441,9 @@ class NetworkContentListWindow : public Window, ContentCallback {
static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter) static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
{ {
filter.string_filter.ResetState(); filter.string_filter.ResetState();
for (int i = 0; i < (*a)->tag_count; i++) { for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag.c_str());
filter.string_filter.AddLine((*a)->tags[i]);
} filter.string_filter.AddLine((*a)->name.c_str());
filter.string_filter.AddLine((*a)->name);
return filter.string_filter.GetState(); return filter.string_filter.GetState();
} }
@ -702,17 +701,17 @@ public:
SetDParamStr(0, this->selected->name); SetDParamStr(0, this->selected->name);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_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); SetDParamStr(0, this->selected->version);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_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); SetDParamStr(0, this->selected->description);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_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); SetDParamStr(0, this->selected->url);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL);
} }
@ -724,20 +723,18 @@ public:
SetDParam(0, this->selected->filesize); SetDParam(0, this->selected->filesize);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_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 */ /* List dependencies */
char buf[DRAW_STRING_BUFFER] = ""; char buf[DRAW_STRING_BUFFER] = "";
char *p = buf; char *p = buf;
for (uint i = 0; i < this->selected->dependency_count; i++) { for (auto &cid : this->selected->dependencies) {
ContentID cid = this->selected->dependencies[i];
/* Try to find the dependency */ /* Try to find the dependency */
ConstContentIterator iter = _network_content_client.Begin(); ConstContentIterator iter = _network_content_client.Begin();
for (; iter != _network_content_client.End(); iter++) { for (; iter != _network_content_client.End(); iter++) {
const ContentInfo *ci = *iter; const ContentInfo *ci = *iter;
if (ci->id != cid) continue; 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; break;
} }
} }
@ -745,12 +742,12 @@ public:
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES); 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 */ /* List all tags */
char buf[DRAW_STRING_BUFFER] = ""; char buf[DRAW_STRING_BUFFER] = "";
char *p = buf; char *p = buf;
for (uint i = 0; i < this->selected->tag_count; i++) { for (auto &tag : this->selected->tags) {
p += seprintf(p, lastof(buf), i == 0 ? "%s" : ", %s", this->selected->tags[i]); p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", tag.c_str());
} }
SetDParamStr(0, buf); SetDParamStr(0, buf);
y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS); y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS);
@ -766,7 +763,7 @@ public:
for (const ContentInfo *ci : tree) { for (const ContentInfo *ci : tree) {
if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue; 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) { if (p != buf) {
SetDParamStr(0, buf); SetDParamStr(0, buf);
@ -843,7 +840,7 @@ public:
case WID_NCL_OPEN_URL: case WID_NCL_OPEN_URL:
if (this->selected != nullptr) { if (this->selected != nullptr) {
extern void OpenBrowser(const char *url); extern void OpenBrowser(const char *url);
OpenBrowser(this->selected->url); OpenBrowser(this->selected->url.c_str());
} }
break; break;
@ -984,7 +981,7 @@ public:
this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0); this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0);
this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all); this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade); 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++) { 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); this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr);
} }

@ -928,13 +928,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
char client_revision[NETWORK_REVISION_LENGTH]; std::string client_revision = p->Recv_string(NETWORK_REVISION_LENGTH);
p->Recv_string(client_revision, sizeof(client_revision));
uint32 newgrf_version = p->Recv_uint32(); uint32 newgrf_version = p->Recv_uint32();
/* Check if the client has revision control enabled */ /* 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!! */ /* Different revisions!! */
return this->SendError(NETWORK_ERROR_WRONG_REVISION); return this->SendError(NETWORK_ERROR_WRONG_REVISION);
} }
@ -1048,11 +1046,10 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SETTINGS_PASSWO
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
char password[NETWORK_PASSWORD_LENGTH]; std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH);
p->Recv_string(password, sizeof(password));
/* Check settings password. Deny if no password is set */ /* Check settings password. Deny if no password is set */
if (StrEmpty(password)) { if (password.empty()) {
if (this->settings_authed) DEBUG(net, 0, "[settings-ctrl] client-id %d deauthed", this->client_id); if (this->settings_authed) DEBUG(net, 0, "[settings-ctrl] client-id %d deauthed", this->client_id);
this->settings_authed = false; this->settings_authed = false;
} else if (_settings_client.network.settings_password.empty() || } else if (_settings_client.network.settings_password.empty() ||

@ -505,15 +505,14 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
if (num_grfs > NETWORK_MAX_GRF_COUNT) return; if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
for (i = 0; i < num_grfs; i++) { for (i = 0; i < num_grfs; i++) {
char name[NETWORK_GRF_NAME_LENGTH];
GRFIdentifier c; GRFIdentifier c;
DeserializeGRFIdentifier(p, &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 /* An empty name is not possible under normal circumstances
* and causes problems when showing the NewGRF list. */ * 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. /* 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 * If it exists and not resolved yet, then name of the fake GRF is

@ -1554,7 +1554,7 @@ void ShowMissingContentWindow(const GRFConfig *list)
ContentInfo *ci = new ContentInfo(); ContentInfo *ci = new ContentInfo();
ci->type = CONTENT_TYPE_NEWGRF; ci->type = CONTENT_TYPE_NEWGRF;
ci->state = ContentInfo::DOES_NOT_EXIST; 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); ci->unique_id = BSWAP32(c->ident.grfid);
memcpy(ci->md5sum, HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum, sizeof(ci->md5sum)); memcpy(ci->md5sum, HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum, sizeof(ci->md5sum));
cv.push_back(ci); cv.push_back(ci);

@ -543,10 +543,10 @@ void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allo
* @param list The list where the text should be added to. * @param list The list where the text should be added to.
* @param text_to_add The text to add to the list. * @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()); if (!list) list.reset(new GRFTextList());
AddGRFTextToList(*list, GRFLX_UNSPECIFIED, std::string(text_to_add)); AddGRFTextToList(*list, GRFLX_UNSPECIFIED, text_to_add);
} }
/** /**

@ -44,7 +44,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); 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(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, 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); bool CheckGrfLangID(byte lang_id, byte grf_version);

@ -32,21 +32,38 @@ static ExtraCheatNameDesc _extra_cheat_descs[] = {
{ "town_rating", &_extra_cheats.town_rating }, { "town_rating", &_extra_cheats.town_rating },
}; };
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. * Save the cheat values.
*/ */
static void Save_CHTS() static void Save_CHTS()
{ {
/* Cannot use lengthof because _cheats is of type Cheats, not Cheat */ SlSetLength(std::size(_cheats_desc));
byte count = sizeof(_cheats) / sizeof(Cheat); SlObject(&_cheats, _cheats_desc);
Cheat *cht = (Cheat*) &_cheats;
Cheat *cht_last = &cht[count];
SlSetLength(count * 2);
for (; cht != cht_last; cht++) {
SlWriteByte(cht->been_used);
SlWriteByte(cht->value);
}
} }
/** /**
@ -54,15 +71,21 @@ static void Save_CHTS()
*/ */
static void Load_CHTS() static void Load_CHTS()
{ {
Cheat *cht = (Cheat*)&_cheats; size_t count = SlGetFieldLength();
size_t count = SlGetFieldLength() / 2; std::vector<SaveLoad> slt;
/* Cannot use lengthof because _cheats is of type Cheats, not Cheat */
if (count > sizeof(_cheats) / sizeof(Cheat)) SlErrorCorrupt("Too many cheat values"); /* 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
for (uint i = 0; i < count; i++) { * are stored for this savegame. So read only "count" SLE_BOOLs (and in
cht[i].been_used = (SlReadByte() != 0); * result "count / 2" cheats). */
cht[i].value = (SlReadByte() != 0); for (auto &sld : _cheats_desc) {
count--;
slt.push_back(sld);
if (count == 0) break;
} }
SlObject(&_cheats, slt);
} }
/** /**

@ -100,8 +100,8 @@ SaveLoadTable GetLinkGraphJobDesc()
SaveLoadTable GetLinkGraphScheduleDesc() SaveLoadTable GetLinkGraphScheduleDesc()
{ {
static const SaveLoad schedule_desc[] = { static const SaveLoad schedule_desc[] = {
SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH), SLE_REFLIST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB), SLE_REFLIST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB),
}; };
return schedule_desc; return schedule_desc;
} }

@ -691,17 +691,17 @@ static inline uint SlGetArrayLength(size_t length)
static inline 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}; 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_STRB:
case SLE_VAR_STR: case SLE_VAR_STR:
case SLE_VAR_STRQ: case SLE_VAR_STRQ:
return SlReadArrayLength(); return SlReadArrayLength();
default: default:
assert(length < lengthof(conv_mem_size)); uint8 type = GetVarMemType(conv) >> 4;
return conv_mem_size[length]; assert(type < lengthof(conv_mem_size));
return conv_mem_size[type];
} }
} }
@ -713,11 +713,11 @@ static inline uint SlCalcConvMemLen(VarType conv)
*/ */
static inline byte SlCalcConvFileLen(VarType conv) static inline byte SlCalcConvFileLen(VarType conv)
{ {
byte length = GB(conv, 0, 4); uint8 type = GetVarFileType(conv);
if (length == SLE_FILE_VEHORDERID) return SlXvIsFeaturePresent(XSLFI_MORE_VEHICLE_ORDERS) ? 2 : 1; if (type == SLE_FILE_VEHORDERID) return SlXvIsFeaturePresent(XSLFI_MORE_VEHICLE_ORDERS) ? 2 : 1;
static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2}; static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
assert(length < lengthof(conv_file_size)); assert(type < lengthof(conv_file_size));
return conv_file_size[length]; return conv_file_size[type];
} }
/** Return the size in bytes of a reference (pointer) */ /** Return the size in bytes of a reference (pointer) */
@ -1083,6 +1083,9 @@ static void SlString(void *ptr, size_t length, VarType conv)
switch (GetVarMemType(conv)) { switch (GetVarMemType(conv)) {
default: NOT_REACHED(); default: NOT_REACHED();
case SLE_VAR_NULL:
SlSkipBytes(len);
return;
case SLE_VAR_STRB: case SLE_VAR_STRB:
if (len >= length) { if (len >= length) {
DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating"); DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
@ -1143,6 +1146,11 @@ static void SlStdString(std::string &str, VarType conv)
case SLA_LOAD_CHECK: case SLA_LOAD_CHECK:
case SLA_LOAD: { case SLA_LOAD: {
size_t len = SlReadArrayLength(); size_t len = SlReadArrayLength();
if (GetVarMemType(conv) == SLE_VAR_NULL) {
SlSkipBytes(len);
return;
}
str.resize(len); str.resize(len);
SlCopyBytes(str.data(), len); SlCopyBytes(str.data(), len);
@ -1345,11 +1353,124 @@ static void *IntToReference(size_t index, SLRefType rt)
} }
/** /**
* Return the size in bytes of a list * Handle conversion for references.
* @param list The std::list to find the size of * @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.
*/
template <template<typename, typename> typename Tstorage, typename Tvar, typename Tallocator = std::allocator<Tvar>>
class SlStorageHelper {
typedef Tstorage<Tvar, Tallocator> 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
* @param cmd The SaveLoadType ware are saving/loading.
*/
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<const SlStorageT *>(storage);
int type_size = SlCalcConvFileLen(SLE_FILE_U32); // Size of the length of the list.
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.
* @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<SlStorageT *>(storage);
switch (_sl.action) {
case SLA_SAVE:
SlWriteUint32((uint32)list->size());
for (auto &item : *list) {
SlSaveLoadMember(cmd, &item, conv);
}
break;
case SLA_LOAD_CHECK:
case SLA_LOAD: {
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();
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.
* @param conv VarType type of variable that is used for calculating the size.
*/ */
template<typename PtrList> template<typename PtrList>
static inline size_t SlCalcListLen(const void *list) static inline size_t SlCalcRefListLen(const void *list)
{ {
const PtrList *l = (const PtrList *) list; const PtrList *l = (const PtrList *) list;
@ -1374,15 +1495,15 @@ static inline size_t SlCalcVarListLen(const void *list, size_t item_size)
/** /**
* Save/Load a list. * Save/Load a list.
* @param list The list being manipulated * @param list The list being manipulated.
* @param conv SLRefType type of the list (Vehicle *, Station *, etc) * @param conv VarType type of variable that is used for calculating the size.
*/ */
template<typename PtrList> template<typename PtrList>
static void SlList(void *list, SLRefType conv) static void SlRefList(void *list, SLRefType conv)
{ {
/* Automatically calculate the length? */ /* Automatically calculate the length? */
if (_sl.need_length != NL_NONE) { if (_sl.need_length != NL_NONE) {
SlSetLength(SlCalcListLen<PtrList>(list)); SlSetLength(SlCalcRefListLen<PtrList>(list));
} }
PtrList *l = (PtrList *)list; PtrList *l = (PtrList *)list;
@ -1475,70 +1596,6 @@ static void SlVarList(void *list, VarType conv)
} }
} }
/**
* Template class to help with std::deque.
*/
template <typename T>
class SlDequeHelper {
typedef std::deque<T> 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. * Return the size in bytes of a std::deque.
* @param deque The std::deque to find the size of * @param deque The std::deque to find the size of
@ -1547,25 +1604,19 @@ public:
static inline size_t SlCalcDequeLen(const void *deque, VarType conv) static inline size_t SlCalcDequeLen(const void *deque, VarType conv)
{ {
switch (GetVarMemType(conv)) { switch (GetVarMemType(conv)) {
case SLE_VAR_BL: case SLE_VAR_BL: return SlStorageHelper<std::deque, bool>::SlCalcLen(deque, conv);
return SlDequeHelper<bool>::SlCalcDequeLen(deque, conv); case SLE_VAR_I8: return SlStorageHelper<std::deque, int8>::SlCalcLen(deque, conv);
case SLE_VAR_I8: case SLE_VAR_U8: return SlStorageHelper<std::deque, uint8>::SlCalcLen(deque, conv);
case SLE_VAR_U8: case SLE_VAR_I16: return SlStorageHelper<std::deque, int16>::SlCalcLen(deque, conv);
return SlDequeHelper<uint8>::SlCalcDequeLen(deque, conv); case SLE_VAR_U16: return SlStorageHelper<std::deque, uint16>::SlCalcLen(deque, conv);
case SLE_VAR_I16: case SLE_VAR_I32: return SlStorageHelper<std::deque, int32>::SlCalcLen(deque, conv);
case SLE_VAR_U16: case SLE_VAR_U32: return SlStorageHelper<std::deque, uint32>::SlCalcLen(deque, conv);
return SlDequeHelper<uint16>::SlCalcDequeLen(deque, conv); case SLE_VAR_I64: return SlStorageHelper<std::deque, int64>::SlCalcLen(deque, conv);
case SLE_VAR_I32: case SLE_VAR_U64: return SlStorageHelper<std::deque, uint64>::SlCalcLen(deque, conv);
case SLE_VAR_U32:
return SlDequeHelper<uint32>::SlCalcDequeLen(deque, conv);
case SLE_VAR_I64:
case SLE_VAR_U64:
return SlDequeHelper<uint64>::SlCalcDequeLen(deque, conv);
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
/** /**
* Save/load a std::deque. * Save/load a std::deque.
* @param deque The std::deque being manipulated * @param deque The std::deque being manipulated
@ -1574,52 +1625,23 @@ static inline size_t SlCalcDequeLen(const void *deque, VarType conv)
static void SlDeque(void *deque, VarType conv) static void SlDeque(void *deque, VarType conv)
{ {
switch (GetVarMemType(conv)) { switch (GetVarMemType(conv)) {
case SLE_VAR_BL: case SLE_VAR_BL: SlStorageHelper<std::deque, bool>::SlSaveLoad(deque, conv); break;
SlDequeHelper<bool>::SlDeque(deque, conv); case SLE_VAR_I8: SlStorageHelper<std::deque, int8>::SlSaveLoad(deque, conv); break;
break; case SLE_VAR_U8: SlStorageHelper<std::deque, uint8>::SlSaveLoad(deque, conv); break;
case SLE_VAR_I8: case SLE_VAR_I16: SlStorageHelper<std::deque, int16>::SlSaveLoad(deque, conv); break;
case SLE_VAR_U8: case SLE_VAR_U16: SlStorageHelper<std::deque, uint16>::SlSaveLoad(deque, conv); break;
SlDequeHelper<uint8>::SlDeque(deque, conv); case SLE_VAR_I32: SlStorageHelper<std::deque, int32>::SlSaveLoad(deque, conv); break;
break; case SLE_VAR_U32: SlStorageHelper<std::deque, uint32>::SlSaveLoad(deque, conv); break;
case SLE_VAR_I16: case SLE_VAR_I64: SlStorageHelper<std::deque, int64>::SlSaveLoad(deque, conv); break;
case SLE_VAR_U16: case SLE_VAR_U64: SlStorageHelper<std::deque, uint64>::SlSaveLoad(deque, conv); break;
SlDequeHelper<uint16>::SlDeque(deque, conv);
break;
case SLE_VAR_I32:
case SLE_VAR_U32:
SlDequeHelper<uint32>::SlDeque(deque, conv);
break;
case SLE_VAR_I64:
case SLE_VAR_U64:
SlDequeHelper<uint64>::SlDeque(deque, conv);
break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
/** Are we going to save this object or not? */ /** Are we going to save this object or not? */
static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld)
{ {
if (!sld.ext_feature_test.IsFeaturePresent(_sl_version, sld.version_from, sld.version_to)) return false; return sld.ext_feature_test.IsFeaturePresent(_sl_version, sld.version_from, sld.version_to);
if (sld.conv & SLF_NOT_IN_SAVE) return false;
return true;
}
/**
* 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;
} }
/** /**
@ -1648,7 +1670,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld)
case SL_REF: case SL_REF:
case SL_ARR: case SL_ARR:
case SL_STR: case SL_STR:
case SL_LST: case SL_REFLIST:
case SL_PTRDEQ: case SL_PTRDEQ:
case SL_VEC: case SL_VEC:
case SL_DEQUE: case SL_DEQUE:
@ -1662,9 +1684,9 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld)
case SL_REF: return SlCalcRefLen(); case SL_REF: return SlCalcRefLen();
case SL_ARR: return SlCalcArrayLen(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_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv);
case SL_LST: return SlCalcListLen<std::list<void *>>(GetVariableAddress(object, sld)); case SL_REFLIST: return SlCalcRefListLen<std::list<void *>>(GetVariableAddress(object, sld));
case SL_PTRDEQ: return SlCalcListLen<std::deque<void *>>(GetVariableAddress(object, sld)); case SL_PTRDEQ: return SlCalcRefListLen<std::deque<void *>>(GetVariableAddress(object, sld));
case SL_VEC: return SlCalcListLen<std::vector<void *>>(GetVariableAddress(object, sld)); case SL_VEC: return SlCalcRefListLen<std::vector<void *>>(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_VARVEC: { case SL_VARVEC: {
const size_t size_len = SlCalcConvMemLen(sld.conv); const size_t size_len = SlCalcConvMemLen(sld.conv);
@ -1695,6 +1717,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld)
*/ */
[[maybe_unused]] static bool IsVariableSizeRight(const SaveLoad &sld) [[maybe_unused]] static bool IsVariableSizeRight(const SaveLoad &sld)
{ {
if (GetVarMemType(sld.conv) == SLE_VAR_NULL) return true;
switch (sld.cmd) { switch (sld.cmd) {
case SL_VAR: case SL_VAR:
switch (GetVarMemType(sld.conv)) { switch (GetVarMemType(sld.conv)) {
@ -1745,7 +1769,7 @@ static void SlFilterObjectMember(const SaveLoad &sld, std::vector<SaveLoad> &sav
case SL_REF: case SL_REF:
case SL_ARR: case SL_ARR:
case SL_STR: case SL_STR:
case SL_LST: case SL_REFLIST:
case SL_PTRDEQ: case SL_PTRDEQ:
case SL_VEC: case SL_VEC:
case SL_DEQUE: case SL_DEQUE:
@ -1753,7 +1777,6 @@ static void SlFilterObjectMember(const SaveLoad &sld, std::vector<SaveLoad> &sav
case SL_VARVEC: case SL_VARVEC:
/* CONDITIONAL saveload types depend on the savegame version */ /* CONDITIONAL saveload types depend on the savegame version */
if (!SlIsObjectValidInSavegame(sld)) return; if (!SlIsObjectValidInSavegame(sld)) return;
if (SlSkipVariableOnLoad(sld)) return;
switch (_sl.action) { switch (_sl.action) {
case SLA_SAVE: case SLA_SAVE:
@ -1764,7 +1787,7 @@ static void SlFilterObjectMember(const SaveLoad &sld, std::vector<SaveLoad> &sav
case SLA_NULL: case SLA_NULL:
switch (sld.cmd) { switch (sld.cmd) {
case SL_REF: case SL_REF:
case SL_LST: case SL_REFLIST:
case SL_PTRDEQ: case SL_PTRDEQ:
case SL_VEC: case SL_VEC:
break; break;
@ -1815,8 +1838,10 @@ std::vector<SaveLoad> SlFilterObject(const SaveLoadTable &slt)
} }
template <SaveLoadAction action, bool check_version> template <SaveLoadAction action, bool check_version>
bool SlObjectMemberGeneric(void *ptr, const SaveLoad &sld) bool SlObjectMemberGeneric(void *object, const SaveLoad &sld)
{ {
void *ptr = GetVariableAddress(object, sld);
if (check_version) assert(IsVariableSizeRight(sld)); if (check_version) assert(IsVariableSizeRight(sld));
VarType conv = GB(sld.conv, 0, 8); VarType conv = GB(sld.conv, 0, 8);
@ -1825,7 +1850,7 @@ bool SlObjectMemberGeneric(void *ptr, const SaveLoad &sld)
case SL_REF: case SL_REF:
case SL_ARR: case SL_ARR:
case SL_STR: case SL_STR:
case SL_LST: case SL_REFLIST:
case SL_PTRDEQ: case SL_PTRDEQ:
case SL_VEC: case SL_VEC:
case SL_DEQUE: case SL_DEQUE:
@ -1834,7 +1859,6 @@ bool SlObjectMemberGeneric(void *ptr, const SaveLoad &sld)
/* CONDITIONAL saveload types depend on the savegame version */ /* CONDITIONAL saveload types depend on the savegame version */
if (check_version) { if (check_version) {
if (!SlIsObjectValidInSavegame(sld)) return false; if (!SlIsObjectValidInSavegame(sld)) return false;
if (SlSkipVariableOnLoad(sld)) return false;
} }
switch (sld.cmd) { switch (sld.cmd) {
@ -1859,9 +1883,9 @@ bool SlObjectMemberGeneric(void *ptr, const SaveLoad &sld)
break; break;
case SL_ARR: SlArray(ptr, sld.length, conv); break; case SL_ARR: SlArray(ptr, sld.length, conv); break;
case SL_STR: SlString(ptr, sld.length, sld.conv); break; case SL_STR: SlString(ptr, sld.length, sld.conv); break;
case SL_LST: SlList<std::list<void *>>(ptr, (SLRefType)conv); break; case SL_REFLIST: SlRefList<std::list<void *>>(ptr, (SLRefType)conv); break;
case SL_PTRDEQ: SlList<std::deque<void *>>(ptr, (SLRefType)conv); break; case SL_PTRDEQ: SlRefList<std::deque<void *>>(ptr, (SLRefType)conv); break;
case SL_VEC: SlList<std::vector<void *>>(ptr, (SLRefType)conv); break; case SL_VEC: SlRefList<std::vector<void *>>(ptr, (SLRefType)conv); break;
case SL_DEQUE: SlDeque(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break;
case SL_VARVEC: { case SL_VARVEC: {
const size_t size_len = SlCalcConvMemLen(sld.conv); const size_t size_len = SlCalcConvMemLen(sld.conv);
@ -1907,18 +1931,18 @@ bool SlObjectMemberGeneric(void *ptr, const SaveLoad &sld)
return true; return true;
} }
bool SlObjectMember(void *ptr, const SaveLoad &sld) bool SlObjectMember(void *object, const SaveLoad &sld)
{ {
switch (_sl.action) { switch (_sl.action) {
case SLA_SAVE: case SLA_SAVE:
return SlObjectMemberGeneric<SLA_SAVE, true>(ptr, sld); return SlObjectMemberGeneric<SLA_SAVE, true>(object, sld);
case SLA_LOAD_CHECK: case SLA_LOAD_CHECK:
case SLA_LOAD: case SLA_LOAD:
return SlObjectMemberGeneric<SLA_LOAD, true>(ptr, sld); return SlObjectMemberGeneric<SLA_LOAD, true>(object, sld);
case SLA_PTRS: case SLA_PTRS:
return SlObjectMemberGeneric<SLA_PTRS, true>(ptr, sld); return SlObjectMemberGeneric<SLA_PTRS, true>(object, sld);
case SLA_NULL: case SLA_NULL:
return SlObjectMemberGeneric<SLA_NULL, true>(ptr, sld); return SlObjectMemberGeneric<SLA_NULL, true>(object, sld);
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
@ -1936,8 +1960,7 @@ void SlObject(void *object, const SaveLoadTable &slt)
} }
for (auto &sld : slt) { for (auto &sld : slt) {
void *ptr = GetVariableAddress(object, sld); SlObjectMember(object, sld);
SlObjectMember(ptr, sld);
} }
} }
@ -1945,8 +1968,7 @@ template <SaveLoadAction action, bool check_version>
void SlObjectIterateBase(void *object, const SaveLoadTable &slt) void SlObjectIterateBase(void *object, const SaveLoadTable &slt)
{ {
for (auto &sld : slt) { for (auto &sld : slt) {
void *ptr = sld.global ? sld.address : GetVariableAddress(object, sld); SlObjectMemberGeneric<action, check_version>(object, sld);
SlObjectMemberGeneric<action, check_version>(ptr, sld);
} }
} }

@ -538,11 +538,8 @@ enum VarTypes {
/* 8 bits allocated for a maximum of 8 flags /* 8 bits allocated for a maximum of 8 flags
* Flags directing saving/loading of a variable */ * Flags directing saving/loading of a variable */
SLF_NOT_IN_SAVE = 1 << 8, ///< do not save with savegame, basically client-based SLF_ALLOW_CONTROL = 1 << 8, ///< Allow control codes in the strings.
SLF_NOT_IN_CONFIG = 1 << 9, ///< do not save to config file SLF_ALLOW_NEWLINE = 1 << 9, ///< Allow new lines in the strings.
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
}; };
typedef uint32 VarType; typedef uint32 VarType;
@ -551,11 +548,11 @@ typedef uint32 VarType;
enum SaveLoadTypes { enum SaveLoadTypes {
SL_VAR = 0, ///< Save/load a variable. SL_VAR = 0, ///< Save/load a variable.
SL_REF = 1, ///< Save/load a reference. 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_STR = 3, ///< Save/load a string.
SL_LST = 4, ///< Save/load a list. SL_REFLIST = 4, ///< Save/load a list of #SL_REF elements.
SL_DEQUE = 5, ///< Save/load a primitive type deque. SL_DEQUE = 5, ///< Save/load a deque of #SL_VAR elements.
SL_VEC = 6, ///< Save/load a vector. SL_VEC = 6, ///< Save/load a vector of #SL_REF elements.
SL_STDSTR = 7, ///< Save/load a std::string. SL_STDSTR = 7, ///< Save/load a std::string.
/* non-normal save-load types */ /* non-normal save-load types */
@ -563,7 +560,7 @@ enum SaveLoadTypes {
SL_VEH_INCLUDE = 9, SL_VEH_INCLUDE = 9,
SL_ST_INCLUDE = 10, SL_ST_INCLUDE = 10,
SL_PTRDEQ = 13, ///< Save/load a pointer type deque. SL_PTRDEQ = 13, ///< Save/load a deque of #SL_REF elements.
SL_VARVEC = 14, ///< Save/load a primitive type vector. SL_VARVEC = 14, ///< Save/load a primitive type vector.
}; };
@ -628,7 +625,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLE_CONDREF(base, variable, type, from, to) SLE_CONDREF_X(base, variable, type, from, to, SlXvFeatureTest()) #define SLE_CONDREF(base, variable, type, from, to) SLE_CONDREF_X(base, variable, type, from, to, SlXvFeatureTest())
/** /**
* 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 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 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 type Storage of the data in memory and in the savegame.
@ -666,7 +663,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to) #define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to)
/** /**
* 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 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 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 type Storage of the data in memory and in the savegame.
@ -674,8 +671,8 @@ using SaveLoadTable = span<const SaveLoad>;
* @param to Last savegame version that has the list. * @param to Last savegame version that has the list.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field * @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
*/ */
#define SLE_CONDLST_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_LST, base, variable, type, 0, from, to, extver) #define SLE_CONDREFLIST_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_REFLIST, base, variable, type, 0, from, to, extver)
#define SLE_CONDLST(base, variable, type, from, to) SLE_CONDLST_X(base, variable, type, from, to, SlXvFeatureTest()) #define SLE_CONDREFLIST(base, variable, type, from, to) SLE_CONDREFLIST_X(base, variable, type, from, to, SlXvFeatureTest())
/** /**
* Storage of a deque in some savegame versions. * Storage of a deque in some savegame versions.
@ -714,7 +711,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLE_CONDVARVEC(base, variable, type, from, to) SLE_CONDVARVEC_X(base, variable, type, from, to, SlXvFeatureTest()) #define SLE_CONDVARVEC(base, variable, type, from, to) SLE_CONDVARVEC_X(base, variable, type, from, to, SlXvFeatureTest())
/** /**
* 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 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 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 type Storage of the data in memory and in the savegame.
@ -742,7 +739,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLE_REF(base, variable, type) SLE_CONDREF(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) #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 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 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 type Storage of the data in memory and in the savegame.
@ -768,12 +765,12 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLE_SSTR(base, variable, type) SLE_CONDSSTR(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION) #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 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 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 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)
/** /**
* Storage of a deque in every savegame version. * Storage of a deque in every savegame version.
@ -804,7 +801,7 @@ using SaveLoadTable = span<const SaveLoad>;
* @param to Last savegame version that has the empty space. * @param to Last savegame version that has the empty space.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space * @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space
*/ */
#define SLE_CONDNULL_X(length, from, to, extver) SLE_CONDARR_X(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, extver) #define SLE_CONDNULL_X(length, from, to, extver) SLE_CONDARR_X(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, extver)
#define SLE_CONDNULL(length, from, to) SLE_CONDNULL_X(length, from, to, SlXvFeatureTest()) #define SLE_CONDNULL(length, from, to) SLE_CONDNULL_X(length, from, to, SlXvFeatureTest())
/** Translate values ingame to different values in the savegame and vv. */ /** Translate values ingame to different values in the savegame and vv. */
@ -849,7 +846,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLEG_CONDREF(variable, type, from, to) SLEG_CONDREF_X(variable, type, from, to, SlXvFeatureTest()) #define SLEG_CONDREF(variable, type, from, to) SLEG_CONDREF_X(variable, type, from, to, SlXvFeatureTest())
/** /**
* 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 variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame. * @param type Storage of the data in memory and in the savegame.
* @param length Number of elements in the array. * @param length Number of elements in the array.
@ -883,15 +880,15 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to) #define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to)
/** /**
* 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 variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame. * @param type Storage of the data in memory and in the savegame.
* @param from First savegame version that has the list. * @param from First savegame version that has the list.
* @param to Last savegame version that has the list. * @param to Last savegame version that has the list.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field * @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
*/ */
#define SLEG_CONDLST_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_LST, variable, type, 0, from, to, extver) #define SLEG_CONDREFLIST_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_REFLIST, variable, type, 0, from, to, extver)
#define SLEG_CONDLST(variable, type, from, to) SLEG_CONDLST_X(variable, type, from, to, SlXvFeatureTest()) #define SLEG_CONDREFLIST(variable, type, from, to) SLEG_CONDREFLIST_X(variable, type, from, to, SlXvFeatureTest())
/** /**
* Storage of a global deque in some savegame versions. * Storage of a global deque in some savegame versions.
@ -930,7 +927,7 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLEG_REF(variable, type) SLEG_CONDREF(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) #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 variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame. * @param type Storage of the data in memory and in the savegame.
*/ */
@ -951,11 +948,11 @@ using SaveLoadTable = span<const SaveLoad>;
#define SLEG_SSTR(variable, type) SLEG_CONDSSTR(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) #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 variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame. * @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)
/** /**
* Storage of a global deque in every savegame version. * Storage of a global deque in every savegame version.
@ -978,7 +975,7 @@ using SaveLoadTable = span<const SaveLoad>;
* @param to Last savegame version that has the empty space. * @param to Last savegame version that has the empty space.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space * @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space
*/ */
#define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)nullptr, SlXvFeatureTest()} #define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, (void*)nullptr, SlXvFeatureTest()}
/** /**
* Checks whether the savegame is below \a major.\a minor. * Checks whether the savegame is below \a major.\a minor.

@ -238,7 +238,7 @@ static const SaveLoad _town_desc[] = {
SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION), SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION),
SLE_CONDVAR(Town, layout, SLE_UINT8, SLV_113, 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(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(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use

@ -35,7 +35,7 @@
const SettingDesc *sd = GetSettingFromName(setting); 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); return ScriptObject::DoCommand(0, 0, value, CMD_CHANGE_SETTING, sd->name);
} }

@ -596,8 +596,9 @@ bool ScriptInstance::IsPaused()
case SQSL_STRING: { case SQSL_STRING: {
SlObject(nullptr, _script_byte); SlObject(nullptr, _script_byte);
static char buf[256]; static char buf[std::numeric_limits<decltype(_script_sl_byte)>::max()];
SlArray(buf, _script_sl_byte, SLE_CHAR); SlArray(buf, _script_sl_byte, SLE_CHAR);
StrMakeValidInPlace(buf, buf + _script_sl_byte);
if (vm != nullptr) sq_pushstring(vm, buf, -1); if (vm != nullptr) sq_pushstring(vm, buf, -1);
return true; return true;
} }

@ -636,7 +636,7 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co
/* If the setting is not saved to the configuration /* If the setting is not saved to the configuration
* file, just continue with the next setting */ * file, just continue with the next setting */
if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue;
if (sd->save.conv & SLF_NOT_IN_CONFIG) continue; if (sd->flags & SF_NOT_IN_CONFIG) continue;
if (sd->flags & SF_NO_NEWGAME) continue; if (sd->flags & SF_NO_NEWGAME) continue;
/* XXX - wtf is this?? (group override?) */ /* XXX - wtf is this?? (group override?) */
@ -787,7 +787,7 @@ void IniSaveWindowSettings(IniFile *ini, const char *grpname, void *desc)
*/ */
bool SettingDesc::IsEditable(bool do_command) const bool SettingDesc::IsEditable(bool do_command) const
{ {
if (!do_command && !(this->save.conv & SLF_NO_NETWORK_SYNC) && _networking && !(_network_server || _network_settings_access) && !(this->flags & SF_PER_COMPANY)) return false; if (!do_command && !(this->flags & SF_NO_NETWORK_SYNC) && _networking && !(_network_server || _network_settings_access) && !(this->flags & SF_PER_COMPANY)) return false;
if ((this->flags & SF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) 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_NO_NETWORK) && _networking) return false;
if ((this->flags & SF_NEWGAME_ONLY) && if ((this->flags & SF_NEWGAME_ONLY) &&
@ -804,7 +804,7 @@ bool SettingDesc::IsEditable(bool do_command) const
SettingType SettingDesc::GetType() const SettingType SettingDesc::GetType() const
{ {
if (this->flags & SF_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; return (this->flags & SF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME;
} }
/** /**
@ -2331,7 +2331,7 @@ bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame)
* changes its defaults. At least that is the convention we have chosen */ * changes its defaults. At least that is the convention we have chosen */
bool no_newgame = setting->flags & SF_NO_NEWGAME; bool no_newgame = setting->flags & SF_NO_NEWGAME;
if (no_newgame && _game_mode == GM_MENU) return false; if (no_newgame && _game_mode == GM_MENU) return false;
if (setting->save.conv & SLF_NO_NETWORK_SYNC) { if (setting->flags & SF_NO_NETWORK_SYNC) {
if (_game_mode != GM_MENU && !no_newgame) { if (_game_mode != GM_MENU && !no_newgame) {
setting->ChangeValue(&_settings_newgame, value); setting->ChangeValue(&_settings_newgame, value);
} }
@ -2388,7 +2388,7 @@ void SyncCompanySettings()
*/ */
bool SetSettingValue(const StringSettingDesc *sd, std::string value, bool force_newgame) 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) { if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && value.compare("(null)") == 0) {
value.clear(); value.clear();
@ -2565,14 +2565,13 @@ static void LoadSettingsXref(const SettingDesc *osd, void *object) {
sld.version_from = osd->save.version_from; sld.version_from = osd->save.version_from;
sld.version_to = osd->save.version_to; sld.version_to = osd->save.version_to;
sld.ext_feature_test = osd->save.ext_feature_test; sld.ext_feature_test = osd->save.ext_feature_test;
void *ptr = GetVariableAddress(object, sld);
if (!SlObjectMember(ptr, sld)) return; if (!SlObjectMember(object, sld)) return;
int64 val = ReadValue(ptr, sld.conv);
if (osd->xref.conv != nullptr) val = osd->xref.conv(val);
if (setting_xref->IsIntSetting()) { if (setting_xref->IsIntSetting()) {
const IntSettingDesc *int_setting = setting_xref->AsIntSetting(); const IntSettingDesc *int_setting = setting_xref->AsIntSetting();
int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); int64 val = int_setting->Read(object);
if (osd->xref.conv != nullptr) val = osd->xref.conv(val);
int_setting->MakeValueValidAndWrite(object, val);
} }
} }
@ -2587,15 +2586,15 @@ static void LoadSettings(const SettingTable &settings, void *object)
extern SaveLoadVersion _sl_version; extern SaveLoadVersion _sl_version;
for (auto &osd : settings) { for (auto &osd : settings) {
if (osd->flags & SF_NOT_IN_SAVE) continue;
if (osd->patx_name != nullptr) continue; if (osd->patx_name != nullptr) continue;
const SaveLoad &sld = osd->save; const SaveLoad &sld = osd->save;
if (osd->xref.target != nullptr) { if (osd->xref.target != nullptr) {
if (sld.ext_feature_test.IsFeaturePresent(_sl_version, sld.version_from, sld.version_to)) LoadSettingsXref(osd.get(), object); if (sld.ext_feature_test.IsFeaturePresent(_sl_version, sld.version_from, sld.version_to)) LoadSettingsXref(osd.get(), object);
continue; continue;
} }
void *ptr = GetVariableAddress(object, sld);
if (!SlObjectMember(ptr, osd->save)) continue; if (!SlObjectMember(object, osd->save)) continue;
if (osd->IsIntSetting()) { if (osd->IsIntSetting()) {
const IntSettingDesc *int_setting = osd->AsIntSetting(); const IntSettingDesc *int_setting = osd->AsIntSetting();
int_setting->MakeValueValidAndWrite(object, int_setting->Read(object)); int_setting->MakeValueValidAndWrite(object, int_setting->Read(object));
@ -2615,6 +2614,7 @@ static void SaveSettings(const SettingTable &settings, void *object)
* SlCalcLength() because we have a different format. So do this manually */ * SlCalcLength() because we have a different format. So do this manually */
size_t length = 0; size_t length = 0;
for (auto &sd : settings) { for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;
if (sd->patx_name != nullptr) continue; if (sd->patx_name != nullptr) continue;
if (sd->xref.target != nullptr) continue; if (sd->xref.target != nullptr) continue;
length += SlCalcObjMemberLength(object, sd->save); length += SlCalcObjMemberLength(object, sd->save);
@ -2622,9 +2622,10 @@ static void SaveSettings(const SettingTable &settings, void *object)
SlSetLength(length); SlSetLength(length);
for (auto &sd : settings) { for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;
if (sd->patx_name != nullptr) continue; if (sd->patx_name != nullptr) continue;
void *ptr = GetVariableAddress(object, sd->save); if (sd->xref.target != nullptr) continue;
SlObjectMember(ptr, sd->save); SlObjectMember(object, sd->save);
} }
} }
@ -2738,8 +2739,7 @@ static void LoadSettingsPatx(const SettingTable &settings, void *object)
const SettingDesc *setting = (*iter); const SettingDesc *setting = (*iter);
const SaveLoad &sld = setting->save; const SaveLoad &sld = setting->save;
size_t read = SlGetBytesRead(); size_t read = SlGetBytesRead();
void *ptr = GetVariableAddress(object, sld); SlObjectMember(object, sld);
SlObjectMember(ptr, sld);
if (SlGetBytesRead() != read + current_setting.setting_length) { if (SlGetBytesRead() != read + current_setting.setting_length) {
SlErrorCorruptFmt("PATX chunk: setting read length mismatch for setting: '%s'", current_setting.name); SlErrorCorruptFmt("PATX chunk: setting read length mismatch for setting: '%s'", current_setting.name);
} }
@ -2799,8 +2799,7 @@ static void SaveSettingsPatx(const SettingTable &settings, void *object)
current_setting.name = desc->patx_name; current_setting.name = desc->patx_name;
current_setting.setting_length = settings_to_add[i].setting_length; current_setting.setting_length = settings_to_add[i].setting_length;
SlObject(&current_setting, _settings_ext_save_desc); SlObject(&current_setting, _settings_ext_save_desc);
void *ptr = GetVariableAddress(object, desc->save); SlObjectMember(object, desc->save);
SlObjectMember(ptr, desc->save);
} }
} }
@ -2879,8 +2878,7 @@ void LoadSettingsPlyx(bool skip)
// found setting // found setting
const SaveLoad &sld = setting->save; const SaveLoad &sld = setting->save;
size_t read = SlGetBytesRead(); size_t read = SlGetBytesRead();
void *ptr = GetVariableAddress(&(c->settings), sld); SlObjectMember(const_cast<CompanySettings *>(&(c->settings)), sld);
SlObjectMember(ptr, sld);
if (SlGetBytesRead() != read + current_setting.setting_length) { if (SlGetBytesRead() != read + current_setting.setting_length) {
SlErrorCorruptFmt("PLYX chunk: setting read length mismatch for setting: '%s'", current_setting.name); SlErrorCorruptFmt("PLYX chunk: setting read length mismatch for setting: '%s'", current_setting.name);
} }
@ -2958,8 +2956,7 @@ void SaveSettingsPlyx()
current_setting.name = sd->patx_name; current_setting.name = sd->patx_name;
current_setting.setting_length = setting_length; current_setting.setting_length = setting_length;
SlObject(&current_setting, _settings_plyx_desc); SlObject(&current_setting, _settings_plyx_desc);
void *ptr = GetVariableAddress(&(c->settings), sd->save); SlObjectMember(&(c->settings), sd->save);
SlObjectMember(ptr, sd->save);
} }
} }
} }

@ -12,22 +12,25 @@
#include "saveload/saveload.h" #include "saveload/saveload.h"
enum SettingFlag : uint16 { enum SettingFlag : uint32 {
SF_NONE = 0, 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_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_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_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_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_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_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_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_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_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_PER_COMPANY = 1 << 9, ///< This setting can be different for each company (saved in company struct).
SF_DECIMAL1 = 1 << 10,///< display a decimal representation of the setting value divided by 10 SF_NOT_IN_SAVE = 1 << 10, ///< Do not save with savegame, basically client-based.
SF_ENUM = 1 << 11,///< the setting can take one of the values given by an array of struct SettingDescEnumEntry SF_NOT_IN_CONFIG = 1 << 11, ///< Do not save to config file.
SF_NO_NEWGAME = 1 << 12,///< the setting does not apply and is not shown in a new game context SF_NO_NETWORK_SYNC = 1 << 12, ///< Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set).
SF_DEC1SCALE = 1 << 13,///< also display a float representation of the scale of a decimal1 scale parameter SF_DECIMAL1 = 1 << 13, ///< display a decimal representation of the setting value divided by 10
SF_ENUM = 1 << 14, ///< the setting can take one of the values given by an array of struct SettingDescEnumEntry
SF_NO_NEWGAME = 1 << 15, ///< the setting does not apply and is not shown in a new game context
SF_DEC1SCALE = 1 << 16, ///< also display a float representation of the scale of a decimal1 scale parameter
}; };
DECLARE_ENUM_AS_BIT_SET(SettingFlag) DECLARE_ENUM_AS_BIT_SET(SettingFlag)
@ -326,7 +329,7 @@ struct ListSettingDesc : SettingDesc {
/** Placeholder for settings that have been removed, but might still linger in the savegame. */ /** Placeholder for settings that have been removed, but might still linger in the savegame. */
struct NullSettingDesc : SettingDesc { struct NullSettingDesc : SettingDesc {
NullSettingDesc(SaveLoad save) : NullSettingDesc(SaveLoad save) :
SettingDesc(save, "", SF_NONE, nullptr, false, nullptr) {} SettingDesc(save, "", SF_NOT_IN_CONFIG, nullptr, false, nullptr) {}
virtual ~NullSettingDesc() {} virtual ~NullSettingDesc() {}
void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); }

@ -58,67 +58,67 @@ static size_t ConvertLandscape(const char *value);
/* Macros for various objects to go in the configuration file. /* Macros for various objects to go in the configuration file.
* This section is for global variables */ * 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, extver, cat, guiproc, startup, patxname)\ #define SDTG_VAR(name, type, flags, var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(Int, SLEG_GENERAL_X(SL_VAR, var, type | flags, 1, from, to, extver), name, guiflags, guiproc, startup, patxname, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback, nullptr) NSD(Int, SLEG_GENERAL_X(SL_VAR, var, type, 1, from, to, extver), name, flags, guiproc, startup, patxname, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback, nullptr)
#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTG_BOOL(name, flags, var, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(Bool, SLEG_GENERAL_X(SL_VAR, var, SLE_BOOL | flags, 1, from, to, extver), name, guiflags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback) NSD(Bool, SLEG_GENERAL_X(SL_VAR, var, SLE_BOOL, 1, from, to, extver), name, flags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback)
#define SDTG_LIST(name, type, flags, guiflags, var, def, length, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTG_LIST(name, type, flags, var, def, length, from, to, extver, cat, guiproc, startup, patxname)\
NSD(List, SLEG_GENERAL_X(SL_ARR, var, type | flags, length, from, to, extver), name, guiflags, guiproc, startup, patxname, def) NSD(List, SLEG_GENERAL_X(SL_ARR, var, type, length, from, to, extver), name, flags, guiproc, startup, patxname, def)
#define SDTG_SSTR(name, type, flags, guiflags, var, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTG_SSTR(name, type, flags, var, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(String, SLEG_GENERAL_X(SL_STDSTR, var, type | flags, sizeof(var), from, to, extver), name, guiflags, guiproc, startup, patxname, def, max_length, pre_check, post_callback) NSD(String, SLEG_GENERAL_X(SL_STDSTR, var, type, sizeof(var), from, to, extver), name, flags, guiproc, startup, patxname, 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, extver, cat, guiproc, startup, patxname)\ #define SDTG_OMANY(name, type, flags, var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(OneOfMany, SLEG_GENERAL_X(SL_VAR, var, type | flags, 1, from, to, extver), name, guiflags, guiproc, startup, patxname, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) NSD(OneOfMany, SLEG_GENERAL_X(SL_VAR, var, type, 1, from, to, extver), name, flags, guiproc, startup, patxname, 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, extver, cat, guiproc, startup, patxname)\ #define SDTG_MMANY(name, type, flags, var, def, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(ManyOfMany, SLEG_GENERAL_X(SL_VAR, var, type | flags, 1, from, to, extver), name, guiflags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) NSD(ManyOfMany, SLEG_GENERAL_X(SL_VAR, var, type, 1, from, to, extver), name, flags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr)
#define SDTG_NULL(length, from, to, extver)\ #define SDTG_NULL(length, from, to, extver)\
NSD(Null, SLE_CONDNULL_X(length, from, to, extver)) NSD(Null, SLE_CONDNULL_X(length, from, to, extver))
/* Macros for various objects to go in the configuration file. /* Macros for various objects to go in the configuration file.
* This section is for structures where their various members are saved */ * 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, extver, cat, guiproc, startup, patxname)\ #define SDT_VAR(base, var, type, flags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(Int, SLE_GENERAL_X(SL_VAR, base, var, type | flags, 1, from, to, extver), #var, guiflags, guiproc, startup, patxname, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback, nullptr) NSD(Int, SLE_GENERAL_X(SL_VAR, base, var, type, 1, from, to, extver), #var, flags, guiproc, startup, patxname, def, min, max, interval, str, strhelp, strval, cat, pre_check, post_callback, nullptr)
#define SDT_ENUM(base, var, type, flags, guiflags, def, str, strhelp, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname, enumlist)\ #define SDT_ENUM(base, var, type, flags, def, str, strhelp, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname, enumlist)\
NSD(Int, SLE_GENERAL_X(SL_VAR, base, var, type | flags, 1, from, to, extver), #var, guiflags | SF_ENUM, guiproc, startup, patxname, def, 0, 0, 0, str, strhelp, STR_NULL, cat, pre_check, post_callback, enumlist) NSD(Int, SLE_GENERAL_X(SL_VAR, base, var, type, 1, from, to, extver), #var, flags | SF_ENUM, guiproc, startup, patxname, def, 0, 0, 0, str, strhelp, STR_NULL, cat, pre_check, post_callback, enumlist)
#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDT_BOOL(base, var, flags, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(Bool, SLE_GENERAL_X(SL_VAR, base, var, SLE_BOOL | flags, 1, from, to, extver), #var, guiflags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback) NSD(Bool, SLE_GENERAL_X(SL_VAR, base, var, SLE_BOOL, 1, from, to, extver), #var, flags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback)
#define SDT_LIST(base, var, type, flags, guiflags, def, from, to, extver, cat, guiproc, startup, patxname)\ #define SDT_LIST(base, var, type, flags, def, from, to, extver, cat, guiproc, startup, patxname)\
NSD(List, SLE_GENERAL_X(SL_ARR, base, var, type | flags, lengthof(((base*)8)->var), from, to, extver), #var, guiflags, guiproc, startup, patxname, def) NSD(List, SLE_GENERAL_X(SL_ARR, base, var, type, lengthof(((base*)8)->var), from, to, extver), #var, flags, guiproc, startup, patxname, def)
#define SDT_SSTR(base, var, type, flags, guiflags, def, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDT_SSTR(base, var, type, flags, def, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
NSD(String, SLE_GENERAL_X(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extver), #var, guiflags, guiproc, startup, patxname, def, 0, pre_check, post_callback) NSD(String, SLE_GENERAL_X(SL_STDSTR, base, var, type, sizeof(((base*)8)->var), from, to, extver), #var, flags, guiproc, startup, patxname, 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, extver, load, cat, guiproc, startup, patxname)\ #define SDT_OMANY(base, var, type, flags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, load, cat, guiproc, startup, patxname)\
NSD(OneOfMany, SLE_GENERAL_X(SL_VAR, base, var, type | flags, 1, from, to, extver), #var, guiflags, guiproc, startup, patxname, def, max, str, strhelp, strval, cat, pre_check, post_callback, full, load) NSD(OneOfMany, SLE_GENERAL_X(SL_VAR, base, var, type, 1, from, to, extver), #var, flags, guiproc, startup, patxname, 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, extver, cat, guiproc, startup, patxname)\ #define SDT_MMANY(base, var, type, flags, def, full, str, pre_check, post_callback, strhelp, strval, from, to, extver, cat, guiproc, startup, patxname)\
NSD(ManyOfMany, SLE_GENERAL_X(SL_VAR, base, var, type | flags, 1, from, to, extver), #var, guiflags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr) NSD(ManyOfMany, SLE_GENERAL_X(SL_VAR, base, var, type, 1, from, to, extver), #var, flags, guiproc, startup, patxname, def, str, strhelp, strval, cat, pre_check, post_callback, full, nullptr)
#define SDT_NULL(length, from, to, extver)\ #define SDT_NULL(length, from, to, extver)\
NSD(Null, SLE_CONDNULL_X(length, from, to, extver)) NSD(Null, SLE_CONDNULL_X(length, from, to, extver))
#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTC_VAR(var, type, flags, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
SDTG_VAR(#var, type, flags, guiflags, _settings_client.var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname) SDTG_VAR(#var, type, flags, _settings_client.var, def, min, max, interval, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)
#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTC_BOOL(var, flags, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
SDTG_BOOL(#var, flags, guiflags, _settings_client.var, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname) SDTG_BOOL(#var, flags, _settings_client.var, def, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)
#define SDTC_LIST(var, type, flags, guiflags, def, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTC_LIST(var, type, flags, def, from, to, extver, cat, guiproc, startup, patxname)\
SDTG_LIST(#var, type, flags, guiflags, _settings_client.var, def, lengthof(_settings_client.var), from, to, extver, cat, guiproc, startup, patxname) SDTG_LIST(#var, type, flags, _settings_client.var, def, lengthof(_settings_client.var), from, to, extver, cat, guiproc, startup, patxname)
#define SDTC_SSTR(var, type, flags, guiflags, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTC_SSTR(var, type, flags, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
SDTG_SSTR(#var, type, flags, guiflags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ SDTG_SSTR(#var, type, flags, _settings_client.var, def, max_length, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\ #define SDTC_OMANY(var, type, flags, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)\
SDTG_OMANY(#var, type, flags, guiflags, _settings_client.var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname) SDTG_OMANY(#var, type, flags, _settings_client.var, def, max, full, str, strhelp, strval, pre_check, post_callback, from, to, extver, cat, guiproc, startup, patxname)
#define SDT_XREF(from, to, extver, xref, xrefcvt)\ #define SDT_XREF(from, to, extver, xref, xrefcvt)\
NSD(Xref, SLE_CONDNULL_X(0, from, to, extver), SettingsXref(xref, xrefcvt)) NSD(Xref, SLE_CONDNULL_X(0, from, to, extver), SettingsXref(xref, xrefcvt))

@ -16,16 +16,15 @@ static const SettingTable _company_settings{
[post-amble] [post-amble]
}; };
[templates] [templates]
SDT_BOOL = SDT_BOOL(CompanySettings, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, $patxname), SDT_BOOL = SDT_BOOL(CompanySettings, $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, $patxname),
SDT_VAR = SDT_VAR(CompanySettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, $patxname), SDT_VAR = SDT_VAR(CompanySettings, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, $patxname),
SDT_NULL = SDT_NULL($length, $from, $to, $extver), SDT_NULL = SDT_NULL($length, $from, $to, $extver),
[validation] [validation]
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CompanySettings.$var exceeds storage size"); SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CompanySettings.$var exceeds storage size");
[defaults] [defaults]
flags = 0 flags = SF_PER_COMPANY
guiflags = SF_PER_COMPANY
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
@ -53,7 +52,7 @@ cat = SC_BASIC
[SDT_VAR] [SDT_VAR]
var = engine_renew_months var = engine_renew_months
type = SLE_INT16 type = SLE_INT16
guiflags = SF_PER_COMPANY | SF_GUI_NEGATIVE_IS_SPECIAL flags = SF_PER_COMPANY | SF_GUI_NEGATIVE_IS_SPECIAL
def = 6 def = 6
min = -12 min = -12
max = 12 max = 12
@ -64,7 +63,7 @@ strval = STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE
[SDT_VAR] [SDT_VAR]
var = engine_renew_money var = engine_renew_money
type = SLE_UINT type = SLE_UINT
guiflags = SF_PER_COMPANY | SF_GUI_CURRENCY flags = SF_PER_COMPANY | SF_GUI_CURRENCY
def = 100000 def = 100000
min = 0 min = 0
max = 2000000 max = 2000000
@ -91,7 +90,7 @@ post_cb = UpdateServiceInterval
[SDT_VAR] [SDT_VAR]
var = vehicle.servint_trains var = vehicle.servint_trains
type = SLE_UINT16 type = SLE_UINT16
guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = 150 def = 150
min = 5 min = 5
max = 800 max = 800
@ -104,7 +103,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_TRAIN, new_value); }
[SDT_VAR] [SDT_VAR]
var = vehicle.servint_roadveh var = vehicle.servint_roadveh
type = SLE_UINT16 type = SLE_UINT16
guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = 150 def = 150
min = 5 min = 5
max = 800 max = 800
@ -117,7 +116,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_ROAD, new_value); }
[SDT_VAR] [SDT_VAR]
var = vehicle.servint_ships var = vehicle.servint_ships
type = SLE_UINT16 type = SLE_UINT16
guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = 360 def = 360
min = 5 min = 5
max = 800 max = 800
@ -130,7 +129,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_SHIP, new_value); }
[SDT_VAR] [SDT_VAR]
var = vehicle.servint_aircraft var = vehicle.servint_aircraft
type = SLE_UINT16 type = SLE_UINT16
guiflags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = 100 def = 100
min = 5 min = 5
max = 800 max = 800
@ -143,7 +142,7 @@ post_cb = [](auto new_value) { UpdateServiceInterval(VEH_AIRCRAFT, new_value);
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = vehicle.auto_timetable_by_default var = vehicle.auto_timetable_by_default
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_AUTO_TIMETABLE_BY_DEFAULT str = STR_CONFIG_SETTING_AUTO_TIMETABLE_BY_DEFAULT
strhelp = STR_CONFIG_SETTING_AUTO_TIMETABLE_BY_DEFAULT_HELPTEXT strhelp = STR_CONFIG_SETTING_AUTO_TIMETABLE_BY_DEFAULT_HELPTEXT
@ -152,7 +151,7 @@ patxname = ""vehicle.auto_timetable_by_default""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = vehicle.auto_separation_by_default var = vehicle.auto_separation_by_default
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = true def = true
str = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_BY_DEFAULT str = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_BY_DEFAULT
strhelp = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_BY_DEFAULT_HELPTEXT strhelp = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_BY_DEFAULT_HELPTEXT
@ -162,7 +161,7 @@ patxname = ""vehicle.auto_separation_by_default""
base = CompanySettings base = CompanySettings
var = auto_timetable_separation_rate var = auto_timetable_separation_rate
type = SLE_UINT8 type = SLE_UINT8
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = 40 def = 40
min = 0 min = 0
max = 100 max = 100
@ -177,7 +176,7 @@ patxname = ""auto_timetable_separation_rate""
base = CompanySettings base = CompanySettings
var = timetable_autofill_rounding var = timetable_autofill_rounding
type = SLE_UINT16 type = SLE_UINT16
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = 74 def = 74
min = 1 min = 1
max = 1000 max = 1000
@ -192,7 +191,7 @@ patxname = ""timetable_autofill_rounding""
base = CompanySettings base = CompanySettings
var = order_occupancy_smoothness var = order_occupancy_smoothness
type = SLE_UINT8 type = SLE_UINT8
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = 75 def = 75
min = 0 min = 0
max = 100 max = 100
@ -206,7 +205,7 @@ patxname = ""order_occupancy_smoothness""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = infra_others_buy_in_depot[0] var = infra_others_buy_in_depot[0]
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_RAIL str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_RAIL
patxname = ""infra_sharing.infra_others_buy_in_depot.rail"" patxname = ""infra_sharing.infra_others_buy_in_depot.rail""
@ -214,7 +213,7 @@ patxname = ""infra_sharing.infra_others_buy_in_depot.rail""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = infra_others_buy_in_depot[1] var = infra_others_buy_in_depot[1]
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_ROAD str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_ROAD
patxname = ""infra_sharing.infra_others_buy_in_depot.road"" patxname = ""infra_sharing.infra_others_buy_in_depot.road""
@ -222,7 +221,7 @@ patxname = ""infra_sharing.infra_others_buy_in_depot.road""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = infra_others_buy_in_depot[2] var = infra_others_buy_in_depot[2]
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_WATER str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_WATER
patxname = ""infra_sharing.infra_others_buy_in_depot.water"" patxname = ""infra_sharing.infra_others_buy_in_depot.water""
@ -230,7 +229,7 @@ patxname = ""infra_sharing.infra_others_buy_in_depot.water""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = infra_others_buy_in_depot[3] var = infra_others_buy_in_depot[3]
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_AIR str = STR_CONFIG_SETTING_INFRA_OTHERS_BUY_IN_DEPOT_AIR
patxname = ""infra_sharing.infra_others_buy_in_depot.air"" patxname = ""infra_sharing.infra_others_buy_in_depot.air""
@ -239,7 +238,7 @@ patxname = ""infra_sharing.infra_others_buy_in_depot.air""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = advance_order_on_clone var = advance_order_on_clone
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = false def = false
str = STR_CONFIG_SETTING_ADVANCE_ORDER_ON_CLONE str = STR_CONFIG_SETTING_ADVANCE_ORDER_ON_CLONE
strhelp = STR_CONFIG_SETTING_ADVANCE_ORDER_ON_CLONE_HELPTEXT strhelp = STR_CONFIG_SETTING_ADVANCE_ORDER_ON_CLONE_HELPTEXT
@ -248,7 +247,7 @@ patxname = ""advance_order_on_clone""
[SDT_BOOL] [SDT_BOOL]
base = CompanySettings base = CompanySettings
var = copy_clone_add_to_group var = copy_clone_add_to_group
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = true def = true
str = STR_CONFIG_SETTING_COPY_CLONE_ADD_TO_GROUP str = STR_CONFIG_SETTING_COPY_CLONE_ADD_TO_GROUP
strhelp = STR_CONFIG_SETTING_COPY_CLONE_ADD_TO_GROUP_HELPTEXT strhelp = STR_CONFIG_SETTING_COPY_CLONE_ADD_TO_GROUP_HELPTEXT
@ -258,7 +257,7 @@ patxname = ""copy_clone_add_to_group""
base = CompanySettings base = CompanySettings
var = simulated_wormhole_signals var = simulated_wormhole_signals
type = SLE_UINT8 type = SLE_UINT8
guiflags = SF_PER_COMPANY flags = SF_PER_COMPANY
def = 4 def = 4
min = 1 min = 1
max = 16 max = 16

@ -11,15 +11,14 @@ static const SettingTable _currency_settings{
[post-amble] [post-amble]
}; };
[templates] [templates]
SDT_VAR = SDT_VAR (CurrencySpec, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDT_VAR = SDT_VAR (CurrencySpec, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDT_SSTR = SDT_SSTR(CurrencySpec, $var, $type, $flags, $guiflags, $def, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDT_SSTR = SDT_SSTR(CurrencySpec, $var, $type, $flags, $def, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
[validation] [validation]
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CurrencySpec.$var exceeds storage size"); SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for CurrencySpec.$var exceeds storage size");
[defaults] [defaults]
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
guiflags = SF_NONE
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT

@ -47,13 +47,13 @@ static const SettingTable _gameopt_settings{
[post-amble] [post-amble]
}; };
[templates] [templates]
SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_LIST = SDTG_LIST($name, $type, $flags, $var, $def, $length, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDT_NULL = SDT_NULL( $length, $from, $to, $extver), SDT_NULL = SDT_NULL( $length, $from, $to, $extver),
SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $load, $cat, $guiproc, $startup, nullptr), SDT_OMANY = SDT_OMANY(GameSettings, $var, $type, $flags, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $load, $cat, $guiproc, $startup, nullptr),
SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDT_VAR = SDT_VAR(GameSettings, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
[validation] [validation]
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
@ -63,8 +63,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"); SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size");
[defaults] [defaults]
flags = 0 flags = SF_NONE
guiflags = SF_NONE
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
@ -86,7 +85,7 @@ name = ""diff_custom""
sdt_cmd = SDT_INTLIST sdt_cmd = SDT_INTLIST
sle_cmd = SL_ARR sle_cmd = SL_ARR
type = SLE_FILE_I16 | SLE_VAR_U16 type = SLE_FILE_I16 | SLE_VAR_U16
flags = SLF_NOT_IN_CONFIG flags = SF_NOT_IN_CONFIG
var = _old_diff_custom var = _old_diff_custom
length = 17 length = 17
def = nullptr def = nullptr
@ -97,19 +96,18 @@ name = ""diff_custom""
sdt_cmd = SDT_INTLIST sdt_cmd = SDT_INTLIST
sle_cmd = SL_ARR sle_cmd = SL_ARR
type = SLE_UINT16 type = SLE_UINT16
flags = SLF_NOT_IN_CONFIG flags = SF_NOT_IN_CONFIG
var = _old_diff_custom var = _old_diff_custom
length = 18 length = 18
def = nullptr def = nullptr
full = nullptr full = nullptr
from = SLV_4 from = SLV_4
##
[SDTG_VAR] [SDTG_VAR]
name = ""diff_level"" name = ""diff_level""
var = _old_diff_level var = _old_diff_level
type = SLE_UINT8 type = SLE_UINT8
flags = SLF_NOT_IN_CONFIG flags = SF_NOT_IN_CONFIG
def = SP_CUSTOM def = SP_CUSTOM
min = SP_EASY min = SP_EASY
max = SP_CUSTOM max = SP_CUSTOM
@ -118,7 +116,7 @@ cat = SC_BASIC
[SDT_OMANY] [SDT_OMANY]
var = locale.currency var = locale.currency
type = SLE_UINT8 type = SLE_UINT8
flags = SLF_NO_NETWORK_SYNC flags = SF_NO_NETWORK_SYNC
def = 0 def = 0
max = CURRENCY_END - 1 max = CURRENCY_END - 1
full = _locale_currencies full = _locale_currencies
@ -128,7 +126,7 @@ cat = SC_BASIC
name = ""units"" name = ""units""
var = _old_units var = _old_units
type = SLE_UINT8 type = SLE_UINT8
flags = SLF_NOT_IN_CONFIG flags = SF_NOT_IN_CONFIG
def = 1 def = 1
max = 2 max = 2
full = _locale_units full = _locale_units
@ -179,8 +177,7 @@ to = SLV_23
[SDTC_OMANY] [SDTC_OMANY]
var = gui.autosave var = gui.autosave
type = SLE_UINT8 type = SLE_UINT8
from = SLV_23 flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
def = 1 def = 1
max = 4 max = 4
full = _autosave_interval full = _autosave_interval

@ -25,20 +25,19 @@ static const SettingTable _misc_settings{
[post-amble] [post-amble]
}; };
[templates] [templates]
SDTG_LIST = SDTG_LIST($name, $type, $flags, $guiflags, $var, $def, $length, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_LIST = SDTG_LIST($name, $type, $flags, $var, $def, $length, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $var, $def, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $var, $def, $max, $full, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $var, $def, 0, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
[validation] [validation]
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); 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"); SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
[defaults] [defaults]
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
guiflags = SF_NONE
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT

File diff suppressed because it is too large Load Diff

@ -17,15 +17,14 @@ static const SettingTable _win32_settings{
}; };
#endif /* _WIN32 */ #endif /* _WIN32 */
[templates] [templates]
SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr), SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr), SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr),
[validation] [validation]
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
[defaults] [defaults]
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
guiflags = SF_NONE
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT

@ -13,15 +13,14 @@ static const SettingTable _window_settings{
[post-amble] [post-amble]
}; };
[templates] [templates]
SDT_BOOL = SDT_BOOL(WindowDesc, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDT_BOOL = SDT_BOOL(WindowDesc, $var, $flags, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDT_VAR = SDT_VAR(WindowDesc, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr), SDT_VAR = SDT_VAR(WindowDesc, $var, $type, $flags, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
[validation] [validation]
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for WindowDesc.$var exceeds storage size"); SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for WindowDesc.$var exceeds storage size");
[defaults] [defaults]
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
guiflags = SF_NONE
interval = 0 interval = 0
str = STR_NULL str = STR_NULL
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT

Loading…
Cancel
Save