2009-08-21 20:21:05 +00:00
/*
* This file is part of OpenTTD .
* OpenTTD is free software ; you can redistribute it and / or modify it under the terms of the GNU General Public License as published by the Free Software Foundation , version 2.
* OpenTTD is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details . You should have received a copy of the GNU General Public License along with OpenTTD . If not , see < http : //www.gnu.org/licenses/>.
*/
2010-08-01 19:22:34 +00:00
/**
* @ file settings . cpp
2006-04-22 00:10:38 +00:00
* All actions handling saving and loading of the settings / configuration goes on in this file .
2009-03-21 23:16:09 +00:00
* The file consists of three parts :
2006-04-22 00:10:38 +00:00
* < ol >
* < li > Parsing the configuration file ( openttd . cfg ) . This is achieved with the ini_ functions which
* handle various types , such as normal ' key = value ' pairs , lists and value combinations of
* lists , strings , integers , ' bit ' - masks and element selections .
* < li > Handle reading and writing to the setting - structures from inside the game either from
* the console for example or through the gui with CMD_ functions .
* < li > Handle saving / loading of the PATS chunk inside the savegame .
* < / ol >
* @ see SettingDesc
* @ see SaveLoad
*/
2004-08-09 17:04:08 +00:00
# include "stdafx.h"
2021-05-30 08:40:59 +00:00
# include <array>
2021-06-28 14:39:48 +00:00
# include <charconv>
2019-03-22 03:16:21 +00:00
# include <limits>
2005-08-06 14:59:54 +00:00
# include "currency.h"
2005-07-19 06:47:07 +00:00
# include "screenshot.h"
2007-01-02 17:34:03 +00:00
# include "network/network.h"
2008-05-30 18:20:26 +00:00
# include "network/network_func.h"
2008-01-07 00:19:09 +00:00
# include "settings_internal.h"
2007-12-21 21:50:46 +00:00
# include "command_func.h"
2008-05-24 10:15:06 +00:00
# include "console_func.h"
2009-12-02 16:38:33 +00:00
# include "pathfinder/pathfinder_type.h"
(svn r5946) -Add: merged the TGP branch to mainline. TGP adds:
- New optional landscape generator (TerraGenesis Perlin)
- Load heightmaps (either BMP or PNG)
- Progress dialog while generating worlds (no longer a 'hanging' screen)
- New dialogs for NewGame, Create Scenario and Play Heightmap
- Easier to configure your landscape
- More things to configure (tree-placer, ..)
- Speedup of world generation
- New console command 'restart': restart the map EXACTLY as it was when you
first started it (needs a game made after or with this commit)
- New console command 'getseed': get the seed of your map and share it with
others (of course only works with generated maps)
- Many new, world generation related, things
- Many internal cleanups and rewrites
Many tnx to those people who helped making this:
Belugas, DaleStan, glx, KUDr, RichK67, Rubidium, and TrueLight (alfabetic)
Many tnx to those who helped testing:
Arnau, Bjarni, and tokai (alfabetic)
And to all other people who helped testing and sending comments / bugs
Stats: 673 lines changed, 3534 new lines, 79 new strings
2006-08-19 10:00:30 +00:00
# include "genworld.h"
2007-10-18 20:32:36 +00:00
# include "train.h"
2008-03-28 08:53:36 +00:00
# include "news_func.h"
2007-12-19 20:45:46 +00:00
# include "window_func.h"
2007-12-29 09:24:26 +00:00
# include "sound_func.h"
2008-09-30 20:51:04 +00:00
# include "company_func.h"
2008-05-04 21:53:36 +00:00
# include "rev.h"
2021-02-13 21:51:18 +00:00
# if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
2006-11-16 22:05:33 +00:00
# include "fontcache.h"
# endif
2008-03-26 10:08:17 +00:00
# include "textbuf_gui.h"
2008-04-03 21:54:31 +00:00
# include "rail_gui.h"
2008-05-08 16:48:29 +00:00
# include "elrail_func.h"
2011-12-10 13:54:10 +00:00
# include "error.h"
2008-01-13 01:21:35 +00:00
# include "town.h"
2008-01-13 21:41:24 +00:00
# include "video/video_driver.hpp"
# include "sound/sound_driver.hpp"
# include "music/music_driver.hpp"
# include "blitter/factory.hpp"
2009-08-09 16:54:03 +00:00
# include "base_media_base.h"
2008-06-03 18:35:58 +00:00
# include "gamelog.h"
2008-07-22 14:17:29 +00:00
# include "settings_func.h"
2008-08-24 13:50:31 +00:00
# include "ini_type.h"
2009-01-12 17:11:45 +00:00
# include "ai/ai_config.hpp"
2010-01-21 23:19:50 +00:00
# include "ai/ai.hpp"
2011-12-19 20:56:34 +00:00
# include "game/game_config.hpp"
# include "game/game.hpp"
2009-05-26 22:45:48 +00:00
# include "ship.h"
2010-02-08 23:46:35 +00:00
# include "smallmap_gui.h"
2010-03-06 12:56:57 +00:00
# include "roadveh.h"
2010-06-13 14:14:37 +00:00
# include "fios.h"
2011-12-10 16:05:26 +00:00
# include "strings_func.h"
2021-04-11 12:30:13 +00:00
# include "vehicle_func.h"
2008-01-13 01:21:35 +00:00
2021-05-30 13:59:40 +00:00
# include "saveload/compat/settings_sl_compat.h"
2009-01-21 02:31:55 +00:00
# include "void_map.h"
# include "station_base.h"
2021-02-13 21:51:18 +00:00
# if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
2018-11-25 00:32:48 +00:00
# define HAS_TRUETYPE_FONT
# endif
2008-01-13 01:21:35 +00:00
# include "table/strings.h"
2009-03-21 23:16:09 +00:00
# include "table/settings.h"
2004-08-09 17:04:08 +00:00
2014-04-23 20:13:33 +00:00
# include "safeguards.h"
2008-05-29 15:13:28 +00:00
ClientSettings _settings_client ;
2010-12-11 15:14:28 +00:00
GameSettings _settings_game ; ///< Game settings of a running game or the scenario editor.
GameSettings _settings_newgame ; ///< Game settings for new games (updated from the intro screen).
2021-06-28 14:39:48 +00:00
VehicleDefaultSettings _old_vds ; ///< Used for loading default vehicles settings from old savegames.
std : : string _config_file ; ///< Configuration file of OpenTTD.
std : : string _private_file ; ///< Private configuration file of OpenTTD.
std : : string _secrets_file ; ///< Secrets configuration file of OpenTTD.
2006-03-02 02:22:15 +00:00
2012-05-14 21:04:49 +00:00
typedef std : : list < ErrorMessageData > ErrorList ;
static ErrorList _settings_error_list ; ///< Errors while loading minimal settings.
2021-06-21 16:46:27 +00:00
typedef span < const SettingVariant > SettingTable ;
2012-05-14 21:04:49 +00:00
2021-06-28 13:35:00 +00:00
/**
2021-06-28 14:39:48 +00:00
* List of all the generic setting tables .
2021-06-28 13:35:00 +00:00
*
* There are a few tables that are special and not processed like the rest :
* - _currency_settings
* - _misc_settings
* - _company_settings
* - _win32_settings
* As such , they are not part of this list .
*/
2021-06-28 14:39:48 +00:00
static const SettingTable _generic_setting_tables [ ] = {
2021-06-28 13:35:00 +00:00
_settings ,
_network_settings ,
} ;
2021-06-28 14:39:48 +00:00
/**
* List of all the private setting tables .
*/
static const SettingTable _private_setting_tables [ ] = {
_network_private_settings ,
} ;
/**
* List of all the secrets setting tables .
*/
static const SettingTable _secrets_setting_tables [ ] = {
_network_secrets_settings ,
} ;
2021-07-01 17:59:13 +00:00
typedef void SettingDescProc ( IniFile & ini , const SettingTable & desc , const char * grpname , void * object , bool only_startup ) ;
typedef void SettingDescProcList ( IniFile & ini , const char * grpname , StringList & list ) ;
2006-04-22 13:17:13 +00:00
2006-05-27 16:12:16 +00:00
static bool IsSignedVarMemType ( VarType vt ) ;
2004-08-09 17:04:08 +00:00
2021-07-01 17:59:13 +00:00
/**
* IniFile to store a configuration .
*/
class ConfigIniFile : public IniFile {
private :
inline static const char * const list_group_names [ ] = {
" bans " ,
" newgrf " ,
" servers " ,
" server_bind_addresses " ,
nullptr ,
} ;
public :
ConfigIniFile ( const std : : string & filename ) : IniFile ( list_group_names )
{
this - > LoadFromDisk ( filename , NO_DIRECTORY ) ;
}
} ;
2021-06-28 14:39:48 +00:00
/**
* Ini - file versions .
*
* Sometimes we move settings between different ini - files , as we need to know
* when we have to load / remove it from the old versus reading it from the new
* location . These versions assist with situations like that .
*/
enum IniFileVersion : uint32 {
IFV_0 , ///< 0 All versions prior to introduction.
IFV_PRIVATE_SECRETS , ///< 1 PR#9298 Moving of settings from openttd.cfg to private.cfg / secrets.cfg.
IFV_MAX_VERSION , ///< Highest possible ini-file version.
} ;
const uint16 INIFILE_VERSION = ( IniFileVersion ) ( IFV_MAX_VERSION - 1 ) ; ///< Current ini-file version of OpenTTD.
2021-06-21 16:39:27 +00:00
/**
* Helper to convert the type of the iterated settings description to a pointer to it .
* @ param desc The type of the iterator of the value in SettingTable .
* @ return The actual pointer to SettingDesc .
*/
2021-06-21 16:46:27 +00:00
static constexpr const SettingDesc * GetSettingDesc ( const SettingVariant & desc )
2021-06-21 16:39:27 +00:00
{
2021-06-21 16:46:27 +00:00
return std : : visit ( [ ] ( auto & & arg ) - > const SettingDesc * { return & arg ; } , desc ) ;
2021-06-21 16:39:27 +00:00
}
2010-08-01 19:22:34 +00:00
/**
2013-01-08 22:46:42 +00:00
* Find the index value of a ONEofMANY type in a string separated by |
2021-05-23 17:16:56 +00:00
* @ param str the current value of the setting for which a value needs found
* @ param len length of the string
2006-02-04 22:48:57 +00:00
* @ param many full domain of values the ONEofMANY setting can have
2010-08-01 19:44:49 +00:00
* @ return the integer index of the full - list , or - 1 if not found
*/
2021-05-23 17:16:56 +00:00
size_t OneOfManySettingDesc : : ParseSingleValue ( const char * str , size_t len , const std : : vector < std : : string > & many )
2004-08-09 17:04:08 +00:00
{
2007-04-04 01:35:16 +00:00
/* check if it's an integer */
2021-05-23 17:16:56 +00:00
if ( isdigit ( * str ) ) return strtoul ( str , nullptr , 0 ) ;
2004-09-10 19:02:27 +00:00
2021-05-23 17:16:56 +00:00
size_t idx = 0 ;
for ( auto one : many ) {
if ( one . size ( ) = = len & & strncmp ( one . c_str ( ) , str , len ) = = 0 ) return idx ;
2004-08-09 17:04:08 +00:00
idx + + ;
}
2021-05-23 17:16:56 +00:00
return ( size_t ) - 1 ;
2004-08-09 17:04:08 +00:00
}
2010-08-01 19:22:34 +00:00
/**
* Find the set - integer value MANYofMANY type in a string
2006-02-04 22:48:57 +00:00
* @ param many full domain of values the MANYofMANY setting can have
* @ param str the current string value of the setting , each individual
2013-01-08 22:46:42 +00:00
* of separated by a whitespace , tab or | character
2010-08-01 19:44:49 +00:00
* @ return the ' fully ' set integer , or - 1 if a set is not found
*/
2021-05-23 17:16:56 +00:00
static size_t LookupManyOfMany ( const std : : vector < std : : string > & many , const char * str )
2004-08-09 17:04:08 +00:00
{
const char * s ;
2011-05-29 18:35:31 +00:00
size_t r ;
size_t res = 0 ;
2004-08-09 17:04:08 +00:00
2006-02-01 07:36:15 +00:00
for ( ; ; ) {
2007-04-04 01:35:16 +00:00
/* skip "whitespace" */
2004-08-09 17:04:08 +00:00
while ( * str = = ' ' | | * str = = ' \t ' | | * str = = ' | ' ) str + + ;
if ( * str = = 0 ) break ;
s = str ;
while ( * s ! = 0 & & * s ! = ' ' & & * s ! = ' \t ' & & * s ! = ' | ' ) s + + ;
2021-05-23 17:16:56 +00:00
r = OneOfManySettingDesc : : ParseSingleValue ( str , s - str , many ) ;
2011-05-29 18:35:31 +00:00
if ( r = = ( size_t ) - 1 ) return r ;
2004-08-09 17:04:08 +00:00
2011-06-13 07:43:48 +00:00
SetBit ( res , ( uint8 ) r ) ; // value found, set it
2004-08-09 17:04:08 +00:00
if ( * s = = 0 ) break ;
str = s + 1 ;
}
return res ;
}
2010-08-01 19:22:34 +00:00
/**
* Parse an integerlist string and set each found value
2013-01-08 22:46:42 +00:00
* @ param p the string to be parsed . Each element in the list is separated by a
2006-04-22 00:10:38 +00:00
* comma or a space character
2006-02-04 22:48:57 +00:00
* @ param items pointer to the integerlist - array that will be filled with values
* @ param maxitems the maximum number of elements the integerlist - array has
2010-08-01 19:44:49 +00:00
* @ return returns the number of items found , or - 1 on an error
*/
2019-03-22 03:16:21 +00:00
template < typename T >
static int ParseIntList ( const char * p , T * items , int maxitems )
2004-08-09 17:04:08 +00:00
{
2010-04-07 21:18:17 +00:00
int n = 0 ; // number of items read so far
bool comma = false ; // do we accept comma?
while ( * p ! = ' \0 ' ) {
switch ( * p ) {
case ' , ' :
/* Do not accept multiple commas between numbers */
if ( ! comma ) return - 1 ;
comma = false ;
2017-08-13 18:38:42 +00:00
FALLTHROUGH ;
2010-04-07 21:18:17 +00:00
case ' ' :
p + + ;
break ;
default : {
if ( n = = maxitems ) return - 1 ; // we don't accept that many numbers
char * end ;
2019-03-22 03:16:21 +00:00
unsigned long v = strtoul ( p , & end , 0 ) ;
2010-04-07 21:18:17 +00:00
if ( p = = end ) return - 1 ; // invalid character (not a number)
2019-03-22 03:16:21 +00:00
if ( sizeof ( T ) < sizeof ( v ) ) v = Clamp < unsigned long > ( v , std : : numeric_limits < T > : : min ( ) , std : : numeric_limits < T > : : max ( ) ) ;
2010-04-07 21:18:17 +00:00
items [ n + + ] = v ;
p = end ; // first non-number
comma = true ; // we accept comma now
break ;
}
}
2004-08-09 17:04:08 +00:00
}
2010-04-07 21:18:17 +00:00
/* If we have read comma but no number after it, fail.
* We have read comma when ( n ! = 0 ) and comma is not allowed */
if ( n ! = 0 & & ! comma ) return - 1 ;
2004-08-09 17:04:08 +00:00
return n ;
}
2010-08-01 19:22:34 +00:00
/**
* Load parsed string - values into an integer - array ( intlist )
2006-02-04 22:48:57 +00:00
* @ param str the string that contains the values ( and will be parsed )
* @ param array pointer to the integer - arrays that will be filled
* @ param nelems the number of elements the array holds . Maximum is 64 elements
* @ param type the type of elements the array holds ( eg INT8 , UINT16 , etc . )
2010-08-01 19:44:49 +00:00
* @ return return true on success and false on error
*/
2010-04-07 20:28:02 +00:00
static bool LoadIntList ( const char * str , void * array , int nelems , VarType type )
2004-08-09 17:04:08 +00:00
{
2019-03-22 03:16:21 +00:00
unsigned long items [ 64 ] ;
2006-02-04 22:48:57 +00:00
int i , nitems ;
2004-09-10 19:02:27 +00:00
2019-04-10 21:07:06 +00:00
if ( str = = nullptr ) {
2004-08-09 17:04:08 +00:00
memset ( items , 0 , sizeof ( items ) ) ;
nitems = nelems ;
} else {
2010-04-07 20:28:02 +00:00
nitems = ParseIntList ( str , items , lengthof ( items ) ) ;
2006-02-04 22:48:57 +00:00
if ( nitems ! = nelems ) return false ;
2004-08-09 17:04:08 +00:00
}
2006-02-01 07:36:15 +00:00
switch ( type ) {
2012-04-17 19:44:59 +00:00
case SLE_VAR_BL :
case SLE_VAR_I8 :
case SLE_VAR_U8 :
for ( i = 0 ; i ! = nitems ; i + + ) ( ( byte * ) array ) [ i ] = items [ i ] ;
break ;
case SLE_VAR_I16 :
case SLE_VAR_U16 :
for ( i = 0 ; i ! = nitems ; i + + ) ( ( uint16 * ) array ) [ i ] = items [ i ] ;
break ;
case SLE_VAR_I32 :
case SLE_VAR_U32 :
for ( i = 0 ; i ! = nitems ; i + + ) ( ( uint32 * ) array ) [ i ] = items [ i ] ;
break ;
default : NOT_REACHED ( ) ;
2004-08-09 17:04:08 +00:00
}
return true ;
}
2010-08-01 19:22:34 +00:00
/**
* Convert an integer - array ( intlist ) to a string representation . Each value
2013-01-08 22:46:42 +00:00
* is separated by a comma or a space character
2006-02-04 22:48:57 +00:00
* @ param buf output buffer where the string - representation will be stored
2008-10-28 14:42:31 +00:00
* @ param last last item to write to in the output buffer
2006-02-04 22:48:57 +00:00
* @ param array pointer to the integer - arrays that is read from
* @ param nelems the number of elements the array holds .
2010-08-01 19:44:49 +00:00
* @ param type the type of elements the array holds ( eg INT8 , UINT16 , etc . )
*/
2021-05-22 11:39:41 +00:00
void ListSettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
2004-08-09 17:04:08 +00:00
{
2021-05-31 20:26:44 +00:00
const byte * p = static_cast < const byte * > ( GetVariableAddress ( object , this - > save ) ) ;
2004-08-09 17:04:08 +00:00
int i , v = 0 ;
2006-02-01 07:36:15 +00:00
2021-05-22 11:39:41 +00:00
for ( i = 0 ; i ! = this - > save . length ; i + + ) {
switch ( GetVarMemType ( this - > save . conv ) ) {
2012-04-17 19:44:59 +00:00
case SLE_VAR_BL :
case SLE_VAR_I8 : v = * ( const int8 * ) p ; p + = 1 ; break ;
case SLE_VAR_U8 : v = * ( const uint8 * ) p ; p + = 1 ; break ;
case SLE_VAR_I16 : v = * ( const int16 * ) p ; p + = 2 ; break ;
case SLE_VAR_U16 : v = * ( const uint16 * ) p ; p + = 2 ; break ;
case SLE_VAR_I32 : v = * ( const int32 * ) p ; p + = 4 ; break ;
case SLE_VAR_U32 : v = * ( const uint32 * ) p ; p + = 4 ; break ;
default : NOT_REACHED ( ) ;
2004-08-09 17:04:08 +00:00
}
2021-05-22 11:39:41 +00:00
if ( IsSignedVarMemType ( this - > save . conv ) ) {
2019-03-22 03:37:53 +00:00
buf + = seprintf ( buf , last , ( i = = 0 ) ? " %d " : " ,%d " , v ) ;
} else {
buf + = seprintf ( buf , last , ( i = = 0 ) ? " %u " : " ,%u " , v ) ;
}
2004-08-09 17:04:08 +00:00
}
}
2021-05-23 17:16:56 +00:00
char * OneOfManySettingDesc : : FormatSingleValue ( char * buf , const char * last , uint id ) const
2004-08-09 17:04:08 +00:00
{
2021-05-23 17:16:56 +00:00
if ( id > = this - > many . size ( ) ) {
return buf + seprintf ( buf , last , " %d " , id ) ;
2004-08-09 17:04:08 +00:00
}
2021-05-23 17:16:56 +00:00
return strecpy ( buf , this - > many [ id ] . c_str ( ) , last ) ;
2004-08-09 17:04:08 +00:00
}
2021-05-23 17:16:56 +00:00
void OneOfManySettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
2004-08-09 17:04:08 +00:00
{
2021-05-24 08:42:02 +00:00
uint id = ( uint ) this - > Read ( object ) ;
2021-05-23 17:16:56 +00:00
this - > FormatSingleValue ( buf , last , id ) ;
}
2006-02-04 22:52:30 +00:00
2021-05-23 17:16:56 +00:00
void ManyOfManySettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
{
2021-05-24 08:42:02 +00:00
uint bitmask = ( uint ) this - > Read ( object ) ;
2021-05-23 17:16:56 +00:00
uint id = 0 ;
bool first = true ;
FOR_EACH_SET_BIT ( id , bitmask ) {
if ( ! first ) buf = strecpy ( buf , " | " , last ) ;
buf = this - > FormatSingleValue ( buf , last , id ) ;
first = false ;
2006-02-04 22:52:30 +00:00
}
2004-08-09 17:04:08 +00:00
}
2010-08-01 19:22:34 +00:00
/**
2021-05-22 18:57:41 +00:00
* Convert a string representation ( external ) of an integer - like setting to an integer .
* @ param str Input string that will be parsed based on the type of desc .
* @ return The value from the parse string , or the default value of the setting .
2010-08-01 19:44:49 +00:00
*/
2021-05-22 18:57:41 +00:00
size_t IntSettingDesc : : ParseValue ( const char * str ) const
2006-02-04 22:48:57 +00:00
{
2021-05-23 17:16:56 +00:00
char * end ;
size_t val = strtoul ( str , & end , 0 ) ;
if ( end = = str ) {
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_INVALID_VALUE ) ;
msg . SetDParamStr ( 0 , str ) ;
msg . SetDParamStr ( 1 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
return this - > def ;
}
if ( * end ! = ' \0 ' ) {
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_TRAILING_CHARACTERS ) ;
msg . SetDParamStr ( 0 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
}
return val ;
}
2012-04-17 19:44:59 +00:00
2021-05-23 17:16:56 +00:00
size_t OneOfManySettingDesc : : ParseValue ( const char * str ) const
{
size_t r = OneOfManySettingDesc : : ParseSingleValue ( str , strlen ( str ) , this - > many ) ;
/* if the first attempt of conversion from string to the appropriate value fails,
* look if we have defined a converter from old value to new value . */
if ( r = = ( size_t ) - 1 & & this - > many_cnvt ! = nullptr ) r = this - > many_cnvt ( str ) ;
if ( r ! = ( size_t ) - 1 ) return r ; // and here goes converted value
2012-04-17 19:44:59 +00:00
2021-05-23 17:16:56 +00:00
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_INVALID_VALUE ) ;
msg . SetDParamStr ( 0 , str ) ;
msg . SetDParamStr ( 1 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
return this - > def ;
}
2004-08-09 17:04:08 +00:00
2021-05-23 17:16:56 +00:00
size_t ManyOfManySettingDesc : : ParseValue ( const char * str ) const
{
size_t r = LookupManyOfMany ( this - > many , str ) ;
if ( r ! = ( size_t ) - 1 ) return r ;
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_INVALID_VALUE ) ;
msg . SetDParamStr ( 0 , str ) ;
msg . SetDParamStr ( 1 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
2021-05-22 19:09:30 +00:00
return this - > def ;
2004-08-09 17:04:08 +00:00
}
2021-05-23 16:20:49 +00:00
size_t BoolSettingDesc : : ParseValue ( const char * str ) const
{
if ( strcmp ( str , " true " ) = = 0 | | strcmp ( str , " on " ) = = 0 | | strcmp ( str , " 1 " ) = = 0 ) return true ;
if ( strcmp ( str , " false " ) = = 0 | | strcmp ( str , " off " ) = = 0 | | strcmp ( str , " 0 " ) = = 0 ) return false ;
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_INVALID_VALUE ) ;
msg . SetDParamStr ( 0 , str ) ;
msg . SetDParamStr ( 1 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
return this - > def ;
}
2010-08-01 19:22:34 +00:00
/**
2021-05-24 08:42:02 +00:00
* Make the value valid and then write it to the setting .
* See # MakeValidValid and # Write for more details .
2021-05-22 18:44:09 +00:00
* @ param object The object the setting is to be saved in .
* @ param val Signed version of the new value .
*/
2021-05-24 08:42:02 +00:00
void IntSettingDesc : : MakeValueValidAndWrite ( const void * object , int32 val ) const
2021-05-22 18:44:09 +00:00
{
2021-05-24 08:42:02 +00:00
this - > MakeValueValid ( val ) ;
this - > Write ( object , val ) ;
}
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2021-05-24 08:42:02 +00:00
/**
* Make the value valid given the limitations of this setting .
*
* In the case of int settings this is ensuring the value is between the minimum and
2021-06-03 19:18:29 +00:00
* maximum value , with a special case for 0 if SF_GUI_0_IS_SPECIAL is set .
2021-05-24 08:42:02 +00:00
* This is generally done by clamping the value so it is within the allowed value range .
2021-06-03 19:18:29 +00:00
* However , for SF_GUI_DROPDOWN the default is used when the value is not valid .
2021-05-24 08:42:02 +00:00
* @ param val The value to make valid .
*/
void IntSettingDesc : : MakeValueValid ( int32 & val ) const
{
2021-05-23 17:27:46 +00:00
/* We need to take special care of the uint32 type as we receive from the function
* a signed integer . While here also bail out on 64 - bit settings as those are not
* supported . Unsigned 8 and 16 - bit variables are safe since they fit into a signed
* 32 - bit variable
* TODO : Support 64 - bit settings / variables ; requires 64 bit over command protocol ! */
switch ( GetVarMemType ( this - > save . conv ) ) {
case SLE_VAR_NULL : return ;
case SLE_VAR_BL :
case SLE_VAR_I8 :
case SLE_VAR_U8 :
case SLE_VAR_I16 :
case SLE_VAR_U16 :
case SLE_VAR_I32 : {
/* Override the minimum value. No value below this->min, except special value 0 */
2021-06-03 19:18:29 +00:00
if ( ! ( this - > flags & SF_GUI_0_IS_SPECIAL ) | | val ! = 0 ) {
if ( ! ( this - > flags & SF_GUI_DROPDOWN ) ) {
2021-05-23 17:27:46 +00:00
/* Clamp value-type setting to its valid range */
val = Clamp ( val , this - > min , this - > max ) ;
} else if ( val < this - > min | | val > ( int32 ) this - > max ) {
/* Reset invalid discrete setting (where different values change gameplay) to its default value */
val = this - > def ;
2019-03-16 16:52:07 +00:00
}
2010-08-01 18:53:30 +00:00
}
2021-05-23 17:27:46 +00:00
break ;
}
case SLE_VAR_U32 : {
/* Override the minimum value. No value below this->min, except special value 0 */
uint32 uval = ( uint32 ) val ;
2021-06-03 19:18:29 +00:00
if ( ! ( this - > flags & SF_GUI_0_IS_SPECIAL ) | | uval ! = 0 ) {
if ( ! ( this - > flags & SF_GUI_DROPDOWN ) ) {
2021-05-23 17:27:46 +00:00
/* Clamp value-type setting to its valid range */
uval = ClampU ( uval , this - > min , this - > max ) ;
} else if ( uval < ( uint ) this - > min | | uval > this - > max ) {
/* Reset invalid discrete setting to its default value */
uval = ( uint32 ) this - > def ;
2019-03-16 16:52:07 +00:00
}
2006-03-28 21:51:14 +00:00
}
2021-06-27 22:58:54 +00:00
val = ( int32 ) uval ;
2021-05-23 17:27:46 +00:00
return ;
2006-03-28 21:51:14 +00:00
}
2021-05-23 17:27:46 +00:00
case SLE_VAR_I64 :
case SLE_VAR_U64 :
default : NOT_REACHED ( ) ;
2006-03-28 21:51:14 +00:00
}
2021-05-24 08:42:02 +00:00
}
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2021-05-24 08:42:02 +00:00
/**
* Set the value of a setting .
* @ param object The object the setting is to be saved in .
* @ param val Signed version of the new value .
*/
void IntSettingDesc : : Write ( const void * object , int32 val ) const
{
2021-05-31 20:26:44 +00:00
void * ptr = GetVariableAddress ( object , this - > save ) ;
2021-05-22 18:44:09 +00:00
WriteValue ( ptr , this - > save . conv , ( int64 ) val ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
}
2021-05-24 08:42:02 +00:00
/**
* Read the integer from the the actual setting .
* @ param object The object the setting is to be saved in .
* @ return The value of the saved integer .
*/
int32 IntSettingDesc : : Read ( const void * object ) const
{
2021-05-31 20:26:44 +00:00
void * ptr = GetVariableAddress ( object , this - > save ) ;
2021-05-24 08:42:02 +00:00
return ( int32 ) ReadValue ( ptr , this - > save . conv ) ;
}
2021-04-27 16:24:33 +00:00
/**
2021-05-24 07:44:20 +00:00
* Make the value valid given the limitations of this setting .
*
* In the case of string settings this is ensuring the string contains only accepted
* Utf8 characters and is at most the maximum length defined in this setting .
* @ param str The string to make valid .
2021-04-27 16:24:33 +00:00
*/
2021-05-24 07:44:20 +00:00
void StringSettingDesc : : MakeValueValid ( std : : string & str ) const
2021-04-27 16:24:33 +00:00
{
2021-05-24 07:44:20 +00:00
if ( this - > max_length = = 0 | | str . size ( ) < this - > max_length ) return ;
2021-04-27 16:24:33 +00:00
2021-05-24 07:44:20 +00:00
/* In case a maximum length is imposed by the setting, the length
* includes the ' \0 ' termination for network transfer purposes .
* Also ensure the string is valid after chopping of some bytes . */
std : : string stdstr ( str , this - > max_length - 1 ) ;
2021-05-29 09:21:38 +00:00
str . assign ( StrMakeValid ( stdstr , SVS_NONE ) ) ;
2021-05-24 07:44:20 +00:00
}
2021-04-27 16:24:33 +00:00
2021-05-24 07:44:20 +00:00
/**
* Write a string to the actual setting .
* @ param object The object the setting is to be saved in .
* @ param str The string to save .
*/
void StringSettingDesc : : Write ( const void * object , const std : : string & str ) const
{
2021-05-31 20:26:44 +00:00
reinterpret_cast < std : : string * > ( GetVariableAddress ( object , this - > save ) ) - > assign ( str ) ;
2021-04-27 16:24:33 +00:00
}
2021-05-22 11:39:41 +00:00
/**
* Read the string from the the actual setting .
* @ param object The object the setting is to be saved in .
* @ return The value of the saved string .
*/
const std : : string & StringSettingDesc : : Read ( const void * object ) const
{
2021-05-31 20:26:44 +00:00
return * reinterpret_cast < std : : string * > ( GetVariableAddress ( object , this - > save ) ) ;
2021-05-22 11:39:41 +00:00
}
2010-08-01 19:22:34 +00:00
/**
* Load values from a group of an IniFile structure into the internal representation
2006-02-04 22:48:57 +00:00
* @ param ini pointer to IniFile structure that holds administrative information
2021-05-18 19:01:42 +00:00
* @ param settings_table table with SettingDesc structures whose internally pointed variables will
2006-02-04 22:48:57 +00:00
* be given values
2007-04-17 21:09:38 +00:00
* @ param grpname the group of the IniFile to search in for the new values
2010-08-01 19:44:49 +00:00
* @ param object pointer to the object been loaded
2021-02-15 23:09:52 +00:00
* @ param only_startup load only the startup settings set
2010-08-01 19:44:49 +00:00
*/
2021-07-01 17:59:13 +00:00
static void IniLoadSettings ( IniFile & ini , const SettingTable & settings_table , const char * grpname , void * object , bool only_startup )
2004-08-09 17:04:08 +00:00
{
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
IniGroup * group ;
2021-07-01 17:59:13 +00:00
IniGroup * group_def = ini . GetGroup ( grpname ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings_table ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-05-23 09:55:22 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2021-05-23 08:47:12 +00:00
if ( sd - > startup ! = only_startup ) continue ;
2006-03-02 00:32:48 +00:00
2009-02-08 12:25:13 +00:00
/* For settings.xx.yy load the settings from [xx] yy = ? */
2021-05-23 09:55:22 +00:00
std : : string s { sd - > name } ;
2020-05-17 21:32:03 +00:00
auto sc = s . find ( ' . ' ) ;
if ( sc ! = std : : string : : npos ) {
2021-07-01 17:59:13 +00:00
group = ini . GetGroup ( s . substr ( 0 , sc ) ) ;
2020-05-17 21:32:03 +00:00
s = s . substr ( sc + 1 ) ;
2004-08-09 17:04:08 +00:00
} else {
group = group_def ;
}
2004-09-10 19:02:27 +00:00
2020-05-17 21:32:03 +00:00
IniItem * item = group - > GetItem ( s , false ) ;
2019-04-10 21:07:06 +00:00
if ( item = = nullptr & & group ! = group_def ) {
2020-05-17 21:32:03 +00:00
/* For settings.xx.yy load the settings from [settings] yy = ? in case the previous
2009-02-08 12:25:13 +00:00
* did not exist ( e . g . loading old config files with a [ settings ] section */
2008-08-24 13:50:31 +00:00
item = group_def - > GetItem ( s , false ) ;
2008-05-25 19:17:03 +00:00
}
2019-04-10 21:07:06 +00:00
if ( item = = nullptr ) {
2009-02-08 12:25:13 +00:00
/* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous
2008-05-25 19:17:03 +00:00
* did not exist ( e . g . loading old config files with a [ yapf ] section */
2020-05-17 21:32:03 +00:00
sc = s . find ( ' . ' ) ;
2021-07-01 17:59:13 +00:00
if ( sc ! = std : : string : : npos ) item = ini . GetGroup ( s . substr ( 0 , sc ) ) - > GetItem ( s . substr ( sc + 1 ) , false ) ;
2008-05-25 19:17:03 +00:00
}
2021-05-23 09:55:22 +00:00
sd - > ParseValue ( item , object ) ;
2021-05-22 18:57:41 +00:00
}
}
2004-09-10 19:02:27 +00:00
2021-05-22 18:57:41 +00:00
void IntSettingDesc : : ParseValue ( const IniItem * item , void * object ) const
{
2021-05-22 19:09:30 +00:00
size_t val = ( item = = nullptr ) ? this - > def : this - > ParseValue ( item - > value . has_value ( ) ? item - > value - > c_str ( ) : " " ) ;
2021-05-24 08:42:02 +00:00
this - > MakeValueValidAndWrite ( object , ( int32 ) val ) ;
2021-05-22 18:57:41 +00:00
}
2012-04-17 19:44:59 +00:00
2021-05-22 18:57:41 +00:00
void StringSettingDesc : : ParseValue ( const IniItem * item , void * object ) const
{
2021-05-24 07:44:20 +00:00
std : : string str = ( item = = nullptr ) ? this - > def : item - > value . value_or ( " " ) ;
this - > MakeValueValid ( str ) ;
this - > Write ( object , str ) ;
2021-05-22 18:57:41 +00:00
}
2020-05-17 21:32:06 +00:00
2021-05-22 18:57:41 +00:00
void ListSettingDesc : : ParseValue ( const IniItem * item , void * object ) const
{
2021-05-22 19:09:30 +00:00
const char * str = ( item = = nullptr ) ? this - > def : item - > value . has_value ( ) ? item - > value - > c_str ( ) : nullptr ;
2021-05-31 20:26:44 +00:00
void * ptr = GetVariableAddress ( object , this - > save ) ;
2021-05-22 18:57:41 +00:00
if ( ! LoadIntList ( str , ptr , this - > save . length , GetVarMemType ( this - > save . conv ) ) ) {
ErrorMessageData msg ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_ARRAY ) ;
msg . SetDParamStr ( 0 , this - > name ) ;
_settings_error_list . push_back ( msg ) ;
2012-05-14 20:53:39 +00:00
2021-05-22 18:57:41 +00:00
/* Use default */
2021-05-22 19:09:30 +00:00
LoadIntList ( this - > def , ptr , this - > save . length , GetVarMemType ( this - > save . conv ) ) ;
2004-09-10 19:02:27 +00:00
}
2004-08-09 17:04:08 +00:00
}
2010-08-01 19:22:34 +00:00
/**
* Save the values of settings to the inifile .
2006-02-04 22:48:57 +00:00
* @ param ini pointer to IniFile structure
2006-04-22 00:10:38 +00:00
* @ param sd read - only SettingDesc structure which contains the unmodified ,
2006-02-04 22:48:57 +00:00
* loaded values of the configuration file and various information about it
* @ param grpname holds the name of the group ( eg . [ network ] ) where these will be saved
2007-04-17 21:09:38 +00:00
* @ param object pointer to the object been saved
2006-06-10 08:37:41 +00:00
* The function works as follows : for each item in the SettingDesc structure we
* have a look if the value has changed since we started the game ( the original
* values are reloaded when saving ) . If settings indeed have changed , we get
* these and save them .
*/
2021-07-01 17:59:13 +00:00
static void IniSaveSettings ( IniFile & ini , const SettingTable & settings_table , const char * grpname , void * object , bool )
2004-08-09 17:04:08 +00:00
{
2019-04-10 21:07:06 +00:00
IniGroup * group_def = nullptr , * group ;
2004-08-09 17:04:08 +00:00
IniItem * item ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
char buf [ 512 ] ;
2004-08-09 17:04:08 +00:00
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings_table ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
/* If the setting is not saved to the configuration
* file , just continue with the next setting */
2021-05-23 09:55:22 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2021-06-03 18:55:03 +00:00
if ( sd - > flags & SF_NOT_IN_CONFIG ) continue ;
2004-09-10 19:02:27 +00:00
2007-04-04 01:35:16 +00:00
/* XXX - wtf is this?? (group override?) */
2021-05-23 09:55:22 +00:00
std : : string s { sd - > name } ;
2020-05-17 21:32:03 +00:00
auto sc = s . find ( ' . ' ) ;
if ( sc ! = std : : string : : npos ) {
2021-07-01 17:59:13 +00:00
group = ini . GetGroup ( s . substr ( 0 , sc ) ) ;
2020-05-17 21:32:03 +00:00
s = s . substr ( sc + 1 ) ;
2004-08-09 17:04:08 +00:00
} else {
2021-07-01 17:59:13 +00:00
if ( group_def = = nullptr ) group_def = ini . GetGroup ( grpname ) ;
2004-08-09 17:04:08 +00:00
group = group_def ;
}
2004-09-10 19:02:27 +00:00
2008-08-24 13:50:31 +00:00
item = group - > GetItem ( s , true ) ;
2004-09-10 19:02:27 +00:00
2021-05-23 09:55:22 +00:00
if ( ! item - > value . has_value ( ) | | ! sd - > IsSameValue ( item , object ) ) {
2021-05-22 18:57:41 +00:00
/* Value has changed, get the new value and put it into a buffer */
2021-05-23 09:55:22 +00:00
sd - > FormatValue ( buf , lastof ( buf ) , object ) ;
2012-04-17 19:44:59 +00:00
2021-05-22 18:57:41 +00:00
/* The value is different, that means we have to write it to the ini */
item - > value . emplace ( buf ) ;
2004-08-09 17:04:08 +00:00
}
2021-05-22 11:39:41 +00:00
}
}
2020-05-17 21:32:06 +00:00
2021-05-22 11:39:41 +00:00
void IntSettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
{
2021-05-24 08:42:02 +00:00
uint32 i = ( uint32 ) this - > Read ( object ) ;
2021-06-03 19:01:00 +00:00
seprintf ( buf , last , IsSignedVarMemType ( this - > save . conv ) ? " %d " : " %u " , i ) ;
2021-05-22 11:39:41 +00:00
}
2012-04-17 19:44:59 +00:00
2021-05-23 16:20:49 +00:00
void BoolSettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
{
2021-05-24 08:42:02 +00:00
bool val = this - > Read ( object ) ! = 0 ;
2021-05-23 16:20:49 +00:00
strecpy ( buf , val ? " true " : " false " , last ) ;
}
2021-05-22 18:57:41 +00:00
bool IntSettingDesc : : IsSameValue ( const IniItem * item , void * object ) const
{
2021-05-24 08:42:02 +00:00
int32 item_value = ( int32 ) this - > ParseValue ( item - > value - > c_str ( ) ) ;
int32 object_value = this - > Read ( object ) ;
2021-05-22 18:57:41 +00:00
return item_value = = object_value ;
}
2021-05-22 11:39:41 +00:00
void StringSettingDesc : : FormatValue ( char * buf , const char * last , const void * object ) const
{
const std : : string & str = this - > Read ( object ) ;
2021-05-22 18:57:41 +00:00
switch ( GetVarMemType ( this - > save . conv ) ) {
2021-05-22 11:39:41 +00:00
case SLE_VAR_STR : strecpy ( buf , str . c_str ( ) , last ) ; break ;
2006-02-04 22:48:57 +00:00
2021-05-22 11:39:41 +00:00
case SLE_VAR_STRQ :
if ( str . empty ( ) ) {
buf [ 0 ] = ' \0 ' ;
} else {
seprintf ( buf , last , " \" %s \" " , str . c_str ( ) ) ;
}
break ;
default : NOT_REACHED ( ) ;
2004-09-10 19:02:27 +00:00
}
2004-08-09 17:04:08 +00:00
}
2021-05-22 18:57:41 +00:00
bool StringSettingDesc : : IsSameValue ( const IniItem * item , void * object ) const
{
/* The ini parsing removes the quotes, which are needed to retain the spaces in STRQs,
* so those values are always different in the parsed ini item than they should be . */
if ( GetVarMemType ( this - > save . conv ) = = SLE_VAR_STRQ ) return false ;
const std : : string & str = this - > Read ( object ) ;
return item - > value - > compare ( str ) = = 0 ;
}
bool ListSettingDesc : : IsSameValue ( const IniItem * item , void * object ) const
{
/* Checking for equality is way more expensive than just writing the value. */
return false ;
}
2010-08-01 19:22:34 +00:00
/**
* Loads all items from a ' grpname ' section into a list
2019-04-10 21:07:06 +00:00
* The list parameter can be a nullptr pointer , in this case nothing will be
2006-04-22 00:10:38 +00:00
* saved and a callback function should be defined that will take over the
* list - handling and store the data itself somewhere .
2007-04-17 21:09:38 +00:00
* @ param ini IniFile handle to the ini file with the source data
2009-09-19 09:51:14 +00:00
* @ param grpname character string identifying the section - header of the ini file that will be parsed
* @ param list new list with entries of the given section
2009-04-03 12:49:58 +00:00
*/
2021-07-01 17:59:13 +00:00
static void IniLoadSettingList ( IniFile & ini , const char * grpname , StringList & list )
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2006-04-22 13:17:13 +00:00
2019-04-02 19:31:33 +00:00
list . clear ( ) ;
2006-04-22 13:17:13 +00:00
2019-04-10 21:07:06 +00:00
for ( const IniItem * item = group - > item ; item ! = nullptr ; item = item - > next ) {
2020-05-17 21:32:03 +00:00
if ( ! item - > name . empty ( ) ) list . push_back ( item - > name ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
}
}
2010-08-01 19:22:34 +00:00
/**
* Saves all items from a list into the ' grpname ' section
2019-04-10 21:07:06 +00:00
* The list parameter can be a nullptr pointer , in this case a callback function
2006-04-22 00:10:38 +00:00
* should be defined that will provide the source data to be saved .
2007-04-18 18:00:33 +00:00
* @ param ini IniFile handle to the ini file where the destination data is saved
2006-04-22 00:10:38 +00:00
* @ param grpname character string identifying the section - header of the ini file
* @ param list pointer to an string ( pointer ) array that will be used as the
2007-04-18 18:00:33 +00:00
* source to be saved into the relevant ini section
2009-04-03 12:49:58 +00:00
*/
2021-07-01 17:59:13 +00:00
static void IniSaveSettingList ( IniFile & ini , const char * grpname , StringList & list )
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2009-01-14 20:23:45 +00:00
group - > Clear ( ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
2019-04-02 19:31:33 +00:00
for ( const auto & iter : list ) {
2021-06-14 21:17:58 +00:00
group - > GetItem ( iter , true ) - > SetValue ( " " ) ;
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
2006-03-01 23:53:20 +00:00
}
}
2013-05-26 19:27:22 +00:00
/**
* Load a WindowDesc from config .
* @ param ini IniFile handle to the ini file with the source data
* @ param grpname character string identifying the section - header of the ini file that will be parsed
* @ param desc Destination WindowDesc
*/
2021-07-01 17:59:13 +00:00
void IniLoadWindowSettings ( IniFile & ini , const char * grpname , void * desc )
2013-05-26 19:27:22 +00:00
{
2021-02-15 23:09:52 +00:00
IniLoadSettings ( ini , _window_settings , grpname , desc , false ) ;
2013-05-26 19:27:22 +00:00
}
/**
* Save a WindowDesc to config .
* @ param ini IniFile handle to the ini file where the destination data is saved
* @ param grpname character string identifying the section - header of the ini file
* @ param desc Source WindowDesc
*/
2021-07-01 17:59:13 +00:00
void IniSaveWindowSettings ( IniFile & ini , const char * grpname , void * desc )
2013-05-26 19:27:22 +00:00
{
2021-02-15 23:09:52 +00:00
IniSaveSettings ( ini , _window_settings , grpname , desc , false ) ;
2013-05-26 19:27:22 +00:00
}
2012-12-05 19:35:09 +00:00
/**
* Check whether the setting is editable in the current gamemode .
* @ param do_command true if this is about checking a command from the server .
* @ return true if editable .
*/
bool SettingDesc : : IsEditable ( bool do_command ) const
{
2021-06-03 18:55:03 +00:00
if ( ! do_command & & ! ( this - > flags & SF_NO_NETWORK_SYNC ) & & _networking & & ! _network_server & & ! ( this - > flags & SF_PER_COMPANY ) ) return false ;
2021-06-03 19:18:29 +00:00
if ( ( this - > flags & SF_NETWORK_ONLY ) & & ! _networking & & _game_mode ! = GM_MENU ) return false ;
if ( ( this - > flags & SF_NO_NETWORK ) & & _networking ) return false ;
if ( ( this - > flags & SF_NEWGAME_ONLY ) & &
2012-12-05 19:35:09 +00:00
( _game_mode = = GM_NORMAL | |
2021-06-03 19:18:29 +00:00
( _game_mode = = GM_EDITOR & & ! ( this - > flags & SF_SCENEDIT_TOO ) ) ) ) return false ;
if ( ( this - > flags & SF_SCENEDIT_ONLY ) & & _game_mode ! = GM_EDITOR ) return false ;
2012-12-05 19:35:09 +00:00
return true ;
}
2012-12-26 17:43:35 +00:00
/**
* Return the type of the setting .
* @ return type of setting
*/
SettingType SettingDesc : : GetType ( ) const
{
2021-06-03 19:18:29 +00:00
if ( this - > flags & SF_PER_COMPANY ) return ST_COMPANY ;
2021-06-03 18:55:03 +00:00
return ( this - > flags & SF_NOT_IN_SAVE ) ? ST_CLIENT : ST_GAME ;
2012-12-26 17:43:35 +00:00
}
2021-05-22 18:44:09 +00:00
/**
* Get the setting description of this setting as an integer setting .
* @ return The integer setting description .
*/
const IntSettingDesc * SettingDesc : : AsIntSetting ( ) const
{
assert ( this - > IsIntSetting ( ) ) ;
return static_cast < const IntSettingDesc * > ( this ) ;
}
2021-05-22 18:52:24 +00:00
/**
* Get the setting description of this setting as a string setting .
* @ return The string setting description .
*/
const StringSettingDesc * SettingDesc : : AsStringSetting ( ) const
{
assert ( this - > IsStringSetting ( ) ) ;
return static_cast < const StringSettingDesc * > ( this ) ;
}
2010-11-13 23:40:36 +00:00
/* Begin - Callback Functions for the various settings. */
/** Reposition the main toolbar as the setting changed. */
2021-05-24 09:47:37 +00:00
static void v_PositionMainToolbar ( int32 new_value )
2006-03-03 11:27:18 +00:00
{
2019-04-10 21:07:06 +00:00
if ( _game_mode ! = GM_MENU ) PositionMainToolbar ( nullptr ) ;
2006-03-03 11:27:18 +00:00
}
2010-11-13 23:40:36 +00:00
/** Reposition the statusbar as the setting changed. */
2021-05-24 09:47:37 +00:00
static void v_PositionStatusbar ( int32 new_value )
2010-11-13 23:40:36 +00:00
{
2010-11-18 19:24:40 +00:00
if ( _game_mode ! = GM_MENU ) {
2019-04-10 21:07:06 +00:00
PositionStatusbar ( nullptr ) ;
PositionNewsMessage ( nullptr ) ;
PositionNetworkChatWindow ( nullptr ) ;
2010-11-18 19:24:40 +00:00
}
2010-02-08 23:46:35 +00:00
}
/**
* Redraw the smallmap after a colour scheme change .
* @ param p1 Callback parameter .
*/
2021-05-24 09:47:37 +00:00
static void RedrawSmallmap ( int32 new_value )
2010-02-08 23:46:35 +00:00
{
BuildLandLegend ( ) ;
2011-01-04 20:53:57 +00:00
BuildOwnerLegend ( ) ;
2010-02-08 23:46:35 +00:00
SetWindowClassesDirty ( WC_SMALLMAP ) ;
2006-03-03 11:27:18 +00:00
}
2021-05-24 09:47:37 +00:00
static void StationSpreadChanged ( int32 p1 )
2006-03-03 11:27:18 +00:00
{
2013-01-08 17:44:39 +00:00
InvalidateWindowData ( WC_SELECT_STATION , 0 ) ;
2013-01-08 22:38:59 +00:00
InvalidateWindowData ( WC_BUILD_STATION , 0 ) ;
2008-05-12 14:54:33 +00:00
}
2021-05-24 09:47:37 +00:00
static void CloseSignalGUI ( int32 new_value )
2008-05-11 02:15:02 +00:00
{
2021-05-24 09:47:37 +00:00
if ( new_value = = 0 ) {
2021-05-17 13:46:38 +00:00
CloseWindowByClass ( WC_BUILD_SIGNAL ) ;
2008-05-11 02:15:02 +00:00
}
}
2021-05-24 09:47:37 +00:00
static void UpdateConsists ( int32 new_value )
2007-10-18 20:32:36 +00:00
{
2019-12-17 02:37:43 +00:00
for ( Train * t : Train : : Iterate ( ) ) {
2007-10-18 20:32:36 +00:00
/* Update the consist of all trains so the maximum speed is set correctly. */
2014-02-07 23:48:56 +00:00
if ( t - > IsFrontEngine ( ) | | t - > IsFreeWagon ( ) ) t - > ConsistChanged ( CCF_TRACK ) ;
2007-10-18 20:32:36 +00:00
}
2011-11-14 10:42:47 +00:00
InvalidateWindowClassesData ( WC_BUILD_VEHICLE , 0 ) ;
2007-10-18 20:32:36 +00:00
}
2021-05-24 09:47:37 +00:00
/* Check service intervals of vehicles, newvalue is value of % or day based servicing */
2021-06-21 16:31:56 +00:00
static void UpdateAllServiceInterval ( int32 new_value )
2006-03-03 11:27:18 +00:00
{
2013-02-14 17:08:56 +00:00
bool update_vehicles ;
2009-05-26 21:59:49 +00:00
VehicleDefaultSettings * vds ;
if ( _game_mode = = GM_MENU | | ! Company : : IsValidID ( _current_company ) ) {
vds = & _settings_client . company . vehicle ;
2013-02-14 17:08:56 +00:00
update_vehicles = false ;
2009-05-26 21:59:49 +00:00
} else {
vds = & Company : : Get ( _current_company ) - > settings . vehicle ;
2013-02-14 17:08:56 +00:00
update_vehicles = true ;
2009-05-26 21:59:49 +00:00
}
2006-03-03 11:27:18 +00:00
2021-05-24 09:47:37 +00:00
if ( new_value ! = 0 ) {
2009-05-26 21:59:49 +00:00
vds - > servint_trains = 50 ;
vds - > servint_roadveh = 50 ;
vds - > servint_aircraft = 50 ;
vds - > servint_ships = 50 ;
2006-03-03 11:27:18 +00:00
} else {
2009-05-26 21:59:49 +00:00
vds - > servint_trains = 150 ;
vds - > servint_roadveh = 150 ;
2010-11-12 21:40:43 +00:00
vds - > servint_aircraft = 100 ;
vds - > servint_ships = 360 ;
2006-03-03 11:27:18 +00:00
}
2013-02-14 17:08:56 +00:00
if ( update_vehicles ) {
const Company * c = Company : : Get ( _current_company ) ;
2019-12-17 02:37:43 +00:00
for ( Vehicle * v : Vehicle : : Iterate ( ) ) {
2013-02-14 17:08:56 +00:00
if ( v - > owner = = _current_company & & v - > IsPrimaryVehicle ( ) & & ! v - > ServiceIntervalIsCustom ( ) ) {
v - > SetServiceInterval ( CompanyServiceInterval ( c , v - > type ) ) ;
2021-05-24 09:47:37 +00:00
v - > SetServiceIntervalIsPercent ( new_value ! = 0 ) ;
2013-02-14 17:08:56 +00:00
}
}
}
2021-05-24 09:47:37 +00:00
SetWindowClassesDirty ( WC_VEHICLE_DETAILS ) ;
2013-02-14 17:08:56 +00:00
}
2021-05-24 09:47:37 +00:00
static bool CanUpdateServiceInterval ( VehicleType type , int32 & new_value )
2013-02-14 17:08:56 +00:00
{
VehicleDefaultSettings * vds ;
if ( _game_mode = = GM_MENU | | ! Company : : IsValidID ( _current_company ) ) {
vds = & _settings_client . company . vehicle ;
} else {
vds = & Company : : Get ( _current_company ) - > settings . vehicle ;
}
/* Test if the interval is valid */
2021-05-24 09:47:37 +00:00
int32 interval = GetServiceIntervalClamped ( new_value , vds - > servint_ispercent ) ;
return interval = = new_value ;
}
2013-02-14 17:08:56 +00:00
2021-05-24 09:47:37 +00:00
static void UpdateServiceInterval ( VehicleType type , int32 new_value )
{
if ( _game_mode ! = GM_MENU & & Company : : IsValidID ( _current_company ) ) {
2019-12-17 02:37:43 +00:00
for ( Vehicle * v : Vehicle : : Iterate ( ) ) {
2013-02-14 17:08:56 +00:00
if ( v - > owner = = _current_company & & v - > type = = type & & v - > IsPrimaryVehicle ( ) & & ! v - > ServiceIntervalIsCustom ( ) ) {
2021-05-24 09:47:37 +00:00
v - > SetServiceInterval ( new_value ) ;
2013-02-14 17:08:56 +00:00
}
}
}
2021-05-24 09:47:37 +00:00
SetWindowClassesDirty ( WC_VEHICLE_DETAILS ) ;
2013-02-14 17:08:56 +00:00
}
2021-05-24 09:47:37 +00:00
static void TrainAccelerationModelChanged ( int32 new_value )
2008-03-15 19:24:13 +00:00
{
2019-12-17 02:37:43 +00:00
for ( Train * t : Train : : Iterate ( ) ) {
2009-07-01 22:22:01 +00:00
if ( t - > IsFrontEngine ( ) ) {
2010-01-15 18:23:52 +00:00
t - > tcache . cached_max_curve_speed = t - > GetCurveSpeedLimit ( ) ;
t - > UpdateAcceleration ( ) ;
2009-06-01 13:14:56 +00:00
}
2008-03-15 19:24:13 +00:00
}
2010-12-15 09:01:04 +00:00
/* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */
SetWindowClassesDirty ( WC_ENGINE_PREVIEW ) ;
InvalidateWindowClassesData ( WC_BUILD_VEHICLE , 0 ) ;
SetWindowClassesDirty ( WC_VEHICLE_DETAILS ) ;
2008-03-15 19:24:13 +00:00
}
2010-01-16 22:30:04 +00:00
/**
* This function updates the train acceleration cache after a steepness change .
2021-05-24 09:47:37 +00:00
* @ param new_value Unused new value of setting .
2010-01-16 22:30:04 +00:00
*/
2021-05-24 09:47:37 +00:00
static void TrainSlopeSteepnessChanged ( int32 new_value )
2010-01-16 22:30:04 +00:00
{
2019-12-17 02:37:43 +00:00
for ( Train * t : Train : : Iterate ( ) ) {
2010-01-16 22:30:04 +00:00
if ( t - > IsFrontEngine ( ) ) t - > CargoChanged ( ) ;
}
}
2010-03-06 12:56:57 +00:00
/**
* This function updates realistic acceleration caches when the setting " Road vehicle acceleration model " is set .
2021-05-24 09:47:37 +00:00
* @ param new_value Unused new value of setting .
2010-03-06 12:56:57 +00:00
*/
2021-05-24 09:47:37 +00:00
static void RoadVehAccelerationModelChanged ( int32 new_value )
2010-03-06 12:56:57 +00:00
{
if ( _settings_game . vehicle . roadveh_acceleration_model ! = AM_ORIGINAL ) {
2019-12-17 02:37:43 +00:00
for ( RoadVehicle * rv : RoadVehicle : : Iterate ( ) ) {
2011-01-19 18:44:13 +00:00
if ( rv - > IsFrontEngine ( ) ) {
2010-03-06 12:56:57 +00:00
rv - > CargoChanged ( ) ;
}
}
}
2010-03-06 12:59:28 +00:00
/* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */
SetWindowClassesDirty ( WC_ENGINE_PREVIEW ) ;
2010-03-06 13:03:17 +00:00
InvalidateWindowClassesData ( WC_BUILD_VEHICLE , 0 ) ;
2010-03-06 12:59:28 +00:00
SetWindowClassesDirty ( WC_VEHICLE_DETAILS ) ;
2010-03-06 12:56:57 +00:00
}
2010-03-06 12:58:33 +00:00
/**
* This function updates the road vehicle acceleration cache after a steepness change .
2021-05-24 09:47:37 +00:00
* @ param new_value Unused new value of setting .
2010-03-06 12:58:33 +00:00
*/
2021-05-24 09:47:37 +00:00
static void RoadVehSlopeSteepnessChanged ( int32 new_value )
2010-03-06 12:58:33 +00:00
{
2019-12-17 02:37:43 +00:00
for ( RoadVehicle * rv : RoadVehicle : : Iterate ( ) ) {
2011-01-19 18:44:13 +00:00
if ( rv - > IsFrontEngine ( ) ) rv - > CargoChanged ( ) ;
2010-03-06 12:58:33 +00:00
}
2008-04-03 22:31:57 +00:00
}
2021-05-24 09:47:37 +00:00
static void TownFoundingChanged ( int32 new_value )
2009-11-24 21:18:11 +00:00
{
if ( _game_mode ! = GM_EDITOR & & _settings_game . economy . found_town = = TF_FORBIDDEN ) {
2021-05-17 13:46:38 +00:00
CloseWindowById ( WC_FOUND_TOWN , 0 ) ;
2021-05-24 09:47:37 +00:00
} else {
InvalidateWindowData ( WC_FOUND_TOWN , 0 ) ;
2009-11-24 21:18:11 +00:00
}
2009-11-25 16:17:06 +00:00
}
2009-11-24 21:18:11 +00:00
2021-05-24 09:47:37 +00:00
static void ZoomMinMaxChanged ( int32 new_value )
2011-11-24 12:20:14 +00:00
{
extern void ConstrainAllViewportsZoom ( ) ;
2014-10-12 20:43:25 +00:00
ConstrainAllViewportsZoom ( ) ;
GfxClearSpriteCache ( ) ;
2014-10-11 13:22:37 +00:00
if ( _settings_client . gui . zoom_min > _gui_zoom ) {
/* Restrict GUI zoom if it is no longer available. */
_gui_zoom = _settings_client . gui . zoom_min ;
UpdateCursorSize ( ) ;
2014-10-12 20:43:25 +00:00
LoadStringWidthTable ( ) ;
2014-10-11 13:22:37 +00:00
}
2011-11-24 12:20:14 +00:00
}
2021-05-24 09:47:37 +00:00
static void SpriteZoomMinChanged ( int32 new_value )
{
2021-03-13 09:00:53 +00:00
GfxClearSpriteCache ( ) ;
/* Force all sprites to redraw at the new chosen zoom level */
MarkWholeScreenDirty ( ) ;
}
2010-11-07 21:46:41 +00:00
/**
* Update any possible saveload window and delete any newgrf dialogue as
* its widget parts might change . Reinit all windows as it allows access to the
* newgrf debug button .
2021-05-24 09:47:37 +00:00
* @ param new_value unused .
2010-11-07 21:46:41 +00:00
*/
2021-05-24 09:47:37 +00:00
static void InvalidateNewGRFChangeWindows ( int32 new_value )
2010-11-07 21:46:41 +00:00
{
InvalidateWindowClassesData ( WC_SAVELOAD ) ;
2021-05-17 13:46:38 +00:00
CloseWindowByClass ( WC_GAME_OPTIONS ) ;
2021-04-05 17:43:12 +00:00
ReInitAllWindows ( _gui_zoom_cfg ) ;
2010-11-07 21:46:41 +00:00
}
2021-05-24 09:47:37 +00:00
static void InvalidateCompanyLiveryWindow ( int32 new_value )
2010-09-25 22:00:49 +00:00
{
2019-01-31 13:57:44 +00:00
InvalidateWindowClassesData ( WC_COMPANY_COLOUR , - 1 ) ;
2021-04-11 12:30:13 +00:00
ResetVehicleColourMap ( ) ;
2013-02-04 20:29:38 +00:00
}
2010-11-04 19:34:40 +00:00
/** Checks if any settings are set to incorrect values, and sets them to correct values in that case. */
static void ValidateSettings ( )
{
/* Do not allow a custom sea level with the original land generator. */
2015-05-16 12:01:19 +00:00
if ( _settings_newgame . game_creation . land_generator = = LG_ORIGINAL & &
2010-11-04 19:34:40 +00:00
_settings_newgame . difficulty . quantity_sea_lakes = = CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY ) {
_settings_newgame . difficulty . quantity_sea_lakes = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE ;
}
}
2021-05-24 09:47:37 +00:00
static void DifficultyNoiseChange ( int32 new_value )
2008-05-26 00:31:36 +00:00
{
if ( _game_mode = = GM_NORMAL ) {
UpdateAirportsNoise ( ) ;
2008-05-29 15:13:28 +00:00
if ( _settings_game . economy . station_noise_level ) {
2008-05-26 00:31:36 +00:00
InvalidateWindowClassesData ( WC_TOWN_VIEW , 0 ) ;
}
}
}
2021-05-24 09:47:37 +00:00
static void MaxNoAIsChange ( int32 new_value )
2010-03-12 01:37:41 +00:00
{
2011-01-02 00:34:21 +00:00
if ( GetGameSettings ( ) . difficulty . max_no_competitors ! = 0 & &
2010-03-12 01:37:41 +00:00
AI : : GetInfoList ( ) - > size ( ) = = 0 & &
( ! _networking | | _network_server ) ) {
ShowErrorMessage ( STR_WARNING_NO_SUITABLE_AI , INVALID_STRING_ID , WL_CRITICAL ) ;
}
2019-02-01 15:05:43 +00:00
InvalidateWindowClassesData ( WC_GAME_OPTIONS , 0 ) ;
2010-03-12 01:37:41 +00:00
}
2009-02-04 16:09:16 +00:00
/**
* Check whether the road side may be changed .
2021-05-24 09:47:37 +00:00
* @ param new_value unused
2009-02-04 16:09:16 +00:00
* @ return true if the road side may be changed .
*/
2021-05-24 09:47:37 +00:00
static bool CheckRoadSide ( int32 & new_value )
2009-02-04 16:09:16 +00:00
{
extern bool RoadVehiclesAreBuilt ( ) ;
return _game_mode = = GM_MENU | | ! RoadVehiclesAreBuilt ( ) ;
}
2010-08-01 19:22:34 +00:00
/**
* Conversion callback for _gameopt_settings_game . landscape
2007-03-22 03:35:18 +00:00
* It converts ( or try ) between old values and the new ones ,
2008-08-25 20:10:45 +00:00
* without losing initial setting of the user
2007-03-22 03:35:18 +00:00
* @ param value that was read from config file
* @ return the " hopefully " converted value
*/
2011-05-29 18:35:31 +00:00
static size_t ConvertLandscape ( const char * value )
2007-03-22 03:35:18 +00:00
{
/* try with the old values */
2021-05-23 17:16:56 +00:00
static std : : vector < std : : string > _old_landscape_values { " normal " , " hilly " , " desert " , " candy " } ;
return OneOfManySettingDesc : : ParseSingleValue ( value , strlen ( value ) , _old_landscape_values ) ;
2007-03-22 03:35:18 +00:00
}
2021-05-24 09:47:37 +00:00
static bool CheckFreeformEdges ( int32 & new_value )
2009-01-21 02:31:55 +00:00
{
2009-02-04 15:01:37 +00:00
if ( _game_mode = = GM_MENU ) return true ;
2021-05-24 09:47:37 +00:00
if ( new_value ! = 0 ) {
2019-12-17 02:37:43 +00:00
for ( Ship * s : Ship : : Iterate ( ) ) {
2011-04-07 15:48:13 +00:00
/* Check if there is a ship on the northern border. */
2009-05-26 22:45:48 +00:00
if ( TileX ( s - > tile ) = = 0 | | TileY ( s - > tile ) = = 0 ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_EMPTY , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
2019-12-15 04:55:59 +00:00
for ( const BaseStation * st : BaseStation : : Iterate ( ) ) {
2011-04-07 15:58:21 +00:00
/* Check if there is a non-deleted buoy on the northern border. */
if ( st - > IsInUse ( ) & & ( TileX ( st - > xy ) = = 0 | | TileY ( st - > xy ) = = 0 ) ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_EMPTY , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
} else {
for ( uint i = 0 ; i < MapMaxX ( ) ; i + + ) {
if ( TileHeight ( TileXY ( i , 1 ) ) ! = 0 ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_WATER , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
for ( uint i = 1 ; i < MapMaxX ( ) ; i + + ) {
if ( ! IsTileType ( TileXY ( i , MapMaxY ( ) - 1 ) , MP_WATER ) | | TileHeight ( TileXY ( 1 , MapMaxY ( ) ) ) ! = 0 ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_WATER , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
for ( uint i = 0 ; i < MapMaxY ( ) ; i + + ) {
if ( TileHeight ( TileXY ( 1 , i ) ) ! = 0 ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_WATER , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
for ( uint i = 1 ; i < MapMaxY ( ) ; i + + ) {
if ( ! IsTileType ( TileXY ( MapMaxX ( ) - 1 , i ) , MP_WATER ) | | TileHeight ( TileXY ( MapMaxX ( ) , i ) ) ! = 0 ) {
2010-02-24 14:46:15 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_EDGES_NOT_WATER , INVALID_STRING_ID , WL_ERROR ) ;
2009-02-04 15:01:37 +00:00
return false ;
2009-01-21 02:31:55 +00:00
}
}
2021-05-24 09:47:37 +00:00
}
return true ;
}
static void UpdateFreeformEdges ( int32 new_value )
{
if ( _game_mode = = GM_MENU ) return ;
if ( new_value ! = 0 ) {
for ( uint x = 0 ; x < MapSizeX ( ) ; x + + ) MakeVoid ( TileXY ( x , 0 ) ) ;
for ( uint y = 0 ; y < MapSizeY ( ) ; y + + ) MakeVoid ( TileXY ( 0 , y ) ) ;
} else {
2009-01-21 02:31:55 +00:00
/* Make tiles at the border water again. */
for ( uint i = 0 ; i < MapMaxX ( ) ; i + + ) {
SetTileHeight ( TileXY ( i , 0 ) , 0 ) ;
SetTileType ( TileXY ( i , 0 ) , MP_WATER ) ;
}
for ( uint i = 0 ; i < MapMaxY ( ) ; i + + ) {
SetTileHeight ( TileXY ( 0 , i ) , 0 ) ;
SetTileType ( TileXY ( 0 , i ) , MP_WATER ) ;
}
}
MarkWholeScreenDirty ( ) ;
}
2009-02-26 01:53:22 +00:00
/**
* Changing the setting " allow multiple NewGRF sets " is not allowed
* if there are vehicles .
*/
2021-05-24 09:47:37 +00:00
static bool CheckDynamicEngines ( int32 & new_value )
2009-02-26 01:53:22 +00:00
{
if ( _game_mode = = GM_MENU ) return true ;
2011-02-05 16:07:23 +00:00
if ( ! EngineOverrideManager : : ResetToCurrentNewGRFConfig ( ) ) {
ShowErrorMessage ( STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES , INVALID_STRING_ID , WL_ERROR ) ;
return false ;
2009-02-26 01:53:22 +00:00
}
2009-03-09 21:33:05 +00:00
2009-02-26 01:53:22 +00:00
return true ;
}
2021-05-24 09:47:37 +00:00
static bool CheckMaxHeightLevel ( int32 & new_value )
2015-02-14 21:55:30 +00:00
{
if ( _game_mode = = GM_NORMAL ) return false ;
if ( _game_mode ! = GM_EDITOR ) return true ;
/* Check if at least one mountain on the map is higher than the new value.
* If yes , disallow the change . */
for ( TileIndex t = 0 ; t < MapSize ( ) ; t + + ) {
2021-05-24 09:47:37 +00:00
if ( ( int32 ) TileHeight ( t ) > new_value ) {
2015-02-14 21:55:30 +00:00
ShowErrorMessage ( STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN , INVALID_STRING_ID , WL_ERROR ) ;
/* Return old, unchanged value */
return false ;
}
}
return true ;
}
2021-05-24 09:47:37 +00:00
static void StationCatchmentChanged ( int32 new_value )
2009-06-25 15:42:03 +00:00
{
2019-02-14 21:07:15 +00:00
Station : : RecomputeCatchmentForAll ( ) ;
2019-02-22 18:14:06 +00:00
MarkWholeScreenDirty ( ) ;
2009-06-25 15:42:03 +00:00
}
2021-05-24 09:47:37 +00:00
static void MaxVehiclesChanged ( int32 new_value )
2015-02-22 15:26:27 +00:00
{
InvalidateWindowClassesData ( WC_BUILD_TOOLBAR ) ;
MarkWholeScreenDirty ( ) ;
}
2021-05-24 09:47:37 +00:00
static void InvalidateShipPathCache ( int32 new_value )
2019-01-19 20:59:27 +00:00
{
2019-12-17 02:37:43 +00:00
for ( Ship * s : Ship : : Iterate ( ) ) {
2019-01-19 20:59:27 +00:00
s - > path . clear ( ) ;
}
}
2021-05-24 07:44:20 +00:00
/**
* Replace a passwords that are a literal asterisk with an empty string .
* @ param newval The new string value for this password field .
* @ return Always true .
*/
static bool ReplaceAsteriskWithEmptyPassword ( std : : string & newval )
2008-05-30 09:23:05 +00:00
{
2021-05-24 07:44:20 +00:00
if ( newval . compare ( " * " ) = = 0 ) newval . clear ( ) ;
2009-02-04 15:01:37 +00:00
return true ;
2008-05-30 09:23:05 +00:00
}
2021-05-24 07:44:20 +00:00
/** Update the game info, and send it to the clients when we are running as a server. */
static void UpdateClientConfigValues ( )
2009-01-23 22:18:06 +00:00
{
2021-05-05 17:21:12 +00:00
NetworkServerUpdateGameInfo ( ) ;
2009-01-23 22:18:06 +00:00
if ( _network_server ) NetworkServerSendConfigUpdate ( ) ;
}
2006-03-03 11:27:18 +00:00
/* End - Callback Functions */
2008-05-28 14:36:06 +00:00
/**
* Prepare for reading and old diff_custom by zero - ing the memory .
*/
2008-05-26 00:31:36 +00:00
static void PrepareOldDiffCustom ( )
{
memset ( _old_diff_custom , 0 , sizeof ( _old_diff_custom ) ) ;
}
2008-05-28 14:36:06 +00:00
/**
* Reading of the old diff_custom array and transforming it to the new format .
* @ param savegame is it read from the config or savegame . In the latter case
* we are sure there is an array ; in the former case we have
* to check that .
*/
static void HandleOldDiffCustom ( bool savegame )
2008-05-26 00:31:36 +00:00
{
2021-05-30 08:40:59 +00:00
/* Savegames before v4 didn't have "town_council_tolerance" in savegame yet. */
bool has_no_town_council_tolerance = savegame & & IsSavegameVersionBefore ( SLV_4 ) ;
uint options_to_load = GAME_DIFFICULTY_NUM - ( has_no_town_council_tolerance ? 1 : 0 ) ;
2008-05-26 00:31:36 +00:00
2008-05-28 14:36:06 +00:00
if ( ! savegame ) {
/* If we did read to old_diff_custom, then at least one value must be non 0. */
bool old_diff_custom_used = false ;
for ( uint i = 0 ; i < options_to_load & & ! old_diff_custom_used ; i + + ) {
old_diff_custom_used = ( _old_diff_custom [ i ] ! = 0 ) ;
}
2008-05-26 00:31:36 +00:00
2008-05-28 14:36:06 +00:00
if ( ! old_diff_custom_used ) return ;
}
2008-05-26 00:31:36 +00:00
2021-05-30 08:40:59 +00:00
/* Iterate over all the old difficulty settings, and convert the list-value to the new setting. */
uint i = 0 ;
for ( const auto & name : _old_diff_settings ) {
if ( has_no_town_council_tolerance & & name = = " town_council_tolerance " ) continue ;
std : : string fullname = " difficulty. " + name ;
2021-05-30 09:30:03 +00:00
const SettingDesc * sd = GetSettingFromName ( fullname ) ;
2021-05-30 08:40:59 +00:00
/* Some settings are no longer in use; skip reading those. */
if ( sd = = nullptr ) {
i + + ;
continue ;
}
int32 value = ( int32 ) ( ( name = = " max_loan " ? 1000 : 1 ) * _old_diff_custom [ i + + ] ) ;
2021-05-24 08:42:02 +00:00
sd - > AsIntSetting ( ) - > MakeValueValidAndWrite ( savegame ? & _settings_game : & _settings_newgame , value ) ;
2008-05-26 00:31:36 +00:00
}
}
2021-07-01 17:59:13 +00:00
static void AILoadConfig ( IniFile & ini , const char * grpname )
2009-01-12 17:11:45 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
2009-01-12 17:11:45 +00:00
IniItem * item ;
/* Clean any configured AI */
for ( CompanyID c = COMPANY_FIRST ; c < MAX_COMPANIES ; c + + ) {
2019-04-10 21:07:06 +00:00
AIConfig : : GetConfig ( c , AIConfig : : SSS_FORCE_NEWGAME ) - > Change ( nullptr ) ;
2009-01-12 17:11:45 +00:00
}
/* If no group exists, return */
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2009-01-12 17:11:45 +00:00
CompanyID c = COMPANY_FIRST ;
2019-04-10 21:07:06 +00:00
for ( item = group - > item ; c < MAX_COMPANIES & & item ! = nullptr ; c + + , item = item - > next ) {
2011-11-29 23:26:35 +00:00
AIConfig * config = AIConfig : : GetConfig ( c , AIConfig : : SSS_FORCE_NEWGAME ) ;
2009-01-12 17:11:45 +00:00
2020-05-17 21:32:03 +00:00
config - > Change ( item - > name . c_str ( ) ) ;
2011-11-29 23:26:35 +00:00
if ( ! config - > HasScript ( ) ) {
2020-05-17 21:32:03 +00:00
if ( item - > name ! = " none " ) {
2021-06-12 07:10:17 +00:00
Debug ( script , 0 , " The AI by the name '{}' was no longer found, and removed from the list. " , item - > name ) ;
2009-01-23 21:52:29 +00:00
continue ;
}
2009-01-12 17:11:45 +00:00
}
2021-06-14 21:17:58 +00:00
if ( item - > value . has_value ( ) ) config - > StringToSettings ( * item - > value ) ;
2009-01-12 17:11:45 +00:00
}
}
2021-07-01 17:59:13 +00:00
static void GameLoadConfig ( IniFile & ini , const char * grpname )
2011-12-19 20:56:34 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
2011-12-19 20:56:34 +00:00
IniItem * item ;
/* Clean any configured GameScript */
2019-04-10 21:07:06 +00:00
GameConfig : : GetConfig ( GameConfig : : SSS_FORCE_NEWGAME ) - > Change ( nullptr ) ;
2011-12-19 20:56:34 +00:00
/* If no group exists, return */
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2011-12-19 20:56:34 +00:00
item = group - > item ;
2019-04-10 21:07:06 +00:00
if ( item = = nullptr ) return ;
2011-12-19 20:56:34 +00:00
GameConfig * config = GameConfig : : GetConfig ( AIConfig : : SSS_FORCE_NEWGAME ) ;
2020-05-17 21:32:03 +00:00
config - > Change ( item - > name . c_str ( ) ) ;
2011-12-19 20:56:34 +00:00
if ( ! config - > HasScript ( ) ) {
2020-05-17 21:32:03 +00:00
if ( item - > name ! = " none " ) {
2021-06-12 07:10:17 +00:00
Debug ( script , 0 , " The GameScript by the name '{}' was no longer found, and removed from the list. " , item - > name ) ;
2011-12-19 20:56:34 +00:00
return ;
}
}
2021-06-14 21:17:58 +00:00
if ( item - > value . has_value ( ) ) config - > StringToSettings ( * item - > value ) ;
2011-12-19 20:56:34 +00:00
}
2014-05-24 19:12:48 +00:00
/**
* Convert a character to a hex nibble value , or \ c - 1 otherwise .
* @ param c Character to convert .
* @ return Hex value of the character , or \ c - 1 if not a hex digit .
*/
static int DecodeHexNibble ( char c )
{
if ( c > = ' 0 ' & & c < = ' 9 ' ) return c - ' 0 ' ;
if ( c > = ' A ' & & c < = ' F ' ) return c + 10 - ' A ' ;
if ( c > = ' a ' & & c < = ' f ' ) return c + 10 - ' a ' ;
return - 1 ;
}
/**
* Parse a sequence of characters ( supposedly hex digits ) into a sequence of bytes .
* After the hex number should be a \ c ' | ' character .
* @ param pos First character to convert .
2018-10-28 02:17:36 +00:00
* @ param [ out ] dest Output byte array to write the bytes .
2014-05-24 19:12:48 +00:00
* @ param dest_size Number of bytes in \ a dest .
* @ return Whether reading was successful .
*/
2020-05-17 21:32:03 +00:00
static bool DecodeHexText ( const char * pos , uint8 * dest , size_t dest_size )
2014-05-24 19:12:48 +00:00
{
while ( dest_size > 0 ) {
int hi = DecodeHexNibble ( pos [ 0 ] ) ;
int lo = ( hi > = 0 ) ? DecodeHexNibble ( pos [ 1 ] ) : - 1 ;
if ( lo < 0 ) return false ;
* dest + + = ( hi < < 4 ) | lo ;
pos + = 2 ;
dest_size - - ;
}
return * pos = = ' | ' ;
}
2010-12-11 15:14:28 +00:00
/**
* Load a GRF configuration
* @ param ini The configuration to read from .
* @ param grpname Group name containing the configuration of the GRF .
* @ param is_static GRF is static .
*/
2021-07-01 17:59:13 +00:00
static GRFConfig * GRFLoadConfig ( IniFile & ini , const char * grpname , bool is_static )
2006-04-22 13:17:13 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
2006-12-12 19:38:41 +00:00
IniItem * item ;
2019-04-10 21:07:06 +00:00
GRFConfig * first = nullptr ;
2006-12-12 19:38:41 +00:00
GRFConfig * * curr = & first ;
2006-04-22 13:17:13 +00:00
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return nullptr ;
2006-04-22 13:17:13 +00:00
2019-04-10 21:07:06 +00:00
for ( item = group - > item ; item ! = nullptr ; item = item - > next ) {
GRFConfig * c = nullptr ;
2014-05-24 19:12:48 +00:00
uint8 grfid_buf [ 4 ] , md5sum [ 16 ] ;
2020-05-17 21:32:03 +00:00
const char * filename = item - > name . c_str ( ) ;
2014-05-24 19:12:48 +00:00
bool has_grfid = false ;
bool has_md5sum = false ;
/* Try reading "<grfid>|" and on success, "<md5sum>|". */
has_grfid = DecodeHexText ( filename , grfid_buf , lengthof ( grfid_buf ) ) ;
if ( has_grfid ) {
filename + = 1 + 2 * lengthof ( grfid_buf ) ;
has_md5sum = DecodeHexText ( filename , md5sum , lengthof ( md5sum ) ) ;
if ( has_md5sum ) filename + = 1 + 2 * lengthof ( md5sum ) ;
uint32 grfid = grfid_buf [ 0 ] | ( grfid_buf [ 1 ] < < 8 ) | ( grfid_buf [ 2 ] < < 16 ) | ( grfid_buf [ 3 ] < < 24 ) ;
if ( has_md5sum ) {
const GRFConfig * s = FindGRFConfig ( grfid , FGCM_EXACT , md5sum ) ;
2019-04-10 21:07:06 +00:00
if ( s ! = nullptr ) c = new GRFConfig ( * s ) ;
2014-05-24 19:12:48 +00:00
}
2019-04-10 21:07:06 +00:00
if ( c = = nullptr & & ! FioCheckFileExists ( filename , NEWGRF_DIR ) ) {
2014-05-24 19:12:48 +00:00
const GRFConfig * s = FindGRFConfig ( grfid , FGCM_NEWEST_VALID ) ;
2019-04-10 21:07:06 +00:00
if ( s ! = nullptr ) c = new GRFConfig ( * s ) ;
2014-05-24 19:12:48 +00:00
}
}
2019-04-10 21:07:06 +00:00
if ( c = = nullptr ) c = new GRFConfig ( filename ) ;
2006-04-22 13:59:21 +00:00
2006-12-12 19:38:41 +00:00
/* Parse parameters */
2020-05-17 21:32:03 +00:00
if ( item - > value . has_value ( ) & & ! item - > value - > empty ( ) ) {
int count = ParseIntList ( item - > value - > c_str ( ) , c - > param , lengthof ( c - > param ) ) ;
2014-05-24 19:12:48 +00:00
if ( count < 0 ) {
SetDParamStr ( 0 , filename ) ;
2011-12-10 16:05:26 +00:00
ShowErrorMessage ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_ARRAY , WL_CRITICAL ) ;
2014-05-24 19:12:48 +00:00
count = 0 ;
2006-12-12 19:38:41 +00:00
}
2014-05-24 19:12:48 +00:00
c - > num_params = count ;
2006-04-22 14:06:46 +00:00
}
2006-04-22 13:17:13 +00:00
2006-12-12 19:38:41 +00:00
/* Check if item is valid */
2011-01-15 21:13:47 +00:00
if ( ! FillGRFDetails ( c , is_static ) | | HasBit ( c - > flags , GCF_INVALID ) ) {
2007-03-06 19:33:28 +00:00
if ( c - > status = = GCS_NOT_FOUND ) {
2011-12-10 16:05:26 +00:00
SetDParam ( 1 , STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND ) ;
2007-11-19 21:02:30 +00:00
} else if ( HasBit ( c - > flags , GCF_UNSAFE ) ) {
2011-12-10 16:05:26 +00:00
SetDParam ( 1 , STR_CONFIG_ERROR_INVALID_GRF_UNSAFE ) ;
2007-11-19 21:02:30 +00:00
} else if ( HasBit ( c - > flags , GCF_SYSTEM ) ) {
2011-12-10 16:05:26 +00:00
SetDParam ( 1 , STR_CONFIG_ERROR_INVALID_GRF_SYSTEM ) ;
2011-01-15 21:13:47 +00:00
} else if ( HasBit ( c - > flags , GCF_INVALID ) ) {
2011-12-10 16:05:26 +00:00
SetDParam ( 1 , STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE ) ;
2006-12-12 19:38:41 +00:00
} else {
2011-12-10 16:05:26 +00:00
SetDParam ( 1 , STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN ) ;
2006-12-12 19:38:41 +00:00
}
2021-04-27 18:58:17 +00:00
SetDParamStr ( 0 , StrEmpty ( filename ) ? item - > name : filename ) ;
2011-12-10 16:05:26 +00:00
ShowErrorMessage ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_INVALID_GRF , WL_CRITICAL ) ;
2010-02-25 20:06:11 +00:00
delete c ;
2006-12-12 19:38:41 +00:00
continue ;
}
2009-09-12 14:40:26 +00:00
/* Check for duplicate GRFID (will also check for duplicate filenames) */
bool duplicate = false ;
2019-04-10 21:07:06 +00:00
for ( const GRFConfig * gc = first ; gc ! = nullptr ; gc = gc - > next ) {
2010-02-25 20:05:31 +00:00
if ( gc - > ident . grfid = = c - > ident . grfid ) {
2014-05-24 19:12:48 +00:00
SetDParamStr ( 0 , c - > filename ) ;
2011-12-10 16:05:26 +00:00
SetDParamStr ( 1 , gc - > filename ) ;
ShowErrorMessage ( STR_CONFIG_ERROR , STR_CONFIG_ERROR_DUPLICATE_GRFID , WL_CRITICAL ) ;
2009-09-12 14:40:26 +00:00
duplicate = true ;
break ;
}
}
if ( duplicate ) {
2010-02-25 20:06:11 +00:00
delete c ;
2009-09-12 14:40:26 +00:00
continue ;
}
2006-12-12 19:38:41 +00:00
/* Mark file as static to avoid saving in savegame. */
2007-11-20 13:35:54 +00:00
if ( is_static ) SetBit ( c - > flags , GCF_STATIC ) ;
2006-12-12 19:38:41 +00:00
/* Add item to list */
* curr = c ;
curr = & c - > next ;
2006-04-22 13:17:13 +00:00
}
2006-12-12 19:38:41 +00:00
return first ;
2006-04-22 13:17:13 +00:00
}
2004-08-09 17:04:08 +00:00
2021-06-28 14:39:48 +00:00
static IniFileVersion LoadVersionFromConfig ( IniFile & ini )
{
IniGroup * group = ini . GetGroup ( " version " ) ;
auto version_number = group - > GetItem ( " ini_version " , false ) ;
/* Older ini-file versions don't have this key yet. */
if ( version_number = = nullptr | | ! version_number - > value . has_value ( ) ) return IFV_0 ;
uint32 version = 0 ;
std : : from_chars ( version_number - > value - > data ( ) , version_number - > value - > data ( ) + version_number - > value - > size ( ) , version ) ;
return static_cast < IniFileVersion > ( version ) ;
}
2021-07-01 17:59:13 +00:00
static void AISaveConfig ( IniFile & ini , const char * grpname )
2009-01-12 17:11:45 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
2009-01-12 17:11:45 +00:00
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2009-01-14 20:23:45 +00:00
group - > Clear ( ) ;
2009-01-12 17:11:45 +00:00
for ( CompanyID c = COMPANY_FIRST ; c < MAX_COMPANIES ; c + + ) {
2011-11-29 23:26:35 +00:00
AIConfig * config = AIConfig : : GetConfig ( c , AIConfig : : SSS_FORCE_NEWGAME ) ;
2009-01-12 17:11:45 +00:00
const char * name ;
2021-04-29 17:04:27 +00:00
std : : string value = config - > SettingsToString ( ) ;
2009-01-12 17:11:45 +00:00
2011-11-29 23:26:35 +00:00
if ( config - > HasScript ( ) ) {
2009-01-12 17:11:45 +00:00
name = config - > GetName ( ) ;
} else {
name = " none " ;
}
2014-04-24 18:37:39 +00:00
IniItem * item = new IniItem ( group , name ) ;
2009-01-14 20:23:45 +00:00
item - > SetValue ( value ) ;
2009-01-12 17:11:45 +00:00
}
}
2021-07-01 17:59:13 +00:00
static void GameSaveConfig ( IniFile & ini , const char * grpname )
2011-12-19 20:56:34 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( grpname ) ;
2011-12-19 20:56:34 +00:00
2019-04-10 21:07:06 +00:00
if ( group = = nullptr ) return ;
2011-12-19 20:56:34 +00:00
group - > Clear ( ) ;
GameConfig * config = GameConfig : : GetConfig ( AIConfig : : SSS_FORCE_NEWGAME ) ;
const char * name ;
2021-04-29 17:04:27 +00:00
std : : string value = config - > SettingsToString ( ) ;
2011-12-19 20:56:34 +00:00
if ( config - > HasScript ( ) ) {
name = config - > GetName ( ) ;
} else {
name = " none " ;
}
2014-04-24 18:37:39 +00:00
IniItem * item = new IniItem ( group , name ) ;
2011-12-19 20:56:34 +00:00
item - > SetValue ( value ) ;
}
2008-03-27 15:29:42 +00:00
/**
* Save the version of OpenTTD to the ini file .
* @ param ini the ini to write to
*/
2021-07-01 17:59:13 +00:00
static void SaveVersionInConfig ( IniFile & ini )
2008-03-27 15:29:42 +00:00
{
2021-07-01 17:59:13 +00:00
IniGroup * group = ini . GetGroup ( " version " ) ;
2021-07-01 18:06:04 +00:00
group - > GetItem ( " version_string " , true ) - > SetValue ( _openttd_revision ) ;
group - > GetItem ( " version_number " , true ) - > SetValue ( fmt : : format ( " {:08X} " , _openttd_newgrf_version ) ) ;
2021-06-28 14:39:48 +00:00
group - > GetItem ( " ini_version " , true ) - > SetValue ( std : : to_string ( INIFILE_VERSION ) ) ;
2008-03-27 15:29:42 +00:00
}
2006-12-12 19:38:41 +00:00
/* Save a GRF configuration to the given group name */
2021-07-01 17:59:13 +00:00
static void GRFSaveConfig ( IniFile & ini , const char * grpname , const GRFConfig * list )
2006-12-10 11:32:54 +00:00
{
2021-07-01 17:59:13 +00:00
ini . RemoveGroup ( grpname ) ;
IniGroup * group = ini . GetGroup ( grpname ) ;
2006-12-10 11:32:54 +00:00
const GRFConfig * c ;
2019-04-10 21:07:06 +00:00
for ( c = list ; c ! = nullptr ; c = c - > next ) {
2014-05-24 19:12:48 +00:00
/* Hex grfid (4 bytes in nibbles), "|", hex md5sum (16 bytes in nibbles), "|", file system path. */
char key [ 4 * 2 + 1 + 16 * 2 + 1 + MAX_PATH ] ;
2006-12-10 11:32:54 +00:00
char params [ 512 ] ;
GRFBuildParamList ( params , c , lastof ( params ) ) ;
2014-05-24 19:12:48 +00:00
char * pos = key + seprintf ( key , lastof ( key ) , " %08X| " , BSWAP32 ( c - > ident . grfid ) ) ;
pos = md5sumToString ( pos , lastof ( key ) , c - > ident . md5sum ) ;
seprintf ( pos , lastof ( key ) , " |%s " , c - > filename ) ;
group - > GetItem ( key , true ) - > SetValue ( params ) ;
2006-12-10 11:32:54 +00:00
}
}
2006-03-02 00:07:41 +00:00
/* Common handler for saving/loading variables to the configuration file */
2021-06-28 14:39:48 +00:00
static void HandleSettingDescs ( IniFile & generic_ini , IniFile & private_ini , IniFile & secrets_ini , SettingDescProc * proc , SettingDescProcList * proc_list , bool only_startup = false )
2004-08-09 17:04:08 +00:00
{
2021-06-28 14:39:48 +00:00
proc ( generic_ini , _misc_settings , " misc " , nullptr , only_startup ) ;
2018-12-09 01:28:14 +00:00
# if defined(_WIN32) && !defined(DEDICATED)
2021-06-28 14:39:48 +00:00
proc ( generic_ini , _win32_settings , " win32 " , nullptr , only_startup ) ;
2018-12-09 01:28:14 +00:00
# endif /* _WIN32 */
2006-03-02 00:07:41 +00:00
2021-06-28 14:39:48 +00:00
/* The name "patches" is a fallback, as every setting should sets its own group. */
for ( auto & table : _generic_setting_tables ) {
proc ( generic_ini , table , " patches " , & _settings_newgame , only_startup ) ;
}
for ( auto & table : _private_setting_tables ) {
proc ( private_ini , table , " patches " , & _settings_newgame , only_startup ) ;
}
for ( auto & table : _secrets_setting_tables ) {
proc ( secrets_ini , table , " patches " , & _settings_newgame , only_startup ) ;
2021-06-28 13:35:00 +00:00
}
2021-06-28 14:39:48 +00:00
proc ( generic_ini , _currency_settings , " currency " , & _custom_currency , only_startup ) ;
proc ( generic_ini , _company_settings , " company " , & _settings_client . company , only_startup ) ;
2006-03-02 00:07:41 +00:00
2021-02-15 23:09:52 +00:00
if ( ! only_startup ) {
2021-06-28 14:39:48 +00:00
proc_list ( private_ini , " server_bind_addresses " , _network_bind_list ) ;
proc_list ( private_ini , " servers " , _network_host_list ) ;
proc_list ( private_ini , " bans " , _network_ban_list ) ;
}
}
/**
* Remove all entries from a settings table from an ini - file .
*
* This is only useful if those entries are moved to another file , and you
* want to clean up what is left behind .
*
* @ param ini The ini file to remove the entries from .
* @ param table The table to look for entries to remove .
*/
static void RemoveEntriesFromIni ( IniFile & ini , const SettingTable & table )
{
for ( auto & desc : table ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
/* For settings.xx.yy load the settings from [xx] yy = ? */
std : : string s { sd - > name } ;
auto sc = s . find ( ' . ' ) ;
if ( sc = = std : : string : : npos ) continue ;
IniGroup * group = ini . GetGroup ( s . substr ( 0 , sc ) ) ;
s = s . substr ( sc + 1 ) ;
group - > RemoveItem ( s ) ;
2011-12-04 13:21:51 +00:00
}
2004-08-09 17:04:08 +00:00
}
2011-11-14 21:42:54 +00:00
/**
* Load the values from the configuration files
2021-02-15 23:09:52 +00:00
* @ param startup Load the minimal amount of the configuration to " bootstrap " the blitter and such .
2011-11-14 21:42:54 +00:00
*/
2021-02-15 23:09:52 +00:00
void LoadFromConfig ( bool startup )
2004-08-09 17:04:08 +00:00
{
2021-06-28 14:39:48 +00:00
ConfigIniFile generic_ini ( _config_file ) ;
ConfigIniFile private_ini ( _private_file ) ;
ConfigIniFile secrets_ini ( _secrets_file ) ;
2021-02-15 23:09:52 +00:00
if ( ! startup ) ResetCurrencies ( false ) ; // Initialize the array of currencies, without preserving the custom one
2008-05-28 14:36:06 +00:00
2021-06-28 14:39:48 +00:00
IniFileVersion generic_version = LoadVersionFromConfig ( generic_ini ) ;
/* Before the split of private/secrets, we have to look in the generic for these settings. */
if ( generic_version < IFV_PRIVATE_SECRETS ) {
HandleSettingDescs ( generic_ini , generic_ini , generic_ini , IniLoadSettings , IniLoadSettingList , startup ) ;
} else {
HandleSettingDescs ( generic_ini , private_ini , secrets_ini , IniLoadSettings , IniLoadSettingList , startup ) ;
}
2009-03-19 22:37:41 +00:00
2021-06-28 14:39:48 +00:00
/* Load basic settings only during bootstrap, load other settings not during bootstrap */
2021-02-15 23:09:52 +00:00
if ( ! startup ) {
2021-06-28 14:39:48 +00:00
_grfconfig_newgame = GRFLoadConfig ( generic_ini , " newgrf " , false ) ;
_grfconfig_static = GRFLoadConfig ( generic_ini , " newgrf-static " , true ) ;
AILoadConfig ( generic_ini , " ai_players " ) ;
GameLoadConfig ( generic_ini , " game_scripts " ) ;
2011-11-14 21:42:54 +00:00
PrepareOldDiffCustom ( ) ;
2021-06-28 14:39:48 +00:00
IniLoadSettings ( generic_ini , _gameopt_settings , " gameopt " , & _settings_newgame , false ) ;
2011-11-14 21:42:54 +00:00
HandleOldDiffCustom ( false ) ;
ValidateSettings ( ) ;
2012-05-14 21:04:49 +00:00
2019-09-29 20:27:32 +00:00
/* Display scheduled errors */
2012-05-14 21:04:49 +00:00
extern void ScheduleErrorMessage ( ErrorList & datas ) ;
ScheduleErrorMessage ( _settings_error_list ) ;
2019-04-10 21:07:06 +00:00
if ( FindWindowById ( WC_ERRMSG , 0 ) = = nullptr ) ShowFirstError ( ) ;
2011-11-14 21:42:54 +00:00
}
2004-08-09 17:04:08 +00:00
}
2006-03-02 00:07:41 +00:00
/** Save the values to the configuration file */
2007-03-07 11:47:46 +00:00
void SaveToConfig ( )
2004-08-09 17:04:08 +00:00
{
2021-06-28 14:39:48 +00:00
ConfigIniFile generic_ini ( _config_file ) ;
ConfigIniFile private_ini ( _private_file ) ;
ConfigIniFile secrets_ini ( _secrets_file ) ;
IniFileVersion generic_version = LoadVersionFromConfig ( generic_ini ) ;
/* If we newly create the private/secrets file, add a dummy group on top
* just so we can add a comment before it ( that is how IniFile works ) .
* This to explain what the file is about . After doing it once , never touch
* it again , as otherwise we might be reverting user changes . */
if ( ! private_ini . GetGroup ( " private " , false ) ) private_ini . GetGroup ( " private " ) - > comment = " ; This file possibly contains private information which can identify you as person. \n " ;
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 " ;
if ( generic_version = = IFV_0 ) {
/* Remove some obsolete groups. These have all been loaded into other groups. */
generic_ini . RemoveGroup ( " patches " ) ;
generic_ini . RemoveGroup ( " yapf " ) ;
generic_ini . RemoveGroup ( " gameopt " ) ;
/* Remove all settings from the generic ini that are now in the private ini. */
generic_ini . RemoveGroup ( " server_bind_addresses " ) ;
generic_ini . RemoveGroup ( " servers " ) ;
generic_ini . RemoveGroup ( " bans " ) ;
for ( auto & table : _private_setting_tables ) {
RemoveEntriesFromIni ( generic_ini , table ) ;
}
2008-05-25 19:17:03 +00:00
2021-06-28 14:39:48 +00:00
/* Remove all settings from the generic ini that are now in the secrets ini. */
for ( auto & table : _secrets_setting_tables ) {
RemoveEntriesFromIni ( generic_ini , table ) ;
}
}
HandleSettingDescs ( generic_ini , private_ini , secrets_ini , IniSaveSettings , IniSaveSettingList ) ;
GRFSaveConfig ( generic_ini , " newgrf " , _grfconfig_newgame ) ;
GRFSaveConfig ( generic_ini , " newgrf-static " , _grfconfig_static ) ;
AISaveConfig ( generic_ini , " ai_players " ) ;
GameSaveConfig ( generic_ini , " game_scripts " ) ;
SaveVersionInConfig ( generic_ini ) ;
SaveVersionInConfig ( private_ini ) ;
SaveVersionInConfig ( secrets_ini ) ;
generic_ini . SaveToDisk ( _config_file ) ;
private_ini . SaveToDisk ( _private_file ) ;
secrets_ini . SaveToDisk ( _secrets_file ) ;
2004-08-09 17:04:08 +00:00
}
2005-04-13 23:03:31 +00:00
2010-05-30 13:16:51 +00:00
/**
* Get the list of known NewGrf presets .
2019-04-02 19:31:33 +00:00
* @ returns List of preset names .
2010-05-30 13:16:51 +00:00
*/
2019-04-02 19:31:33 +00:00
StringList GetGRFPresetList ( )
2008-07-22 14:17:29 +00:00
{
2019-04-02 19:31:33 +00:00
StringList list ;
2008-07-22 14:17:29 +00:00
2021-07-01 17:59:13 +00:00
ConfigIniFile ini ( _config_file ) ;
for ( IniGroup * group = ini . group ; group ! = nullptr ; group = group - > next ) {
2020-05-17 21:32:03 +00:00
if ( group - > name . compare ( 0 , 7 , " preset- " ) = = 0 ) {
list . push_back ( group - > name . substr ( 7 ) ) ;
2008-07-22 14:17:29 +00:00
}
}
2019-04-02 19:31:33 +00:00
return list ;
2008-07-22 14:17:29 +00:00
}
2010-05-30 13:16:51 +00:00
/**
* Load a NewGRF configuration by preset - name .
* @ param config_name Name of the preset .
* @ return NewGRF configuration .
* @ see GetGRFPresetList
*/
2008-07-22 14:17:29 +00:00
GRFConfig * LoadGRFPresetFromConfig ( const char * config_name )
{
2014-04-24 17:40:43 +00:00
size_t len = strlen ( config_name ) + 8 ;
char * section = ( char * ) alloca ( len ) ;
seprintf ( section , section + len - 1 , " preset-%s " , config_name ) ;
2008-07-22 14:17:29 +00:00
2021-07-01 17:59:13 +00:00
ConfigIniFile ini ( _config_file ) ;
2008-07-22 14:17:29 +00:00
GRFConfig * config = GRFLoadConfig ( ini , section , false ) ;
return config ;
}
2010-05-30 13:16:51 +00:00
/**
* Save a NewGRF configuration with a preset name .
* @ param config_name Name of the preset .
* @ param config NewGRF configuration to save .
* @ see GetGRFPresetList
*/
2008-07-22 14:17:29 +00:00
void SaveGRFPresetToConfig ( const char * config_name , GRFConfig * config )
{
2014-04-24 17:40:43 +00:00
size_t len = strlen ( config_name ) + 8 ;
char * section = ( char * ) alloca ( len ) ;
seprintf ( section , section + len - 1 , " preset-%s " , config_name ) ;
2008-07-22 14:17:29 +00:00
2021-07-01 17:59:13 +00:00
ConfigIniFile ini ( _config_file ) ;
2008-07-22 14:17:29 +00:00
GRFSaveConfig ( ini , section , config ) ;
2021-07-01 17:59:13 +00:00
ini . SaveToDisk ( _config_file ) ;
2008-07-22 14:17:29 +00:00
}
2010-05-30 13:16:51 +00:00
/**
* Delete a NewGRF configuration by preset name .
* @ param config_name Name of the preset .
*/
2008-07-22 14:17:29 +00:00
void DeleteGRFPresetFromConfig ( const char * config_name )
{
2014-04-24 17:40:43 +00:00
size_t len = strlen ( config_name ) + 8 ;
char * section = ( char * ) alloca ( len ) ;
seprintf ( section , section + len - 1 , " preset-%s " , config_name ) ;
2008-07-22 14:17:29 +00:00
2021-07-01 17:59:13 +00:00
ConfigIniFile ini ( _config_file ) ;
ini . RemoveGroup ( section ) ;
ini . SaveToDisk ( _config_file ) ;
2008-07-22 14:17:29 +00:00
}
2021-05-22 18:44:09 +00:00
/**
* Handle changing a value . This performs validation of the input value and
* calls the appropriate callbacks , and saves it when the value is changed .
* @ param object The object the setting is in .
* @ param newval The new value for the setting .
*/
void IntSettingDesc : : ChangeValue ( const void * object , int32 newval ) const
{
2021-05-24 08:42:02 +00:00
int32 oldval = this - > Read ( object ) ;
2021-05-24 09:47:37 +00:00
this - > MakeValueValid ( newval ) ;
if ( this - > pre_check ! = nullptr & & ! this - > pre_check ( newval ) ) return ;
2021-05-22 18:44:09 +00:00
if ( oldval = = newval ) return ;
2021-05-24 09:47:37 +00:00
this - > Write ( object , newval ) ;
if ( this - > post_callback ! = nullptr ) this - > post_callback ( newval ) ;
2021-05-22 18:44:09 +00:00
2021-06-03 19:18:29 +00:00
if ( this - > flags & SF_NO_NETWORK ) {
2021-05-22 18:44:09 +00:00
GamelogStartAction ( GLAT_SETTING ) ;
GamelogSetting ( this - > name , oldval , newval ) ;
GamelogStopAction ( ) ;
}
SetWindowClassesDirty ( WC_GAME_OPTIONS ) ;
if ( _save_config ) SaveToConfig ( ) ;
}
2021-05-29 21:27:01 +00:00
/**
* Given a name of setting , return a setting description from the table .
* @ param name Name of the setting to return a setting description of .
* @ param settings Table to look in for the setting .
* @ return Pointer to the setting description of setting \ a name if it can be found ,
* \ c nullptr indicates failure to obtain the description .
*/
2021-05-30 09:30:03 +00:00
static const SettingDesc * GetSettingFromName ( const std : : string_view name , const SettingTable & settings )
2021-05-29 21:27:01 +00:00
{
/* First check all full names */
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-05-29 21:27:01 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2021-06-21 16:39:27 +00:00
if ( sd - > name = = name ) return sd ;
2021-05-29 21:27:01 +00:00
}
/* Then check the shortcut variant of the name. */
2021-05-30 09:30:03 +00:00
std : : string short_name_suffix = std : : string { " . " } . append ( name ) ;
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-05-29 21:27:01 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2021-06-21 16:39:27 +00:00
if ( StrEndsWith ( sd - > name , short_name_suffix ) ) return sd ;
2021-05-29 21:27:01 +00:00
}
return nullptr ;
}
2021-05-30 08:55:52 +00:00
/**
* Get the SaveLoad from all settings matching the prefix .
* @ param prefix The prefix to look for .
* @ param saveloads A vector to store the result in .
*/
2021-05-30 09:30:03 +00:00
void GetSettingSaveLoadByPrefix ( std : : string_view prefix , std : : vector < SaveLoad > & saveloads )
2021-05-30 08:55:52 +00:00
{
2021-06-21 16:39:27 +00:00
for ( auto & desc : _settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-05-30 08:55:52 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2021-05-30 09:30:03 +00:00
if ( StrStartsWith ( sd - > name , prefix ) ) saveloads . push_back ( sd - > save ) ;
2021-05-30 08:55:52 +00:00
}
}
2021-05-29 21:27:01 +00:00
/**
* Given a name of setting , return a company setting description of it .
* @ param name Name of the company setting to return a setting description of .
* @ return Pointer to the setting description of setting \ a name if it can be found ,
* \ c nullptr indicates failure to obtain the description .
*/
2021-05-30 09:30:03 +00:00
static const SettingDesc * GetCompanySettingFromName ( std : : string_view name )
2021-05-29 21:27:01 +00:00
{
2021-05-30 09:30:03 +00:00
static const std : : string_view company_prefix = " company. " ;
if ( StrStartsWith ( name , company_prefix ) ) name . remove_prefix ( company_prefix . size ( ) ) ;
2021-05-29 21:27:01 +00:00
return GetSettingFromName ( name , _company_settings ) ;
}
/**
* Given a name of any setting , return any setting description of it .
* @ param name Name of the setting to return a setting description of .
* @ return Pointer to the setting description of setting \ a name if it can be found ,
* \ c nullptr indicates failure to obtain the description .
*/
2021-05-30 09:30:03 +00:00
const SettingDesc * GetSettingFromName ( const std : : string_view name )
2021-05-29 21:27:01 +00:00
{
2021-06-28 14:39:48 +00:00
for ( auto & table : _generic_setting_tables ) {
auto sd = GetSettingFromName ( name , table ) ;
if ( sd ! = nullptr ) return sd ;
}
for ( auto & table : _private_setting_tables ) {
auto sd = GetSettingFromName ( name , table ) ;
if ( sd ! = nullptr ) return sd ;
}
for ( auto & table : _secrets_setting_tables ) {
2021-06-28 13:35:00 +00:00
auto sd = GetSettingFromName ( name , table ) ;
if ( sd ! = nullptr ) return sd ;
}
2021-05-29 21:27:01 +00:00
return GetCompanySettingFromName ( name ) ;
}
2010-08-01 19:22:34 +00:00
/**
* Network - safe changing of settings ( server - only ) .
2007-04-17 21:09:38 +00:00
* @ param tile unused
* @ param flags operation to perform
2021-05-29 21:27:01 +00:00
* @ param p1 unused
2009-02-08 12:25:13 +00:00
* @ param p2 the new value for the setting
2006-03-02 01:56:25 +00:00
* The new value is properly clamped to its minimum / maximum when setting
2021-05-29 21:27:01 +00:00
* @ param text the name of the setting to change
2009-09-18 14:23:58 +00:00
* @ return the cost of this operation or an error
2009-02-08 12:25:13 +00:00
* @ see _settings
2006-03-02 01:56:25 +00:00
*/
2021-05-29 14:09:25 +00:00
CommandCost CmdChangeSetting ( TileIndex tile , DoCommandFlag flags , uint32 p1 , uint32 p2 , const std : : string & text )
2006-03-02 01:56:25 +00:00
{
2021-05-29 21:27:01 +00:00
if ( text . empty ( ) ) return CMD_ERROR ;
2021-05-30 09:30:03 +00:00
const SettingDesc * sd = GetSettingFromName ( text ) ;
2006-03-02 01:56:25 +00:00
2019-04-10 21:07:06 +00:00
if ( sd = = nullptr ) return CMD_ERROR ;
2006-03-16 00:22:36 +00:00
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) return CMD_ERROR ;
2021-05-22 18:44:09 +00:00
if ( ! sd - > IsIntSetting ( ) ) return CMD_ERROR ;
2006-03-02 01:56:25 +00:00
2012-12-05 19:35:09 +00:00
if ( ! sd - > IsEditable ( true ) ) return CMD_ERROR ;
2007-11-17 22:25:16 +00:00
2006-03-02 01:56:25 +00:00
if ( flags & DC_EXEC ) {
2021-05-22 18:44:09 +00:00
sd - > AsIntSetting ( ) - > ChangeValue ( & GetGameSettings ( ) , p2 ) ;
2006-03-02 01:56:25 +00:00
}
2007-06-18 19:53:50 +00:00
return CommandCost ( ) ;
2006-03-02 01:56:25 +00:00
}
2010-08-01 19:22:34 +00:00
/**
* Change one of the per - company settings .
2009-05-26 11:40:14 +00:00
* @ param tile unused
* @ param flags operation to perform
2021-05-29 21:27:01 +00:00
* @ param p1 unused
2009-05-26 11:40:14 +00:00
* @ param p2 the new value for the setting
* The new value is properly clamped to its minimum / maximum when setting
2021-05-29 21:27:01 +00:00
* @ param text the name of the company setting to change
2009-09-18 14:23:58 +00:00
* @ return the cost of this operation or an error
2009-05-26 11:40:14 +00:00
*/
2021-05-29 14:09:25 +00:00
CommandCost CmdChangeCompanySetting ( TileIndex tile , DoCommandFlag flags , uint32 p1 , uint32 p2 , const std : : string & text )
2009-05-26 11:40:14 +00:00
{
2021-05-29 21:27:01 +00:00
if ( text . empty ( ) ) return CMD_ERROR ;
const SettingDesc * sd = GetCompanySettingFromName ( text . c_str ( ) ) ;
2021-05-18 19:01:42 +00:00
if ( sd = = nullptr ) return CMD_ERROR ;
2021-05-22 18:44:09 +00:00
if ( ! sd - > IsIntSetting ( ) ) return CMD_ERROR ;
2009-05-26 11:40:14 +00:00
if ( flags & DC_EXEC ) {
2021-05-22 18:44:09 +00:00
sd - > AsIntSetting ( ) - > ChangeValue ( & Company : : Get ( _current_company ) - > settings , p2 ) ;
2009-05-26 11:40:14 +00:00
}
return CommandCost ( ) ;
}
2010-08-01 19:22:34 +00:00
/**
* Top function to save the new value of an element of the Settings struct
2009-02-08 12:25:13 +00:00
* @ param index offset in the SettingDesc array of the Settings struct which
* identifies the setting member we want to change
2009-09-19 15:17:47 +00:00
* @ param value new value of the setting
2010-01-28 23:17:28 +00:00
* @ param force_newgame force the newgame settings
2009-09-19 15:17:47 +00:00
*/
2021-05-23 09:55:22 +00:00
bool SetSettingValue ( const IntSettingDesc * sd , int32 value , bool force_newgame )
2006-03-02 01:41:25 +00:00
{
2021-05-22 18:44:09 +00:00
const IntSettingDesc * setting = sd - > AsIntSetting ( ) ;
2021-06-03 19:18:29 +00:00
if ( ( setting - > flags & SF_PER_COMPANY ) ! = 0 ) {
2021-05-18 18:57:44 +00:00
if ( Company : : IsValidID ( _local_company ) & & _game_mode ! = GM_MENU ) {
2021-05-29 21:27:01 +00:00
return DoCommandP ( 0 , 0 , value , CMD_CHANGE_COMPANY_SETTING , nullptr , setting - > name ) ;
2021-05-18 18:57:44 +00:00
}
2021-05-22 18:44:09 +00:00
setting - > ChangeValue ( & _settings_client . company , value ) ;
2021-05-18 18:57:44 +00:00
return true ;
}
2008-09-30 20:39:50 +00:00
/* If an item is company-based, we do not send it over the network
2006-03-02 01:41:25 +00:00
* ( if any ) to change . Also * hack * hack * we update the _newgame version
2009-02-08 12:25:13 +00:00
* of settings because changing a company - based setting in a game also
2006-03-02 01:41:25 +00:00
* changes its defaults . At least that is the convention we have chosen */
2021-06-03 18:55:03 +00:00
if ( setting - > flags & SF_NO_NETWORK_SYNC ) {
2006-03-02 02:22:15 +00:00
if ( _game_mode ! = GM_MENU ) {
2021-05-22 18:44:09 +00:00
setting - > ChangeValue ( & _settings_newgame , value ) ;
2006-03-02 02:22:15 +00:00
}
2021-05-22 18:44:09 +00:00
setting - > ChangeValue ( & GetGameSettings ( ) , value ) ;
2006-09-14 23:26:58 +00:00
return true ;
2006-03-02 01:41:25 +00:00
}
2006-09-14 23:26:58 +00:00
2010-01-28 23:17:28 +00:00
if ( force_newgame ) {
2021-05-22 18:44:09 +00:00
setting - > ChangeValue ( & _settings_newgame , value ) ;
2010-01-28 23:17:28 +00:00
return true ;
}
2008-09-30 20:39:50 +00:00
/* send non-company-based settings over the network */
2006-09-14 23:26:58 +00:00
if ( ! _networking | | ( _networking & & _network_server ) ) {
2021-05-29 21:27:01 +00:00
return DoCommandP ( 0 , 0 , value , CMD_CHANGE_SETTING , nullptr , setting - > name ) ;
2006-09-14 23:26:58 +00:00
}
return false ;
2006-03-02 01:41:25 +00:00
}
2009-05-26 23:14:02 +00:00
/**
* Set the company settings for a new company to their default values .
*/
void SetDefaultCompanySettings ( CompanyID cid )
{
Company * c = Company : : Get ( cid ) ;
2021-06-21 16:39:27 +00:00
for ( auto & desc : _company_settings ) {
const IntSettingDesc * int_setting = GetSettingDesc ( desc ) - > AsIntSetting ( ) ;
2021-05-24 08:42:02 +00:00
int_setting - > MakeValueValidAndWrite ( & c - > settings , int_setting - > def ) ;
2009-05-26 23:14:02 +00:00
}
}
2009-05-26 13:29:01 +00:00
/**
* Sync all company settings in a multiplayer game .
*/
void SyncCompanySettings ( )
{
2021-05-24 08:42:02 +00:00
const void * old_object = & Company : : Get ( _current_company ) - > settings ;
const void * new_object = & _settings_client . company ;
2021-06-21 16:39:27 +00:00
for ( auto & desc : _company_settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-05-24 08:42:02 +00:00
uint32 old_value = ( uint32 ) sd - > AsIntSetting ( ) - > Read ( new_object ) ;
uint32 new_value = ( uint32 ) sd - > AsIntSetting ( ) - > Read ( old_object ) ;
2021-05-29 21:27:01 +00:00
if ( old_value ! = new_value ) NetworkSendCommand ( 0 , 0 , new_value , CMD_CHANGE_COMPANY_SETTING , nullptr , sd - > name , _local_company ) ;
2009-05-26 13:29:01 +00:00
}
}
2008-05-30 09:23:05 +00:00
/**
2009-02-08 12:25:13 +00:00
* Set a setting value with a string .
2021-05-18 18:57:44 +00:00
* @ param sd the setting to change .
2008-05-30 09:23:05 +00:00
* @ param value the value to write
2010-05-20 15:14:10 +00:00
* @ param force_newgame force the newgame settings
* @ note Strings WILL NOT be synced over the network
2008-05-30 09:23:05 +00:00
*/
2021-05-24 07:44:20 +00:00
bool SetSettingValue ( const StringSettingDesc * sd , std : : string value , bool force_newgame )
2008-05-30 09:23:05 +00:00
{
2021-06-03 18:55:03 +00:00
assert ( sd - > flags & SF_NO_NETWORK_SYNC ) ;
2008-05-30 09:23:05 +00:00
2021-05-24 07:44:20 +00:00
if ( GetVarMemType ( sd - > save . conv ) = = SLE_VAR_STRQ & & value . compare ( " (null) " ) = = 0 ) {
value . clear ( ) ;
2021-04-27 16:24:33 +00:00
}
2021-05-22 18:52:24 +00:00
const void * object = ( _game_mode = = GM_MENU | | force_newgame ) ? & _settings_newgame : & _settings_game ;
sd - > AsStringSetting ( ) - > ChangeValue ( object , value ) ;
return true ;
}
/**
* Handle changing a string value . This performs validation of the input value
* and calls the appropriate callbacks , and saves it when the value is changed .
* @ param object The object the setting is in .
* @ param newval The new value for the setting .
*/
2021-05-24 07:44:20 +00:00
void StringSettingDesc : : ChangeValue ( const void * object , std : : string & newval ) const
2021-05-22 18:52:24 +00:00
{
2021-05-24 07:44:20 +00:00
this - > MakeValueValid ( newval ) ;
2021-05-24 07:44:20 +00:00
if ( this - > pre_check ! = nullptr & & ! this - > pre_check ( newval ) ) return ;
2021-05-24 07:44:20 +00:00
this - > Write ( object , newval ) ;
2021-05-24 07:44:20 +00:00
if ( this - > post_callback ! = nullptr ) this - > post_callback ( newval ) ;
2008-05-30 09:23:05 +00:00
2020-12-13 15:28:06 +00:00
if ( _save_config ) SaveToConfig ( ) ;
2008-05-30 09:23:05 +00:00
}
2006-03-02 01:56:25 +00:00
/* Those 2 functions need to be here, else we have to make some stuff non-static
2006-08-15 07:37:01 +00:00
* and besides , it is also better to keep stuff like this at the same place */
2010-01-28 23:17:28 +00:00
void IConsoleSetSetting ( const char * name , const char * value , bool force_newgame )
2006-03-02 01:56:25 +00:00
{
2021-05-18 18:57:44 +00:00
const SettingDesc * sd = GetSettingFromName ( name ) ;
2019-04-10 21:07:06 +00:00
if ( sd = = nullptr ) {
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_ERROR , " '{}' is an unknown setting. " , name ) ;
2008-06-02 23:01:57 +00:00
return ;
2006-03-02 01:56:25 +00:00
}
2021-05-23 17:27:46 +00:00
bool success = true ;
if ( sd - > IsStringSetting ( ) ) {
2021-05-23 09:55:22 +00:00
success = SetSettingValue ( sd - > AsStringSetting ( ) , value , force_newgame ) ;
2021-05-23 17:27:46 +00:00
} else if ( sd - > IsIntSetting ( ) ) {
2008-05-30 09:23:05 +00:00
uint32 val ;
extern bool GetArgumentInteger ( uint32 * value , const char * arg ) ;
success = GetArgumentInteger ( & val , value ) ;
2009-06-19 15:48:13 +00:00
if ( ! success ) {
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_ERROR , " '{}' is not an integer. " , value ) ;
2009-06-19 15:48:13 +00:00
return ;
}
2021-05-23 09:55:22 +00:00
success = SetSettingValue ( sd - > AsIntSetting ( ) , val , force_newgame ) ;
2008-05-30 09:23:05 +00:00
}
if ( ! success ) {
if ( _network_server ) {
2021-06-12 19:07:04 +00:00
IConsolePrint ( CC_ERROR , " This command/variable is not available during network games. " ) ;
2008-05-30 09:23:05 +00:00
} else {
2021-06-12 19:07:04 +00:00
IConsolePrint ( CC_ERROR , " This command/variable is only available to a network server. " ) ;
2008-05-30 09:23:05 +00:00
}
}
}
2006-03-02 01:56:25 +00:00
2009-02-08 12:25:13 +00:00
void IConsoleSetSetting ( const char * name , int value )
2008-05-30 09:23:05 +00:00
{
2021-05-18 18:57:44 +00:00
const SettingDesc * sd = GetSettingFromName ( name ) ;
2019-04-10 21:07:06 +00:00
assert ( sd ! = nullptr ) ;
2021-05-23 09:55:22 +00:00
SetSettingValue ( sd - > AsIntSetting ( ) , value ) ;
2006-03-02 01:56:25 +00:00
}
2008-09-28 15:42:15 +00:00
/**
2009-02-08 12:25:13 +00:00
* Output value of a specific setting to the console
* @ param name Name of the setting to output its value
2010-01-28 23:17:28 +00:00
* @ param force_newgame force the newgame settings
2008-09-28 15:42:15 +00:00
*/
2010-01-28 23:17:28 +00:00
void IConsoleGetSetting ( const char * name , bool force_newgame )
2006-03-02 01:56:25 +00:00
{
2021-05-18 18:57:44 +00:00
const SettingDesc * sd = GetSettingFromName ( name ) ;
2019-04-10 21:07:06 +00:00
if ( sd = = nullptr ) {
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_ERROR , " '{}' is an unknown setting. " , name ) ;
2006-03-02 01:56:25 +00:00
return ;
}
2021-05-22 11:46:39 +00:00
const void * object = ( _game_mode = = GM_MENU | | force_newgame ) ? & _settings_newgame : & _settings_game ;
2006-03-02 01:56:25 +00:00
2021-05-23 17:27:46 +00:00
if ( sd - > IsStringSetting ( ) ) {
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_INFO , " Current value for '{}' is '{}'. " , sd - > name , sd - > AsStringSetting ( ) - > Read ( object ) ) ;
2021-05-22 19:09:30 +00:00
} else if ( sd - > IsIntSetting ( ) ) {
2021-05-22 11:46:39 +00:00
char value [ 20 ] ;
sd - > FormatValue ( value , lastof ( value ) , object ) ;
2021-05-22 19:09:30 +00:00
const IntSettingDesc * int_setting = sd - > AsIntSetting ( ) ;
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_INFO , " Current value for '{}' is '{}' (min: {}{}, max: {}). " ,
2021-05-30 09:51:21 +00:00
sd - > name . c_str ( ) , value , ( sd - > flags & SF_GUI_0_IS_SPECIAL ) ? " (0) " : " " , int_setting - > min , int_setting - > max ) ;
2008-05-30 09:23:05 +00:00
}
2006-03-02 01:56:25 +00:00
}
2021-06-28 14:39:48 +00:00
static void IConsoleListSettingsTable ( const SettingTable & table , const char * prefilter )
{
for ( auto & desc : table ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
if ( prefilter ! = nullptr & & sd - > name . find ( prefilter ) = = std : : string : : npos ) continue ;
char value [ 80 ] ;
sd - > FormatValue ( value , lastof ( value ) , & GetGameSettings ( ) ) ;
IConsolePrint ( CC_DEFAULT , " {} = {} " , sd - > name , value ) ;
}
}
2008-09-28 15:42:15 +00:00
/**
2009-02-08 12:25:13 +00:00
* List all settings and their value to the console
2008-09-28 15:42:15 +00:00
*
2019-04-10 21:07:06 +00:00
* @ param prefilter If not \ c nullptr , only list settings with names that begin with \ a prefilter prefix
2008-09-28 15:42:15 +00:00
*/
2009-02-08 12:25:13 +00:00
void IConsoleListSettings ( const char * prefilter )
2007-04-05 12:59:57 +00:00
{
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_HELP , " All settings with their current value: " ) ;
2007-04-05 12:59:57 +00:00
2021-06-28 14:39:48 +00:00
for ( auto & table : _generic_setting_tables ) {
IConsoleListSettingsTable ( table , prefilter ) ;
}
for ( auto & table : _private_setting_tables ) {
IConsoleListSettingsTable ( table , prefilter ) ;
}
for ( auto & table : _secrets_setting_tables ) {
IConsoleListSettingsTable ( table , prefilter ) ;
2007-04-05 12:59:57 +00:00
}
2021-06-12 19:33:01 +00:00
IConsolePrint ( CC_HELP , " Use 'setting' command to change a value. " ) ;
2007-04-05 12:59:57 +00:00
}
2021-06-07 21:03:12 +00:00
/**
* Get the SaveLoad description for the SettingTable .
* @ param settings SettingDesc struct containing all information .
* @ param is_loading True iff the SaveLoad table is for loading .
* @ return Vector with SaveLoad entries for the SettingTable .
*/
static std : : vector < SaveLoad > GetSettingsDesc ( const SettingTable & settings , bool is_loading )
{
std : : vector < SaveLoad > saveloads ;
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-06-07 21:03:12 +00:00
if ( sd - > flags & SF_NOT_IN_SAVE ) continue ;
if ( is_loading & & ( sd - > flags & SF_NO_NETWORK_SYNC ) & & _networking & & ! _network_server ) {
2021-05-30 13:59:40 +00:00
if ( IsSavegameVersionBefore ( SLV_TABLE_CHUNKS ) ) {
/* We don't want to read this setting, so we do need to skip over it. */
saveloads . push_back ( { sd - > name , sd - > save . cmd , GetVarFileType ( sd - > save . conv ) | SLE_VAR_NULL , sd - > save . length , sd - > save . version_from , sd - > save . version_to , 0 , nullptr , 0 , nullptr } ) ;
}
2021-06-07 21:03:12 +00:00
continue ;
}
2021-05-30 13:59:40 +00:00
SaveLoad sv = sd - > save ;
/* Replace the name with the actual name of the setting. */
if ( ! sd - > name . empty ( ) ) sv . name = sd - > name ;
saveloads . push_back ( sv ) ;
2021-06-07 21:03:12 +00:00
}
return saveloads ;
}
2010-08-01 19:22:34 +00:00
/**
* Save and load handler for settings
2021-05-18 19:01:42 +00:00
* @ param settings SettingDesc struct containing all information
2019-04-10 21:07:06 +00:00
* @ param object can be either nullptr in which case we load global variables or
2010-08-01 19:44:49 +00:00
* a pointer to a struct which is getting saved
*/
2021-05-30 13:59:40 +00:00
static void LoadSettings ( const SettingTable & settings , void * object , const SaveLoadCompatTable & slct )
2006-03-02 00:32:48 +00:00
{
2021-05-30 13:59:40 +00:00
const std : : vector < SaveLoad > slt = SlCompatTableHeader ( GetSettingsDesc ( settings , true ) , slct ) ;
2021-06-04 07:28:38 +00:00
2021-06-06 07:59:33 +00:00
if ( ! IsSavegameVersionBefore ( SLV_RIFF_TO_ARRAY ) & & SlIterateArray ( ) = = - 1 ) return ;
2021-06-07 21:03:12 +00:00
SlObject ( object , slt ) ;
2021-06-06 07:59:33 +00:00
if ( ! IsSavegameVersionBefore ( SLV_RIFF_TO_ARRAY ) & & SlIterateArray ( ) ! = - 1 ) SlErrorCorrupt ( " Too many settings entries " ) ;
2021-06-04 07:31:28 +00:00
2021-06-07 21:03:12 +00:00
/* Ensure all IntSettings are valid (min/max could have changed between versions etc). */
2021-06-21 16:39:27 +00:00
for ( auto & desc : settings ) {
const SettingDesc * sd = GetSettingDesc ( desc ) ;
2021-06-07 21:03:12 +00:00
if ( sd - > flags & SF_NOT_IN_SAVE ) continue ;
if ( ( sd - > flags & SF_NO_NETWORK_SYNC ) & & _networking & & ! _network_server ) continue ;
if ( ! SlIsObjectCurrentlyValid ( sd - > save . version_from , sd - > save . version_to ) ) continue ;
2006-03-02 00:32:48 +00:00
2021-06-07 21:03:12 +00:00
if ( sd - > IsIntSetting ( ) ) {
const IntSettingDesc * int_setting = sd - > AsIntSetting ( ) ;
2021-05-24 08:42:02 +00:00
int_setting - > MakeValueValidAndWrite ( object , int_setting - > Read ( object ) ) ;
2021-05-24 08:42:02 +00:00
}
2006-03-02 00:32:48 +00:00
}
}
2010-08-01 19:22:34 +00:00
/**
* Save and load handler for settings
2021-05-18 19:01:42 +00:00
* @ param settings SettingDesc struct containing all information
2019-04-10 21:07:06 +00:00
* @ param object can be either nullptr in which case we load global variables or
2010-08-01 19:44:49 +00:00
* a pointer to a struct which is getting saved
*/
2021-05-18 19:01:42 +00:00
static void SaveSettings ( const SettingTable & settings , void * object )
2006-03-02 00:32:48 +00:00
{
2021-06-07 21:03:12 +00:00
const std : : vector < SaveLoad > slt = GetSettingsDesc ( settings , false ) ;
2006-03-02 00:32:48 +00:00
2021-05-30 13:59:40 +00:00
SlTableHeader ( slt ) ;
2021-06-06 07:59:33 +00:00
SlSetArrayIndex ( 0 ) ;
2021-06-07 21:03:12 +00:00
SlObject ( object , slt ) ;
2006-03-02 00:32:48 +00:00
}
2007-03-07 11:47:46 +00:00
static void Load_OPTS ( )
2006-03-02 00:32:48 +00:00
{
/* Copy over default setting since some might not get loaded in
* a networking environment . This ensures for example that the local
* autosave - frequency stays when joining a network - server */
2008-05-26 00:31:36 +00:00
PrepareOldDiffCustom ( ) ;
2021-05-30 13:59:40 +00:00
LoadSettings ( _gameopt_settings , & _settings_game , _gameopt_sl_compat ) ;
2008-05-28 14:36:06 +00:00
HandleOldDiffCustom ( true ) ;
2006-03-02 00:32:48 +00:00
}
2007-03-07 11:47:46 +00:00
static void Load_PATS ( )
2006-03-02 02:22:15 +00:00
{
/* Copy over default setting since some might not get loaded in
* a networking environment . This ensures for example that the local
2012-05-01 15:34:45 +00:00
* currency setting stays when joining a network - server */
2021-05-30 13:59:40 +00:00
LoadSettings ( _settings , & _settings_game , _settings_sl_compat ) ;
2006-03-02 02:22:15 +00:00
}
2010-06-13 14:14:37 +00:00
static void Check_PATS ( )
{
2021-05-30 13:59:40 +00:00
LoadSettings ( _settings , & _load_check_data . settings , _settings_sl_compat ) ;
2010-06-13 14:14:37 +00:00
}
2007-03-07 11:47:46 +00:00
static void Save_PATS ( )
2006-03-02 02:22:15 +00:00
{
2009-02-08 12:25:13 +00:00
SaveSettings ( _settings , & _settings_game ) ;
2006-03-02 02:22:15 +00:00
}
2021-05-02 20:41:34 +00:00
static const ChunkHandler setting_chunk_handlers [ ] = {
2021-05-30 13:59:40 +00:00
{ ' OPTS ' , nullptr , Load_OPTS , nullptr , nullptr , CH_READONLY } ,
{ ' PATS ' , Save_PATS , Load_PATS , nullptr , Check_PATS , CH_TABLE } ,
2006-03-01 21:15:25 +00:00
} ;
2006-05-27 16:12:16 +00:00
2021-05-02 20:41:34 +00:00
extern const ChunkHandlerTable _setting_chunk_handlers ( setting_chunk_handlers ) ;
2006-05-27 16:12:16 +00:00
static bool IsSignedVarMemType ( VarType vt )
{
switch ( GetVarMemType ( vt ) ) {
case SLE_VAR_I8 :
case SLE_VAR_I16 :
case SLE_VAR_I32 :
case SLE_VAR_I64 :
return true ;
}
return false ;
}