2019-08-27 01:01:45 +08:00
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
The Goldberg Emulator 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator ; if not , see
< http : //www.gnu.org/licenses/>. */
2023-12-27 15:21:59 +08:00
# include "dll/settings_parser.h"
2019-08-27 01:01:45 +08:00
2024-04-14 16:32:24 +08:00
# define SI_CONVERT_GENERIC
# define SI_SUPPORT_IOSTREAMS
# define SI_NO_MBCS
# include "simpleini/SimpleIni.h"
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
constexpr const static char config_ini_app [ ] = " configs.app.ini " ;
constexpr const static char config_ini_main [ ] = " configs.main.ini " ;
constexpr const static char config_ini_overlay [ ] = " configs.overlay.ini " ;
constexpr const static char config_ini_user [ ] = " configs.user.ini " ;
2024-04-15 00:41:09 +08:00
static CSimpleIniA ini { } ;
2024-04-20 07:17:32 +08:00
typedef struct IniValue {
enum class Type {
STR ,
BOOL ,
DOUBLE ,
LONG ,
} ;
explicit IniValue ( const char * new_val ) : type ( Type : : STR ) , val_str ( new_val ) { }
explicit IniValue ( bool new_val ) : type ( Type : : BOOL ) , val_bool ( new_val ) { }
explicit IniValue ( double new_val ) : type ( Type : : DOUBLE ) , val_double ( new_val ) { }
explicit IniValue ( long new_val ) : type ( Type : : LONG ) , val_long ( new_val ) { }
Type type ;
union {
const char * val_str ;
bool val_bool ;
double val_double ;
long val_long ;
} ;
} IniValue ;
static void save_global_ini_value ( const char * filename , const char * section , const char * key , IniValue val , const char * comment = nullptr ) {
CSimpleIniA new_ini { } ;
new_ini . SetUnicode ( ) ;
new_ini . SetSpaces ( false ) ;
std : : wstring fullpath ( utf8_decode ( Local_Storage : : get_user_appdata_path ( ) + Local_Storage : : settings_storage_folder + PATH_SEPARATOR + filename ) ) ;
if ( ! common_helpers : : create_dir ( fullpath ) ) return ;
std : : ifstream ini_file ( fullpath , std : : ios : : binary | std : : ios : : in ) ;
if ( ini_file . is_open ( ) ) {
new_ini . LoadData ( ini_file ) ;
ini_file . close ( ) ;
}
std : : ofstream new_ini_file ( fullpath , std : : ios : : binary | std : : ios : : out ) ;
if ( new_ini_file . is_open ( ) ) {
std : : string comment_str { } ;
if ( comment ) {
comment_str . append ( " # " ) . append ( comment ) ;
comment = comment_str . c_str ( ) ;
}
switch ( val . type )
{
case IniValue : : Type : : STR :
new_ini . SetValue ( section , key , val . val_str , comment ) ;
break ;
case IniValue : : Type : : BOOL :
new_ini . SetBoolValue ( section , key , val . val_bool , comment ) ;
break ;
case IniValue : : Type : : DOUBLE :
new_ini . SetDoubleValue ( section , key , val . val_double , comment ) ;
break ;
case IniValue : : Type : : LONG :
new_ini . SetLongValue ( section , key , val . val_long , comment ) ;
break ;
default : break ;
}
new_ini . Save ( new_ini_file , false ) ;
new_ini_file . close ( ) ;
}
}
static void merge_ini ( const CSimpleIniA & new_ini , bool overwrite = false ) {
std : : list < CSimpleIniA : : Entry > sections { } ;
new_ini . GetAllSections ( sections ) ;
for ( auto const & sec : sections ) {
std : : list < CSimpleIniA : : Entry > keys { } ;
new_ini . GetAllKeys ( sec . pItem , keys ) ;
for ( auto const & key : keys ) {
// only add the key if it didn't exist already
if ( ! ini . KeyExists ( sec . pItem , key . pItem ) | | overwrite ) {
std : : list < CSimpleIniA : : Entry > vals { } ;
new_ini . GetAllValues ( sec . pItem , key . pItem , vals ) ;
for ( const auto & val : vals ) {
ini . SetValue ( sec . pItem , key . pItem , val . pItem ) ;
}
}
}
}
}
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
// custom_broadcasts.txt
static void load_custom_broadcasts ( const std : : string & base_path , std : : set < IP_PORT > & custom_broadcasts )
2019-08-27 01:01:45 +08:00
{
2024-04-20 07:17:32 +08:00
const std : : string broadcasts_filepath ( base_path + " custom_broadcasts.txt " ) ;
2021-04-26 00:44:41 +08:00
std : : ifstream broadcasts_file ( utf8_decode ( broadcasts_filepath ) ) ;
2019-08-27 01:01:45 +08:00
if ( broadcasts_file . is_open ( ) ) {
2024-04-20 07:17:32 +08:00
common_helpers : : consume_bom ( broadcasts_file ) ;
PRINT_DEBUG ( " loading broadcasts file '%s' " , broadcasts_filepath . c_str ( ) ) ;
std : : string line { } ;
2019-08-27 01:01:45 +08:00
while ( std : : getline ( broadcasts_file , line ) ) {
2024-04-20 07:17:32 +08:00
if ( line . length ( ) < = 0 ) continue ;
2021-05-31 06:18:19 +08:00
std : : set < IP_PORT > ips = Networking : : resolve_ip ( line ) ;
2019-08-27 01:01:45 +08:00
custom_broadcasts . insert ( ips . begin ( ) , ips . end ( ) ) ;
2024-04-20 07:17:32 +08:00
PRINT_DEBUG ( " added ip/port to broadcast list '%s' " , line . c_str ( ) ) ;
2019-08-27 01:01:45 +08:00
}
}
}
2024-04-20 07:17:32 +08:00
// subscribed_groups_clans.txt
static void load_subscribed_groups_clans ( const std : : string & base_path , Settings * settings_client , Settings * settings_server )
2023-08-21 11:58:55 +08:00
{
2024-04-20 07:17:32 +08:00
const std : : string clans_filepath ( base_path + " subscribed_groups_clans.txt " ) ;
2023-08-21 11:58:55 +08:00
std : : ifstream clans_file ( utf8_decode ( clans_filepath ) ) ;
if ( clans_file . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( clans_file ) ;
2024-04-20 07:17:32 +08:00
PRINT_DEBUG ( " loading group clans file '%s' " , clans_filepath . c_str ( ) ) ;
std : : string line { } ;
2023-08-21 11:58:55 +08:00
while ( std : : getline ( clans_file , line ) ) {
2024-04-06 13:55:08 +08:00
if ( line . length ( ) < = 0 ) continue ;
2023-08-21 11:58:55 +08:00
std : : size_t seperator1 = line . find ( " \t \t " ) ;
std : : size_t seperator2 = line . rfind ( " \t \t " ) ;
std : : string clan_id ;
std : : string clan_name ;
std : : string clan_tag ;
if ( ( seperator1 ! = std : : string : : npos ) & & ( seperator2 ! = std : : string : : npos ) ) {
clan_id = line . substr ( 0 , seperator1 ) ;
clan_name = line . substr ( seperator1 + 2 , seperator2 - 2 ) ;
clan_tag = line . substr ( seperator2 + 2 ) ;
// fix persistant tabbing problem for clan name
std : : size_t seperator3 = clan_name . find ( " \t " ) ;
std : : string clan_name_fix = clan_name . substr ( 0 , seperator3 ) ;
clan_name = clan_name_fix ;
}
Group_Clans nclan ;
nclan . id = CSteamID ( std : : stoull ( clan_id . c_str ( ) , NULL , 0 ) ) ;
nclan . name = clan_name ;
nclan . tag = clan_tag ;
try {
settings_client - > subscribed_groups_clans . push_back ( nclan ) ;
settings_server - > subscribed_groups_clans . push_back ( nclan ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added clan %s " , clan_name . c_str ( ) ) ;
2023-08-21 11:58:55 +08:00
} catch ( . . . ) { }
}
}
}
2024-04-20 07:17:32 +08:00
// overlay::appearance
static void load_overlay_appearance ( class Settings * settings_client , class Settings * settings_server , class Local_Storage * local_storage )
2023-08-25 01:59:01 +08:00
{
2024-04-20 07:17:32 +08:00
std : : list < CSimpleIniA : : Entry > names { } ;
if ( ! ini . GetAllKeys ( " overlay::appearance " , names ) | | names . empty ( ) ) return ;
2023-08-25 01:59:01 +08:00
2024-04-20 07:17:32 +08:00
for ( const auto & name_ent : names ) {
auto val_ptr = ini . GetValue ( " overlay::appearance " , name_ent . pItem ) ;
if ( ! val_ptr | | ! val_ptr [ 0 ] ) continue ;
2024-01-26 11:49:03 +08:00
2024-04-20 07:17:32 +08:00
std : : string name ( name_ent . pItem ) ;
std : : string value ( val_ptr ) ;
PRINT_DEBUG ( " Overlay appearance line '%s'='%s' " , name . c_str ( ) , value . c_str ( ) ) ;
try {
if ( name . compare ( " Font_Override " ) = = 0 ) {
value = common_helpers : : string_strip ( Settings : : sanitize ( value ) ) ;
// first try the local settings folder
std : : string nfont_override ( common_helpers : : to_absolute ( value , Local_Storage : : get_game_settings_path ( ) + " fonts " ) ) ;
if ( ! common_helpers : : file_exist ( nfont_override ) ) {
nfont_override . clear ( ) ;
}
2024-04-11 07:16:53 +08:00
2024-04-20 07:17:32 +08:00
// then try the global settings folder
if ( nfont_override . empty ( ) ) {
nfont_override = common_helpers : : to_absolute ( value , local_storage - > get_global_settings_path ( ) + " fonts " ) ;
if ( ! common_helpers : : file_exist ( nfont_override ) ) {
nfont_override . clear ( ) ;
2024-04-11 07:16:53 +08:00
}
2024-04-20 07:17:32 +08:00
}
2024-04-11 07:16:53 +08:00
2024-04-20 07:17:32 +08:00
if ( nfont_override . size ( ) ) {
settings_client - > overlay_appearance . font_override = nfont_override ;
settings_server - > overlay_appearance . font_override = nfont_override ;
PRINT_DEBUG ( " loaded font '%s' " , nfont_override . c_str ( ) ) ;
} else {
PRINT_DEBUG ( " ERROR font file '%s' doesn't exist and will be ignored " , value . c_str ( ) ) ;
2023-08-25 01:59:01 +08:00
}
2024-04-20 07:17:32 +08:00
} else if ( name . compare ( " Font_Size " ) = = 0 ) {
float nfont_size = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . font_size = nfont_size ;
settings_server - > overlay_appearance . font_size = nfont_size ;
} else if ( name . compare ( " Icon_Size " ) = = 0 ) {
float nicon_size = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . icon_size = nicon_size ;
settings_server - > overlay_appearance . icon_size = nicon_size ;
} else if ( name . compare ( " Font_Glyph_Extra_Spacing_x " ) = = 0 ) {
float size = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . font_glyph_extra_spacing_x = size ;
settings_server - > overlay_appearance . font_glyph_extra_spacing_x = size ;
} else if ( name . compare ( " Font_Glyph_Extra_Spacing_y " ) = = 0 ) {
float size = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . font_glyph_extra_spacing_y = size ;
settings_server - > overlay_appearance . font_glyph_extra_spacing_y = size ;
} else if ( name . compare ( " Notification_R " ) = = 0 ) {
float nnotification_r = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . notification_r = nnotification_r ;
settings_server - > overlay_appearance . notification_r = nnotification_r ;
} else if ( name . compare ( " Notification_G " ) = = 0 ) {
float nnotification_g = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . notification_g = nnotification_g ;
settings_server - > overlay_appearance . notification_g = nnotification_g ;
} else if ( name . compare ( " Notification_B " ) = = 0 ) {
float nnotification_b = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . notification_b = nnotification_b ;
settings_server - > overlay_appearance . notification_b = nnotification_b ;
} else if ( name . compare ( " Notification_A " ) = = 0 ) {
float nnotification_a = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . notification_a = nnotification_a ;
settings_server - > overlay_appearance . notification_a = nnotification_a ;
} else if ( name . compare ( " Background_R " ) = = 0 ) {
float nbackground_r = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . background_r = nbackground_r ;
settings_server - > overlay_appearance . background_r = nbackground_r ;
} else if ( name . compare ( " Background_G " ) = = 0 ) {
float nbackground_g = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . background_g = nbackground_g ;
settings_server - > overlay_appearance . background_g = nbackground_g ;
} else if ( name . compare ( " Background_B " ) = = 0 ) {
float nbackground_b = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . background_b = nbackground_b ;
settings_server - > overlay_appearance . background_b = nbackground_b ;
} else if ( name . compare ( " Background_A " ) = = 0 ) {
float nbackground_a = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . background_a = nbackground_a ;
settings_server - > overlay_appearance . background_a = nbackground_a ;
} else if ( name . compare ( " Element_R " ) = = 0 ) {
float nelement_r = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_r = nelement_r ;
settings_server - > overlay_appearance . element_r = nelement_r ;
} else if ( name . compare ( " Element_G " ) = = 0 ) {
float nelement_g = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_g = nelement_g ;
settings_server - > overlay_appearance . element_g = nelement_g ;
} else if ( name . compare ( " Element_B " ) = = 0 ) {
float nelement_b = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_b = nelement_b ;
settings_server - > overlay_appearance . element_b = nelement_b ;
} else if ( name . compare ( " Element_A " ) = = 0 ) {
float nelement_a = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_a = nelement_a ;
settings_server - > overlay_appearance . element_a = nelement_a ;
} else if ( name . compare ( " ElementHovered_R " ) = = 0 ) {
float nelement_hovered_r = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_hovered_r = nelement_hovered_r ;
settings_server - > overlay_appearance . element_hovered_r = nelement_hovered_r ;
} else if ( name . compare ( " ElementHovered_G " ) = = 0 ) {
float nelement_hovered_g = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_hovered_g = nelement_hovered_g ;
settings_server - > overlay_appearance . element_hovered_g = nelement_hovered_g ;
} else if ( name . compare ( " ElementHovered_B " ) = = 0 ) {
float nelement_hovered_b = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_hovered_b = nelement_hovered_b ;
settings_server - > overlay_appearance . element_hovered_b = nelement_hovered_b ;
} else if ( name . compare ( " ElementHovered_A " ) = = 0 ) {
float nelement_hovered_a = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_hovered_a = nelement_hovered_a ;
settings_server - > overlay_appearance . element_hovered_a = nelement_hovered_a ;
} else if ( name . compare ( " ElementActive_R " ) = = 0 ) {
float nelement_active_r = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_active_r = nelement_active_r ;
settings_server - > overlay_appearance . element_active_r = nelement_active_r ;
} else if ( name . compare ( " ElementActive_G " ) = = 0 ) {
float nelement_active_g = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_active_g = nelement_active_g ;
settings_server - > overlay_appearance . element_active_g = nelement_active_g ;
} else if ( name . compare ( " ElementActive_B " ) = = 0 ) {
float nelement_active_b = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_active_b = nelement_active_b ;
settings_server - > overlay_appearance . element_active_b = nelement_active_b ;
} else if ( name . compare ( " ElementActive_A " ) = = 0 ) {
float nelement_active_a = std : : stof ( value , NULL ) ;
settings_client - > overlay_appearance . element_active_a = nelement_active_a ;
settings_server - > overlay_appearance . element_active_a = nelement_active_a ;
} else if ( name . compare ( " PosAchievement " ) = = 0 ) {
auto pos = Overlay_Appearance : : translate_notification_position ( value ) ;
settings_client - > overlay_appearance . ach_earned_pos = pos ;
settings_server - > overlay_appearance . ach_earned_pos = pos ;
} else if ( name . compare ( " PosInvitation " ) = = 0 ) {
auto pos = Overlay_Appearance : : translate_notification_position ( value ) ;
settings_client - > overlay_appearance . invite_pos = pos ;
settings_server - > overlay_appearance . invite_pos = pos ;
} else if ( name . compare ( " PosChatMsg " ) = = 0 ) {
auto pos = Overlay_Appearance : : translate_notification_position ( value ) ;
settings_client - > overlay_appearance . chat_msg_pos = pos ;
settings_server - > overlay_appearance . chat_msg_pos = pos ;
}
2024-01-26 11:49:03 +08:00
2024-04-20 07:17:32 +08:00
} catch ( . . . ) { }
2023-08-25 01:59:01 +08:00
}
}
2019-09-11 02:54:54 +08:00
template < typename Out >
static void split_string ( const std : : string & s , char delim , Out result ) {
std : : stringstream ss ( s ) ;
2024-04-20 07:17:32 +08:00
std : : string item { } ;
2019-09-11 02:54:54 +08:00
while ( std : : getline ( ss , item , delim ) ) {
* ( result + + ) = item ;
}
}
2024-04-20 07:17:32 +08:00
// folder "controller"
2019-09-11 02:54:54 +08:00
static void load_gamecontroller_settings ( Settings * settings )
{
std : : string path = Local_Storage : : get_game_settings_path ( ) + " controller " ;
std : : vector < std : : string > paths = Local_Storage : : get_filenames_path ( path ) ;
for ( auto & p : paths ) {
size_t length = p . length ( ) ;
if ( length < 4 ) continue ;
if ( std : : toupper ( p . back ( ) ) ! = ' T ' ) continue ;
if ( std : : toupper ( p [ length - 2 ] ) ! = ' X ' ) continue ;
if ( std : : toupper ( p [ length - 3 ] ) ! = ' T ' ) continue ;
if ( p [ length - 4 ] ! = ' . ' ) continue ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " controller config %s " , p . c_str ( ) ) ;
2019-09-11 02:54:54 +08:00
std : : string action_set_name = p . substr ( 0 , length - 4 ) ;
std : : transform ( action_set_name . begin ( ) , action_set_name . end ( ) , action_set_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
std : : string controller_config_path = path + PATH_SEPARATOR + p ;
2021-04-26 00:44:41 +08:00
std : : ifstream input ( utf8_decode ( controller_config_path ) ) ;
2019-09-11 02:54:54 +08:00
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2019-09-11 02:54:54 +08:00
std : : map < std : : string , std : : pair < std : : set < std : : string > , std : : string > > button_pairs ;
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
std : : string action_name ;
std : : string button_name ;
std : : string source_mode ;
std : : size_t deliminator = line . find ( " = " ) ;
if ( deliminator ! = 0 & & deliminator ! = std : : string : : npos & & deliminator ! = line . size ( ) ) {
action_name = line . substr ( 0 , deliminator ) ;
std : : size_t deliminator2 = line . find ( " = " , deliminator + 1 ) ;
if ( deliminator2 ! = std : : string : : npos & & deliminator2 ! = line . size ( ) ) {
button_name = line . substr ( deliminator + 1 , deliminator2 - ( deliminator + 1 ) ) ;
source_mode = line . substr ( deliminator2 + 1 ) ;
} else {
button_name = line . substr ( deliminator + 1 ) ;
source_mode = " " ;
}
}
std : : transform ( action_name . begin ( ) , action_name . end ( ) , action_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
std : : transform ( button_name . begin ( ) , button_name . end ( ) , button_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
std : : pair < std : : set < std : : string > , std : : string > button_config = { { } , source_mode } ;
split_string ( button_name , ' , ' , std : : inserter ( button_config . first , button_config . first . begin ( ) ) ) ;
button_pairs [ action_name ] = button_config ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added %s %s %s " , action_name . c_str ( ) , button_name . c_str ( ) , source_mode . c_str ( ) ) ;
2019-09-11 02:54:54 +08:00
}
settings - > controller_settings . action_sets [ action_set_name ] = button_pairs ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added %zu action names to %s " , button_pairs . size ( ) , action_set_name . c_str ( ) ) ;
2019-09-11 02:54:54 +08:00
}
}
2019-12-12 01:06:19 +08:00
settings - > glyphs_directory = path + ( PATH_SEPARATOR " glyphs " PATH_SEPARATOR ) ;
2019-09-11 02:54:54 +08:00
}
2019-08-27 01:01:45 +08:00
2023-12-20 23:30:06 +08:00
// steam_appid.txt
2024-04-10 03:08:23 +08:00
static uint32 parse_steam_app_id ( const std : : string & program_path )
2019-08-27 01:01:45 +08:00
{
2024-04-10 03:08:23 +08:00
uint32 appid = 0 ;
// try steam_settings folder
2019-08-27 01:01:45 +08:00
char array [ 10 ] = { } ;
array [ 0 ] = ' 0 ' ;
Local_Storage : : get_file_data ( Local_Storage : : get_game_settings_path ( ) + " steam_appid.txt " , array , sizeof ( array ) - 1 ) ;
try {
2024-04-10 03:08:23 +08:00
appid = std : : stoul ( array ) ;
2019-08-27 01:01:45 +08:00
} catch ( . . . ) { }
2024-04-10 03:08:23 +08:00
// try current dir
2019-08-27 01:01:45 +08:00
if ( ! appid ) {
memset ( array , 0 , sizeof ( array ) ) ;
array [ 0 ] = ' 0 ' ;
Local_Storage : : get_file_data ( " steam_appid.txt " , array , sizeof ( array ) - 1 ) ;
try {
2024-04-10 03:08:23 +08:00
appid = std : : stoul ( array ) ;
2019-08-27 01:01:45 +08:00
} catch ( . . . ) { }
}
2024-04-10 03:08:23 +08:00
// try exe dir
if ( ! appid ) {
memset ( array , 0 , sizeof ( array ) ) ;
array [ 0 ] = ' 0 ' ;
Local_Storage : : get_file_data ( program_path + " steam_appid.txt " , array , sizeof ( array ) - 1 ) ;
try {
appid = std : : stoul ( array ) ;
} catch ( . . . ) { }
}
// try env vars
2019-08-27 01:01:45 +08:00
if ( ! appid ) {
std : : string str_appid = get_env_variable ( " SteamAppId " ) ;
std : : string str_gameid = get_env_variable ( " SteamGameId " ) ;
2023-12-19 22:48:07 +08:00
std : : string str_overlay_gameid = get_env_variable ( " SteamOverlayGameId " ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " str_appid %s str_gameid: %s str_overlay_gameid: %s " , str_appid . c_str ( ) , str_gameid . c_str ( ) , str_overlay_gameid . c_str ( ) ) ;
2019-08-27 01:01:45 +08:00
uint32 appid_env = 0 ;
uint32 gameid_env = 0 ;
2023-12-19 22:48:07 +08:00
uint32 overlay_gameid = 0 ;
2019-08-27 01:01:45 +08:00
if ( str_appid . size ( ) > 0 ) {
try {
appid_env = std : : stoul ( str_appid ) ;
} catch ( . . . ) {
appid_env = 0 ;
}
}
if ( str_gameid . size ( ) > 0 ) {
try {
gameid_env = std : : stoul ( str_gameid ) ;
} catch ( . . . ) {
gameid_env = 0 ;
}
}
2023-12-19 22:48:07 +08:00
if ( str_overlay_gameid . size ( ) > 0 ) {
try {
overlay_gameid = std : : stoul ( str_overlay_gameid ) ;
} catch ( . . . ) {
overlay_gameid = 0 ;
}
}
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " appid_env %u gameid_env: %u overlay_gameid: %u " , appid_env , gameid_env , overlay_gameid ) ;
2019-08-27 01:01:45 +08:00
if ( appid_env ) {
appid = appid_env ;
}
if ( gameid_env ) {
appid = gameid_env ;
}
2023-12-19 22:48:07 +08:00
if ( overlay_gameid ) {
appid = overlay_gameid ;
}
2019-08-27 01:01:45 +08:00
}
2024-04-10 03:08:23 +08:00
PRINT_DEBUG ( " final appid = %u " , appid ) ;
2023-12-20 23:30:06 +08:00
return appid ;
}
2024-04-20 07:17:32 +08:00
// user::saves::local_save_path
static bool parse_local_save ( std : : string & save_path )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
auto ptr = ini . GetValue ( " user::saves " , " local_save_path " ) ;
if ( ! ptr | | ! ptr [ 0 ] ) return false ;
save_path = common_helpers : : to_absolute ( common_helpers : : string_strip ( Settings : : sanitize ( ptr ) ) , Local_Storage : : get_program_path ( ) ) ;
PRINT_DEBUG ( " using local save path '%s' " , save_path . c_str ( ) ) ;
return true ;
2023-12-20 23:30:06 +08:00
}
2019-08-27 01:01:45 +08:00
2024-04-20 07:17:32 +08:00
// main::connectivity::listen_port
2024-04-10 03:08:23 +08:00
static uint16 parse_listen_port ( class Local_Storage * local_storage )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
uint16 port = ini . GetLongValue ( " main::connectivity " , " listen_port " ) ;
2019-08-27 01:01:45 +08:00
if ( port = = 0 ) {
port = DEFAULT_PORT ;
2024-04-20 07:17:32 +08:00
save_global_ini_value (
config_ini_main ,
" main::connectivity " , " listen_port " , IniValue ( ( long ) port ) ,
" change the UDP/TCP port the emulator listens on "
) ;
2019-08-27 01:01:45 +08:00
}
2023-12-20 23:30:06 +08:00
return port ;
}
2019-08-27 01:01:45 +08:00
2024-04-20 07:17:32 +08:00
// user::general::account_name
2024-04-10 03:08:23 +08:00
static std : : string parse_account_name ( class Local_Storage * local_storage )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
auto name = ini . GetValue ( " user::general " , " account_name " ) ;
if ( ! name | | ! name [ 0 ] ) {
name = DEFAULT_NAME ;
save_global_ini_value (
config_ini_user ,
" user::general " , " account_name " , IniValue ( name ) ,
" user account name "
) ;
2019-08-27 01:01:45 +08:00
}
2023-12-20 23:30:06 +08:00
return std : : string ( name ) ;
}
2019-08-27 01:01:45 +08:00
2024-04-20 07:17:32 +08:00
// user::general::account_steamid
2024-04-10 03:08:23 +08:00
static CSteamID parse_user_steam_id ( class Local_Storage * local_storage )
2023-12-20 23:30:06 +08:00
{
2019-08-27 01:01:45 +08:00
char array_steam_id [ 32 ] = { } ;
2024-04-20 07:17:32 +08:00
CSteamID user_id ( ( uint64 ) std : : atoll ( ini . GetValue ( " user::general " , " account_steamid " , " 0 " ) ) ) ;
if ( ! user_id . IsValid ( ) ) {
2019-08-27 01:01:45 +08:00
user_id = generate_steam_id_user ( ) ;
2024-04-20 07:17:32 +08:00
char temp_text [ 32 ] { } ;
snprintf ( temp_text , sizeof ( temp_text ) , " %llu " , ( uint64 ) user_id . ConvertToUint64 ( ) ) ;
save_global_ini_value (
config_ini_user ,
" user::general " , " account_steamid " , IniValue ( temp_text ) ,
" Steam64 format "
) ;
2019-08-27 01:01:45 +08:00
}
2023-12-20 23:30:06 +08:00
return user_id ;
}
2024-04-20 07:17:32 +08:00
// user::general::language
2024-04-06 13:55:08 +08:00
// valid list: https://partner.steamgames.com/doc/store/localization/languages
2024-04-10 03:08:23 +08:00
static std : : string parse_current_language ( class Local_Storage * local_storage )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
auto lang = ini . GetValue ( " user::general " , " language " ) ;
if ( ! lang | | ! lang [ 0 ] ) {
lang = DEFAULT_LANGUAGE ;
save_global_ini_value (
config_ini_user ,
" user::general " , " language " , IniValue ( lang ) ,
" the language reported to the game, default is 'english', check 'API language code' in https://partner.steamgames.com/doc/store/localization/languages "
) ;
2023-12-20 23:30:06 +08:00
}
2024-04-20 07:17:32 +08:00
return common_helpers : : to_lower ( std : : string ( lang ) ) ;
2023-12-20 23:30:06 +08:00
}
// supported_languages.txt
2024-04-06 13:55:08 +08:00
// valid list: https://partner.steamgames.com/doc/store/localization/languages
2024-04-10 03:08:23 +08:00
static std : : set < std : : string > parse_supported_languages ( class Local_Storage * local_storage , std : : string & language )
2023-12-20 23:30:06 +08:00
{
2024-04-06 13:55:08 +08:00
std : : set < std : : string > supported_languages { } ;
2022-08-14 02:40:55 +08:00
2023-12-20 23:30:06 +08:00
std : : string lang_config_path = Local_Storage : : get_game_settings_path ( ) + " supported_languages.txt " ;
std : : ifstream input ( utf8_decode ( lang_config_path ) ) ;
2022-08-14 02:40:55 +08:00
2024-04-06 13:55:08 +08:00
std : : string first_language { } ;
2023-12-20 23:30:06 +08:00
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
try {
2024-04-06 13:55:08 +08:00
std : : string lang = common_helpers : : to_lower ( line ) ;
2023-12-20 23:30:06 +08:00
if ( ! first_language . size ( ) ) first_language = lang ;
supported_languages . insert ( lang ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added supported_language %s " , lang . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
} catch ( . . . ) { }
}
}
// if the current emu language is not in the supported languages list
if ( ! supported_languages . count ( language ) ) {
2024-04-06 13:55:08 +08:00
if ( first_language . size ( ) ) { // get the first supported language if the list wasn't empty
2023-12-20 23:30:06 +08:00
language = first_language ;
2024-04-06 13:55:08 +08:00
} else { // otherwise just lie and add it then!
supported_languages . insert ( language ) ;
PRINT_DEBUG ( " Forced current language '%s' into supported_languages " , language . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
}
}
return supported_languages ;
}
// DLC.txt
2024-04-10 03:08:23 +08:00
static void parse_dlc ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string dlc_config_path = Local_Storage : : get_game_settings_path ( ) + " DLC.txt " ;
std : : ifstream input ( utf8_decode ( dlc_config_path ) ) ;
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
settings_client - > unlockAllDLC ( false ) ;
settings_server - > unlockAllDLC ( false ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Locking all DLC " ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; std : : getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line . front ( ) = = ' # ' ) {
continue ;
}
if ( ! line . empty ( ) & & line . back ( ) = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line . back ( ) = = ' \r ' ) {
line . pop_back ( ) ;
}
std : : size_t deliminator = line . find ( " = " ) ;
if ( deliminator ! = 0 & & deliminator ! = std : : string : : npos & & deliminator ! = line . size ( ) ) {
AppId_t appid = stol ( line . substr ( 0 , deliminator ) ) ;
std : : string name = line . substr ( deliminator + 1 ) ;
bool available = true ;
if ( appid ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Adding DLC: %u|%s| %u " , appid , name . c_str ( ) , available ) ;
2023-12-20 23:30:06 +08:00
settings_client - > addDLC ( appid , name , available ) ;
settings_server - > addDLC ( appid , name , available ) ;
}
}
}
} else {
//unlock all DLC
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Unlocking all DLC " ) ;
2023-12-20 23:30:06 +08:00
settings_client - > unlockAllDLC ( true ) ;
settings_server - > unlockAllDLC ( true ) ;
}
}
2024-04-20 07:17:32 +08:00
// app::paths
2024-04-16 03:13:11 +08:00
static void parse_app_paths ( class Settings * settings_client , Settings * settings_server , const std : : string & program_path )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
std : : list < CSimpleIniA : : Entry > ids { } ;
if ( ! ini . GetAllKeys ( " app::paths " , ids ) | | ids . empty ( ) ) return ;
for ( const auto & id : ids ) {
auto val_ptr = ini . GetValue ( " app::paths " , id . pItem ) ;
if ( ! val_ptr | | ! val_ptr [ 0 ] ) continue ;
AppId_t appid = std : : stol ( id . pItem ) ;
std : : string rel_path ( val_ptr ) ;
std : : string path = canonical_path ( program_path + rel_path ) ;
if ( appid ) {
if ( path . size ( ) ) {
PRINT_DEBUG ( " Adding app path: %u|%s| " , appid , path . c_str ( ) ) ;
settings_client - > setAppInstallPath ( appid , path ) ;
settings_server - > setAppInstallPath ( appid , path ) ;
} else {
PRINT_DEBUG ( " Error adding app path for: %u does this path exist? |%s| " , appid , rel_path . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
}
}
}
}
// leaderboards.txt
2024-04-10 03:08:23 +08:00
static void parse_leaderboards ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string dlc_config_path = Local_Storage : : get_game_settings_path ( ) + " leaderboards.txt " ;
std : : ifstream input ( utf8_decode ( dlc_config_path ) ) ;
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
2024-03-30 13:55:56 +08:00
std : : string leaderboard { } ;
2023-12-20 23:30:06 +08:00
unsigned int sort_method = 0 ;
unsigned int display_type = 0 ;
std : : size_t deliminator = line . find ( " = " ) ;
if ( deliminator ! = 0 & & deliminator ! = std : : string : : npos & & deliminator ! = line . size ( ) ) {
leaderboard = line . substr ( 0 , deliminator ) ;
std : : size_t deliminator2 = line . find ( " = " , deliminator + 1 ) ;
if ( deliminator2 ! = std : : string : : npos & & deliminator2 ! = line . size ( ) ) {
sort_method = stol ( line . substr ( deliminator + 1 , deliminator2 - ( deliminator + 1 ) ) ) ;
display_type = stol ( line . substr ( deliminator2 + 1 ) ) ;
2022-08-14 02:40:55 +08:00
}
2023-12-20 23:30:06 +08:00
}
2022-08-14 02:40:55 +08:00
2023-12-20 23:30:06 +08:00
if ( leaderboard . size ( ) & & sort_method < = k_ELeaderboardSortMethodDescending & & display_type < = k_ELeaderboardDisplayTypeTimeMilliSeconds ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Adding leaderboard: %s|%u|%u " , leaderboard . c_str ( ) , sort_method , display_type ) ;
2023-12-20 23:30:06 +08:00
settings_client - > setLeaderboard ( leaderboard , ( ELeaderboardSortMethod ) sort_method , ( ELeaderboardDisplayType ) display_type ) ;
settings_server - > setLeaderboard ( leaderboard , ( ELeaderboardSortMethod ) sort_method , ( ELeaderboardDisplayType ) display_type ) ;
} else {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Error adding leaderboard for: '%s', are sort method %u or display type %u valid? " , leaderboard . c_str ( ) , sort_method , display_type ) ;
2022-08-14 02:40:55 +08:00
}
}
2023-12-20 23:30:06 +08:00
}
2022-08-14 02:40:55 +08:00
2023-12-20 23:30:06 +08:00
}
// stats.txt
2024-04-10 03:08:23 +08:00
static void parse_stats ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string stats_config_path = Local_Storage : : get_game_settings_path ( ) + " stats.txt " ;
std : : ifstream input ( utf8_decode ( stats_config_path ) ) ;
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
std : : string stat_name ;
std : : string stat_type ;
std : : string stat_default_value ;
std : : size_t deliminator = line . find ( " = " ) ;
if ( deliminator ! = 0 & & deliminator ! = std : : string : : npos & & deliminator ! = line . size ( ) ) {
stat_name = line . substr ( 0 , deliminator ) ;
std : : size_t deliminator2 = line . find ( " = " , deliminator + 1 ) ;
if ( deliminator2 ! = std : : string : : npos & & deliminator2 ! = line . size ( ) ) {
stat_type = line . substr ( deliminator + 1 , deliminator2 - ( deliminator + 1 ) ) ;
stat_default_value = line . substr ( deliminator2 + 1 ) ;
} else {
stat_type = line . substr ( deliminator + 1 ) ;
stat_default_value = " 0 " ;
}
}
std : : transform ( stat_type . begin ( ) , stat_type . end ( ) , stat_type . begin ( ) , [ ] ( unsigned char c ) { return std : : tolower ( c ) ; } ) ;
struct Stat_config config = { } ;
try {
if ( stat_type = = " float " ) {
2024-03-23 13:22:47 +08:00
config . type = GameServerStats_Messages : : StatInfo : : STAT_TYPE_FLOAT ;
2023-12-20 23:30:06 +08:00
config . default_value_float = std : : stof ( stat_default_value ) ;
} else if ( stat_type = = " int " ) {
2024-03-23 13:22:47 +08:00
config . type = GameServerStats_Messages : : StatInfo : : STAT_TYPE_INT ;
2023-12-20 23:30:06 +08:00
config . default_value_int = std : : stol ( stat_default_value ) ;
} else if ( stat_type = = " avgrate " ) {
2024-03-23 13:22:47 +08:00
config . type = GameServerStats_Messages : : StatInfo : : STAT_TYPE_AVGRATE ;
2023-12-20 23:30:06 +08:00
config . default_value_float = std : : stof ( stat_default_value ) ;
} else {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Error adding stat %s, type %s isn't valid " , stat_name . c_str ( ) , stat_type . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
continue ;
}
} catch ( . . . ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Error adding stat %s, default value %s isn't valid " , stat_name . c_str ( ) , stat_default_value . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
continue ;
}
if ( stat_name . size ( ) ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Adding stat type: %s|%u|%f|%i " , stat_name . c_str ( ) , config . type , config . default_value_float , config . default_value_int ) ;
2023-12-20 23:30:06 +08:00
settings_client - > setStatDefiniton ( stat_name , config ) ;
settings_server - > setStatDefiniton ( stat_name , config ) ;
} else {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Error adding stat for: %s, empty name " , stat_name . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
}
}
}
}
// depots.txt
2024-04-10 03:08:23 +08:00
static void parse_depots ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string depots_config_path = Local_Storage : : get_game_settings_path ( ) + " depots.txt " ;
std : : ifstream input ( utf8_decode ( depots_config_path ) ) ;
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
try {
DepotId_t depot_id = std : : stoul ( line ) ;
settings_client - > depots . push_back ( depot_id ) ;
settings_server - > depots . push_back ( depot_id ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added depot %u " , depot_id ) ;
2023-12-20 23:30:06 +08:00
} catch ( . . . ) { }
}
}
}
// subscribed_groups.txt
2024-04-10 03:08:23 +08:00
static void parse_subscribed_groups ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string depots_config_path = Local_Storage : : get_game_settings_path ( ) + " subscribed_groups.txt " ;
std : : ifstream input ( utf8_decode ( depots_config_path ) ) ;
if ( input . is_open ( ) ) {
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
}
try {
uint64 source_id = std : : stoull ( line ) ;
settings_client - > subscribed_groups . insert ( source_id ) ;
settings_server - > subscribed_groups . insert ( source_id ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added source %llu " , source_id ) ;
2023-12-20 23:30:06 +08:00
} catch ( . . . ) { }
}
}
}
// installed_app_ids.txt
2024-04-10 03:08:23 +08:00
static void parse_installed_app_Ids ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
std : : string installed_apps_list_path = Local_Storage : : get_game_settings_path ( ) + " installed_app_ids.txt " ;
std : : ifstream input ( utf8_decode ( installed_apps_list_path ) ) ;
if ( input . is_open ( ) ) {
settings_client - > assume_any_app_installed = false ;
settings_server - > assume_any_app_installed = false ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Limiting/Locking installed apps " ) ;
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-20 23:30:06 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \n ' ) {
line . pop_back ( ) ;
}
if ( ! line . empty ( ) & & line [ line . length ( ) - 1 ] = = ' \r ' ) {
line . pop_back ( ) ;
2022-08-14 02:40:55 +08:00
}
2023-12-20 23:30:06 +08:00
try {
AppId_t app_id = std : : stoul ( line ) ;
settings_client - > installed_app_ids . insert ( app_id ) ;
settings_server - > installed_app_ids . insert ( app_id ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Added installed app with ID %u " , app_id ) ;
2023-12-20 23:30:06 +08:00
} catch ( . . . ) { }
}
} else {
settings_client - > assume_any_app_installed = true ;
settings_server - > assume_any_app_installed = true ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Assuming any app is installed " ) ;
2023-12-20 23:30:06 +08:00
}
}
2024-04-20 07:17:32 +08:00
2023-12-20 23:30:06 +08:00
// steam_settings/mods
2024-01-20 23:50:16 +08:00
static const auto one_week_ago_epoch = std : : chrono : : duration_cast < std : : chrono : : seconds > (
( startup_time - std : : chrono : : hours ( 24 * 7 ) ) . time_since_epoch ( )
) . count ( ) ;
static size_t get_file_size_safe ( const std : : string & filepath , const std : : string & basepath , int32 default_val = 0 )
{
try
{
const auto file_p = common_helpers : : to_absolute ( filepath , basepath ) ;
if ( file_p . empty ( ) ) return default_val ;
size_t size = 0 ;
if ( common_helpers : : file_size ( file_p , size ) ) {
return size ;
}
} catch ( . . . ) { }
return default_val ;
}
static std : : string get_mod_preview_url ( const std : : string & previewFileName , const std : : string & mod_id )
{
if ( previewFileName . empty ( ) ) {
return std : : string ( ) ;
} else {
auto settings_folder = std : : string ( Local_Storage : : get_game_settings_path ( ) ) ;
std : : replace ( settings_folder . begin ( ) , settings_folder . end ( ) , ' \\ ' , ' / ' ) ;
return " file:// " + settings_folder + " mod_images/ " + mod_id + " / " + previewFileName ;
}
}
static void try_parse_mods_file ( class Settings * settings_client , Settings * settings_server , nlohmann : : json & mod_items , const std : : string & mods_folder )
{
for ( auto mod = mod_items . begin ( ) ; mod ! = mod_items . end ( ) ; + + mod ) {
try {
std : : string mod_images_fullpath = Local_Storage : : get_game_settings_path ( ) + " mod_images " + PATH_SEPARATOR + std : : string ( mod . key ( ) ) ;
Mod_entry newMod ;
newMod . id = std : : stoull ( mod . key ( ) ) ;
newMod . title = mod . value ( ) . value ( " title " , std : : string ( mod . key ( ) ) ) ;
// make sure this is never empty
newMod . path = mod . value ( ) . value ( " path " , std : : string ( " " ) ) ;
if ( newMod . path . empty ( ) ) {
newMod . path = mods_folder + PATH_SEPARATOR + std : : string ( mod . key ( ) ) ;
2024-01-21 04:51:40 +08:00
} else {
// make sure the path is normalized for current OS, and absolute
2024-01-25 23:06:45 +08:00
newMod . path = common_helpers : : to_absolute (
newMod . path ,
get_full_program_path ( )
2024-01-26 04:56:27 +08:00
) ;
2024-01-20 23:50:16 +08:00
}
newMod . fileType = k_EWorkshopFileTypeCommunity ;
newMod . description = mod . value ( ) . value ( " description " , std : : string ( " " ) ) ;
newMod . steamIDOwner = mod . value ( ) . value ( " steam_id_owner " , settings_client - > get_local_steam_id ( ) . ConvertToUint64 ( ) ) ;
newMod . timeCreated = mod . value ( ) . value ( " time_created " , ( uint32 ) one_week_ago_epoch ) ;
newMod . timeUpdated = mod . value ( ) . value ( " time_updated " , ( uint32 ) one_week_ago_epoch ) ;
newMod . timeAddedToUserList = mod . value ( ) . value ( " time_added " , ( uint32 ) one_week_ago_epoch ) ;
newMod . visibility = k_ERemoteStoragePublishedFileVisibilityPublic ;
newMod . banned = false ;
newMod . acceptedForUse = true ;
newMod . tagsTruncated = false ;
newMod . tags = mod . value ( ) . value ( " tags " , std : : string ( " " ) ) ;
newMod . primaryFileName = mod . value ( ) . value ( " primary_filename " , std : : string ( " " ) ) ;
int32 primary_filesize = 0 ;
if ( ! newMod . primaryFileName . empty ( ) ) {
primary_filesize = ( int32 ) get_file_size_safe ( newMod . primaryFileName , newMod . path , primary_filesize ) ;
}
newMod . primaryFileSize = mod . value ( ) . value ( " primary_filesize " , primary_filesize ) ;
newMod . previewFileName = mod . value ( ) . value ( " preview_filename " , std : : string ( " " ) ) ;
int32 preview_filesize = 0 ;
if ( ! newMod . previewFileName . empty ( ) ) {
preview_filesize = ( int32 ) get_file_size_safe ( newMod . previewFileName , mod_images_fullpath , preview_filesize ) ;
}
newMod . previewFileSize = mod . value ( ) . value ( " preview_filesize " , preview_filesize ) ;
newMod . workshopItemURL = mod . value ( ) . value ( " workshop_item_url " , " https://steamcommunity.com/sharedfiles/filedetails/?id= " + std : : string ( mod . key ( ) ) ) ;
newMod . votesUp = mod . value ( ) . value ( " upvotes " , ( uint32 ) 500 ) ;
newMod . votesDown = mod . value ( ) . value ( " downvotes " , ( uint32 ) 12 ) ;
float score = 0.97f ;
try
{
score = newMod . votesUp / ( float ) ( newMod . votesUp + newMod . votesDown ) ;
} catch ( . . . ) { }
newMod . score = mod . value ( ) . value ( " score " , score ) ;
newMod . numChildren = mod . value ( ) . value ( " num_children " , ( uint32 ) 0 ) ;
newMod . previewURL = mod . value ( ) . value ( " preview_url " , get_mod_preview_url ( newMod . previewFileName , std : : string ( mod . key ( ) ) ) ) ;
settings_client - > addMod ( newMod . id , newMod . title , newMod . path ) ;
settings_server - > addMod ( newMod . id , newMod . title , newMod . path ) ;
settings_client - > addModDetails ( newMod . id , newMod ) ;
settings_server - > addModDetails ( newMod . id , newMod ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " parsed mod '%s': " , std : : string ( mod . key ( ) ) . c_str ( ) ) ;
PRINT_DEBUG ( " path (will be used for primary file): '%s' " , newMod . path . c_str ( ) ) ;
PRINT_DEBUG ( " images path (will be used for preview file): '%s' " , mod_images_fullpath . c_str ( ) ) ;
PRINT_DEBUG ( " primary_filename: '%s' " , newMod . primaryFileName . c_str ( ) ) ;
PRINT_DEBUG ( " primary_filesize: %i bytes " , newMod . primaryFileSize ) ;
PRINT_DEBUG ( " primary file handle: %llu " , settings_client - > getMod ( newMod . id ) . handleFile ) ;
PRINT_DEBUG ( " preview_filename: '%s' " , newMod . previewFileName . c_str ( ) ) ;
PRINT_DEBUG ( " preview_filesize: %i bytes " , newMod . previewFileSize ) ;
PRINT_DEBUG ( " preview file handle: %llu " , settings_client - > getMod ( newMod . id ) . handlePreviewFile ) ;
PRINT_DEBUG ( " workshop_item_url: '%s' " , newMod . workshopItemURL . c_str ( ) ) ;
PRINT_DEBUG ( " preview_url: '%s' " , newMod . previewURL . c_str ( ) ) ;
2024-01-20 23:50:16 +08:00
} catch ( std : : exception & e ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " MODLOADER ERROR: %s " , e . what ( ) ) ;
2024-01-20 23:50:16 +08:00
}
}
}
// called if mods.json doesn't exist or invalid
static void try_detect_mods_folder ( class Settings * settings_client , Settings * settings_server , const std : : string & mods_folder )
{
std : : vector < std : : string > all_mods = Local_Storage : : get_folders_path ( mods_folder ) ;
for ( auto & mod_folder : all_mods ) {
std : : string mod_images_fullpath = Local_Storage : : get_game_settings_path ( ) + " mod_images " + PATH_SEPARATOR + mod_folder ;
try {
Mod_entry newMod ;
newMod . id = std : : stoull ( mod_folder ) ;
newMod . title = mod_folder ;
// make sure this is never empty
newMod . path = mods_folder + PATH_SEPARATOR + mod_folder ;
newMod . fileType = k_EWorkshopFileTypeCommunity ;
newMod . description = " mod # " + mod_folder ;
newMod . steamIDOwner = settings_client - > get_local_steam_id ( ) . ConvertToUint64 ( ) ;
newMod . timeCreated = ( uint32 ) one_week_ago_epoch ;
newMod . timeUpdated = ( uint32 ) one_week_ago_epoch ;
newMod . timeAddedToUserList = ( uint32 ) one_week_ago_epoch ;
newMod . visibility = k_ERemoteStoragePublishedFileVisibilityPublic ;
newMod . banned = false ;
newMod . acceptedForUse = true ;
newMod . tagsTruncated = false ;
newMod . tags = " " ;
std : : vector < std : : string > mod_primary_files = Local_Storage : : get_filenames_path ( newMod . path ) ;
newMod . primaryFileName = mod_primary_files . size ( ) ? mod_primary_files [ 0 ] : " " ;
newMod . primaryFileSize = ( int32 ) get_file_size_safe ( newMod . primaryFileName , newMod . path ) ;
std : : vector < std : : string > mod_preview_files = Local_Storage : : get_filenames_path ( mod_images_fullpath ) ;
newMod . previewFileName = mod_preview_files . size ( ) ? mod_preview_files [ 0 ] : " " ;
newMod . previewFileSize = ( int32 ) get_file_size_safe ( newMod . previewFileName , mod_images_fullpath ) ;
newMod . workshopItemURL = " https://steamcommunity.com/sharedfiles/filedetails/?id= " + mod_folder ;
newMod . votesUp = ( uint32 ) 500 ;
newMod . votesDown = ( uint32 ) 12 ;
newMod . score = 0.97f ;
newMod . numChildren = ( uint32 ) 0 ;
newMod . previewURL = get_mod_preview_url ( newMod . previewFileName , mod_folder ) ;
settings_client - > addMod ( newMod . id , newMod . title , newMod . path ) ;
settings_server - > addMod ( newMod . id , newMod . title , newMod . path ) ;
settings_client - > addModDetails ( newMod . id , newMod ) ;
settings_server - > addModDetails ( newMod . id , newMod ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " detected mod '%s': " , mod_folder . c_str ( ) ) ;
PRINT_DEBUG ( " path (will be used for primary file): '%s' " , newMod . path . c_str ( ) ) ;
PRINT_DEBUG ( " images path (will be used for preview file): '%s' " , mod_images_fullpath . c_str ( ) ) ;
PRINT_DEBUG ( " primary_filename: '%s' " , newMod . primaryFileName . c_str ( ) ) ;
PRINT_DEBUG ( " primary_filesize: %i bytes " , newMod . primaryFileSize ) ;
PRINT_DEBUG ( " primary file handle: %llu " , settings_client - > getMod ( newMod . id ) . handleFile ) ;
PRINT_DEBUG ( " preview_filename: '%s' " , newMod . previewFileName . c_str ( ) ) ;
PRINT_DEBUG ( " preview_filesize: %i bytes " , newMod . previewFileSize ) ;
PRINT_DEBUG ( " preview file handle: %llu " , settings_client - > getMod ( newMod . id ) . handlePreviewFile ) ;
PRINT_DEBUG ( " workshop_item_url: '%s' " , newMod . workshopItemURL . c_str ( ) ) ;
PRINT_DEBUG ( " preview_url: '%s' " , newMod . previewURL . c_str ( ) ) ;
2024-01-20 23:50:16 +08:00
} catch ( . . . ) { }
}
}
2023-12-20 23:30:06 +08:00
static void parse_mods_folder ( class Settings * settings_client , Settings * settings_server , class Local_Storage * local_storage )
{
2024-01-20 23:50:16 +08:00
std : : string mods_folder = Local_Storage : : get_game_settings_path ( ) + " mods " ;
2023-12-20 23:30:06 +08:00
nlohmann : : json mod_items = nlohmann : : json : : object ( ) ;
static constexpr auto mods_json_file = " mods.json " ;
std : : string mods_json_path = Local_Storage : : get_game_settings_path ( ) + mods_json_file ;
if ( local_storage - > load_json ( mods_json_path , mod_items ) ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Attempting to parse mods.json " ) ;
2024-01-20 23:50:16 +08:00
try_parse_mods_file ( settings_client , settings_server , mod_items , mods_folder ) ;
2023-12-24 00:28:54 +08:00
} else { // invalid mods.json or doesn't exist
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Failed to load mods.json, attempting to auto detect mods folder " ) ;
2024-01-20 23:50:16 +08:00
try_detect_mods_folder ( settings_client , settings_server , mods_folder ) ;
2022-08-14 02:40:55 +08:00
}
2023-12-20 23:30:06 +08:00
}
2024-04-20 07:17:32 +08:00
// app::general::build_id
2024-04-10 03:08:23 +08:00
static void parse_build_id ( class Settings * settings_client , class Settings * settings_server )
2023-12-20 23:30:06 +08:00
{
2024-04-20 07:17:32 +08:00
std : : string line ( common_helpers : : string_strip ( ini . GetValue ( " app::general " , " build_id " , " " ) ) ) ;
if ( line . size ( ) ) {
int build_id = std : : stoi ( line ) ;
PRINT_DEBUG ( " setting build id = %i " , build_id ) ;
2024-04-10 03:08:23 +08:00
settings_client - > build_id = build_id ;
settings_server - > build_id = build_id ;
2023-12-20 23:30:06 +08:00
}
}
2024-04-20 07:17:32 +08:00
// main::general::crash_printer_location
2024-01-07 21:43:53 +08:00
static void parse_crash_printer_location ( )
{
2024-04-20 07:17:32 +08:00
std : : wstring crash_path { } ;
std : : string line ( common_helpers : : string_strip ( Settings : : sanitize ( ini . GetValue ( " main::general " , " crash_printer_location " , " " ) ) ) ) ;
if ( line . size ( ) ) {
crash_path = utf8_decode ( common_helpers : : to_absolute ( line , get_full_program_path ( ) ) ) ;
}
if ( crash_path . size ( ) ) {
if ( crash_printer : : init ( crash_path ) ) {
PRINT_DEBUG ( " Unhandled crashes will be saved to '%s' " , utf8_encode ( crash_path ) . c_str ( ) ) ;
} else {
PRINT_DEBUG ( " Failed to setup unhandled crash printer with path: '%s' " , utf8_encode ( crash_path ) . c_str ( ) ) ;
2024-01-07 21:43:53 +08:00
}
}
}
2023-12-29 14:41:34 +08:00
// auto_accept_invite.txt
2024-04-10 03:08:23 +08:00
static void parse_auto_accept_invite ( class Settings * settings_client , class Settings * settings_server )
2023-12-29 14:41:34 +08:00
{
std : : string auto_accept_list_path = Local_Storage : : get_game_settings_path ( ) + " auto_accept_invite.txt " ;
std : : ifstream input ( utf8_decode ( auto_accept_list_path ) ) ;
if ( input . is_open ( ) ) {
2024-01-22 07:19:41 +08:00
bool accept_any_invite = true ;
2024-03-08 18:48:49 +08:00
common_helpers : : consume_bom ( input ) ;
2023-12-29 14:41:34 +08:00
for ( std : : string line ; getline ( input , line ) ; ) {
2024-03-08 18:48:49 +08:00
line = common_helpers : : string_strip ( line ) ;
2023-12-29 14:41:34 +08:00
if ( ! line . empty ( ) ) {
2024-01-22 07:19:41 +08:00
accept_any_invite = false ;
2023-12-29 14:41:34 +08:00
try {
auto friend_id = std : : stoull ( line ) ;
2024-01-22 07:19:41 +08:00
settings_client - > addFriendToOverlayAutoAccept ( ( uint64_t ) friend_id ) ;
settings_server - > addFriendToOverlayAutoAccept ( ( uint64_t ) friend_id ) ;
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Auto accepting overlay invitations from user with ID (SteamID64) = %llu " , friend_id ) ;
2023-12-29 14:41:34 +08:00
} catch ( . . . ) { }
}
}
2024-01-22 07:19:41 +08:00
if ( accept_any_invite ) {
2024-04-06 13:55:08 +08:00
PRINT_DEBUG ( " Auto accepting any overlay invitation " ) ;
2024-01-22 07:19:41 +08:00
settings_client - > acceptAnyOverlayInvites ( true ) ;
2024-03-06 04:45:36 +08:00
settings_server - > acceptAnyOverlayInvites ( true ) ;
2024-01-22 07:19:41 +08:00
} else {
settings_client - > acceptAnyOverlayInvites ( false ) ;
2024-03-06 04:45:36 +08:00
settings_server - > acceptAnyOverlayInvites ( false ) ;
2024-01-22 07:19:41 +08:00
}
2023-12-29 14:41:34 +08:00
}
}
2024-04-20 07:17:32 +08:00
// user::general::ip_country
2024-04-10 03:08:23 +08:00
static void parse_ip_country ( class Settings * settings_client , class Settings * settings_server )
2024-02-07 10:22:33 +08:00
{
2024-04-20 07:17:32 +08:00
std : : string line ( common_helpers : : to_upper ( common_helpers : : string_strip ( ini . GetValue ( " user::general " , " ip_country " , " " ) ) ) ) ;
if ( line . empty ( ) ) {
line = DEFAULT_IP_COUNTRY ;
save_global_ini_value (
config_ini_user ,
" user::general " , " ip_country " , IniValue ( line . c_str ( ) ) ,
" ISO 3166-1-alpha-2 format, use this link to get the 'Alpha-2' country code: https://www.iban.com/country-codes "
) ;
}
// ISO 3166-1-alpha-2 format is 2 chars only
if ( line . size ( ) = = 2 ) {
settings_client - > ip_country = line ;
settings_server - > ip_country = line ;
PRINT_DEBUG ( " Setting IP country to: '%s' " , line . c_str ( ) ) ;
2024-02-07 10:22:33 +08:00
}
}
2024-04-20 07:17:32 +08:00
// overlay::general
static void parse_overlay_general_config ( class Settings * settings_client , class Settings * settings_server )
2024-03-06 04:45:36 +08:00
{
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay = ! ini . GetBoolValue ( " overlay::general " , " enable_experimental_overlay " , settings_client - > disable_overlay ) ;
settings_server - > disable_overlay = ! ini . GetBoolValue ( " overlay::general " , " enable_experimental_overlay " , settings_server - > disable_overlay ) ;
{
auto val = ini . GetLongValue ( " overlay::general " , " hook_delay_sec " , - 1 ) ;
if ( val > = 0 ) {
2024-04-15 00:41:09 +08:00
settings_client - > overlay_hook_delay_sec = val ;
settings_server - > overlay_hook_delay_sec = val ;
PRINT_DEBUG ( " Setting overlay hook delay to %i seconds " , ( int ) val ) ;
2024-03-06 04:45:36 +08:00
}
2024-04-20 07:17:32 +08:00
}
2024-03-06 04:45:36 +08:00
2024-04-20 07:17:32 +08:00
{
auto val = ini . GetLongValue ( " overlay::general " , " renderer_detector_timeout_sec " , - 1 ) ;
if ( val > 0 ) {
2024-04-15 00:41:09 +08:00
settings_client - > overlay_renderer_detector_timeout_sec = val ;
settings_server - > overlay_renderer_detector_timeout_sec = val ;
PRINT_DEBUG ( " Setting overlay renderer detector timeout to %i seconds " , ( int ) val ) ;
2024-03-08 19:50:25 +08:00
}
2024-04-20 07:17:32 +08:00
}
2024-03-08 19:50:25 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay_achievement_notification = ini . GetBoolValue ( " overlay::general " , " disable_achievement_notification " , settings_client - > disable_overlay_achievement_notification ) ;
settings_server - > disable_overlay_achievement_notification = ini . GetBoolValue ( " overlay::general " , " disable_achievement_notification " , settings_server - > disable_overlay_achievement_notification ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay_friend_notification = ini . GetBoolValue ( " overlay::general " , " disable_friend_notification " , settings_client - > disable_overlay_friend_notification ) ;
settings_server - > disable_overlay_friend_notification = ini . GetBoolValue ( " overlay::general " , " disable_friend_notification " , settings_server - > disable_overlay_friend_notification ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay_warning_any = ini . GetBoolValue ( " overlay::general " , " disable_warning_any " , settings_client - > disable_overlay_warning_any ) ;
settings_server - > disable_overlay_warning_any = ini . GetBoolValue ( " overlay::general " , " disable_warning_any " , settings_server - > disable_overlay_warning_any ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay_warning_bad_appid = ini . GetBoolValue ( " overlay::general " , " disable_warning_bad_appid " , settings_client - > disable_overlay_warning_bad_appid ) ;
settings_server - > disable_overlay_warning_bad_appid = ini . GetBoolValue ( " overlay::general " , " disable_warning_bad_appid " , settings_server - > disable_overlay_warning_bad_appid ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_overlay_warning_local_save = ini . GetBoolValue ( " overlay::general " , " disable_warning_local_save " , settings_client - > disable_overlay_warning_local_save ) ;
settings_server - > disable_overlay_warning_local_save = ini . GetBoolValue ( " overlay::general " , " disable_warning_local_save " , settings_server - > disable_overlay_warning_local_save ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
}
// mainly enable/disable features
static void parse_simple_features ( class Settings * settings_client , class Settings * settings_server )
{
// app::general::branch_name
{
std : : string line ( common_helpers : : string_strip ( ini . GetValue ( " app::general " , " branch_name " , " " ) ) ) ;
if ( line . size ( ) ) {
settings_client - > current_branch_name = line ;
settings_server - > current_branch_name = line ;
PRINT_DEBUG ( " setting current branch name to '%s' " , line . c_str ( ) ) ;
}
}
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
// [main::general]
settings_client - > enable_new_app_ticket = ini . GetBoolValue ( " main::general " , " new_app_ticket " , settings_client - > enable_new_app_ticket ) ;
settings_server - > enable_new_app_ticket = ini . GetBoolValue ( " main::general " , " new_app_ticket " , settings_server - > enable_new_app_ticket ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > use_gc_token = ini . GetBoolValue ( " main::general " , " gc_token " , settings_client - > use_gc_token ) ;
settings_server - > use_gc_token = ini . GetBoolValue ( " main::general " , " gc_token " , settings_server - > use_gc_token ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_account_avatar = ini . GetBoolValue ( " main::general " , " disable_account_avatar " , settings_client - > disable_account_avatar ) ;
settings_server - > disable_account_avatar = ini . GetBoolValue ( " main::general " , " disable_account_avatar " , settings_server - > disable_account_avatar ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > is_beta_branch = ini . GetBoolValue ( " main::general " , " is_beta_branch " , settings_client - > is_beta_branch ) ;
settings_server - > is_beta_branch = ini . GetBoolValue ( " main::general " , " is_beta_branch " , settings_server - > is_beta_branch ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > steam_deck = ini . GetBoolValue ( " main::general " , " steam_deck " , settings_client - > steam_deck ) ;
settings_server - > steam_deck = ini . GetBoolValue ( " main::general " , " steam_deck " , settings_server - > steam_deck ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_leaderboards_create_unknown = ini . GetBoolValue ( " main::general " , " disable_leaderboards_create_unknown " , settings_client - > disable_leaderboards_create_unknown ) ;
settings_server - > disable_leaderboards_create_unknown = ini . GetBoolValue ( " main::general " , " disable_leaderboards_create_unknown " , settings_server - > disable_leaderboards_create_unknown ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > immediate_gameserver_stats = ini . GetBoolValue ( " main::general " , " immediate_gameserver_stats " , settings_client - > immediate_gameserver_stats ) ;
settings_server - > immediate_gameserver_stats = ini . GetBoolValue ( " main::general " , " immediate_gameserver_stats " , settings_server - > immediate_gameserver_stats ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > matchmaking_server_details_via_source_query = ini . GetBoolValue ( " main::general " , " matchmaking_server_details_via_source_query " , settings_client - > matchmaking_server_details_via_source_query ) ;
settings_server - > matchmaking_server_details_via_source_query = ini . GetBoolValue ( " main::general " , " matchmaking_server_details_via_source_query " , settings_server - > matchmaking_server_details_via_source_query ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > matchmaking_server_list_always_lan_type = ini . GetBoolValue ( " main::general " , " matchmaking_server_list_actual_type " , settings_client - > matchmaking_server_list_always_lan_type ) ;
settings_server - > matchmaking_server_list_always_lan_type = ini . GetBoolValue ( " main::general " , " matchmaking_server_list_actual_type " , settings_server - > matchmaking_server_list_always_lan_type ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
// [main::connectivity]
settings_client - > disable_networking = ini . GetBoolValue ( " main::connectivity " , " disable_networking " , settings_client - > disable_networking ) ;
settings_server - > disable_networking = ini . GetBoolValue ( " main::connectivity " , " disable_networking " , settings_server - > disable_networking ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_sharing_stats_with_gameserver = ini . GetBoolValue ( " main::connectivity " , " disable_sharing_stats_with_gameserver " , settings_client - > disable_sharing_stats_with_gameserver ) ;
settings_server - > disable_sharing_stats_with_gameserver = ini . GetBoolValue ( " main::connectivity " , " disable_sharing_stats_with_gameserver " , settings_server - > disable_sharing_stats_with_gameserver ) ;
settings_client - > disable_source_query = ini . GetBoolValue ( " main::connectivity " , " disable_source_query " , settings_client - > disable_source_query ) ;
settings_server - > disable_source_query = ini . GetBoolValue ( " main::connectivity " , " disable_source_query " , settings_server - > disable_source_query ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > share_leaderboards_over_network = ini . GetBoolValue ( " main::connectivity " , " share_leaderboards_over_network " , settings_client - > share_leaderboards_over_network ) ;
settings_server - > share_leaderboards_over_network = ini . GetBoolValue ( " main::connectivity " , " share_leaderboards_over_network " , settings_server - > share_leaderboards_over_network ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_lobby_creation = ini . GetBoolValue ( " main::connectivity " , " disable_lobby_creation " , settings_client - > disable_lobby_creation ) ;
settings_server - > disable_lobby_creation = ini . GetBoolValue ( " main::connectivity " , " disable_lobby_creation " , settings_server - > disable_lobby_creation ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > download_steamhttp_requests = ini . GetBoolValue ( " main::connectivity " , " download_steamhttp_requests " , settings_client - > download_steamhttp_requests ) ;
settings_server - > download_steamhttp_requests = ini . GetBoolValue ( " main::connectivity " , " download_steamhttp_requests " , settings_server - > download_steamhttp_requests ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
// [main::misc]
settings_client - > achievement_bypass = ini . GetBoolValue ( " main::misc " , " achievements_bypass " , settings_client - > achievement_bypass ) ;
settings_server - > achievement_bypass = ini . GetBoolValue ( " main::misc " , " achievements_bypass " , settings_server - > achievement_bypass ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > force_steamhttp_success = ini . GetBoolValue ( " main::misc " , " force_steamhttp_success " , settings_client - > force_steamhttp_success ) ;
settings_server - > force_steamhttp_success = ini . GetBoolValue ( " main::misc " , " force_steamhttp_success " , settings_server - > force_steamhttp_success ) ;
2024-04-15 00:41:09 +08:00
2024-04-20 07:17:32 +08:00
settings_client - > disable_steamoverlaygameid_env_var = ini . GetBoolValue ( " main::misc " , " disable_steamoverlaygameid_env_var " , settings_client - > disable_steamoverlaygameid_env_var ) ;
settings_server - > disable_steamoverlaygameid_env_var = ini . GetBoolValue ( " main::misc " , " disable_steamoverlaygameid_env_var " , settings_server - > disable_steamoverlaygameid_env_var ) ;
2024-04-15 00:41:09 +08:00
2024-04-10 03:08:23 +08:00
}
2023-12-20 23:30:06 +08:00
2024-04-20 07:17:32 +08:00
static std : : map < SettingsItf , std : : string > old_itfs_map { } ;
static void load_all_config_settings ( )
2024-04-15 00:41:09 +08:00
{
static std : : recursive_mutex ini_mtx { } ;
static bool loaded = false ;
2024-04-15 01:10:35 +08:00
2024-04-15 00:41:09 +08:00
std : : lock_guard lck ( ini_mtx ) ;
if ( loaded ) return ;
loaded = true ;
2024-04-20 07:17:32 +08:00
constexpr const static char * config_files [ ] = {
config_ini_app ,
config_ini_main ,
config_ini_overlay ,
config_ini_user ,
2024-04-17 04:58:05 +08:00
} ;
2024-04-15 00:41:09 +08:00
ini . SetUnicode ( ) ;
2024-04-20 07:17:32 +08:00
ini . SetSpaces ( false ) ;
2024-04-17 04:58:05 +08:00
// we have to load the local one first, since it might change base saves_folder_name
{
2024-04-20 07:17:32 +08:00
CSimpleIniA local_ini { } ;
local_ini . SetUnicode ( ) ;
for ( const auto & config_file : config_files ) {
std : : ifstream local_ini_file ( utf8_decode ( Local_Storage : : get_game_settings_path ( ) + config_file ) , std : : ios : : binary | std : : ios : : in ) ;
if ( ! local_ini_file . is_open ( ) ) continue ;
2024-04-17 04:58:05 +08:00
auto err = local_ini . LoadData ( local_ini_file ) ;
local_ini_file . close ( ) ;
2024-04-20 07:17:32 +08:00
PRINT_DEBUG ( " result of parsing local '%s' %i (success == 0) " , config_file , ( int ) err ) ;
2024-04-17 04:58:05 +08:00
if ( err = = SI_OK ) {
2024-04-20 07:17:32 +08:00
merge_ini ( local_ini ) ;
2024-04-17 04:58:05 +08:00
}
}
2024-04-20 07:17:32 +08:00
std : : string saves_folder_name ( common_helpers : : string_strip ( Settings : : sanitize ( local_ini . GetValue ( " user::saves " , " saves_folder_name " , " " ) ) ) ) ;
if ( saves_folder_name . size ( ) ) {
Local_Storage : : set_saves_folder_name ( saves_folder_name ) ;
PRINT_DEBUG ( " changed base folder for save data to '%s' " , saves_folder_name . c_str ( ) ) ;
}
2024-04-17 04:58:05 +08:00
}
2024-04-20 07:17:32 +08:00
// now we can access get_user_appdata_path() which might have been changed by the above code
2024-04-17 04:58:05 +08:00
{
CSimpleIniA global_ini { } ;
global_ini . SetUnicode ( ) ;
2024-04-20 07:17:32 +08:00
for ( const auto & config_file : config_files ) {
std : : ifstream ini_file ( utf8_decode ( Local_Storage : : get_user_appdata_path ( ) + Local_Storage : : settings_storage_folder + PATH_SEPARATOR + config_file ) , std : : ios : : binary | std : : ios : : in ) ;
if ( ! ini_file . is_open ( ) ) continue ;
2024-04-17 04:58:05 +08:00
auto err = global_ini . LoadData ( ini_file ) ;
ini_file . close ( ) ;
2024-04-20 07:17:32 +08:00
PRINT_DEBUG ( " result of parsing global '%s' %i (success == 0) " , config_file , ( int ) err ) ;
2024-04-17 04:58:05 +08:00
if ( err = = SI_OK ) {
merge_ini ( global_ini ) ;
}
}
}
2024-04-20 07:17:32 +08:00
old_itfs_map [ SettingsItf : : CLIENT ] = ini . GetValue ( " app::steam_interfaces " , " client " , " " ) ;
old_itfs_map [ SettingsItf : : GAMESERVER_STATS ] = ini . GetValue ( " app::steam_interfaces " , " gameserver_stats " , " " ) ;
old_itfs_map [ SettingsItf : : GAMESERVER ] = ini . GetValue ( " app::steam_interfaces " , " gameserver " , " " ) ;
old_itfs_map [ SettingsItf : : MATCHMAKING_SERVERS ] = ini . GetValue ( " app::steam_interfaces " , " matchmaking_servers " , " " ) ;
old_itfs_map [ SettingsItf : : MATCHMAKING ] = ini . GetValue ( " app::steam_interfaces " , " matchmaking " , " " ) ;
old_itfs_map [ SettingsItf : : USER ] = ini . GetValue ( " app::steam_interfaces " , " user " , " " ) ;
old_itfs_map [ SettingsItf : : FRIENDS ] = ini . GetValue ( " app::steam_interfaces " , " friends " , " " ) ;
old_itfs_map [ SettingsItf : : UTILS ] = ini . GetValue ( " app::steam_interfaces " , " utils " , " " ) ;
old_itfs_map [ SettingsItf : : USER_STATS ] = ini . GetValue ( " app::steam_interfaces " , " user_stats " , " " ) ;
old_itfs_map [ SettingsItf : : APPS ] = ini . GetValue ( " app::steam_interfaces " , " apps " , " " ) ;
old_itfs_map [ SettingsItf : : NETWORKING ] = ini . GetValue ( " app::steam_interfaces " , " networking " , " " ) ;
old_itfs_map [ SettingsItf : : REMOTE_STORAGE ] = ini . GetValue ( " app::steam_interfaces " , " remote_storage " , " " ) ;
old_itfs_map [ SettingsItf : : SCREENSHOTS ] = ini . GetValue ( " app::steam_interfaces " , " screenshots " , " " ) ;
old_itfs_map [ SettingsItf : : HTTP ] = ini . GetValue ( " app::steam_interfaces " , " http " , " " ) ;
old_itfs_map [ SettingsItf : : UNIFIED_MESSAGES ] = ini . GetValue ( " app::steam_interfaces " , " unified_messages " , " " ) ;
old_itfs_map [ SettingsItf : : CONTROLLER ] = ini . GetValue ( " app::steam_interfaces " , " controller " , " " ) ;
old_itfs_map [ SettingsItf : : UGC ] = ini . GetValue ( " app::steam_interfaces " , " ugc " , " " ) ;
old_itfs_map [ SettingsItf : : APPLIST ] = ini . GetValue ( " app::steam_interfaces " , " applist " , " " ) ;
old_itfs_map [ SettingsItf : : MUSIC ] = ini . GetValue ( " app::steam_interfaces " , " music " , " " ) ;
old_itfs_map [ SettingsItf : : MUSIC_REMOTE ] = ini . GetValue ( " app::steam_interfaces " , " music_remote " , " " ) ;
old_itfs_map [ SettingsItf : : HTML_SURFACE ] = ini . GetValue ( " app::steam_interfaces " , " html_surface " , " " ) ;
old_itfs_map [ SettingsItf : : INVENTORY ] = ini . GetValue ( " app::steam_interfaces " , " inventory " , " " ) ;
old_itfs_map [ SettingsItf : : VIDEO ] = ini . GetValue ( " app::steam_interfaces " , " video " , " " ) ;
old_itfs_map [ SettingsItf : : MASTERSERVER_UPDATER ] = ini . GetValue ( " app::steam_interfaces " , " masterserver_updater " , " " ) ;
2024-04-17 04:58:05 +08:00
# ifndef EMU_RELEASE_BUILD
// dump the final ini file
{
PRINT_DEBUG ( " final ini start --------- " ) ;
std : : list < CSimpleIniA : : Entry > sections { } ;
ini . GetAllSections ( sections ) ;
for ( auto const & sec : sections ) {
PRINT_DEBUG ( " [%s] " , sec . pItem ) ;
std : : list < CSimpleIniA : : Entry > keys { } ;
ini . GetAllKeys ( sec . pItem , keys ) ;
for ( auto const & key : keys ) {
std : : list < CSimpleIniA : : Entry > vals { } ;
ini . GetAllValues ( sec . pItem , key . pItem , vals ) ;
for ( const auto & val : vals ) {
PRINT_DEBUG ( " %s=%s " , key . pItem , val . pItem ) ;
}
}
PRINT_DEBUG ( " " ) ;
}
PRINT_DEBUG ( " final ini end ********* " ) ;
}
# endif // EMU_RELEASE_BUILD
reset_LastError ( ) ;
2024-04-15 00:41:09 +08:00
}
2023-12-20 23:30:06 +08:00
2024-04-10 03:08:23 +08:00
uint32 create_localstorage_settings ( Settings * * settings_client_out , Settings * * settings_server_out , Local_Storage * * local_storage_out )
{
2024-04-11 08:56:38 +08:00
PRINT_DEBUG ( " start ---------- " ) ;
2024-04-10 16:59:51 +08:00
2024-04-20 07:17:32 +08:00
load_all_config_settings ( ) ;
2024-04-15 00:41:09 +08:00
2024-04-10 16:59:51 +08:00
# if defined(EMU_BUILD_STRING)
PRINT_DEBUG ( " emu build '%s' " , EXPAND_AS_STR ( EMU_BUILD_STRING ) ) ;
# else
PRINT_DEBUG ( " <unspecified emu build> " ) ;
# endif
2024-01-07 21:43:53 +08:00
parse_crash_printer_location ( ) ;
2024-04-16 03:13:11 +08:00
const std : : string program_path ( Local_Storage : : get_program_path ( ) ) ;
const std : : string steam_settings_path ( Local_Storage : : get_game_settings_path ( ) ) ;
2024-04-10 03:08:23 +08:00
std : : string save_path ( Local_Storage : : get_user_appdata_path ( ) ) ;
2024-04-20 07:17:32 +08:00
bool local_save = parse_local_save ( save_path ) ;
PRINT_DEBUG ( " program path: '%s', base path for saves: '%s' " , program_path . c_str ( ) , save_path . c_str ( ) ) ;
2023-12-20 23:30:06 +08:00
Local_Storage * local_storage = new Local_Storage ( save_path ) ;
2024-04-20 07:17:32 +08:00
PRINT_DEBUG ( " global settings path: '%s' " , local_storage - > get_global_settings_path ( ) . c_str ( ) ) ;
uint32 appid = parse_steam_app_id ( program_path ) ;
2023-12-20 23:30:06 +08:00
local_storage - > setAppId ( appid ) ;
// Custom broadcasts
2024-04-10 03:08:23 +08:00
std : : set < IP_PORT > custom_broadcasts { } ;
2024-04-20 07:17:32 +08:00
load_custom_broadcasts ( local_storage - > get_global_settings_path ( ) , custom_broadcasts ) ;
load_custom_broadcasts ( steam_settings_path , custom_broadcasts ) ;
2023-12-20 23:30:06 +08:00
2024-04-20 07:17:32 +08:00
// Listen port
uint16 port = parse_listen_port ( local_storage ) ;
2023-12-20 23:30:06 +08:00
// Acount name
2024-04-10 03:08:23 +08:00
std : : string name ( parse_account_name ( local_storage ) ) ;
2023-12-20 23:30:06 +08:00
// Steam ID
CSteamID user_id = parse_user_steam_id ( local_storage ) ;
// Language
2024-04-10 03:08:23 +08:00
std : : string language ( parse_current_language ( local_storage ) ) ;
2023-12-20 23:30:06 +08:00
// Supported languages, this will change the current language if needed
2024-04-10 03:08:23 +08:00
std : : set < std : : string > supported_languages ( parse_supported_languages ( local_storage , language ) ) ;
2023-12-20 23:30:06 +08:00
2024-04-20 07:17:32 +08:00
bool steam_offline_mode = ini . GetBoolValue ( " main::connectivity " , " offline " , false ) ;
2019-08-27 01:01:45 +08:00
Settings * settings_client = new Settings ( user_id , CGameID ( appid ) , name , language , steam_offline_mode ) ;
Settings * settings_server = new Settings ( generate_steam_id_server ( ) , CGameID ( appid ) , name , language , steam_offline_mode ) ;
2024-04-10 03:08:23 +08:00
// listen port
2019-08-27 01:01:45 +08:00
settings_client - > set_port ( port ) ;
settings_server - > set_port ( port ) ;
2024-04-10 03:08:23 +08:00
// broadcasts list
2019-08-27 01:01:45 +08:00
settings_client - > custom_broadcasts = custom_broadcasts ;
settings_server - > custom_broadcasts = custom_broadcasts ;
2023-12-29 07:52:20 +08:00
// overlay warning for local save
settings_client - > overlay_warn_local_save = local_save ;
settings_server - > overlay_warn_local_save = local_save ;
2024-04-10 03:08:23 +08:00
// supported languages list
2024-04-06 13:55:08 +08:00
settings_client - > set_supported_languages ( supported_languages ) ;
settings_server - > set_supported_languages ( supported_languages ) ;
2023-10-30 05:48:51 +08:00
2024-04-15 00:41:09 +08:00
parse_build_id ( settings_client , settings_server ) ;
2024-04-10 03:08:23 +08:00
parse_simple_features ( settings_client , settings_server ) ;
2023-12-20 23:30:06 +08:00
parse_dlc ( settings_client , settings_server ) ;
parse_app_paths ( settings_client , settings_server , program_path ) ;
parse_leaderboards ( settings_client , settings_server ) ;
parse_stats ( settings_client , settings_server ) ;
parse_depots ( settings_client , settings_server ) ;
parse_subscribed_groups ( settings_client , settings_server ) ;
parse_installed_app_Ids ( settings_client , settings_server ) ;
2024-04-20 07:17:32 +08:00
load_subscribed_groups_clans ( local_storage - > get_global_settings_path ( ) , settings_client , settings_server ) ;
load_subscribed_groups_clans ( steam_settings_path , settings_client , settings_server ) ;
2023-08-21 11:58:55 +08:00
2024-04-20 07:17:32 +08:00
load_overlay_appearance ( settings_client , settings_server , local_storage ) ;
2023-08-25 01:59:01 +08:00
2023-12-20 23:30:06 +08:00
parse_mods_folder ( settings_client , settings_server , local_storage ) ;
2019-09-11 02:54:54 +08:00
load_gamecontroller_settings ( settings_client ) ;
2023-12-29 14:41:34 +08:00
parse_auto_accept_invite ( settings_client , settings_server ) ;
2024-02-07 10:22:33 +08:00
parse_ip_country ( settings_client , settings_server ) ;
2024-04-20 07:17:32 +08:00
parse_overlay_general_config ( settings_client , settings_server ) ;
2023-12-29 14:41:34 +08:00
2019-08-27 01:01:45 +08:00
* settings_client_out = settings_client ;
* settings_server_out = settings_server ;
* local_storage_out = local_storage ;
2022-08-12 08:52:02 +08:00
reset_LastError ( ) ;
2024-04-11 08:56:38 +08:00
PRINT_DEBUG ( " end ********* " ) ;
2019-08-27 01:01:45 +08:00
return appid ;
2021-04-26 00:44:41 +08:00
}
2022-08-05 14:09:43 +08:00
2024-04-20 07:17:32 +08:00
void save_global_settings ( const char * name , const char * language )
2022-08-05 14:09:43 +08:00
{
2024-04-20 07:17:32 +08:00
save_global_ini_value (
config_ini_user ,
" user::general " , " account_name " , IniValue ( name ) ,
" user account name "
) ;
save_global_ini_value (
config_ini_user ,
" user::general " , " language " , IniValue ( language ) ,
" the language reported to the game, default is 'english', check 'API language code' in https://partner.steamgames.com/doc/store/localization/languages "
) ;
2022-08-05 14:09:43 +08:00
}
2024-04-15 00:41:09 +08:00
bool settings_disable_lan_only ( )
{
2024-04-20 07:17:32 +08:00
load_all_config_settings ( ) ;
return ini . GetBoolValue ( " main::connectivity " , " disable_lan_only " , false ) ;
}
const std : : map < SettingsItf , std : : string > & settings_old_interfaces ( )
{
load_all_config_settings ( ) ;
return old_itfs_map ;
2024-04-15 00:41:09 +08:00
}