71 #include "table/strings.h"
72 #include "table/settings.h"
82 typedef std::list<ErrorMessageData>
ErrorList;
86 typedef void SettingDescProc(
IniFile *ini,
const SettingDesc *desc,
const char *grpname,
void *
object);
87 typedef void SettingDescProcList(
IniFile *ini,
const char *grpname,
StringList *list);
89 static bool IsSignedVarMemType(VarType vt);
98 "server_bind_addresses",
114 if (onelen == 0) onelen = strlen(one);
117 if (*one >=
'0' && *one <=
'9')
return strtoul(one, NULL, 0);
123 while (*s !=
'|' && *s != 0) s++;
124 if ((
size_t)(s - many) == onelen && !memcmp(one, many, onelen))
return idx;
125 if (*s == 0)
return (
size_t)-1;
146 while (*str ==
' ' || *str ==
'\t' || *str ==
'|') str++;
147 if (*str == 0)
break;
150 while (*s != 0 && *s !=
' ' && *s !=
'\t' && *s !=
'|') s++;
153 if (r == (
size_t)-1)
return r;
179 if (!comma)
return -1;
187 if (n == maxitems)
return -1;
189 long v = strtol(p, &end, 0);
190 if (p == end)
return -1;
191 if (
sizeof(
int) <
sizeof(
long)) v =
ClampToI32(v);
202 if (n != 0 && !comma)
return -1;
215 static bool LoadIntList(
const char *str,
void *array,
int nelems, VarType type)
221 memset(items, 0,
sizeof(items));
225 if (nitems != nelems)
return false;
232 for (i = 0; i != nitems; i++) ((byte*)array)[i] = items[i];
237 for (i = 0; i != nitems; i++) ((uint16*)array)[i] = items[i];
242 for (i = 0; i != nitems; i++) ((uint32*)array)[i] = items[i];
245 default: NOT_REACHED();
260 static void MakeIntList(
char *buf,
const char *last,
const void *array,
int nelems, VarType type)
263 const byte *p = (
const byte *)array;
265 for (i = 0; i != nelems; i++) {
268 case SLE_VAR_I8: v = *(
const int8 *)p; p += 1;
break;
269 case SLE_VAR_U8: v = *(
const uint8 *)p; p += 1;
break;
270 case SLE_VAR_I16: v = *(
const int16 *)p; p += 2;
break;
271 case SLE_VAR_U16: v = *(
const uint16 *)p; p += 2;
break;
272 case SLE_VAR_I32: v = *(
const int32 *)p; p += 4;
break;
273 case SLE_VAR_U32: v = *(
const uint32 *)p; p += 4;
break;
274 default: NOT_REACHED();
276 buf +=
seprintf(buf, last, (i == 0) ?
"%d" :
",%d", v);
287 static void MakeOneOfMany(
char *buf,
const char *last,
const char *many,
int id)
293 for (; *many !=
'|'; many++) {
303 while (*many !=
'\0' && *many !=
'|' && buf < last) *buf++ = *many++;
315 static void MakeManyOfMany(
char *buf,
const char *last,
const char *many, uint32 x)
321 for (; x != 0; x >>= 1, i++) {
323 while (*many != 0 && *many !=
'|') many++;
326 if (!init) buf +=
seprintf(buf, last,
"|");
329 buf +=
seprintf(buf, last,
"%d", i);
331 memcpy(buf, start, many - start);
336 if (*many ==
'|') many++;
350 const char *str = orig_str == NULL ?
"" : orig_str;
355 size_t val = strtoul(str, &end, 0);
364 ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS);
376 if (r != (
size_t)-1)
return (
void*)r;
387 if (r != (
size_t)-1)
return (
void*)r;
396 if (strcmp(str,
"true") == 0 || strcmp(str,
"on") == 0 || strcmp(str,
"1") == 0)
return (
void*)
true;
397 if (strcmp(str,
"false") == 0 || strcmp(str,
"off") == 0 || strcmp(str,
"0") == 0)
return (
void*)
false;
461 default: NOT_REACHED();
485 for (; sd->
save.
cmd != SL_END; sd++) {
492 s = strchr(sdb->
name,
'.');
501 item = group->
GetItem(s,
false);
502 if (item == NULL && group != group_def) {
505 item = group_def->
GetItem(s,
false);
510 const char *sc = strchr(s,
'.');
511 if (sc != NULL) item = ini->
GetGroup(s, sc - s)->
GetItem(sc + 1,
false);
529 if (p != NULL)
strecpy((
char*)ptr, (
const char*)p, (
char*)ptr + sld->
length - 1);
535 *(
char**)ptr = p == NULL ? NULL :
stredup((
const char*)p);
538 case SLE_VAR_CHAR:
if (p != NULL) *(
char *)ptr = *(
const char *)p;
break;
540 default: NOT_REACHED();
557 default: NOT_REACHED();
582 for (; sd->
save.
cmd != SL_END; sd++) {
592 s = strchr(sdb->
name,
'.');
597 if (group_def == NULL) group_def = ini->
GetGroup(grpname);
602 item = group->GetItem(s,
true);
605 if (item->
value != NULL) {
618 if (*(
bool*)ptr == (p != NULL))
continue;
623 if (*(byte*)ptr == (byte)(
size_t)p)
continue;
628 if (*(uint16*)ptr == (uint16)(
size_t)p)
continue;
633 if (*(uint32*)ptr == (uint32)(
size_t)p)
continue;
636 default: NOT_REACHED();
657 default: NOT_REACHED();
669 if (*(
char**)ptr == NULL) {
676 case SLE_VAR_CHAR: buf[0] = *(
char*)ptr; buf[1] =
'\0';
break;
677 default: NOT_REACHED();
685 default: NOT_REACHED();
707 if (group == NULL || list == NULL)
return;
711 for (
const IniItem *item = group->
item; item != NULL; item = item->
next) {
712 if (item->name != NULL) *list->
Append() =
stredup(item->name);
729 if (group == NULL || list == NULL)
return;
732 for (
char **iter = list->
Begin(); iter != list->
End(); iter++) {
770 (_game_mode == GM_NORMAL ||
771 (_game_mode == GM_EDITOR && !(this->desc.flags &
SGF_SCENEDIT_TOO))))
return false;
797 if (_game_mode != GM_MENU) {
805 static bool PopulationInLabelActive(int32 p1)
811 static bool RedrawScreen(int32 p1)
830 static bool InvalidateDetailsWindow(int32 p1)
836 static bool StationSpreadChanged(int32 p1)
843 static bool InvalidateBuildIndustryWindow(int32 p1)
849 static bool CloseSignalGUI(int32 p1)
857 static bool InvalidateTownViewWindow(int32 p1)
863 static bool DeleteSelectStationWindow(int32 p1)
869 static bool UpdateConsists(int32 p1)
881 static bool CheckInterval(int32 p1)
883 bool update_vehicles;
887 update_vehicles =
false;
890 update_vehicles =
true;
905 if (update_vehicles) {
911 v->SetServiceIntervalIsPercent(p1 != 0);
916 InvalidateDetailsWindow(0);
921 static bool UpdateInterval(
VehicleType type, int32 p1)
923 bool update_vehicles;
927 update_vehicles =
false;
930 update_vehicles =
true;
935 if (interval != p1)
return false;
937 if (update_vehicles) {
941 v->SetServiceInterval(p1);
946 InvalidateDetailsWindow(0);
951 static bool UpdateIntervalTrains(int32 p1)
956 static bool UpdateIntervalRoadVeh(int32 p1)
958 return UpdateInterval(
VEH_ROAD, p1);
961 static bool UpdateIntervalShips(int32 p1)
963 return UpdateInterval(
VEH_SHIP, p1);
966 static bool UpdateIntervalAircraft(int32 p1)
971 static bool TrainAccelerationModelChanged(int32 p1)
1013 FOR_ALL_ROADVEHICLES(rv) {
1036 FOR_ALL_ROADVEHICLES(rv) {
1043 static bool DragSignalsDensityChanged(int32)
1050 static bool TownFoundingChanged(int32 p1)
1060 static bool InvalidateVehTimetableWindow(int32 p1)
1066 static bool ZoomMinMaxChanged(int32 p1)
1068 extern void ConstrainAllViewportsZoom();
1069 ConstrainAllViewportsZoom();
1095 static bool InvalidateCompanyLiveryWindow(int32 p1)
1098 return RedrawScreen(p1);
1101 static bool InvalidateIndustryViewWindow(int32 p1)
1107 static bool InvalidateAISettingsWindow(int32 p1)
1156 static bool DifficultyNoiseChange(int32 i)
1158 if (_game_mode == GM_NORMAL) {
1168 static bool MaxNoAIsChange(int32 i)
1203 static bool CheckFreeformEdges(int32 p1)
1205 if (_game_mode == GM_MENU)
return true;
1216 FOR_ALL_BASE_STATIONS(st) {
1226 for (uint i = 0; i <
MapMaxX(); i++) {
1232 for (uint i = 1; i <
MapMaxX(); i++) {
1238 for (uint i = 0; i <
MapMaxY(); i++) {
1244 for (uint i = 1; i <
MapMaxY(); i++) {
1251 for (uint i = 0; i <
MapMaxX(); i++) {
1255 for (uint i = 0; i <
MapMaxY(); i++) {
1270 if (_game_mode == GM_MENU)
return true;
1280 static bool ChangeMaxHeightLevel(int32 p1)
1282 if (_game_mode == GM_NORMAL)
return false;
1283 if (_game_mode != GM_EDITOR)
return true;
1301 static bool StationCatchmentChanged(int32 p1)
1308 #ifdef ENABLE_NETWORK
1310 static bool UpdateClientName(int32 p1)
1316 static bool UpdateServerPassword(int32 p1)
1325 static bool UpdateRconPassword(int32 p1)
1334 static bool UpdateClientConfigValues(int32 p1)
1351 memset(_old_diff_custom, 0,
sizeof(_old_diff_custom));
1366 bool old_diff_custom_used =
false;
1367 for (uint i = 0; i < options_to_load && !old_diff_custom_used; i++) {
1368 old_diff_custom_used = (_old_diff_custom[i] != 0);
1371 if (!old_diff_custom_used)
return;
1374 for (uint i = 0; i < options_to_load; i++) {
1383 static void AILoadConfig(
IniFile *ini,
const char *grpname)
1394 if (group == NULL)
return;
1397 for (item = group->
item; c < MAX_COMPANIES && item != NULL; c++, item = item->next) {
1402 if (strcmp(item->
name,
"none") != 0) {
1403 DEBUG(script, 0,
"The AI by the name '%s' was no longer found, and removed from the list.", item->
name);
1411 static void GameLoadConfig(
IniFile *ini,
const char *grpname)
1420 if (group == NULL)
return;
1423 if (item == NULL)
return;
1429 if (strcmp(item->
name,
"none") != 0) {
1430 DEBUG(script, 0,
"The GameScript by the name '%s' was no longer found, and removed from the list.", item->
name);
1444 if (c >=
'0' && c <=
'9')
return c -
'0';
1445 if (c >=
'A' && c <=
'F')
return c + 10 -
'A';
1446 if (c >=
'a' && c <=
'f')
return c + 10 -
'a';
1460 while (dest_size > 0) {
1463 if (lo < 0)
return false;
1464 *dest++ = (hi << 4) | lo;
1484 if (group == NULL)
return NULL;
1486 for (item = group->
item; item != NULL; item = item->
next) {
1489 uint8 grfid_buf[4], md5sum[16];
1490 char *filename = item->
name;
1491 bool has_grfid =
false;
1492 bool has_md5sum =
false;
1497 filename += 1 + 2 *
lengthof(grfid_buf);
1499 if (has_md5sum) filename += 1 + 2 *
lengthof(md5sum);
1501 uint32 grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24);
1511 if (c == NULL) c =
new GRFConfig(filename);
1527 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND);
1529 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNSAFE);
1531 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_SYSTEM);
1533 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE);
1535 SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN);
1545 bool duplicate =
false;
1546 for (
const GRFConfig *gc = first; gc != NULL; gc = gc->
next) {
1571 static void AISaveConfig(
IniFile *ini,
const char *grpname)
1575 if (group == NULL)
return;
1595 static void GameSaveConfig(
IniFile *ini,
const char *grpname)
1599 if (group == NULL)
return;
1626 seprintf(version,
lastof(version),
"%08X", _openttd_newgrf_version);
1628 const char *
const versions[][2] = {
1629 {
"version_string", _openttd_revision },
1630 {
"version_number", version }
1633 for (uint i = 0; i <
lengthof(versions); i++) {
1639 static void GRFSaveConfig(
IniFile *ini,
const char *grpname,
const GRFConfig *list)
1645 for (c = list; c != NULL; c = c->
next) {
1647 char key[4 * 2 + 1 + 16 * 2 + 1 + MAX_PATH];
1659 static void HandleSettingDescs(
IniFile *ini, SettingDescProc *proc, SettingDescProcList *proc_list,
bool basic_settings =
true,
bool other_settings =
true)
1661 if (basic_settings) {
1662 proc(ini, (
const SettingDesc*)_misc_settings,
"misc", NULL);
1663 #if defined(WIN32) && !defined(DEDICATED)
1664 proc(ini, (
const SettingDesc*)_win32_settings,
"win32", NULL);
1668 if (other_settings) {
1669 proc(ini, _settings,
"patches", &_settings_newgame);
1670 proc(ini, _currency_settings,
"currency", &_custom_currency);
1671 proc(ini, _company_settings,
"company", &_settings_client.
company);
1673 #ifdef ENABLE_NETWORK
1681 static IniFile *IniLoadConfig()
1694 IniFile *ini = IniLoadConfig();
1703 AILoadConfig(ini,
"ai_players");
1704 GameLoadConfig(ini,
"game_scripts");
1707 IniLoadSettings(ini, _gameopt_settings,
"gameopt", &_settings_newgame);
1724 IniFile *ini = IniLoadConfig();
1734 AISaveConfig(ini,
"ai_players");
1735 GameSaveConfig(ini,
"game_scripts");
1749 IniFile *ini = IniLoadConfig();
1751 for (group = ini->
group; group != NULL; group = group->
next) {
1752 if (strncmp(group->
name,
"preset-", 7) == 0) {
1768 size_t len = strlen(config_name) + 8;
1769 char *section = (
char*)alloca(len);
1770 seprintf(section, section + len - 1,
"preset-%s", config_name);
1772 IniFile *ini = IniLoadConfig();
1787 size_t len = strlen(config_name) + 8;
1788 char *section = (
char*)alloca(len);
1789 seprintf(section, section + len - 1,
"preset-%s", config_name);
1791 IniFile *ini = IniLoadConfig();
1792 GRFSaveConfig(ini, section, config);
1803 size_t len = strlen(config_name) + 8;
1804 char *section = (
char*)alloca(len);
1805 seprintf(section, section + len - 1,
"preset-%s", config_name);
1807 IniFile *ini = IniLoadConfig();
1813 const SettingDesc *GetSettingDescription(uint index)
1815 if (index >=
lengthof(_settings))
return NULL;
1816 return &_settings[index];
1832 const SettingDesc *sd = GetSettingDescription(p1);
1843 int32 newval = (int32)p2;
1886 int32 newval = (int32)p2;
1922 if (_game_mode != GM_MENU) {
1933 if (force_newgame) {
1954 const SettingDesc *sd = &_company_settings[index];
1971 for (sd = _company_settings; sd->
save.
cmd != SL_END; sd++) {
1977 #if defined(ENABLE_NETWORK)
1985 for (sd = _company_settings; sd->
save.
cmd != SL_END; sd++, i++) {
2023 *var = strcmp(value,
"(null)") == 0 ? NULL :
stredup(value);
2045 for (*i = 0, sd = _settings; sd->
save.
cmd != SL_END; sd++, (*i)++) {
2047 if (strcmp(sd->
desc.
name, name) == 0)
return sd;
2051 for (*i = 0, sd = _settings; sd->
save.
cmd != SL_END; sd++, (*i)++) {
2053 const char *short_name = strchr(sd->
desc.
name,
'.');
2054 if (short_name != NULL) {
2056 if (strcmp(short_name, name) == 0)
return sd;
2060 if (strncmp(name,
"company.", 8) == 0) name += 8;
2062 for (*i = 0, sd = _company_settings; sd->
save.
cmd != SL_END; sd++, (*i)++) {
2064 if (strcmp(sd->
desc.
name, name) == 0)
return sd;
2072 void IConsoleSetSetting(
const char *name,
const char *value,
bool force_newgame)
2099 IConsoleError(
"This command/variable is not available during network games.");
2101 IConsoleError(
"This command/variable is only available to a network server.");
2106 void IConsoleSetSetting(
const char *name,
int value)
2131 ptr =
GetVariableAddress((_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game, &sd->
save);
2137 seprintf(value,
lastof(value), (*(
const bool*)ptr != 0) ?
"on" :
"off");
2158 if (prefilter != NULL && strstr(sd->
desc.
name, prefilter) == NULL)
continue;
2163 seprintf(value,
lastof(value), (*(
const bool *)ptr != 0) ?
"on" :
"off");
2183 for (; osd->
save.
cmd != SL_END; osd++) {
2187 if (!SlObjectMember(ptr, sld))
continue;
2204 for (i = sd; i->
save.
cmd != SL_END; i++) {
2205 length += SlCalcObjMemberLength(
object, &i->
save);
2209 for (i = sd; i->
save.
cmd != SL_END; i++) {
2211 SlObjectMember(ptr, &i->
save);
2215 static void Load_OPTS()
2225 static void Load_PATS()
2233 static void Check_PATS()
2238 static void Save_PATS()
2255 extern const ChunkHandler _setting_chunk_handlers[] = {
2256 {
'OPTS', NULL, Load_OPTS, NULL, NULL, CH_RIFF},
2257 {
'PATS', Save_PATS, Load_PATS, NULL, Check_PATS, CH_RIFF |
CH_LAST},
2260 static bool IsSignedVarMemType(VarType vt)