diff --git a/Readme_release.txt b/Readme_release.txt index ae495b8..0926de1 100644 --- a/Readme_release.txt +++ b/Readme_release.txt @@ -87,6 +87,13 @@ For the sort methods: 0 = none, 1 = ascending, 2 = descending For the display type: 0 = none, 1 = numeric, 2 = time seconds, 3 = milliseconds An example can be found in steam_settings.EXAMPLE +Stats: +By default this emulators assumes all stats do not exist unless they have been written once by the game. This works for the majority of games but some games might read a stat for the first time +and expect a default value to be read when doing so. To set the type for each stat along with the default value, put a stats.txt file in the steam_settings/ folder. +The format is: STAT_NAME=type=default value +The type can be: int, float or avgrate +The default value is simply a number that represents the default value for the stat. + Support for CPY steam_api(64).dll cracks: See the build in the experimental folder. diff --git a/build_env_x64.bat b/build_env_x64.bat index 7e622a2..128cc2e 100755 --- a/build_env_x64.bat +++ b/build_env_x64.bat @@ -1,16 +1,22 @@ -if exist "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" goto vs14 -if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" goto vs2017 -if exist "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" goto vs2019 +@echo off +cd /d "%~dp0" +rem Put in the base path in which Visual Studio is installed, default would be C:\Program Files (x86) -:vs14 -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +set VS_Base_Path=C:\Program Files (x86) + +if exist "%VS_Base_Path%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" goto vs2019 +if exist "%VS_Base_Path%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" goto vs2017 +if exist "%VS_Base_Path%\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" goto vs14 + +:vs2019 +call "%VS_Base_Path%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" goto batend :vs2017 -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +call "%VS_Base_Path%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" goto batend -:vs2019 -call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +:vs14 +call "%VS_Base_Path%\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" goto batend :batend diff --git a/build_env_x86.bat b/build_env_x86.bat index 55b3520..cc2d46e 100755 --- a/build_env_x86.bat +++ b/build_env_x86.bat @@ -1,16 +1,22 @@ -if exist "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat" goto vs14 -if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars32.bat" goto vs2017 -if exist "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars32.bat" goto vs2019 +@echo off +cd /d "%~dp0" +rem Put in the base path in which Visual Studio is installed, default would be C:\Program Files (x86) -:vs14 -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat" +set VS_Base_Path=C:\Program Files (x86) + +if exist "%VS_Base_Path%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" goto vs2019 +if exist "%VS_Base_Path%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" goto vs2017 +if exist "%VS_Base_Path%\Microsoft Visual Studio 14.0\VC\bin\amd64_x86\vcvarsamd64_x86.bat" goto vs14 + +:vs2019 +call "%VS_Base_Path%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" goto batend :vs2017 -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars32.bat" +call "%VS_Base_Path%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" goto batend -:vs2019 -call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars32.bat" +:vs14 +call "%VS_Base_Path%\Microsoft Visual Studio 14.0\VC\bin\amd64_x86\vcvarsamd64_x86.bat" goto batend :batend diff --git a/build_win_debug_experimental.bat b/build_win_debug_experimental.bat index 0a49f7b..b2ea89c 100755 --- a/build_win_debug_experimental.bat +++ b/build_win_debug_experimental.bat @@ -1,12 +1,16 @@ +@echo off +cd /d "%~dp0" call build_set_protobuf_directories.bat -%PROTOBUF_X86_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x86.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /I%PROTOBUF_X86_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD dll/*.cpp dll/*.cc detours/*.cpp %PROTOBUF_X86_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /link /OUT:steam_api.dll +cl /LD /I%PROTOBUF_X86_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD dll/*.cpp dll/*.cc detours/*.cpp "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /link /OUT:steam_api.dll cl /LD steamclient.cpp /EHsc /MP12 /link /OUT:steamclient.dll cl /LD steamnetworkingsockets.cpp /EHsc /MP12 /link /OUT:steamnetworkingsockets.dll + +"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x64.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /I%PROTOBUF_X64_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD dll/*.cpp dll/*.cc detours/*.cpp %PROTOBUF_X64_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /link /OUT:steam_api64.dll +cl /LD /I%PROTOBUF_X64_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD dll/*.cpp dll/*.cc detours/*.cpp "%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /link /OUT:steam_api64.dll cl /LD steamclient.cpp /EHsc /MP12 /link /OUT:steamclient64.dll cl /LD steamnetworkingsockets.cpp /EHsc /MP12 /link /OUT:steamnetworkingsockets64.dll diff --git a/build_win_find_interfaces.bat b/build_win_find_interfaces.bat index 8a92ef5..53c157b 100755 --- a/build_win_find_interfaces.bat +++ b/build_win_find_interfaces.bat @@ -1,3 +1,5 @@ +@ecbo off +cd /d "%~dp0" mkdir release\tools del /Q release\tools\* call build_env_x86.bat diff --git a/build_win_lobby_connect.bat b/build_win_lobby_connect.bat index a2fbd18..27c83e5 100755 --- a/build_win_lobby_connect.bat +++ b/build_win_lobby_connect.bat @@ -1,10 +1,12 @@ +@echo off +cd /d "%~dp0" mkdir release\lobby_connect del /Q release\lobby_connect\* call build_set_protobuf_directories.bat -%PROTOBUF_X86_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x86.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /DNO_DISK_WRITES /DLOBBY_CONNECT /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ lobby_connect.cpp dll/*.cpp dll/*.cc %PROTOBUF_X86_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Comdlg32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\lobby_connect\lobby_connect.exe +cl /DNO_DISK_WRITES /DLOBBY_CONNECT /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ lobby_connect.cpp dll/*.cpp dll/*.cc "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Comdlg32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\lobby_connect\lobby_connect.exe del /Q /S release\lobby_connect\*.lib del /Q /S release\lobby_connect\*.exp copy Readme_lobby_connect.txt release\lobby_connect\Readme.txt diff --git a/build_win_release.bat b/build_win_release.bat index 329012d..895303a 100755 --- a/build_win_release.bat +++ b/build_win_release.bat @@ -1,17 +1,20 @@ +@echo off +cd /d "%~dp0" del /Q /S release\* rmdir /S /Q release\experimental rmdir /S /Q release\lobby_connect rmdir /S /Q release mkdir release call build_set_protobuf_directories.bat -%PROTOBUF_X86_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x86.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc %PROTOBUF_X86_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api.dll -%PROTOBUF_X64_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api.dll +call build_set_protobuf_directories.bat +"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x64.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc %PROTOBUF_X64_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api64.dll +cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc "%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api64.dll copy Readme_release.txt release\Readme.txt xcopy /s files_example\* release\ call build_win_release_experimental.bat diff --git a/build_win_release_experimental.bat b/build_win_release_experimental.bat index d4acf0c..0c58b81 100755 --- a/build_win_release_experimental.bat +++ b/build_win_release_experimental.bat @@ -1,14 +1,16 @@ +@echo off +cd /d "%~dp0" mkdir release\experimental del /Q release\experimental\* call build_set_protobuf_directories.bat -%PROTOBUF_X86_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x86.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp %PROTOBUF_X86_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api.dll +cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api.dll cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG steamclient.cpp /EHsc /MP12 /Ox /link /OUT:release\experimental\steamclient.dll -%PROTOBUF_X64_DIRECTORY%%PROTOC_DIRECTORY% -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto call build_env_x64.bat cl dll/rtlgenrandom.c dll/rtlgenrandom.def -cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp %PROTOBUF_X64_DIRECTORY%%PROTOBUF_LIBRARY% Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api64.dll +cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp "%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api64.dll cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG steamclient.cpp /EHsc /MP12 /Ox /link /OUT:release\experimental\steamclient64.dll copy Readme_experimental.txt release\experimental\Readme.txt diff --git a/dll/settings.h b/dll/settings.h index 940f121..cd6d1de 100644 --- a/dll/settings.h +++ b/dll/settings.h @@ -38,6 +38,20 @@ struct Leaderboard_config { enum ELeaderboardDisplayType display_type; }; +enum Stat_Type { + STAT_TYPE_INT, + STAT_TYPE_FLOAT, + STAT_TYPE_AVGRATE +}; + +struct Stat_config { + enum Stat_Type type; + union { + float default_value_float; + uint32 default_value_int; + }; +}; + class Settings { CSteamID steam_id; CGameID game_id; @@ -50,7 +64,9 @@ class Settings { std::vector mods; std::map app_paths; std::map leaderboards; + std::map stats; bool create_unknown_leaderboards; + uint16 port; public: #ifdef LOBBY_CONNECT @@ -68,6 +84,8 @@ public: void set_lobby(CSteamID lobby_id); CSteamID get_lobby(); bool is_offline() {return offline; } + uint16 get_port() {return port;} + void set_port(uint16 port) { this->port = port;} //DLC stuff void unlockAllDLC(bool value); @@ -91,6 +109,13 @@ public: std::map getLeaderboards() { return leaderboards; } void setCreateUnknownLeaderboards(bool enable) {create_unknown_leaderboards = enable;} bool createUnknownLeaderboards() { return create_unknown_leaderboards; } + + //custom broadcasts + std::set custom_broadcasts; + + //stats + std::map getStats() { return stats; } + void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[name] = stat_config; } }; #endif diff --git a/dll/settings_parser.cpp b/dll/settings_parser.cpp new file mode 100644 index 0000000..b2a377a --- /dev/null +++ b/dll/settings_parser.cpp @@ -0,0 +1,394 @@ +/* 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 + . */ + +#include "settings_parser.h" +#include +#include + +static void load_custom_broadcasts(std::string broadcasts_filepath, std::set &custom_broadcasts) +{ + std::ifstream broadcasts_file(broadcasts_filepath); + PRINT_DEBUG("Broadcasts file path: %s\n", broadcasts_filepath.c_str()); + if (broadcasts_file.is_open()) { + std::string line; + while (std::getline(broadcasts_file, line)) { + std::set ips = Networking::resolve_ip(line); + custom_broadcasts.insert(ips.begin(), ips.end()); + } + } +} + + +uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out) +{ + std::string program_path = Local_Storage::get_program_path(), save_path = Local_Storage::get_user_appdata_path();; + + PRINT_DEBUG("Current Path %s save_path: %s\n", program_path.c_str(), save_path.c_str()); + + char array[10] = {}; + array[0] = '0'; + Local_Storage::get_file_data(Local_Storage::get_game_settings_path() + "steam_appid.txt", array, sizeof(array) - 1); + uint32 appid = 0; + try { + appid = std::stoi(array); + } catch (...) {} + if (!appid) { + memset(array, 0, sizeof(array)); + array[0] = '0'; + Local_Storage::get_file_data("steam_appid.txt", array, sizeof(array) - 1); + try { + appid = std::stoi(array); + } catch (...) {} + 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::stoi(array); + } catch (...) {} + } + } + + if (!appid) { + std::string str_appid = get_env_variable("SteamAppId"); + std::string str_gameid = get_env_variable("SteamGameId"); + PRINT_DEBUG("str_appid %s str_gameid: %s\n", str_appid.c_str(), str_gameid.c_str()); + uint32 appid_env = 0; + uint32 gameid_env = 0; + + 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; + } + } + + PRINT_DEBUG("appid_env %u gameid_env: %u\n", appid_env, gameid_env); + if (appid_env) { + appid = appid_env; + } + + if (gameid_env) { + appid = gameid_env; + } + } + + { + char array[33] = {}; + if (Local_Storage::get_file_data(program_path + "local_save.txt", array, sizeof(array) - 1) != -1) { + save_path = program_path + Settings::sanitize(array); + } + } + + PRINT_DEBUG("Set save_path: %s\n", save_path.c_str()); + Local_Storage *local_storage = new Local_Storage(save_path); + local_storage->setAppId(appid); + + // Listen port + char array_port[10] = {}; + array_port[0] = '0'; + local_storage->get_data_settings("listen_port.txt", array_port, sizeof(array_port) - 1); + uint16 port = std::stoi(array_port); + if (port == 0) { + port = DEFAULT_PORT; + snprintf(array_port, sizeof(array_port), "%hu", port); + local_storage->store_data_settings("listen_port.txt", array_port, strlen(array_port)); + } + + + // Custom broadcasts + std::set custom_broadcasts; + load_custom_broadcasts(local_storage->get_global_settings_path() + "custom_broadcasts.txt", custom_broadcasts); + load_custom_broadcasts(Local_Storage::get_game_settings_path() + "custom_broadcasts.txt", custom_broadcasts); + + // Acount name + char name[32] = {}; + if (local_storage->get_data_settings("account_name.txt", name, sizeof(name) - 1) <= 0) { + strcpy(name, DEFAULT_NAME); + local_storage->store_data_settings("account_name.txt", name, strlen(name)); + } + + // Language + char language[32] = {}; + if (local_storage->get_data_settings("language.txt", language, sizeof(language) - 1) <= 0) { + strcpy(language, DEFAULT_LANGUAGE); + local_storage->store_data_settings("language.txt", language, strlen(language)); + } + + // Steam ID + char array_steam_id[32] = {}; + CSteamID user_id; + uint64 steam_id = 0; + bool generate_new = false; + //try to load steam id from game specific settings folder first + if (local_storage->get_data(SETTINGS_STORAGE_FOLDER, "user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) { + user_id = CSteamID((uint64)std::atoll(array_steam_id)); + if (!user_id.IsValid()) { + generate_new = true; + } + } else { + generate_new = true; + } + + if (generate_new) { + generate_new = false; + if (local_storage->get_data_settings("user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) { + user_id = CSteamID((uint64)std::atoll(array_steam_id)); + if (!user_id.IsValid()) { + generate_new = true; + } + } else { + generate_new = true; + } + } + + if (generate_new) { + user_id = generate_steam_id_user(); + uint64 steam_id = user_id.ConvertToUint64(); + char temp_text[32] = {}; + snprintf(temp_text, sizeof(temp_text), "%llu", steam_id); + local_storage->store_data_settings("user_steam_id.txt", temp_text, strlen(temp_text)); + } + + bool steam_offline_mode = false; + { + std::string steam_settings_path = Local_Storage::get_game_settings_path(); + + std::vector paths = Local_Storage::get_filenames_path(steam_settings_path); + for (auto & p: paths) { + PRINT_DEBUG("steam settings path %s\n", p.c_str()); + if (p == "offline.txt") { + steam_offline_mode = true; + } + } + } + + 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); + settings_client->set_port(port); + settings_server->set_port(port); + settings_client->custom_broadcasts = custom_broadcasts; + settings_server->custom_broadcasts = custom_broadcasts; + + { + std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt"; + std::ifstream input( dlc_config_path ); + if (input.is_open()) { + settings_client->unlockAllDLC(false); + settings_server->unlockAllDLC(false); + PRINT_DEBUG("Locking all DLC\n"); + + 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) { + PRINT_DEBUG("Adding DLC: %u|%s| %u\n", appid, name.c_str(), available); + settings_client->addDLC(appid, name, available); + settings_server->addDLC(appid, name, available); + } + } + } + } else { + //unlock all DLC + PRINT_DEBUG("Unlocking all DLC\n"); + settings_client->unlockAllDLC(true); + settings_server->unlockAllDLC(true); + } + } + + { + std::string dlc_config_path = Local_Storage::get_game_settings_path() + "app_paths.txt"; + std::ifstream input( dlc_config_path ); + if (input.is_open()) { + 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::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 rel_path = line.substr(deliminator + 1); + std::string path = canonical_path(program_path + rel_path); + + if (appid) { + if (path.size()) { + PRINT_DEBUG("Adding app path: %u|%s|\n", 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|\n", appid, rel_path.c_str()); + } + } + } + } + } + } + + { + std::string dlc_config_path = Local_Storage::get_game_settings_path() + "leaderboards.txt"; + std::ifstream input( dlc_config_path ); + if (input.is_open()) { + settings_client->setCreateUnknownLeaderboards(false); + settings_server->setCreateUnknownLeaderboards(false); + + 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 leaderboard; + 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)); + } + } + + if (leaderboard.size() && sort_method <= k_ELeaderboardSortMethodDescending && display_type <= k_ELeaderboardDisplayTypeTimeMilliSeconds) { + PRINT_DEBUG("Adding leaderboard: %s|%u|%u\n", leaderboard.c_str(), sort_method, display_type); + settings_client->setLeaderboard(leaderboard, (ELeaderboardSortMethod)sort_method, (ELeaderboardDisplayType)display_type); + settings_server->setLeaderboard(leaderboard, (ELeaderboardSortMethod)sort_method, (ELeaderboardDisplayType)display_type); + } else { + PRINT_DEBUG("Error adding leaderboard for: %s, are sort method %u or display type %u valid?\n", leaderboard.c_str(), sort_method, display_type); + } + } + } + } + + { + std::string stats_config_path = Local_Storage::get_game_settings_path() + "stats.txt"; + std::ifstream input( stats_config_path ); + if (input.is_open()) { + + 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") { + config.type = Stat_Type::STAT_TYPE_FLOAT; + config.default_value_float = std::stof(stat_default_value); + } else if (stat_type == "int") { + config.type = Stat_Type::STAT_TYPE_INT; + config.default_value_int = std::stol(stat_default_value); + } else if (stat_type == "avgrate") { + config.type = Stat_Type::STAT_TYPE_AVGRATE; + config.default_value_float = std::stof(stat_default_value); + } else { + PRINT_DEBUG("Error adding stat %s, type %s isn't valid\n", stat_name.c_str(), stat_type.c_str()); + continue; + } + } catch (...) { + PRINT_DEBUG("Error adding stat %s, default value %s isn't valid\n", stat_name.c_str(), stat_default_value.c_str()); + continue; + } + + if (stat_name.size()) { + PRINT_DEBUG("Adding stat type: %s|%u|%f|%u\n", stat_name.c_str(), config.type, config.default_value_float, config.default_value_int); + settings_client->setStatDefiniton(stat_name, config); + settings_server->setStatDefiniton(stat_name, config); + } else { + PRINT_DEBUG("Error adding stat for: %s, empty name\n", stat_name.c_str()); + } + } + } + } + + { + std::string mod_path = Local_Storage::get_game_settings_path() + "mods"; + std::vector paths = Local_Storage::get_filenames_path(mod_path); + for (auto & p: paths) { + PRINT_DEBUG("mod directory %s\n", p.c_str()); + try { + PublishedFileId_t id = std::stoull(p); + settings_client->addMod(id, p, mod_path + PATH_SEPARATOR + p); + settings_server->addMod(id, p, mod_path + PATH_SEPARATOR + p); + } catch (...) {} + } + } + + *settings_client_out = settings_client; + *settings_server_out = settings_server; + *local_storage_out = local_storage; + + return appid; +} \ No newline at end of file diff --git a/dll/settings_parser.h b/dll/settings_parser.h new file mode 100644 index 0000000..5c20ea4 --- /dev/null +++ b/dll/settings_parser.h @@ -0,0 +1,27 @@ +/* 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 + . */ + +#include "settings.h" + +#ifndef SETTINGS_PARSER_INCLUDE +#define SETTINGS_PARSER_INCLUDE + +//returns appid +uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out); + + +#endif diff --git a/dll/steam_client.cpp b/dll/steam_client.cpp index 8ae55e7..36283fe 100644 --- a/dll/steam_client.cpp +++ b/dll/steam_client.cpp @@ -16,8 +16,8 @@ . */ #include "steam_client.h" +#include "settings_parser.h" -#include static void background_thread(Steam_Client *client) { @@ -39,303 +39,12 @@ static void background_thread(Steam_Client *client) } } -static void load_custom_broadcasts(std::string broadcasts_filepath, std::set &custom_broadcasts) -{ - std::ifstream broadcasts_file(broadcasts_filepath); - PRINT_DEBUG("Broadcasts file path: %s\n", broadcasts_filepath.c_str()); - if (broadcasts_file.is_open()) { - std::string line; - while (std::getline(broadcasts_file, line)) { - std::set ips = Networking::resolve_ip(line); - custom_broadcasts.insert(ips.begin(), ips.end()); - } - } -} - Steam_Client::Steam_Client() { - std::string program_path = Local_Storage::get_program_path(), save_path = Local_Storage::get_user_appdata_path();; - PRINT_DEBUG("Current Path %s save_path: %s\n", program_path.c_str(), save_path.c_str()); + uint32 appid = create_localstorage_settings(&settings_client, &settings_server, &local_storage); - char array[10] = {}; - array[0] = '0'; - Local_Storage::get_file_data(Local_Storage::get_game_settings_path() + "steam_appid.txt", array, sizeof(array) - 1); - uint32 appid = 0; - try { - appid = std::stoi(array); - } catch (...) {} - if (!appid) { - memset(array, 0, sizeof(array)); - array[0] = '0'; - Local_Storage::get_file_data("steam_appid.txt", array, sizeof(array) - 1); - try { - appid = std::stoi(array); - } catch (...) {} - 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::stoi(array); - } catch (...) {} - } - } - - if (!appid) { - std::string str_appid = get_env_variable("SteamAppId"); - std::string str_gameid = get_env_variable("SteamGameId"); - PRINT_DEBUG("str_appid %s str_gameid: %s\n", str_appid.c_str(), str_gameid.c_str()); - uint32 appid_env = 0; - uint32 gameid_env = 0; - - 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; - } - } - - PRINT_DEBUG("appid_env %u gameid_env: %u\n", appid_env, gameid_env); - if (appid_env) { - appid = appid_env; - } - - if (gameid_env) { - appid = gameid_env; - } - } - - { - char array[33] = {}; - if (Local_Storage::get_file_data(program_path + "local_save.txt", array, sizeof(array) - 1) != -1) { - save_path = program_path + Settings::sanitize(array); - } - } - - PRINT_DEBUG("Set save_path: %s\n", save_path.c_str()); - local_storage = new Local_Storage(save_path); - local_storage->setAppId(appid); - - // Listen port - char array_port[10] = {}; - array_port[0] = '0'; - local_storage->get_data_settings("listen_port.txt", array_port, sizeof(array_port) - 1); - uint16 port = std::stoi(array_port); - if (port == 0) { - port = DEFAULT_PORT; - snprintf(array_port, sizeof(array_port), "%hu", port); - local_storage->store_data_settings("listen_port.txt", array_port, strlen(array_port)); - } - - // Custom broadcasts - std::set custom_broadcasts; - load_custom_broadcasts(local_storage->get_global_settings_path() + "custom_broadcasts.txt", custom_broadcasts); - load_custom_broadcasts(Local_Storage::get_game_settings_path() + "custom_broadcasts.txt", custom_broadcasts); - - // Acount name - char name[32] = {}; - if (local_storage->get_data_settings("account_name.txt", name, sizeof(name) - 1) <= 0) { - strcpy(name, DEFAULT_NAME); - local_storage->store_data_settings("account_name.txt", name, strlen(name)); - } - - // Language - char language[32] = {}; - if (local_storage->get_data_settings("language.txt", language, sizeof(language) - 1) <= 0) { - strcpy(language, DEFAULT_LANGUAGE); - local_storage->store_data_settings("language.txt", language, strlen(language)); - } - - // Steam ID - char array_steam_id[32] = {}; - CSteamID user_id; - uint64 steam_id = 0; - bool generate_new = false; - //try to load steam id from game specific settings folder first - if (local_storage->get_data(Local_Storage::settings_storage_folder, "user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) { - user_id = CSteamID((uint64)std::atoll(array_steam_id)); - if (!user_id.IsValid()) { - generate_new = true; - } - } else { - generate_new = true; - } - - if (generate_new) { - generate_new = false; - if (local_storage->get_data_settings("user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) { - user_id = CSteamID((uint64)std::atoll(array_steam_id)); - if (!user_id.IsValid()) { - generate_new = true; - } - } else { - generate_new = true; - } - } - - if (generate_new) { - user_id = generate_steam_id_user(); - uint64 steam_id = user_id.ConvertToUint64(); - char temp_text[32] = {}; - snprintf(temp_text, sizeof(temp_text), "%llu", steam_id); - local_storage->store_data_settings("user_steam_id.txt", temp_text, strlen(temp_text)); - } - - bool steam_offline_mode = false; - { - std::string steam_settings_path = Local_Storage::get_game_settings_path(); - - std::vector paths = Local_Storage::get_filenames_path(steam_settings_path); - for (auto & p: paths) { - PRINT_DEBUG("steam settings path %s\n", p.c_str()); - if (p == "offline.txt") { - steam_offline_mode = true; - } - } - } - - settings_client = new Settings(user_id, CGameID(appid), name, language, steam_offline_mode); - settings_server = new Settings(generate_steam_id_server(), CGameID(appid), name, language, steam_offline_mode); - - { - std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt"; - std::ifstream input( dlc_config_path ); - if (input.is_open()) { - settings_client->unlockAllDLC(false); - settings_server->unlockAllDLC(false); - PRINT_DEBUG("Locking all DLC\n"); - - 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) { - PRINT_DEBUG("Adding DLC: %u|%s| %u\n", appid, name.c_str(), available); - settings_client->addDLC(appid, name, available); - settings_server->addDLC(appid, name, available); - } - } - } - } else { - //unlock all DLC - PRINT_DEBUG("Unlocking all DLC\n"); - settings_client->unlockAllDLC(true); - settings_server->unlockAllDLC(true); - } - } - - { - std::string dlc_config_path = Local_Storage::get_game_settings_path() + "app_paths.txt"; - std::ifstream input( dlc_config_path ); - if (input.is_open()) { - for( std::string line; getline( input, line ); ) { - if (!line.empty() && line[line.length()-1] == '\n') { - line.erase(line.length()-1); - } - - if (!line.empty() && line[line.length()-1] == '\r') { - line.erase(line.length()-1); - } - - 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 rel_path = line.substr(deliminator + 1); - std::string path = canonical_path(program_path + rel_path); - - if (appid) { - if (path.size()) { - PRINT_DEBUG("Adding app path: %u|%s|\n", 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|\n", appid, rel_path.c_str()); - } - } - } - } - } - } - - { - std::string dlc_config_path = Local_Storage::get_game_settings_path() + "leaderboards.txt"; - std::ifstream input( dlc_config_path ); - if (input.is_open()) { - settings_client->setCreateUnknownLeaderboards(false); - settings_server->setCreateUnknownLeaderboards(false); - - for( std::string line; getline( input, line ); ) { - if (!line.empty() && line[line.length()-1] == '\n') { - line.erase(line.length()-1); - } - - if (!line.empty() && line[line.length()-1] == '\r') { - line.erase(line.length()-1); - } - - std::string leaderboard; - 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)); - display_type = stol(line.substr(deliminator2 + 1)); - } - } - - if (leaderboard.size() && sort_method <= k_ELeaderboardSortMethodDescending && display_type <= k_ELeaderboardDisplayTypeTimeMilliSeconds) { - PRINT_DEBUG("Adding leaderboard: %s|%u|%u\n", leaderboard.c_str(), sort_method, display_type); - settings_client->setLeaderboard(leaderboard, (ELeaderboardSortMethod)sort_method, (ELeaderboardDisplayType)display_type); - settings_server->setLeaderboard(leaderboard, (ELeaderboardSortMethod)sort_method, (ELeaderboardDisplayType)display_type); - } else { - PRINT_DEBUG("Error adding leaderboard for: %s, are sort method %u or display type %u valid?\n", leaderboard.c_str(), sort_method, display_type); - } - } - } - } - - { - std::string mod_path = Local_Storage::get_game_settings_path() + "mods"; - std::vector paths = Local_Storage::get_filenames_path(mod_path); - for (auto & p: paths) { - PRINT_DEBUG("mod directory %s\n", p.c_str()); - try { - PublishedFileId_t id = std::stoull(p); - settings_client->addMod(id, p, mod_path + PATH_SEPARATOR + p); - settings_server->addMod(id, p, mod_path + PATH_SEPARATOR + p); - } catch (...) {} - } - } - - network = new Networking(settings_server->get_local_steam_id(), appid, port, &custom_broadcasts); + network = new Networking(settings_server->get_local_steam_id(), appid, settings_server->get_port(), &(settings_server->custom_broadcasts)); callback_results_client = new SteamCallResults(); callback_results_server = new SteamCallResults(); @@ -343,7 +52,7 @@ Steam_Client::Steam_Client() callbacks_server = new SteamCallBacks(callback_results_server); run_every_runcb = new RunEveryRunCB(); - PRINT_DEBUG("steam client init: id: %llu server id: %llu appid: %u port: %u \n", user_id.ConvertToUint64(), settings_server->get_local_steam_id().ConvertToUint64(), appid, port); + PRINT_DEBUG("steam client init: id: %llu server id: %llu appid: %u port: %u \n", settings_client->get_local_steam_id().ConvertToUint64(), settings_server->get_local_steam_id().ConvertToUint64(), appid, settings_server->get_port()); steam_user = new Steam_User(settings_client, local_storage, network, callback_results_client, callbacks_client); steam_friends = new Steam_Friends(settings_client, network, callback_results_client, callbacks_client, run_every_runcb); diff --git a/dll/steam_user.h b/dll/steam_user.h index 8e2d35c..35875ec 100644 --- a/dll/steam_user.h +++ b/dll/steam_user.h @@ -361,7 +361,7 @@ void AdvertiseGame( CSteamID steamIDGameServer, uint32 unIPServer, uint16 usPort STEAM_CALL_RESULT( EncryptedAppTicketResponse_t ) SteamAPICall_t RequestEncryptedAppTicket( void *pDataToInclude, int cbDataToInclude ) { - PRINT_DEBUG("Steam_User::RequestEncryptedAppTicket\n"); + PRINT_DEBUG("Steam_User::RequestEncryptedAppTicket %i\n", cbDataToInclude); std::lock_guard lock(global_mutex); EncryptedAppTicketResponse_t data; data.m_eResult = k_EResultOK; diff --git a/dll/steam_user_stats.h b/dll/steam_user_stats.h index 4b578bb..eee3247 100644 --- a/dll/steam_user_stats.h +++ b/dll/steam_user_stats.h @@ -131,11 +131,21 @@ bool GetStat( const char *pchName, int32 *pData ) PRINT_DEBUG("GetStat int32 %s\n", pchName); if (!pchName || !pData) return false; std::lock_guard lock(global_mutex); + auto stats_config = settings->getStats(); + auto stats_data = stats_config.find(pchName); + if (stats_data != stats_config.end()) { + if (stats_data->second.type != Stat_Type::STAT_TYPE_INT) return false; + } int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, pchName, (char* )pData, sizeof(*pData)); if (read_data == sizeof(int32)) return true; + if (stats_data != stats_config.end()) { + *pData = stats_data->second.default_value_int; + return true; + } + return false; } @@ -144,11 +154,21 @@ bool GetStat( const char *pchName, float *pData ) PRINT_DEBUG("GetStat float %s\n", pchName); if (!pchName || !pData) return false; std::lock_guard lock(global_mutex); + auto stats_config = settings->getStats(); + auto stats_data = stats_config.find(pchName); + if (stats_data != stats_config.end()) { + if (stats_data->second.type == Stat_Type::STAT_TYPE_INT) return false; + } int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, pchName, (char* )pData, sizeof(*pData)); - if (read_data == sizeof(int32)) + if (read_data == sizeof(float)) return true; + if (stats_data != stats_config.end()) { + *pData = stats_data->second.default_value_float; + return true; + } + return false; } diff --git a/files_example/steam_settings.EXAMPLE/stats.EXAMPLE.txt b/files_example/steam_settings.EXAMPLE/stats.EXAMPLE.txt new file mode 100644 index 0000000..7263d56 --- /dev/null +++ b/files_example/steam_settings.EXAMPLE/stats.EXAMPLE.txt @@ -0,0 +1,7 @@ +lifetime_experience=int=0 +experience=int=0 +stat_example_name1=float=3.5 +stat_example_name2=int=1337 +stat_example_name3=int=0 +stat_example_name4=float=0 +stat_example_name5=avgrate=0