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-06-28 14:39:48 +00:00
# include <charconv>
2021-07-05 15:46:38 +00:00
# include "settings_table.h"
# include "debug.h"
2005-08-06 14:59:54 +00:00
# include "currency.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"
2007-12-21 21:50:46 +00:00
# include "command_func.h"
2008-05-24 10:15:06 +00:00
# include "console_func.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-12-19 20:45:46 +00:00
# include "window_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"
2011-12-10 13:54:10 +00:00
# include "error.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"
2011-12-19 20:56:34 +00:00
# include "game/game_config.hpp"
2021-07-05 15:46:38 +00:00
# include "newgrf_config.h"
2010-06-13 14:14:37 +00:00
# include "fios.h"
2021-07-05 15:46:38 +00:00
# include "fileio_func.h"
2008-01-13 01:21:35 +00:00
# include "table/strings.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-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-07-06 01:23:05 +00:00
static auto & GenericSettingTables ( )
{
static const SettingTable _generic_setting_tables [ ] = {
2021-07-09 19:16:03 +00:00
_difficulty_settings ,
_economy_settings ,
_game_settings ,
_gui_settings ,
_linkgraph_settings ,
_locale_settings ,
_multimedia_settings ,
2021-07-06 01:23:05 +00:00
_network_settings ,
2021-07-09 19:16:03 +00:00
_news_display_settings ,
_pathfinding_settings ,
_script_settings ,
_world_settings ,
2021-07-06 01:23:05 +00:00
} ;
return _generic_setting_tables ;
}
2021-06-28 13:35:00 +00:00
2021-06-28 14:39:48 +00:00
/**
* List of all the private setting tables .
*/
2021-07-06 01:23:05 +00:00
static auto & PrivateSettingTables ( )
{
static const SettingTable _private_setting_tables [ ] = {
_network_private_settings ,
} ;
return _private_setting_tables ;
}
2021-06-28 14:39:48 +00:00
/**
* List of all the secrets setting tables .
*/
2021-07-06 01:23:05 +00:00
static auto & SecretSettingTables ( )
{
static const SettingTable _secrets_setting_tables [ ] = {
_network_secrets_settings ,
} ;
return _secrets_setting_tables ;
}
2021-06-28 14:39:48 +00:00
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
2021-07-05 18:14:28 +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 ;
}
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.
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
bool first = true ;
2021-06-13 02:18:21 +00:00
for ( uint id : SetBitIterator ( bitmask ) ) {
2021-05-23 17:16:56 +00:00
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 ) ;
}
2021-07-05 18:14:28 +00:00
void PrepareOldDiffCustom ( ) ;
void HandleOldDiffCustom ( bool savegame ) ;
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-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. */
2021-07-06 01:23:05 +00:00
for ( auto & table : GenericSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
proc ( generic_ini , table , " patches " , & _settings_newgame , only_startup ) ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : PrivateSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
proc ( private_ini , table , " patches " , & _settings_newgame , only_startup ) ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : SecretSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
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-07-09 19:16:03 +00:00
IniLoadSettings ( generic_ini , _old_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 " ) ;
2021-07-06 01:23:05 +00:00
for ( auto & table : PrivateSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
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. */
2021-07-06 01:23:05 +00:00
for ( auto & table : SecretSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
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
/**
2021-07-09 19:16:03 +00:00
* Get the SaveLoad for all settings in the settings table .
* @ param settings The settings table to get the SaveLoad objects from .
2021-05-30 08:55:52 +00:00
* @ param saveloads A vector to store the result in .
*/
2021-07-09 19:16:03 +00:00
void GetSaveLoadFromSettingTable ( SettingTable settings , std : : vector < SaveLoad > & saveloads )
2021-05-30 08:55:52 +00:00
{
2021-07-09 19:16:03 +00:00
for ( auto & desc : settings ) {
2021-06-21 16:39:27 +00:00
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-07-09 19:16:03 +00:00
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-07-06 01:23:05 +00:00
for ( auto & table : GenericSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
auto sd = GetSettingFromName ( name , table ) ;
if ( sd ! = nullptr ) return sd ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : PrivateSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
auto sd = GetSettingFromName ( name , table ) ;
if ( sd ! = nullptr ) return sd ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : SecretSettingTables ( ) ) {
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-07-06 01:23:05 +00:00
for ( auto & table : GenericSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
IConsoleListSettingsTable ( table , prefilter ) ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : PrivateSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
IConsoleListSettingsTable ( table , prefilter ) ;
}
2021-07-06 01:23:05 +00:00
for ( auto & table : SecretSettingTables ( ) ) {
2021-06-28 14:39:48 +00:00
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
}