OpenTTD Source: src/settings.cpp Source File

OpenTTD Source 12.2

settings.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
24 #include "stdafx.h"
25 #include <charconv>
26 #include "settings_table.h"
27 #include "debug.h"
28 #include "currency.h"
29 #include "network/network.h"
30 #include "network/network_func.h"
31 #include "network/core/config.h"
32 #include "command_func.h"
33 #include "console_func.h"
34 #include "genworld.h"
35 #include "window_func.h"
36 #include "company_func.h"
37 #include "rev.h"
38 #include "error.h"
39 #include "gamelog.h"
40 #include "settings_func.h"
41 #include "ini_type.h"
42 #include "ai/ai_config.hpp"
43 #include "game/game_config.hpp"
44 #include "newgrf_config.h"
45 #include "fios.h"
46 #include "fileio_func.h"
47
48 #include "table/strings.h"
49
50 #include "safeguards.h"
51
52 ClientSettings _settings_client;
53 GameSettings _settings_game;
54 GameSettings _settings_newgame;
55 VehicleDefaultSettings _old_vds;
56 std::string _config_file;
57 std::string _private_file;
58 std::string _secrets_file;
59
60 typedef std::list<ErrorMessageData> ErrorList;
61 static ErrorList _settings_error_list;
62
73 static auto &GenericSettingTables()
74 {
75 static const SettingTable _generic_setting_tables[] = {
76 _difficulty_settings,
77 _economy_settings,
78 _game_settings,
79 _gui_settings,
80 _linkgraph_settings,
81 _locale_settings,
82 _multimedia_settings,
83 _network_settings,
84 _news_display_settings,
85 _pathfinding_settings,
86 _script_settings,
87 _world_settings,
88 };
89 return _generic_setting_tables;
90 }
91
95 static auto &PrivateSettingTables()
96 {
97 static const SettingTable _private_setting_tables[] = {
98 _network_private_settings,
99 };
100 return _private_setting_tables;
101 }
102
106 static auto &SecretSettingTables()
107 {
108 static const SettingTable _secrets_setting_tables[] = {
109 _network_secrets_settings,
110 };
111 return _secrets_setting_tables;
112 }
113
114 typedef void SettingDescProc(IniFile &ini, const SettingTable &desc, const char *grpname, void *object, bool only_startup);
115 typedef void SettingDescProcList(IniFile &ini, const char *grpname, StringList &list);
116
117 static bool IsSignedVarMemType(VarType vt)
118 {
119 switch (GetVarMemType(vt)) {
120 case SLE_VAR_I8:
121 case SLE_VAR_I16:
122 case SLE_VAR_I32:
123 case SLE_VAR_I64:
124 return true;
125 }
126 return false;
127 }
128
132 class ConfigIniFile : public IniFile {
133 private:
134 inline static const char * const list_group_names[] = {
135 "bans",
136 "newgrf",
137 "servers",
138 "server_bind_addresses",
139 nullptr,
140 };
141
142 public:
143 ConfigIniFile(const std::string &filename) : IniFile(list_group_names)
144 {
145 this->LoadFromDisk(filename, NO_DIRECTORY);
146 }
147 };
148
156 enum IniFileVersion : uint32 {
157 IFV_0,
158 IFV_PRIVATE_SECRETS,
159 IFV_GAME_TYPE,
160
161 IFV_MAX_VERSION,
162 };
163
164 const uint16 INIFILE_VERSION = (IniFileVersion)(IFV_MAX_VERSION - 1);
165
173 size_t OneOfManySettingDesc::ParseSingleValue(const char *str, size_t len, const std::vector<std::string> &many)
174 {
175 /* check if it's an integer */
176 if (isdigit(*str)) return strtoul(str, nullptr, 0);
177
178 size_t idx = 0;
179 for (auto one : many) {
180 if (one.size() == len && strncmp(one.c_str(), str, len) == 0) return idx;
181 idx++;
182 }
183
184 return (size_t)-1;
185 }
186
194 static size_t LookupManyOfMany(const std::vector<std::string> &many, const char *str)
195 {
196 const char *s;
197 size_t r;
198 size_t res = 0;
199
200 for (;;) {
201 /* skip "whitespace" */
202 while (*str == ' ' || *str == '\t' || *str == '|') str++;
203 if (*str == 0) break;
204
205 s = str;
206 while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++;
207
208 r = OneOfManySettingDesc::ParseSingleValue(str, s - str, many);
209 if (r == (size_t)-1) return r;
210
211 SetBit(res, (uint8)r); // value found, set it
212 if (*s == 0) break;
213 str = s + 1;
214 }
215 return res;
216 }
217
226 template<typename T>
227 static int ParseIntList(const char *p, T *items, int maxitems)
228 {
229 int n = 0; // number of items read so far
230 bool comma = false; // do we accept comma?
231
232 while (*p != '\0') {
233 switch (*p) {
234 case ',':
235 /* Do not accept multiple commas between numbers */
236 if (!comma) return -1;
237 comma = false;
238 FALLTHROUGH;
239
240 case ' ':
241 p++;
242 break;
243
244 default: {
245 if (n == maxitems) return -1; // we don't accept that many numbers
246 char *end;
247 unsigned long v = strtoul(p, &end, 0);
248 if (p == end) return -1; // invalid character (not a number)
249 if (sizeof(T) < sizeof(v)) v = Clamp<unsigned long>(v, std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
250 items[n++] = v;
251 p = end; // first non-number
252 comma = true; // we accept comma now
253 break;
254 }
255 }
256 }
257
258 /* If we have read comma but no number after it, fail.
259 * We have read comma when (n != 0) and comma is not allowed */
260 if (n != 0 && !comma) return -1;
261
262 return n;
263 }
264
273 static bool LoadIntList(const char *str, void *array, int nelems, VarType type)
274 {
275 unsigned long items[64];
276 int i, nitems;
277
278 if (str == nullptr) {
279 memset(items, 0, sizeof(items));
280 nitems = nelems;
281 } else {
282 nitems = ParseIntList(str, items, lengthof(items));
283 if (nitems != nelems) return false;
284 }
285
286 switch (type) {
287 case SLE_VAR_BL:
288 case SLE_VAR_I8:
289 case SLE_VAR_U8:
290 for (i = 0; i != nitems; i++) ((byte*)array)[i] = items[i];
291 break;
292
293 case SLE_VAR_I16:
294 case SLE_VAR_U16:
295 for (i = 0; i != nitems; i++) ((uint16*)array)[i] = items[i];
296 break;
297
298 case SLE_VAR_I32:
299 case SLE_VAR_U32:
300 for (i = 0; i != nitems; i++) ((uint32*)array)[i] = items[i];
301 break;
302
303 default: NOT_REACHED();
304 }
305
306 return true;
307 }
308
318 void ListSettingDesc::FormatValue(char *buf, const char *last, const void *object) const
319 {
320 const byte *p = static_cast<const byte *>(GetVariableAddress(object, this->save));
321 int i, v = 0;
322
323 for (i = 0; i != this->save.length; i++) {
324 switch (GetVarMemType(this->save.conv)) {
325 case SLE_VAR_BL:
326 case SLE_VAR_I8: v = *(const int8 *)p; p += 1; break;
327 case SLE_VAR_U8: v = *(const uint8 *)p; p += 1; break;
328 case SLE_VAR_I16: v = *(const int16 *)p; p += 2; break;
329 case SLE_VAR_U16: v = *(const uint16 *)p; p += 2; break;
330 case SLE_VAR_I32: v = *(const int32 *)p; p += 4; break;
331 case SLE_VAR_U32: v = *(const uint32 *)p; p += 4; break;
332 default: NOT_REACHED();
333 }
334 if (IsSignedVarMemType(this->save.conv)) {
335 buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v);
336 } else {
337 buf += seprintf(buf, last, (i == 0) ? "%u" : ",%u", v);
338 }
339 }
340 }
341
342 char *OneOfManySettingDesc::FormatSingleValue(char *buf, const char *last, uint id) const
343 {
344 if (id >= this->many.size()) {
345 return buf + seprintf(buf, last, "%d", id);
346 }
347 return strecpy(buf, this->many[id].c_str(), last);
348 }
349
350 void OneOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const
351 {
352 uint id = (uint)this->Read(object);
353 this->FormatSingleValue(buf, last, id);
354 }
355
356 void ManyOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const
357 {
358 uint bitmask = (uint)this->Read(object);
359 if (bitmask == 0) {
360 buf[0] = '\0';
361 return;
362 }
363 bool first = true;
364 for (uint id : SetBitIterator(bitmask)) {
365 if (!first) buf = strecpy(buf, "|", last);
366 buf = this->FormatSingleValue(buf, last, id);
367 first = false;
368 }
369 }
370
376 size_t IntSettingDesc::ParseValue(const char *str) const
377 {
378 char *end;
379 size_t val = strtoul(str, &end, 0);
380 if (end == str) {
381 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE);
382 msg.SetDParamStr(0, str);
383 msg.SetDParamStr(1, this->GetName());
384 _settings_error_list.push_back(msg);
385 return this->def;
386 }
387 if (*end != '\0') {
388 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS);
389 msg.SetDParamStr(0, this->GetName());
390 _settings_error_list.push_back(msg);
391 }
392 return val;
393 }
394
395 size_t OneOfManySettingDesc::ParseValue(const char *str) const
396 {
397 size_t r = OneOfManySettingDesc::ParseSingleValue(str, strlen(str), this->many);
398 /* if the first attempt of conversion from string to the appropriate value fails,
399 * look if we have defined a converter from old value to new value. */
400 if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str);
401 if (r != (size_t)-1) return r; // and here goes converted value
402
403 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE);
404 msg.SetDParamStr(0, str);
405 msg.SetDParamStr(1, this->GetName());
406 _settings_error_list.push_back(msg);
407 return this->def;
408 }
409
410 size_t ManyOfManySettingDesc::ParseValue(const char *str) const
411 {
412 size_t r = LookupManyOfMany(this->many, str);
413 if (r != (size_t)-1) return r;
414 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE);
415 msg.SetDParamStr(0, str);
416 msg.SetDParamStr(1, this->GetName());
417 _settings_error_list.push_back(msg);
418 return this->def;
419 }
420
421 size_t BoolSettingDesc::ParseValue(const char *str) const
422 {
423 if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return true;
424 if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return false;
425
426 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE);
427 msg.SetDParamStr(0, str);
428 msg.SetDParamStr(1, this->GetName());
429 _settings_error_list.push_back(msg);
430 return this->def;
431 }
432
439 void IntSettingDesc::MakeValueValidAndWrite(const void *object, int32 val) const
440 {
441 this->MakeValueValid(val);
442 this->Write(object, val);
443 }
444
454 void IntSettingDesc::MakeValueValid(int32 &val) const
455 {
456 /* We need to take special care of the uint32 type as we receive from the function
457 * a signed integer. While here also bail out on 64-bit settings as those are not
458 * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed
459 * 32-bit variable
460 * TODO: Support 64-bit settings/variables; requires 64 bit over command protocol! */
461 switch (GetVarMemType(this->save.conv)) {
462 case SLE_VAR_NULL: return;
463 case SLE_VAR_BL:
464 case SLE_VAR_I8:
465 case SLE_VAR_U8:
466 case SLE_VAR_I16:
467 case SLE_VAR_U16:
468 case SLE_VAR_I32: {
469 /* Override the minimum value. No value below this->min, except special value 0 */
470 if (!(this->flags & SF_GUI_0_IS_SPECIAL) || val != 0) {
471 if (!(this->flags & SF_GUI_DROPDOWN)) {
472 /* Clamp value-type setting to its valid range */
473 val = Clamp(val, this->min, this->max);
474 } else if (val < this->min || val > (int32)this->max) {
475 /* Reset invalid discrete setting (where different values change gameplay) to its default value */
476 val = this->def;
477 }
478 }
479 break;
480 }
481 case SLE_VAR_U32: {
482 /* Override the minimum value. No value below this->min, except special value 0 */
483 uint32 uval = (uint32)val;
484 if (!(this->flags & SF_GUI_0_IS_SPECIAL) || uval != 0) {
485 if (!(this->flags & SF_GUI_DROPDOWN)) {
486 /* Clamp value-type setting to its valid range */
487 uval = ClampU(uval, this->min, this->max);
488 } else if (uval < (uint)this->min || uval > this->max) {
489 /* Reset invalid discrete setting to its default value */
490 uval = (uint32)this->def;
491 }
492 }
493 val = (int32)uval;
494 return;
495 }
496 case SLE_VAR_I64:
497 case SLE_VAR_U64:
498 default: NOT_REACHED();
499 }
500 }
501
507 void IntSettingDesc::Write(const void *object, int32 val) const
508 {
509 void *ptr = GetVariableAddress(object, this->save);
510 WriteValue(ptr, this->save.conv, (int64)val);
511 }
512
518 int32 IntSettingDesc::Read(const void *object) const
519 {
520 void *ptr = GetVariableAddress(object, this->save);
521 return (int32)ReadValue(ptr, this->save.conv);
522 }
523
531 void StringSettingDesc::MakeValueValid(std::string &str) const
532 {
533 if (this->max_length == 0 || str.size() < this->max_length) return;
534
535 /* In case a maximum length is imposed by the setting, the length
536 * includes the '\0' termination for network transfer purposes.
537 * Also ensure the string is valid after chopping of some bytes. */
538 std::string stdstr(str, this->max_length - 1);
539 str.assign(StrMakeValid(stdstr, SVS_NONE));
540 }
541
547 void StringSettingDesc::Write(const void *object, const std::string &str) const
548 {
549 reinterpret_cast<std::string *>(GetVariableAddress(object, this->save))->assign(str);
550 }
551
557 const std::string &StringSettingDesc::Read(const void *object) const
558 {
559 return *reinterpret_cast<std::string *>(GetVariableAddress(object, this->save));
560 }
561
571 static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup)
572 {
573 IniGroup *group;
574 IniGroup *group_def = ini.GetGroup(grpname);
575
576 for (auto &desc : settings_table) {
577 const SettingDesc *sd = GetSettingDesc(desc);
578 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
579 if (sd->startup != only_startup) continue;
580
581 /* For settings.xx.yy load the settings from [xx] yy = ? */
582 std::string s{ sd->GetName() };
583 auto sc = s.find('.');
584 if (sc != std::string::npos) {
585 group = ini.GetGroup(s.substr(0, sc));
586 s = s.substr(sc + 1);
587 } else {
588 group = group_def;
589 }
590
591 IniItem *item = group->GetItem(s, false);
592 if (item == nullptr && group != group_def) {
593 /* For settings.xx.yy load the settings from [settings] yy = ? in case the previous
594 * did not exist (e.g. loading old config files with a [settings] section */
595 item = group_def->GetItem(s, false);
596 }
597 if (item == nullptr) {
598 /* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous
599 * did not exist (e.g. loading old config files with a [yapf] section */
600 sc = s.find('.');
601 if (sc != std::string::npos) item = ini.GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1), false);
602 }
603
604 sd->ParseValue(item, object);
605 }
606 }
607
608 void IntSettingDesc::ParseValue(const IniItem *item, void *object) const
609 {
610 size_t val = (item == nullptr) ? this->def : this->ParseValue(item->value.has_value() ? item->value->c_str() : "");
611 this->MakeValueValidAndWrite(object, (int32)val);
612 }
613
614 void StringSettingDesc::ParseValue(const IniItem *item, void *object) const
615 {
616 std::string str = (item == nullptr) ? this->def : item->value.value_or("");
617 this->MakeValueValid(str);
618 this->Write(object, str);
619 }
620
621 void ListSettingDesc::ParseValue(const IniItem *item, void *object) const
622 {
623 const char *str = (item == nullptr) ? this->def : item->value.has_value() ? item->value->c_str() : nullptr;
624 void *ptr = GetVariableAddress(object, this->save);
625 if (!LoadIntList(str, ptr, this->save.length, GetVarMemType(this->save.conv))) {
626 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY);
627 msg.SetDParamStr(0, this->GetName());
628 _settings_error_list.push_back(msg);
629
630 /* Use default */
631 LoadIntList(this->def, ptr, this->save.length, GetVarMemType(this->save.conv));
632 }
633 }
634
647 static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool)
648 {
649 IniGroup *group_def = nullptr, *group;
650 IniItem *item;
651 char buf[512];
652
653 for (auto &desc : settings_table) {
654 const SettingDesc *sd = GetSettingDesc(desc);
655 /* If the setting is not saved to the configuration
656 * file, just continue with the next setting */
657 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
658 if (sd->flags & SF_NOT_IN_CONFIG) continue;
659
660 /* XXX - wtf is this?? (group override?) */
661 std::string s{ sd->GetName() };
662 auto sc = s.find('.');
663 if (sc != std::string::npos) {
664 group = ini.GetGroup(s.substr(0, sc));
665 s = s.substr(sc + 1);
666 } else {
667 if (group_def == nullptr) group_def = ini.GetGroup(grpname);
668 group = group_def;
669 }
670
671 item = group->GetItem(s, true);
672
673 if (!item->value.has_value() || !sd->IsSameValue(item, object)) {
674 /* Value has changed, get the new value and put it into a buffer */
675 sd->FormatValue(buf, lastof(buf), object);
676
677 /* The value is different, that means we have to write it to the ini */
678 item->value.emplace(buf);
679 }
680 }
681 }
682
683 void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const
684 {
685 uint32 i = (uint32)this->Read(object);
686 seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : "%u", i);
687 }
688
689 void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const
690 {
691 bool val = this->Read(object) != 0;
692 strecpy(buf, val ? "true" : "false", last);
693 }
694
695 bool IntSettingDesc::IsSameValue(const IniItem *item, void *object) const
696 {
697 int32 item_value = (int32)this->ParseValue(item->value->c_str());
698 int32 object_value = this->Read(object);
699 return item_value == object_value;
700 }
701
702 void StringSettingDesc::FormatValue(char *buf, const char *last, const void *object) const
703 {
704 const std::string &str = this->Read(object);
705 switch (GetVarMemType(this->save.conv)) {
706 case SLE_VAR_STR: strecpy(buf, str.c_str(), last); break;
707
708 case SLE_VAR_STRQ:
709 if (str.empty()) {
710 buf[0] = '\0';
711 } else {
712 seprintf(buf, last, "\"%s\"", str.c_str());
713 }
714 break;
715
716 default: NOT_REACHED();
717 }
718 }
719
720 bool StringSettingDesc::IsSameValue(const IniItem *item, void *object) const
721 {
722 /* The ini parsing removes the quotes, which are needed to retain the spaces in STRQs,
723 * so those values are always different in the parsed ini item than they should be. */
724 if (GetVarMemType(this->save.conv) == SLE_VAR_STRQ) return false;
725
726 const std::string &str = this->Read(object);
727 return item->value->compare(str) == 0;
728 }
729
730 bool ListSettingDesc::IsSameValue(const IniItem *item, void *object) const
731 {
732 /* Checking for equality is way more expensive than just writing the value. */
733 return false;
734 }
735
745 static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &list)
746 {
747 IniGroup *group = ini.GetGroup(grpname);
748
749 if (group == nullptr) return;
750
751 list.clear();
752
753 for (const IniItem *item = group->item; item != nullptr; item = item->next) {
754 if (!item->name.empty()) list.push_back(item->name);
755 }
756 }
757
767 static void IniSaveSettingList(IniFile &ini, const char *grpname, StringList &list)
768 {
769 IniGroup *group = ini.GetGroup(grpname);
770
771 if (group == nullptr) return;
772 group->Clear();
773
774 for (const auto &iter : list) {
775 group->GetItem(iter, true)->SetValue("");
776 }
777 }
778
785 void IniLoadWindowSettings(IniFile &ini, const char *grpname, void *desc)
786 {
787 IniLoadSettings(ini, _window_settings, grpname, desc, false);
788 }
789
796 void IniSaveWindowSettings(IniFile &ini, const char *grpname, void *desc)
797 {
798 IniSaveSettings(ini, _window_settings, grpname, desc, false);
799 }
800
806 bool SettingDesc::IsEditable(bool do_command) const
807 {
808 if (!do_command && !(this->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server && !(this->flags & SF_PER_COMPANY)) return false;
809 if ((this->flags & SF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return false;
810 if ((this->flags & SF_NO_NETWORK) && _networking) return false;
811 if ((this->flags & SF_NEWGAME_ONLY) &&
812 (_game_mode == GM_NORMAL ||
813 (_game_mode == GM_EDITOR && !(this->flags & SF_SCENEDIT_TOO)))) return false;
814 if ((this->flags & SF_SCENEDIT_ONLY) && _game_mode != GM_EDITOR) return false;
815 return true;
816 }
817
822 SettingType SettingDesc::GetType() const
823 {
824 if (this->flags & SF_PER_COMPANY) return ST_COMPANY;
825 return (this->flags & SF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME;
826 }
827
832 const IntSettingDesc *SettingDesc::AsIntSetting() const
833 {
834 assert(this->IsIntSetting());
835 return static_cast<const IntSettingDesc *>(this);
836 }
837
842 const StringSettingDesc *SettingDesc::AsStringSetting() const
843 {
844 assert(this->IsStringSetting());
845 return static_cast<const StringSettingDesc *>(this);
846 }
847
848 void PrepareOldDiffCustom();
849 void HandleOldDiffCustom(bool savegame);
850
851
853 static void ValidateSettings()
854 {
855 /* Do not allow a custom sea level with the original land generator. */
856 if (_settings_newgame.game_creation.land_generator == LG_ORIGINAL &&
857 _settings_newgame.difficulty.quantity_sea_lakes == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) {
858 _settings_newgame.difficulty.quantity_sea_lakes = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE;
859 }
860 }
861
862 static void AILoadConfig(IniFile &ini, const char *grpname)
863 {
864 IniGroup *group = ini.GetGroup(grpname);
865 IniItem *item;
866
867 /* Clean any configured AI */
868 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
869 AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME)->Change(nullptr);
870 }
871
872 /* If no group exists, return */
873 if (group == nullptr) return;
874
875 CompanyID c = COMPANY_FIRST;
876 for (item = group->item; c < MAX_COMPANIES && item != nullptr; c++, item = item->next) {
877 AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
878
879 config->Change(item->name.c_str());
880 if (!config->HasScript()) {
881 if (item->name != "none") {
882 Debug(script, 0, "The AI by the name '{}' was no longer found, and removed from the list.", item->name);
883 continue;
884 }
885 }
886 if (item->value.has_value()) config->StringToSettings(*item->value);
887 }
888 }
889
890 static void GameLoadConfig(IniFile &ini, const char *grpname)
891 {
892 IniGroup *group = ini.GetGroup(grpname);
893 IniItem *item;
894
895 /* Clean any configured GameScript */
896 GameConfig::GetConfig(GameConfig::SSS_FORCE_NEWGAME)->Change(nullptr);
897
898 /* If no group exists, return */
899 if (group == nullptr) return;
900
901 item = group->item;
902 if (item == nullptr) return;
903
904 GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME);
905
906 config->Change(item->name.c_str());
907 if (!config->HasScript()) {
908 if (item->name != "none") {
909 Debug(script, 0, "The GameScript by the name '{}' was no longer found, and removed from the list.", item->name);
910 return;
911 }
912 }
913 if (item->value.has_value()) config->StringToSettings(*item->value);
914 }
915
921 static int DecodeHexNibble(char c)
922 {
923 if (c >= '0' && c <= '9') return c - '0';
924 if (c >= 'A' && c <= 'F') return c + 10 - 'A';
925 if (c >= 'a' && c <= 'f') return c + 10 - 'a';
926 return -1;
927 }
928
937 static bool DecodeHexText(const char *pos, uint8 *dest, size_t dest_size)
938 {
939 while (dest_size > 0) {
940 int hi = DecodeHexNibble(pos[0]);
941 int lo = (hi >= 0) ? DecodeHexNibble(pos[1]) : -1;
942 if (lo < 0) return false;
943 *dest++ = (hi << 4) | lo;
944 pos += 2;
945 dest_size--;
946 }
947 return *pos == '|';
948 }
949
956 static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_static)
957 {
958 IniGroup *group = ini.GetGroup(grpname);
959 IniItem *item;
960 GRFConfig *first = nullptr;
961 GRFConfig **curr = &first;
962
963 if (group == nullptr) return nullptr;
964
965 uint num_grfs = 0;
966 for (item = group->item; item != nullptr; item = item->next) {
967 GRFConfig *c = nullptr;
968
969 uint8 grfid_buf[4], md5sum[16];
970 const char *filename = item->name.c_str();
971 bool has_grfid = false;
972 bool has_md5sum = false;
973
974 /* Try reading "<grfid>|" and on success, "<md5sum>|". */
975 has_grfid = DecodeHexText(filename, grfid_buf, lengthof(grfid_buf));
976 if (has_grfid) {
977 filename += 1 + 2 * lengthof(grfid_buf);
978 has_md5sum = DecodeHexText(filename, md5sum, lengthof(md5sum));
979 if (has_md5sum) filename += 1 + 2 * lengthof(md5sum);
980
981 uint32 grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24);
982 if (has_md5sum) {
983 const GRFConfig *s = FindGRFConfig(grfid, FGCM_EXACT, md5sum);
984 if (s != nullptr) c = new GRFConfig(*s);
985 }
986 if (c == nullptr && !FioCheckFileExists(filename, NEWGRF_DIR)) {
987 const GRFConfig *s = FindGRFConfig(grfid, FGCM_NEWEST_VALID);
988 if (s != nullptr) c = new GRFConfig(*s);
989 }
990 }
991 if (c == nullptr) c = new GRFConfig(filename);
992
993 /* Parse parameters */
994 if (item->value.has_value() && !item->value->empty()) {
995 int count = ParseIntList(item->value->c_str(), c->param, lengthof(c->param));
996 if (count < 0) {
997 SetDParamStr(0, filename);
998 ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
999 count = 0;
1000 }
1001 c->num_params = count;
1002 }
1003
1004 /* Check if item is valid */
1005 if (!FillGRFDetails(c, is_static) || HasBit(c->flags, GCF_INVALID)) {
1006 if (c->status == GCS_NOT_FOUND) {
1007 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND);
1008 } else if (HasBit(c->flags, GCF_UNSAFE)) {
1009 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNSAFE);
1010 } else if (HasBit(c->flags, GCF_SYSTEM)) {
1011 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_SYSTEM);
1012 } else if (HasBit(c->flags, GCF_INVALID)) {
1013 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE);
1014 } else {
1015 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN);
1016 }
1017
1018 SetDParamStr(0, StrEmpty(filename) ? item->name : filename);
1019 ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, WL_CRITICAL);
1020 delete c;
1021 continue;
1022 }
1023
1024 /* Check for duplicate GRFID (will also check for duplicate filenames) */
1025 bool duplicate = false;
1026 for (const GRFConfig *gc = first; gc != nullptr; gc = gc->next) {
1027 if (gc->ident.grfid == c->ident.grfid) {
1028 SetDParamStr(0, c->filename);
1029 SetDParamStr(1, gc->filename);
1030 ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_DUPLICATE_GRFID, WL_CRITICAL);
1031 duplicate = true;
1032 break;
1033 }
1034 }
1035 if (duplicate) {
1036 delete c;
1037 continue;
1038 }
1039
1040 if (is_static) {
1041 /* Mark file as static to avoid saving in savegame. */
1042 SetBit(c->flags, GCF_STATIC);
1043 } else if (++num_grfs > NETWORK_MAX_GRF_COUNT) {
1044 /* Check we will not load more non-static NewGRFs than allowed. This could trigger issues for game servers. */
1045 ShowErrorMessage(STR_CONFIG_ERROR, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED, WL_CRITICAL);
1046 break;
1047 }
1048
1049 /* Add item to list */
1050 *curr = c;
1051 curr = &c->next;
1052 }
1053
1054 return first;
1055 }
1056
1057 static IniFileVersion LoadVersionFromConfig(IniFile &ini)
1058 {
1059 IniGroup *group = ini.GetGroup("version");
1060
1061 auto version_number = group->GetItem("ini_version", false);
1062 /* Older ini-file versions don't have this key yet. */
1063 if (version_number == nullptr || !version_number->value.has_value()) return IFV_0;
1064
1065 uint32 version = 0;
1066 std::from_chars(version_number->value->data(), version_number->value->data() + version_number->value->size(), version);
1067
1068 return static_cast<IniFileVersion>(version);
1069 }
1070
1071 static void AISaveConfig(IniFile &ini, const char *grpname)
1072 {
1073 IniGroup *group = ini.GetGroup(grpname);
1074
1075 if (group == nullptr) return;
1076 group->Clear();
1077
1078 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
1079 AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
1080 const char *name;
1081 std::string value = config->SettingsToString();
1082
1083 if (config->HasScript()) {
1084 name = config->GetName();
1085 } else {
1086 name = "none";
1087 }
1088
1089 IniItem *item = new IniItem(group, name);
1090 item->SetValue(value);
1091 }
1092 }
1093
1094 static void GameSaveConfig(IniFile &ini, const char *grpname)
1095 {
1096 IniGroup *group = ini.GetGroup(grpname);
1097
1098 if (group == nullptr) return;
1099 group->Clear();
1100
1101 GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME);
1102 const char *name;
1103 std::string value = config->SettingsToString();
1104
1105 if (config->HasScript()) {
1106 name = config->GetName();
1107 } else {
1108 name = "none";
1109 }
1110
1111 IniItem *item = new IniItem(group, name);
1112 item->SetValue(value);
1113 }
1114
1119 static void SaveVersionInConfig(IniFile &ini)
1120 {
1121 IniGroup *group = ini.GetGroup("version");
1122 group->GetItem("version_string", true)->SetValue(_openttd_revision);
1123 group->GetItem("version_number", true)->SetValue(fmt::format("{:08X}", _openttd_newgrf_version));
1124 group->GetItem("ini_version", true)->SetValue(std::to_string(INIFILE_VERSION));
1125 }
1126
1127 /* Save a GRF configuration to the given group name */
1128 static void GRFSaveConfig(IniFile &ini, const char *grpname, const GRFConfig *list)
1129 {
1130 ini.RemoveGroup(grpname);
1131 IniGroup *group = ini.GetGroup(grpname);
1132 const GRFConfig *c;
1133
1134 for (c = list; c != nullptr; c = c->next) {
1135 /* Hex grfid (4 bytes in nibbles), "|", hex md5sum (16 bytes in nibbles), "|", file system path. */
1136 char key[4 * 2 + 1 + 16 * 2 + 1 + MAX_PATH];
1137 char params[512];
1138 GRFBuildParamList(params, c, lastof(params));
1139
1140 char *pos = key + seprintf(key, lastof(key), "%08X|", BSWAP32(c->ident.grfid));
1141 pos = md5sumToString(pos, lastof(key), c->ident.md5sum);
1142 seprintf(pos, lastof(key), "|%s", c->filename);
1143 group->GetItem(key, true)->SetValue(params);
1144 }
1145 }
1146
1147 /* Common handler for saving/loading variables to the configuration file */
1148 static void HandleSettingDescs(IniFile &generic_ini, IniFile &private_ini, IniFile &secrets_ini, SettingDescProc *proc, SettingDescProcList *proc_list, bool only_startup = false)
1149 {
1150 proc(generic_ini, _misc_settings, "misc", nullptr, only_startup);
1151 #if defined(_WIN32) && !defined(DEDICATED)
1152 proc(generic_ini, _win32_settings, "win32", nullptr, only_startup);
1153 #endif /* _WIN32 */
1154
1155 /* The name "patches" is a fallback, as every setting should sets its own group. */
1156
1157 for (auto &table : GenericSettingTables()) {
1158 proc(generic_ini, table, "patches", &_settings_newgame, only_startup);
1159 }
1160 for (auto &table : PrivateSettingTables()) {
1161 proc(private_ini, table, "patches", &_settings_newgame, only_startup);
1162 }
1163 for (auto &table : SecretSettingTables()) {
1164 proc(secrets_ini, table, "patches", &_settings_newgame, only_startup);
1165 }
1166
1167 proc(generic_ini, _currency_settings, "currency", &_custom_currency, only_startup);
1168 proc(generic_ini, _company_settings, "company", &_settings_client.company, only_startup);
1169
1170 if (!only_startup) {
1171 proc_list(private_ini, "server_bind_addresses", _network_bind_list);
1172 proc_list(private_ini, "servers", _network_host_list);
1173 proc_list(private_ini, "bans", _network_ban_list);
1174 }
1175 }
1176
1186 static void RemoveEntriesFromIni(IniFile &ini, const SettingTable &table)
1187 {
1188 for (auto &desc : table) {
1189 const SettingDesc *sd = GetSettingDesc(desc);
1190
1191 /* For settings.xx.yy load the settings from [xx] yy = ? */
1192 std::string s{ sd->GetName() };
1193 auto sc = s.find('.');
1194 if (sc == std::string::npos) continue;
1195
1196 IniGroup *group = ini.GetGroup(s.substr(0, sc));
1197 s = s.substr(sc + 1);
1198
1199 group->RemoveItem(s);
1200 }
1201 }
1202
1207 void LoadFromConfig(bool startup)
1208 {
1209 ConfigIniFile generic_ini(_config_file);
1210 ConfigIniFile private_ini(_private_file);
1211 ConfigIniFile secrets_ini(_secrets_file);
1212
1213 if (!startup) ResetCurrencies(false); // Initialize the array of currencies, without preserving the custom one
1214
1215 IniFileVersion generic_version = LoadVersionFromConfig(generic_ini);
1216
1217 /* Before the split of private/secrets, we have to look in the generic for these settings. */
1218 if (generic_version < IFV_PRIVATE_SECRETS) {
1219 HandleSettingDescs(generic_ini, generic_ini, generic_ini, IniLoadSettings, IniLoadSettingList, startup);
1220 } else {
1221 HandleSettingDescs(generic_ini, private_ini, secrets_ini, IniLoadSettings, IniLoadSettingList, startup);
1222 }
1223
1224 /* Load basic settings only during bootstrap, load other settings not during bootstrap */
1225 if (!startup) {
1226 /* Convert network.server_advertise to network.server_game_type, but only if network.server_game_type is set to default value. */
1227 if (generic_version < IFV_GAME_TYPE) {
1228 if (_settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) {
1229 IniGroup *network = generic_ini.GetGroup("network", false);
1230 if (network != nullptr) {
1231 IniItem *server_advertise = network->GetItem("server_advertise", false);
1232 if (server_advertise != nullptr && server_advertise->value == "true") {
1233 _settings_client.network.server_game_type = SERVER_GAME_TYPE_PUBLIC;
1234 }
1235 }
1236 }
1237 }
1238
1239 _grfconfig_newgame = GRFLoadConfig(generic_ini, "newgrf", false);
1240 _grfconfig_static = GRFLoadConfig(generic_ini, "newgrf-static", true);
1241 AILoadConfig(generic_ini, "ai_players");
1242 GameLoadConfig(generic_ini, "game_scripts");
1243
1244 PrepareOldDiffCustom();
1245 IniLoadSettings(generic_ini, _old_gameopt_settings, "gameopt", &_settings_newgame, false);
1246 HandleOldDiffCustom(false);
1247
1248 ValidateSettings();
1249 DebugReconsiderSendRemoteMessages();
1250
1251 /* Display scheduled errors */
1252 extern void ScheduleErrorMessage(ErrorList &datas);
1253 ScheduleErrorMessage(_settings_error_list);
1254 if (FindWindowById(WC_ERRMSG, 0) == nullptr) ShowFirstError();
1255 }
1256 }
1257
1259 void SaveToConfig()
1260 {
1261 ConfigIniFile generic_ini(_config_file);
1262 ConfigIniFile private_ini(_private_file);
1263 ConfigIniFile secrets_ini(_secrets_file);
1264
1265 IniFileVersion generic_version = LoadVersionFromConfig(generic_ini);
1266
1267 /* If we newly create the private/secrets file, add a dummy group on top
1268 * just so we can add a comment before it (that is how IniFile works).
1269 * This to explain what the file is about. After doing it once, never touch
1270 * it again, as otherwise we might be reverting user changes. */
1271 if (!private_ini.GetGroup("private", false)) private_ini.GetGroup("private")->comment = "; This file possibly contains private information which can identify you as person.\n";
1272 if (!secrets_ini.GetGroup("secrets", false)) secrets_ini.GetGroup("secrets")->comment = "; Do not share this file with others, not even if they claim to be technical support.\n; This file contains saved passwords and other secrets that should remain private to you!\n";
1273
1274 if (generic_version == IFV_0) {
1275 /* Remove some obsolete groups. These have all been loaded into other groups. */
1276 generic_ini.RemoveGroup("patches");
1277 generic_ini.RemoveGroup("yapf");
1278 generic_ini.RemoveGroup("gameopt");
1279
1280 /* Remove all settings from the generic ini that are now in the private ini. */
1281 generic_ini.RemoveGroup("server_bind_addresses");
1282 generic_ini.RemoveGroup("servers");
1283 generic_ini.RemoveGroup("bans");
1284 for (auto &table : PrivateSettingTables()) {
1285 RemoveEntriesFromIni(generic_ini, table);
1286 }
1287
1288 /* Remove all settings from the generic ini that are now in the secrets ini. */
1289 for (auto &table : SecretSettingTables()) {
1290 RemoveEntriesFromIni(generic_ini, table);
1291 }
1292 }
1293
1294 /* Remove network.server_advertise. */
1295 if (generic_version < IFV_GAME_TYPE) {
1296 IniGroup *network = generic_ini.GetGroup("network", false);
1297 if (network != nullptr) {
1298 network->RemoveItem("server_advertise");
1299 }
1300 }
1301
1302 HandleSettingDescs(generic_ini, private_ini, secrets_ini, IniSaveSettings, IniSaveSettingList);
1303 GRFSaveConfig(generic_ini, "newgrf", _grfconfig_newgame);
1304 GRFSaveConfig(generic_ini, "newgrf-static", _grfconfig_static);
1305 AISaveConfig(generic_ini, "ai_players");
1306 GameSaveConfig(generic_ini, "game_scripts");
1307
1308 SaveVersionInConfig(generic_ini);
1309 SaveVersionInConfig(private_ini);
1310 SaveVersionInConfig(secrets_ini);
1311
1312 generic_ini.SaveToDisk(_config_file);
1313 private_ini.SaveToDisk(_private_file);
1314 secrets_ini.SaveToDisk(_secrets_file);
1315 }
1316
1321 StringList GetGRFPresetList()
1322 {
1323 StringList list;
1324
1325 ConfigIniFile ini(_config_file);
1326 for (IniGroup *group = ini.group; group != nullptr; group = group->next) {
1327 if (group->name.compare(0, 7, "preset-") == 0) {
1328 list.push_back(group->name.substr(7));
1329 }
1330 }
1331
1332 return list;
1333 }
1334
1341 GRFConfig *LoadGRFPresetFromConfig(const char *config_name)
1342 {
1343 size_t len = strlen(config_name) + 8;
1344 char *section = (char*)alloca(len);
1345 seprintf(section, section + len - 1, "preset-%s", config_name);
1346
1347 ConfigIniFile ini(_config_file);
1348 GRFConfig *config = GRFLoadConfig(ini, section, false);
1349
1350 return config;
1351 }
1352
1359 void SaveGRFPresetToConfig(const char *config_name, GRFConfig *config)
1360 {
1361 size_t len = strlen(config_name) + 8;
1362 char *section = (char*)alloca(len);
1363 seprintf(section, section + len - 1, "preset-%s", config_name);
1364
1365 ConfigIniFile ini(_config_file);
1366 GRFSaveConfig(ini, section, config);
1367 ini.SaveToDisk(_config_file);
1368 }
1369
1374 void DeleteGRFPresetFromConfig(const char *config_name)
1375 {
1376 size_t len = strlen(config_name) + 8;
1377 char *section = (char*)alloca(len);
1378 seprintf(section, section + len - 1, "preset-%s", config_name);
1379
1380 ConfigIniFile ini(_config_file);
1381 ini.RemoveGroup(section);
1382 ini.SaveToDisk(_config_file);
1383 }
1384
1391 void IntSettingDesc::ChangeValue(const void *object, int32 newval) const
1392 {
1393 int32 oldval = this->Read(object);
1394 this->MakeValueValid(newval);
1395 if (this->pre_check != nullptr && !this->pre_check(newval)) return;
1396 if (oldval == newval) return;
1397
1398 this->Write(object, newval);
1399 if (this->post_callback != nullptr) this->post_callback(newval);
1400
1401 if (this->flags & SF_NO_NETWORK) {
1402 GamelogStartAction(GLAT_SETTING);
1403 GamelogSetting(this->GetName(), oldval, newval);
1404 GamelogStopAction();
1405 }
1406
1407 SetWindowClassesDirty(WC_GAME_OPTIONS);
1408
1409 if (_save_config) SaveToConfig();
1410 }
1411
1419 static const SettingDesc *GetSettingFromName(const std::string_view name, const SettingTable &settings)
1420 {
1421 /* First check all full names */
1422 for (auto &desc : settings) {
1423 const SettingDesc *sd = GetSettingDesc(desc);
1424 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
1425 if (sd->GetName() == name) return sd;
1426 }
1427
1428 /* Then check the shortcut variant of the name. */
1429 std::string short_name_suffix = std::string{ "." }.append(name);
1430 for (auto &desc : settings) {
1431 const SettingDesc *sd = GetSettingDesc(desc);
1432 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
1433 if (StrEndsWith(sd->GetName(), short_name_suffix)) return sd;
1434 }
1435
1436 return nullptr;
1437 }
1438
1444 void GetSaveLoadFromSettingTable(SettingTable settings, std::vector<SaveLoad> &saveloads)
1445 {
1446 for (auto &desc : settings) {
1447 const SettingDesc *sd = GetSettingDesc(desc);
1448 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
1449 saveloads.push_back(sd->save);
1450 }
1451 }
1452
1459 static const SettingDesc *GetCompanySettingFromName(std::string_view name)
1460 {
1461 static const std::string_view company_prefix = "company.";
1462 if (StrStartsWith(name, company_prefix)) name.remove_prefix(company_prefix.size());
1463 return GetSettingFromName(name, _company_settings);
1464 }
1465
1472 const SettingDesc *GetSettingFromName(const std::string_view name)
1473 {
1474 for (auto &table : GenericSettingTables()) {
1475 auto sd = GetSettingFromName(name, table);
1476 if (sd != nullptr) return sd;
1477 }
1478 for (auto &table : PrivateSettingTables()) {
1479 auto sd = GetSettingFromName(name, table);
1480 if (sd != nullptr) return sd;
1481 }
1482 for (auto &table : SecretSettingTables()) {
1483 auto sd = GetSettingFromName(name, table);
1484 if (sd != nullptr) return sd;
1485 }
1486
1487 return GetCompanySettingFromName(name);
1488 }
1489
1501 CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
1502 {
1503 if (text.empty()) return CMD_ERROR;
1504 const SettingDesc *sd = GetSettingFromName(text);
1505
1506 if (sd == nullptr) return CMD_ERROR;
1507 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR;
1508 if (!sd->IsIntSetting()) return CMD_ERROR;
1509
1510 if (!sd->IsEditable(true)) return CMD_ERROR;
1511
1512 if (flags & DC_EXEC) {
1513 sd->AsIntSetting()->ChangeValue(&GetGameSettings(), p2);
1514 }
1515
1516 return CommandCost();
1517 }
1518
1529 CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
1530 {
1531 if (text.empty()) return CMD_ERROR;
1532 const SettingDesc *sd = GetCompanySettingFromName(text.c_str());
1533
1534 if (sd == nullptr) return CMD_ERROR;
1535 if (!sd->IsIntSetting()) return CMD_ERROR;
1536
1537 if (flags & DC_EXEC) {
1538 sd->AsIntSetting()->ChangeValue(&Company::Get(_current_company)->settings, p2);
1539 }
1540
1541 return CommandCost();
1542 }
1543
1551 bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame)
1552 {
1553 const IntSettingDesc *setting = sd->AsIntSetting();
1554 if ((setting->flags & SF_PER_COMPANY) != 0) {
1555 if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1556 return DoCommandP(0, 0, value, CMD_CHANGE_COMPANY_SETTING, nullptr, setting->GetName());
1557 }
1558
1559 setting->ChangeValue(&_settings_client.company, value);
1560 return true;
1561 }
1562
1563 /* If an item is company-based, we do not send it over the network
1564 * (if any) to change. Also *hack*hack* we update the _newgame version
1565 * of settings because changing a company-based setting in a game also
1566 * changes its defaults. At least that is the convention we have chosen */
1567 if (setting->flags & SF_NO_NETWORK_SYNC) {
1568 if (_game_mode != GM_MENU) {
1569 setting->ChangeValue(&_settings_newgame, value);
1570 }
1571 setting->ChangeValue(&GetGameSettings(), value);
1572 return true;
1573 }
1574
1575 if (force_newgame) {
1576 setting->ChangeValue(&_settings_newgame, value);
1577 return true;
1578 }
1579
1580 /* send non-company-based settings over the network */
1581 if (!_networking || (_networking && _network_server)) {
1582 return DoCommandP(0, 0, value, CMD_CHANGE_SETTING, nullptr, setting->GetName());
1583 }
1584 return false;
1585 }
1586
1590 void SetDefaultCompanySettings(CompanyID cid)
1591 {
1592 Company *c = Company::Get(cid);
1593 for (auto &desc : _company_settings) {
1594 const IntSettingDesc *int_setting = GetSettingDesc(desc)->AsIntSetting();
1595 int_setting->MakeValueValidAndWrite(&c->settings, int_setting->def);
1596 }
1597 }
1598
1602 void SyncCompanySettings()
1603 {
1604 const void *old_object = &Company::Get(_current_company)->settings;
1605 const void *new_object = &_settings_client.company;
1606 for (auto &desc : _company_settings) {
1607 const SettingDesc *sd = GetSettingDesc(desc);
1608 uint32 old_value = (uint32)sd->AsIntSetting()->Read(new_object);
1609 uint32 new_value = (uint32)sd->AsIntSetting()->Read(old_object);
1610 if (old_value != new_value) NetworkSendCommand(0, 0, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, sd->GetName(), _local_company);
1611 }
1612 }
1613
1621 bool SetSettingValue(const StringSettingDesc *sd, std::string value, bool force_newgame)
1622 {
1623 assert(sd->flags & SF_NO_NETWORK_SYNC);
1624
1625 if (GetVarMemType(sd->save.conv) == SLE_VAR_STRQ && value.compare("(null)") == 0) {
1626 value.clear();
1627 }
1628
1629 const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game;
1630 sd->AsStringSetting()->ChangeValue(object, value);
1631 return true;
1632 }
1633
1640 void StringSettingDesc::ChangeValue(const void *object, std::string &newval) const
1641 {
1642 this->MakeValueValid(newval);
1643 if (this->pre_check != nullptr && !this->pre_check(newval)) return;
1644
1645 this->Write(object, newval);
1646 if (this->post_callback != nullptr) this->post_callback(newval);
1647
1648 if (_save_config) SaveToConfig();
1649 }
1650
1651 /* Those 2 functions need to be here, else we have to make some stuff non-static
1652 * and besides, it is also better to keep stuff like this at the same place */
1653 void IConsoleSetSetting(const char *name, const char *value, bool force_newgame)
1654 {
1655 const SettingDesc *sd = GetSettingFromName(name);
1656 if (sd == nullptr) {
1657 IConsolePrint(CC_ERROR, "'{}' is an unknown setting.", name);
1658 return;
1659 }
1660
1661 bool success = true;
1662 if (sd->IsStringSetting()) {
1663 success = SetSettingValue(sd->AsStringSetting(), value, force_newgame);
1664 } else if (sd->IsIntSetting()) {
1665 const IntSettingDesc *isd = sd->AsIntSetting();
1666 size_t val = isd->ParseValue(value);
1667 if (!_settings_error_list.empty()) {
1668 IConsolePrint(CC_ERROR, "'{}' is not a valid value for this setting.", value);
1669 _settings_error_list.clear();
1670 return;
1671 }
1672 success = SetSettingValue(isd, (int32)val, force_newgame);
1673 }
1674
1675 if (!success) {
1676 if (_network_server) {
1677 IConsolePrint(CC_ERROR, "This command/variable is not available during network games.");
1678 } else {
1679 IConsolePrint(CC_ERROR, "This command/variable is only available to a network server.");
1680 }
1681 }
1682 }
1683
1684 void IConsoleSetSetting(const char *name, int value)
1685 {
1686 const SettingDesc *sd = GetSettingFromName(name);
1687 assert(sd != nullptr);
1688 SetSettingValue(sd->AsIntSetting(), value);
1689 }
1690
1696 void IConsoleGetSetting(const char *name, bool force_newgame)
1697 {
1698 const SettingDesc *sd = GetSettingFromName(name);
1699 if (sd == nullptr) {
1700 IConsolePrint(CC_ERROR, "'{}' is an unknown setting.", name);
1701 return;
1702 }
1703
1704 const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game;
1705
1706 if (sd->IsStringSetting()) {
1707 IConsolePrint(CC_INFO, "Current value for '{}' is '{}'.", sd->GetName(), sd->AsStringSetting()->Read(object));
1708 } else if (sd->IsIntSetting()) {
1709 char value[20];
1710 sd->FormatValue(value, lastof(value), object);
1711 const IntSettingDesc *int_setting = sd->AsIntSetting();
1712 IConsolePrint(CC_INFO, "Current value for '{}' is '{}' (min: {}{}, max: {}).",
1713 sd->GetName(), value, (sd->flags & SF_GUI_0_IS_SPECIAL) ? "(0) " : "", int_setting->min, int_setting->max);
1714 }
1715 }
1716
1717 static void IConsoleListSettingsTable(const SettingTable &table, const char *prefilter)
1718 {
1719 for (auto &desc : table) {
1720 const SettingDesc *sd = GetSettingDesc(desc);
1721 if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
1722 if (prefilter != nullptr && sd->GetName().find(prefilter) == std::string::npos) continue;
1723 char value[80];
1724 sd->FormatValue(value, lastof(value), &GetGameSettings());
1725 IConsolePrint(CC_DEFAULT, "{} = {}", sd->GetName(), value);
1726 }
1727 }
1728
1734 void IConsoleListSettings(const char *prefilter)
1735 {
1736 IConsolePrint(CC_HELP, "All settings with their current value:");
1737
1738 for (auto &table : GenericSettingTables()) {
1739 IConsoleListSettingsTable(table, prefilter);
1740 }
1741 for (auto &table : PrivateSettingTables()) {
1742 IConsoleListSettingsTable(table, prefilter);
1743 }
1744 for (auto &table : SecretSettingTables()) {
1745 IConsoleListSettingsTable(table, prefilter);
1746 }
1747
1748 IConsolePrint(CC_HELP, "Use 'setting' command to change a value.");
1749 }
GamelogSetting
void GamelogSetting(const std::string &name, int32 oldval, int32 newval)
Logs change in game settings.
Definition: gamelog.cpp:486
IniLoadFile::RemoveGroup
void RemoveGroup(const char *name)
Remove the group with the given name.
Definition: ini_load.cpp:182
ShowFirstError
void ShowFirstError()
Show the first error of the queue.
Definition: error_gui.cpp:348
OneOfManySettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Format the value of the setting associated with this object.
Definition: settings.cpp:350
ErrorList
std::list< ErrorMessageData > ErrorList
Define a queue with errors.
Definition: error_gui.cpp:178
SaveLoad::version_to
SaveLoadVersion version_to
Save/load the variable before this savegame version.
Definition: saveload.h:661
TileIndex
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:83
StringSettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Format the value of the setting associated with this object.
Definition: settings.cpp:702
CC_INFO
static const TextColour CC_INFO
Colour for information lines.
Definition: console_type.h:27
IntSettingDesc::MakeValueValid
void MakeValueValid(int32 &value) const
Make the value valid given the limitations of this setting.
Definition: settings.cpp:454
SF_PER_COMPANY
@ SF_PER_COMPANY
This setting can be different for each company (saved in company struct).
Definition: settings_internal.h:27
ClientSettings
All settings that are only important for the local client.
Definition: settings_type.h:593
AIConfig
Definition: ai_config.hpp:16
SF_NOT_IN_SAVE
@ SF_NOT_IN_SAVE
Do not save with savegame, basically client-based.
Definition: settings_internal.h:28
SF_GUI_0_IS_SPECIAL
@ SF_GUI_0_IS_SPECIAL
A value of zero is possible and has a custom string (the one after "strval").
Definition: settings_internal.h:18
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:337
StringSettingDesc::MakeValueValid
void MakeValueValid(std::string &str) const
Make the value valid given the limitations of this setting.
Definition: settings.cpp:531
RemoveEntriesFromIni
static void RemoveEntriesFromIni(IniFile &ini, const SettingTable &table)
Remove all entries from a settings table from an ini-file.
Definition: settings.cpp:1186
IFV_GAME_TYPE
@ IFV_GAME_TYPE
2 PR#9515 Convert server_advertise to server_game_type.
Definition: settings.cpp:159
SLE_VAR_STR
@ SLE_VAR_STR
string pointer
Definition: saveload.h:591
command_func.h
FindGRFConfig
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
Definition: newgrf_config.cpp:736
IniItem::SetValue
void SetValue(const std::string_view value)
Replace the current value with another value.
Definition: ini_load.cpp:41
StringSettingDesc::pre_check
PreChangeCheck * pre_check
Callback to check for the validity of the setting.
Definition: settings_internal.h:271
ErrorMessageData::SetDParamStr
void SetDParamStr(uint n, const char *str)
Set a rawstring parameter.
Definition: error_gui.cpp:161
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
IniItem::next
IniItem * next
The next item in this group.
Definition: ini_type.h:26
GRFLoadConfig
static GRFConfig * GRFLoadConfig(IniFile &ini, const char *grpname, bool is_static)
Load a GRF configuration.
Definition: settings.cpp:956
GetSettingFromName
static const SettingDesc * GetSettingFromName(const std::string_view name, const SettingTable &settings)
Given a name of setting, return a setting description from the table.
Definition: settings.cpp:1419
ValidateSettings
static void ValidateSettings()
Checks if any settings are set to incorrect values, and sets them to correct values in that case.
Definition: settings.cpp:853
SetDefaultCompanySettings
void SetDefaultCompanySettings(CompanyID cid)
Set the company settings for a new company to their default values.
Definition: settings.cpp:1590
StringSettingDesc::IsSameValue
bool IsSameValue(const IniItem *item, void *object) const override
Check whether the value in the Ini item is the same as is saved in this setting in the object.
Definition: settings.cpp:720
CUSTOM_SEA_LEVEL_MIN_PERCENTAGE
static const uint CUSTOM_SEA_LEVEL_MIN_PERCENTAGE
Minimum percentage a user can specify for custom sea level.
Definition: genworld.h:48
SF_NOT_IN_CONFIG
@ SF_NOT_IN_CONFIG
Do not save to config file.
Definition: settings_internal.h:29
IntSettingDesc::min
int32 min
minimum values
Definition: settings_internal.h:161
IniLoadWindowSettings
void IniLoadWindowSettings(IniFile &ini, const char *grpname, void *desc)
Load a WindowDesc from config.
Definition: settings.cpp:785
currency.h
GRFConfig::num_params
uint8 num_params
Number of used parameters.
Definition: newgrf_config.h:177
ManyOfManySettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Format the value of the setting associated with this object.
Definition: settings.cpp:356
ST_GAME
@ ST_GAME
Game setting.
Definition: settings_internal.h:62
_network_server
bool _network_server
network-server is active
Definition: network.cpp:58
IntSettingDesc::MakeValueValidAndWrite
void MakeValueValidAndWrite(const void *object, int32 value) const
Make the value valid and then write it to the setting.
Definition: settings.cpp:439
IniItem
A single "line" in an ini file.
Definition: ini_type.h:25
SettingDesc::save
SaveLoad save
Internal structure (going to savegame, parts to config).
Definition: settings_internal.h:79
SettingDesc::GetType
SettingType GetType() const
Return the type of the setting.
Definition: settings.cpp:822
SaveToConfig
void SaveToConfig()
Save the values to the configuration file.
Definition: settings.cpp:1259
PrepareOldDiffCustom
void PrepareOldDiffCustom()
Prepare for reading and old diff_custom by zero-ing the memory.
Definition: settings_sl.cpp:25
_old_vds
VehicleDefaultSettings _old_vds
Used for loading default vehicles settings from old savegames.
Definition: settings.cpp:55
SettingDesc::IsEditable
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition: settings.cpp:806
IniGroup
A group within an ini file.
Definition: ini_type.h:38
ST_CLIENT
@ ST_CLIENT
Client setting.
Definition: settings_internal.h:64
LG_ORIGINAL
@ LG_ORIGINAL
The original landscape generator.
Definition: genworld.h:20
FindWindowById
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1146
ClampU
static uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Definition: math_func.hpp:122
HandleOldDiffCustom
void HandleOldDiffCustom(bool savegame)
Reading of the old diff_custom array and transforming it to the new format.
Definition: settings_sl.cpp:36
SettingDesc::FormatValue
virtual void FormatValue(char *buf, const char *last, const void *object) const =0
Format the value of the setting associated with this object.
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition: settings_type.h:576
HasBit
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103
IniGroup::RemoveItem
void RemoveItem(const std::string &name)
Remove the item with the given name.
Definition: ini_load.cpp:107
SLE_VAR_NULL
@ SLE_VAR_NULL
useful to write zeros in savegame.
Definition: saveload.h:589
IntSettingDesc::ChangeValue
void ChangeValue(const void *object, int32 newvalue) const
Handle changing a value.
Definition: settings.cpp:1391
LookupManyOfMany
static size_t LookupManyOfMany(const std::vector< std::string > &many, const char *str)
Find the set-integer value MANYofMANY type in a string.
Definition: settings.cpp:194
SF_NO_NETWORK_SYNC
@ SF_NO_NETWORK_SYNC
Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set).
Definition: settings_internal.h:30
fileio_func.h
ST_COMPANY
@ ST_COMPANY
Company setting.
Definition: settings_internal.h:63
GCS_NOT_FOUND
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
Definition: newgrf_config.h:37
SaveLoad::length
uint16 length
(Conditional) length of the variable (eg. arrays) (max array size is 65536 elements).
Definition: saveload.h:659
GRFConfig::ident
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
Definition: newgrf_config.h:163
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:52
_network_bind_list
StringList _network_bind_list
The addresses to bind on.
Definition: network.cpp:66
StringSettingDesc::Read
const std::string & Read(const void *object) const
Read the string from the the actual setting.
Definition: settings.cpp:557
GRFConfig::status
GRFStatus status
NOSAVE: GRFStatus, enum.
Definition: newgrf_config.h:174
StringSettingDesc::post_callback
PostChangeCallback * post_callback
Callback when the setting has been changed.
Definition: settings_internal.h:272
SettingDesc::flags
SettingFlag flags
Handles how a setting would show up in the GUI (text/currency, etc.).
Definition: settings_internal.h:77
SaveLoad::conv
VarType conv
Type of the variable to be saved; this field combines both FileVarType and MemVarType.
Definition: saveload.h:658
_private_file
std::string _private_file
Private configuration file of OpenTTD.
Definition: settings.cpp:57
newgrf_config.h
IFV_PRIVATE_SECRETS
@ IFV_PRIVATE_SECRETS
1 PR#9298 Moving of settings from openttd.cfg to private.cfg / secrets.cfg.
Definition: settings.cpp:158
gamelog.h
fios.h
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
GLAT_SETTING
@ GLAT_SETTING
Setting changed.
Definition: gamelog.h:21
DC_EXEC
@ DC_EXEC
execute the given command
Definition: command_type.h:348
SettingDesc::IsSameValue
virtual bool IsSameValue(const IniItem *item, void *object) const =0
Check whether the value in the Ini item is the same as is saved in this setting in the object.
GRFIdentifier::md5sum
uint8 md5sum[16]
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
Definition: newgrf_config.h:85
IntSettingDesc::pre_check
PreChangeCheck * pre_check
Callback to check for the validity of the setting.
Definition: settings_internal.h:168
SetDParam
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:196
NetworkSendCommand
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const std::string &text, CompanyID company)
Prepare a DoCommand to be send over the network.
Definition: network_command.cpp:136
StringSettingDesc::max_length
uint32 max_length
Maximum length of the string, 0 means no maximum length.
Definition: settings_internal.h:270
DoCommandFlag
DoCommandFlag
List of flags for a command.
Definition: command_type.h:346
genworld.h
SettingDesc::AsStringSetting
const struct StringSettingDesc * AsStringSetting() const
Get the setting description of this setting as a string setting.
Definition: settings.cpp:842
CC_DEFAULT
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:23
ManyOfManySettingDesc::ParseValue
size_t ParseValue(const char *str) const override
Convert a string representation (external) of an integer-like setting to an integer.
Definition: settings.cpp:410
ConfigIniFile
IniFile to store a configuration.
Definition: settings.cpp:132
GRFIdentifier::grfid
uint32 grfid
GRF ID (defined by Action 0x08)
Definition: newgrf_config.h:84
IniGroup::Clear
void Clear()
Clear all items in the group.
Definition: ini_load.cpp:130
IFV_MAX_VERSION
@ IFV_MAX_VERSION
Highest possible ini-file version.
Definition: settings.cpp:161
ShowErrorMessage
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:383
GameSettings::game_creation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Definition: settings_type.h:577
GCF_INVALID
@ GCF_INVALID
GRF is unusable with this version of OpenTTD.
Definition: newgrf_config.h:30
GetGameSettings
static GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we're in the ...
Definition: settings_type.h:618
IniSaveSettings
static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool)
Save the values of settings to the inifile.
Definition: settings.cpp:647
SettingDesc::ParseValue
virtual void ParseValue(const IniItem *item, void *object) const =0
Parse/read the value from the Ini item into the setting associated with this object.
StringSettingDesc
String settings.
Definition: settings_internal.h:247
GRFBuildParamList
char * GRFBuildParamList(char *dst, const GRFConfig *c, const char *last)
Build a string containing space separated parameter values, and terminate.
Definition: newgrf_config.cpp:775
ListSettingDesc::ParseValue
void ParseValue(const IniItem *item, void *object) const override
Parse/read the value from the Ini item into the setting associated with this object.
Definition: settings.cpp:621
COMPANY_FIRST
@ COMPANY_FIRST
First company, same as owner.
Definition: company_type.h:22
SettingType
SettingType
Type of settings for filtering.
Definition: settings_internal.h:61
NETWORK_MAX_GRF_COUNT
static const uint NETWORK_MAX_GRF_COUNT
Maximum number of GRFs that can be sent.
Definition: config.h:95
DecodeHexText
static bool DecodeHexText(const char *pos, uint8 *dest, size_t dest_size)
Parse a sequence of characters (supposedly hex digits) into a sequence of bytes.
Definition: settings.cpp:937
StringSettingDesc::ChangeValue
void ChangeValue(const void *object, std::string &newval) const
Handle changing a string value.
Definition: settings.cpp:1640
GetGRFPresetList
StringList GetGRFPresetList()
Get the list of known NewGrf presets.
Definition: settings.cpp:1321
CommandCost
Common return value for all commands.
Definition: command_type.h:23
SetBitIterator
Iterable ensemble of each set bit in a value.
Definition: bitmath_func.hpp:329
IniFile::IniFile
IniFile(const char *const *list_group_names=nullptr)
Create a new ini file with given group names.
Definition: ini.cpp:37
settings_func.h
SF_NETWORK_ONLY
@ SF_NETWORK_ONLY
This setting only applies to network games.
Definition: settings_internal.h:22
GCF_UNSAFE
@ GCF_UNSAFE
GRF file is unsafe for static usage.
Definition: newgrf_config.h:24
GRFConfig
Information about GRF, used in the game and (part of it) in savegames.
Definition: newgrf_config.h:155
ParseIntList
static int ParseIntList(const char *p, T *items, int maxitems)
Parse an integerlist string and set each found value.
Definition: settings.cpp:227
DoCommandP
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:541
CC_HELP
static const TextColour CC_HELP
Colour for help lines.
Definition: console_type.h:26
span
A trimmed down version of what std::span will be in C++20.
Definition: span_type.hpp:60
SettingDesc::startup
bool startup
Setting has to be loaded directly at startup?.
Definition: settings_internal.h:78
GCF_SYSTEM
@ GCF_SYSTEM
GRF file is an openttd-internal system grf.
Definition: newgrf_config.h:23
IntSettingDesc
Base integer type, including boolean, settings.
Definition: settings_internal.h:136
SettingDesc::GetName
constexpr const std::string & GetName() const
Get the name of this setting.
Definition: settings_internal.h:88
IniItem::value
std::optional< std::string > value
The value of this item.
Definition: ini_type.h:28
GRFConfig::flags
uint8 flags
NOSAVE: GCF_Flags, bitset.
Definition: newgrf_config.h:173
GameConfig
Definition: game_config.hpp:15
IniLoadSettingList
static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &list)
Loads all items from a 'grpname' section into a list The list parameter can be a nullptr pointer,...
Definition: settings.cpp:745
ScriptConfig::GetName
const char * GetName() const
Get the name of the Script.
Definition: script_config.cpp:172
SF_NEWGAME_ONLY
@ SF_NEWGAME_ONLY
This setting cannot be changed in a game.
Definition: settings_internal.h:24
IniFile::SaveToDisk
bool SaveToDisk(const std::string &filename)
Save the Ini file's data to the disk.
Definition: ini.cpp:46
AIConfig::GetConfig
static AIConfig * GetConfig(CompanyID company, ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: ai_config.cpp:45
SecretSettingTables
static auto & SecretSettingTables()
List of all the secrets setting tables.
Definition: settings.cpp:106
StringSettingDesc::ParseValue
void ParseValue(const IniItem *item, void *object) const override
Parse/read the value from the Ini item into the setting associated with this object.
Definition: settings.cpp:614
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:53
StrStartsWith
bool StrStartsWith(const std::string_view str, const std::string_view prefix)
Check whether the given string starts with the given prefix.
Definition: string.cpp:367
CompanyProperties::settings
CompanySettings settings
settings specific for each company
Definition: company_base.h:104
GamelogStartAction
void GamelogStartAction(GamelogActionType at)
Stores information about new action, but doesn't allocate it Action is allocated only when there is a...
Definition: gamelog.cpp:69
CmdChangeSetting
CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Network-safe changing of settings (server-only).
Definition: settings.cpp:1501
MAX_COMPANIES
@ MAX_COMPANIES
Maximum number of companies.
Definition: company_type.h:23
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
StringList
std::vector< std::string > StringList
Type for a list of strings.
Definition: string_type.h:58
SyncCompanySettings
void SyncCompanySettings()
Sync all company settings in a multiplayer game.
Definition: settings.cpp:1602
safeguards.h
IniLoadSettings
static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup)
Load values from a group of an IniFile structure into the internal representation.
Definition: settings.cpp:571
ScriptConfig::StringToSettings
void StringToSettings(const std::string &value)
Convert a string which is stored in the config file or savegames to custom settings of this Script.
Definition: script_config.cpp:182
StrEmpty
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:64
DifficultySettings::quantity_sea_lakes
byte quantity_sea_lakes
the amount of seas/lakes
Definition: settings_type.h:88
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
GameSettings
All settings together for the game.
Definition: settings_type.h:575
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:57
OneOfManySettingDesc::many_cnvt
OnConvert * many_cnvt
callback procedure when loading value mechanism fails
Definition: settings_internal.h:223
IFV_0
@ IFV_0
0 All versions prior to introduction.
Definition: settings.cpp:157
ListSettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Convert an integer-array (intlist) to a string representation.
Definition: settings.cpp:318
GetSettingDesc
static constexpr const SettingDesc * GetSettingDesc(const SettingVariant &desc)
Helper to convert the type of the iterated settings description to a pointer to it.
Definition: settings_internal.h:318
DeleteGRFPresetFromConfig
void DeleteGRFPresetFromConfig(const char *config_name)
Delete a NewGRF configuration by preset name.
Definition: settings.cpp:1374
ErrorMessageData
The data of the error message.
Definition: error.h:29
VehicleDefaultSettings
Default settings for vehicles.
Definition: settings_type.h:557
error.h
ResetCurrencies
void ResetCurrencies(bool preserve_custom)
Will fill _currency_specs array with default values from origin_currency_specs Called only from newgr...
Definition: currency.cpp:157
IniSaveSettingList
static void IniSaveSettingList(IniFile &ini, const char *grpname, StringList &list)
Saves all items from a list into the 'grpname' section The list parameter can be a nullptr pointer,...
Definition: settings.cpp:767
stdafx.h
settings_table.h
BSWAP32
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
Definition: bitmath_func.hpp:390
IntSettingDesc::Write
void Write(const void *object, int32 value) const
Set the value of a setting.
Definition: settings.cpp:507
NEWGRF_DIR
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
Definition: fileio_type.h:117
_grfconfig_static
GRFConfig * _grfconfig_static
First item in list of static GRF set up.
Definition: newgrf_config.cpp:173
GamelogStopAction
void GamelogStopAction()
Stops logging of any changes.
Definition: gamelog.cpp:78
StrEndsWith
bool StrEndsWith(const std::string_view str, const std::string_view suffix)
Check whether the given string ends with the given suffix.
Definition: string.cpp:380
SlIsObjectCurrentlyValid
static bool SlIsObjectCurrentlyValid(SaveLoadVersion version_from, SaveLoadVersion version_to)
Checks if some version from/to combination falls within the range of the active savegame version.
Definition: saveload.h:1053
LoadGRFPresetFromConfig
GRFConfig * LoadGRFPresetFromConfig(const char *config_name)
Load a NewGRF configuration by preset-name.
Definition: settings.cpp:1341
OneOfManySettingDesc::ParseValue
size_t ParseValue(const char *str) const override
Convert a string representation (external) of an integer-like setting to an integer.
Definition: settings.cpp:395
WriteValue
void WriteValue(void *ptr, VarType conv, int64 val)
Write the value of a setting.
Definition: saveload.cpp:828
SettingDesc::IsStringSetting
virtual bool IsStringSetting() const
Check whether this setting is an string type setting.
Definition: settings_internal.h:103
OneOfManySettingDesc::many
std::vector< std::string > many
possible values for this type
Definition: settings_internal.h:222
_secrets_file
std::string _secrets_file
Secrets configuration file of OpenTTD.
Definition: settings.cpp:58
GenericSettingTables
static auto & GenericSettingTables()
List of all the generic setting tables.
Definition: settings.cpp:73
BoolSettingDesc::ParseValue
size_t ParseValue(const char *str) const override
Convert a string representation (external) of an integer-like setting to an integer.
Definition: settings.cpp:421
NetworkSettings::server_game_type
ServerGameType server_game_type
Server type: local / public / invite-only.
Definition: settings_type.h:278
IniLoadFile::group
IniGroup * group
the first group in the ini
Definition: ini_type.h:56
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
rev.h
WC_GAME_OPTIONS
@ WC_GAME_OPTIONS
Game options window; Window numbers:
Definition: window_type.h:604
Clamp
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:77
IConsoleListSettings
void IConsoleListSettings(const char *prefilter)
List all settings and their value to the console.
Definition: settings.cpp:1734
IniGroup::comment
std::string comment
comment for group
Definition: ini_type.h:44
FioCheckFileExists
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
Check whether the given file exists.
Definition: fileio.cpp:108
IniGroup::name
std::string name
name of group
Definition: ini_type.h:43
StrMakeValid
std::string StrMakeValid(const std::string &str, StringValidationSettings settings)
Scans the string for invalid characters and replaces then with a question mark '?' (if not ignored).
Definition: string.cpp:281
IniFile
Ini file that supports both loading and saving.
Definition: ini_type.h:89
IntSettingDesc::IsSameValue
bool IsSameValue(const IniItem *item, void *object) const override
Check whether the value in the Ini item is the same as is saved in this setting in the object.
Definition: settings.cpp:695
SettingDesc
Properties of config file settings.
Definition: settings_internal.h:72
PrivateSettingTables
static auto & PrivateSettingTables()
List of all the private setting tables.
Definition: settings.cpp:95
GameCreationSettings::land_generator
byte land_generator
the landscape generator
Definition: settings_type.h:310
SetSettingValue
bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1551
NO_DIRECTORY
@ NO_DIRECTORY
A path without any base directory.
Definition: fileio_type.h:125
GetVarMemType
static VarType GetVarMemType(VarType type)
Get the NumberType of a setting.
Definition: saveload.h:1065
CmdChangeCompanySetting
CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Change one of the per-company settings.
Definition: settings.cpp:1529
ScriptConfig::SettingsToString
std::string SettingsToString() const
Convert the custom settings to a string that can be stored in the config file or savegames.
Definition: script_config.cpp:208
IntSettingDesc::str
StringID str
(translated) string with descriptive text; gui and console
Definition: settings_internal.h:164
GRFConfig::next
struct GRFConfig * next
NOSAVE: Next item in the linked list.
Definition: newgrf_config.h:183
GameConfig::GetConfig
static GameConfig * GetConfig(ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: game_config.cpp:18
ScheduleErrorMessage
void ScheduleErrorMessage(const ErrorMessageData &data)
Schedule an error.
Definition: error_gui.cpp:457
IniSaveWindowSettings
void IniSaveWindowSettings(IniFile &ini, const char *grpname, void *desc)
Save a WindowDesc to config.
Definition: settings.cpp:796
DecodeHexNibble
static int DecodeHexNibble(char c)
Convert a character to a hex nibble value, or -1 otherwise.
Definition: settings.cpp:921
ListSettingDesc::def
const char * def
default value given when none is present
Definition: settings_internal.h:293
ScriptConfig::SSS_FORCE_NEWGAME
@ SSS_FORCE_NEWGAME
Get the newgame Script config.
Definition: script_config.hpp:104
SF_SCENEDIT_ONLY
@ SF_SCENEDIT_ONLY
This setting can only be changed in the scenario editor.
Definition: settings_internal.h:26
FGCM_NEWEST_VALID
@ FGCM_NEWEST_VALID
Find newest Grf, ignoring Grfs with GCF_INVALID set.
Definition: newgrf_config.h:202
seprintf
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:535
SF_GUI_DROPDOWN
@ SF_GUI_DROPDOWN
The value represents a limited number of string-options (internally integer) presented as dropdown.
Definition: settings_internal.h:20
SaveLoad::version_from
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
Definition: saveload.h:660
IntSettingDesc::Read
int32 Read(const void *object) const
Read the integer from the the actual setting.
Definition: settings.cpp:518
company_func.h
CC_ERROR
static const TextColour CC_ERROR
Colour for error lines.
Definition: console_type.h:24
SLE_VAR_STRQ
@ SLE_VAR_STRQ
string pointer enclosed in quotes
Definition: saveload.h:592
ListSettingDesc::IsSameValue
bool IsSameValue(const IniItem *item, void *object) const override
Check whether the value in the Ini item is the same as is saved in this setting in the object.
Definition: settings.cpp:730
SVS_NONE
@ SVS_NONE
Allow nothing and replace nothing.
Definition: string_type.h:49
IntSettingDesc::ParseValue
virtual size_t ParseValue(const char *str) const
Convert a string representation (external) of an integer-like setting to an integer.
Definition: settings.cpp:376
StringSettingDesc::Write
void Write(const void *object, const std::string &str) const
Write a string to the actual setting.
Definition: settings.cpp:547
IConsoleGetSetting
void IConsoleGetSetting(const char *name, bool force_newgame)
Output value of a specific setting to the console.
Definition: settings.cpp:1696
network.h
IntSettingDesc::max
uint32 max
maximum values
Definition: settings_internal.h:162
window_func.h
IniItem::name
std::string name
The name of this item.
Definition: ini_type.h:27
SF_SCENEDIT_TOO
@ SF_SCENEDIT_TOO
This setting can be changed in the scenario editor (only makes sense when SF_NEWGAME_ONLY is set).
Definition: settings_internal.h:25
Debug
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
SetBit
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Definition: bitmath_func.hpp:121
lengthof
#define lengthof(x)
Return the length of an fixed size array.
Definition: stdafx.h:378
StringSettingDesc::def
std::string def
Default value given when none is present.
Definition: settings_internal.h:269
_network_ban_list
StringList _network_ban_list
The banned clients.
Definition: network.cpp:68
ClientSettings::network
NetworkSettings network
settings related to the network
Definition: settings_type.h:595
SaveVersionInConfig
static void SaveVersionInConfig(IniFile &ini)
Save the version of OpenTTD to the ini file.
Definition: settings.cpp:1119
CMD_CHANGE_SETTING
@ CMD_CHANGE_SETTING
change a setting
Definition: command_type.h:309
IniGroup::item
IniItem * item
the first item in the group
Definition: ini_type.h:41
GetVariableAddress
static void * GetVariableAddress(const void *object, const SaveLoad &sld)
Get the address of the variable.
Definition: saveload.h:1096
IntSettingDesc::post_callback
PostChangeCallback * post_callback
Callback when the setting has been changed.
Definition: settings_internal.h:169
config.h
GetCompanySettingFromName
static const SettingDesc * GetCompanySettingFromName(std::string_view name)
Given a name of setting, return a company setting description of it.
Definition: settings.cpp:1459
ScriptConfig::Change
void Change(const char *name, int version=-1, bool force_exact_match=false, bool is_random=false)
Set another Script to be loaded in this slot.
Definition: script_config.cpp:19
ReadValue
int64 ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
Definition: saveload.cpp:804
ClientSettings::company
CompanySettings company
default values for per-company settings
Definition: settings_type.h:596
md5sumToString
char * md5sumToString(char *buf, const char *last, const uint8 md5sum[16])
Convert the md5sum to a hexadecimal string representation.
Definition: string.cpp:553
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:326
INIFILE_VERSION
const uint16 INIFILE_VERSION
Current ini-file version of OpenTTD.
Definition: settings.cpp:164
FGCM_EXACT
@ FGCM_EXACT
Only find Grfs matching md5sum.
Definition: newgrf_config.h:199
IniGroup::GetItem
IniItem * GetItem(const std::string &name, bool create)
Get the item with the given name, and if it doesn't exist and create is true it creates a new item.
Definition: ini_load.cpp:91
SettingDesc::IsIntSetting
virtual bool IsIntSetting() const
Check whether this setting is an integer type setting.
Definition: settings_internal.h:97
_network_host_list
StringList _network_host_list
The servers we know.
Definition: network.cpp:67
GRFConfig::filename
char * filename
Filename - either with or without full path.
Definition: newgrf_config.h:165
console_func.h
BoolSettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Format the value of the setting associated with this object.
Definition: settings.cpp:689
strecpy
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: string.cpp:112
_config_file
std::string _config_file
Configuration file of OpenTTD.
Definition: settings.cpp:56
WC_ERRMSG
@ WC_ERRMSG
Error message; Window numbers:
Definition: window_type.h:102
CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
Definition: genworld.h:47
IniLoadFile::LoadFromDisk
void LoadFromDisk(const std::string &filename, Subdirectory subdir)
Load the Ini file's data from the disk.
Definition: ini_load.cpp:215
Company
Definition: company_base.h:115
game_config.hpp
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3162
SF_NO_NETWORK
@ SF_NO_NETWORK
This setting does not apply to network games; it may not be changed during the game.
Definition: settings_internal.h:23
IniFileVersion
IniFileVersion
Ini-file versions.
Definition: settings.cpp:156
FillGRFDetails
bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir)
Find the GRFID of a given grf, and calculate its md5sum.
Definition: newgrf_config.cpp:368
ini_type.h
lastof
#define lastof(x)
Get the last element of an fixed size array.
Definition: stdafx.h:394
_settings_error_list
static ErrorList _settings_error_list
Errors while loading minimal settings.
Definition: settings.cpp:61
LoadFromConfig
void LoadFromConfig(bool startup)
Load the values from the configuration files.
Definition: settings.cpp:1207
CMD_CHANGE_COMPANY_SETTING
@ CMD_CHANGE_COMPANY_SETTING
change a company setting
Definition: command_type.h:310
SaveGRFPresetToConfig
void SaveGRFPresetToConfig(const char *config_name, GRFConfig *config)
Save a NewGRF configuration with a preset name.
Definition: settings.cpp:1359
DebugReconsiderSendRemoteMessages
void DebugReconsiderSendRemoteMessages()
Reconsider whether we need to send debug messages to either NetworkAdminConsole or IConsolePrint.
Definition: debug.cpp:282
network_func.h
GetSaveLoadFromSettingTable
void GetSaveLoadFromSettingTable(SettingTable settings, std::vector< SaveLoad > &saveloads)
Get the SaveLoad for all settings in the settings table.
Definition: settings.cpp:1444
ScriptConfig::HasScript
bool HasScript() const
Is this config attached to an Script? In other words, is there a Script that is assigned to this slot...
Definition: script_config.cpp:162
IntSettingDesc::def
int32 def
default value given when none is present
Definition: settings_internal.h:160
LoadIntList
static bool LoadIntList(const char *str, void *array, int nelems, VarType type)
Load parsed string-values into an integer-array (intlist)
Definition: settings.cpp:273
SetDParamStr
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:296
_settings_newgame
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:54
GCF_STATIC
@ GCF_STATIC
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:25
OneOfManySettingDesc::ParseSingleValue
static size_t ParseSingleValue(const char *str, size_t len, const std::vector< std::string > &many)
Find the index value of a ONEofMANY type in a string separated by |.
Definition: settings.cpp:173
WL_CRITICAL
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:25
debug.h
GRFConfig::param
uint32 param[0x80]
GRF parameters.
Definition: newgrf_config.h:176
_grfconfig_newgame
GRFConfig * _grfconfig_newgame
First item in list of default GRF set up.
Definition: newgrf_config.cpp:172
SettingDesc::AsIntSetting
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition: settings.cpp:832
ai_config.hpp
IniLoadFile::GetGroup
IniGroup * GetGroup(const std::string &name, bool create_new=true)
Get the group with the given name.
Definition: ini_load.cpp:163
IntSettingDesc::FormatValue
void FormatValue(char *buf, const char *last, const void *object) const override
Format the value of the setting associated with this object.
Definition: settings.cpp:683
IniGroup::next
IniGroup * next
the next group within this file
Definition: ini_type.h:39
IConsolePrint
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Definition: console.cpp:94