diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9816891..016b26d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push jobs: ci: name: CI - uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@a053502132e51e936820f27b7c99316fdb62b3e4 + uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@50dba8cafc7ea9523f73be038c80f1eacd1b4f8c permissions: contents: write with: diff --git a/CMakeLists.txt b/CMakeLists.txt index 124024e..06a125c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.24) -project(SmokeAPI VERSION 3.0.0) +project(SmokeAPI VERSION 3.1.0) include(KoalaBox/cmake/KoalaBox.cmake) @@ -16,6 +16,8 @@ configure_build_config(extra_build_config) set(SMOKE_API_STATIC_SOURCES static/smoke_api/interfaces/steam_apps.hpp static/smoke_api/interfaces/steam_apps.cpp + static/smoke_api/interfaces/steam_http.hpp + static/smoke_api/interfaces/steam_http.cpp static/smoke_api/interfaces/steam_inventory.hpp static/smoke_api/interfaces/steam_inventory.cpp static/smoke_api/interfaces/steam_user.hpp @@ -35,12 +37,11 @@ set(SMOKE_API_SOURCES ${SMOKE_API_STATIC_SOURCES} src/steam_api/exports/steam_api.cpp src/steam_api/exports/steam_api.hpp - src/steam_api/exports/steam_api_flat.cpp - src/steam_api/exports/steam_api_internal.cpp src/steam_api/exports/steam_api_unversioned.cpp src/steam_api/virtuals/isteamapps.cpp src/steam_api/virtuals/isteamclient.cpp src/steam_api/virtuals/isteamgameserver.cpp + src/steam_api/virtuals/isteamhttp.cpp src/steam_api/virtuals/isteaminventory.cpp src/steam_api/virtuals/isteamuser.cpp src/steam_api/virtuals/steam_api_virtuals.hpp @@ -48,7 +49,7 @@ set(SMOKE_API_SOURCES src/steam_api/steam_client.cpp src/steam_api/steam_interface.cpp src/steam_api/steam_interface.hpp - src/steamclient.cpp + src/steamclient/steamclient.cpp src/main.cpp src/smoke_api.cpp src/smoke_api.hpp @@ -81,7 +82,8 @@ configure_version_resource( ) target_include_directories(SmokeAPI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" - "${CMAKE_CURRENT_BINARY_DIR}") + "${CMAKE_CURRENT_BINARY_DIR}" +) ## https://github.com/batterycenter/embed CPMAddPackage( diff --git a/KoalaBox b/KoalaBox index a053502..50dba8c 160000 --- a/KoalaBox +++ b/KoalaBox @@ -1 +1 @@ -Subproject commit a053502132e51e936820f27b7c99316fdb62b3e4 +Subproject commit 50dba8cafc7ea9523f73be038c80f1eacd1b4f8c diff --git a/README.adoc b/README.adoc index d7bd513..9419341 100644 --- a/README.adoc +++ b/README.adoc @@ -114,6 +114,7 @@ To use it, simply place it next to the SmokeAPI DLL. It will be read upon each launch of the game. In the absence of the config file, default values specified below will be used. The configuration file is expected to conform to the JSON standard. +All options within the config file are optional. `logging`:: Toggles generation of a `SmokeAPI.log.log` file. + @@ -121,6 +122,12 @@ The configuration file is expected to conform to the JSON standard. Type::: Boolean Default::: `false` +`log_steam_http`:: Toggles logging of _SteamHTTP_ traffic. ++ +[horizontal] +Type::: Boolean +Default::: `false` + `default_app_status`:: This option sets the default DLC unlocking behaviour. + [horizontal] @@ -184,8 +191,9 @@ Default::: `{}` [source,json] ---- { - "$version": 3, + "$version": 4, "logging": true, + "log_steam_http": true, "default_app_status": "unlocked", "override_app_status": { "1234": "original", @@ -223,7 +231,7 @@ Some games that have a large number of DLCs begin ownership verification by quer Once the game receives the list, it will go over each item and check the ownership. The issue arises from the fact that response from Steamworks SDK may max out at 64, depending on how much unowned DLCs the user has. To alleviate this issue, SmokeAPI will make a web request to Steam API for a full list of DLCs, which works well most of the time. -Unfortunately, even the web API does not solve all of our problems, because it will only return DLCs that are available in Steam store. +Unfortunately, even the web API does not solve all of our problems, because it will return only DLCs that are available in Steam store. This means that DLCs without a dedicated store offer, such as pre-order DLCs will be left out. That's where the `extra_dlcs` config option comes into play. You can specify those missing DLC IDs there, and SmokeAPI will make them available to the game. diff --git a/res/SmokeAPI.config.json b/res/SmokeAPI.config.json index 08efb15..7c28643 100644 --- a/res/SmokeAPI.config.json +++ b/res/SmokeAPI.config.json @@ -1,7 +1,8 @@ { - "$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.0.0/res/SmokeAPI.schema.json", - "$version": 3, + "$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.0/res/SmokeAPI.schema.json", + "$version": 4, "logging": true, + "log_steam_http": true, "default_app_status": "unlocked", "override_app_status": {}, "override_dlc_status": {}, diff --git a/res/SmokeAPI.schema.json b/res/SmokeAPI.schema.json index ac3367f..f1a9e93 100644 --- a/res/SmokeAPI.schema.json +++ b/res/SmokeAPI.schema.json @@ -12,7 +12,7 @@ "$version": { "type": "integer", "minimum": 0, - "default": 3, + "default": 4, "description": "A technical field reserved for tools like GUI config editors. Do not modify this value." }, "logging": { @@ -20,6 +20,11 @@ "default": false, "description": "Toggles generation of a SmokeAPI.log.log file." }, + "log_steam_http": { + "type": "boolean", + "default": false, + "description": "Toggles logging of SteamHTTP traffic" + }, "default_app_status": { "description": "Sets the default DLC unlocking behaviour.", "default": "unlocked", @@ -111,9 +116,10 @@ }, "examples": [ { - "$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/heads/master/res/SmokeAPI.schema.json", - "$version": 3, + "$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.0.0/res/SmokeAPI.schema.json", + "$version": 4, "logging": true, + "log_steam_http": true, "default_app_status": "unlocked", "override_app_status": { "1234": "original", diff --git a/src/smoke_api.cpp b/src/smoke_api.cpp index c8a4873..fd9ae45 100644 --- a/src/smoke_api.cpp +++ b/src/smoke_api.cpp @@ -56,6 +56,9 @@ namespace { } else if(kb::str::eq(library_name, STEAMAPI_DLL)) { KB_HOOK_DETOUR_MODULE(SteamAPI_RestartAppIfNecessary, module_handle); KB_HOOK_DETOUR_MODULE(SteamAPI_Shutdown, module_handle); + + // Note: It is not necessary to hook flat functions or interface accessors + // since the underlying interfaces will be hooked through steamclient. } } ); diff --git a/src/smoke_api.hpp b/src/smoke_api.hpp index d80a1b8..57edb3d 100644 --- a/src/smoke_api.hpp +++ b/src/smoke_api.hpp @@ -4,6 +4,7 @@ constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; constexpr auto STEAM_CLIENT = "SteamClient"; +constexpr auto STEAM_HTTP = "STEAMHTTP_INTERFACE_VERSION"; constexpr auto STEAM_USER = "SteamUser"; constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; constexpr auto STEAM_GAME_SERVER = "SteamGameServer"; diff --git a/src/steam_api/exports/steam_api_flat.cpp b/src/steam_api/exports/steam_api_flat.cpp deleted file mode 100644 index 541ebc3..0000000 --- a/src/steam_api/exports/steam_api_flat.cpp +++ /dev/null @@ -1,321 +0,0 @@ -#include - -#include "smoke_api.hpp" -#include "smoke_api/interfaces/steam_apps.hpp" -#include "smoke_api/interfaces/steam_inventory.hpp" -#include "smoke_api/interfaces/steam_user.hpp" -#include "steam_api/steam_client.hpp" -#include "steam_api/steam_interface.hpp" - -// ISteamApps - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, const AppId_t dlcID) { - try { - return smoke_api::steam_apps::IsDlcUnlocked( - __func__, - steam_interface::get_app_id(), - dlcID, - MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_BIsSubscribedApp, self, dlcID) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, const AppId_t dlcID) { - try { - return smoke_api::steam_apps::IsDlcUnlocked( - __func__, - steam_interface::get_app_id(), - dlcID, - MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_BIsDlcInstalled, self, dlcID) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void* self) { - try { - return smoke_api::steam_apps::GetDLCCount( - __func__, - steam_interface::get_app_id(), - MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_GetDLCCount, self) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return 0; - } -} - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex( - void* self, - const int iDLC, - AppId_t* pDlcID, - bool* pbAvailable, - char* pchName, - const int cchNameBufferSize -) { - try { - return smoke_api::steam_apps::GetDLCDataByIndex( - __func__, - steam_interface::get_app_id(), - iDLC, - pDlcID, - pbAvailable, - pchName, - cchNameBufferSize, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamApps_BGetDLCDataByIndex, - self, - iDLC, - pDlcID, - pbAvailable, - pchName, - cchNameBufferSize - ), - [&](const AppId_t dlc_id) { - return SteamAPI_ISteamApps_BIsDlcInstalled(self, dlc_id); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -// ISteamClient - -DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface( - void* self, - const HSteamUser hSteamUser, - const HSteamPipe hSteamPipe, - const char* pchVersion -) { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamClient_GetISteamGenericInterface, - self, - hSteamUser, - hSteamPipe, - pchVersion - ) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} - -// ISteamInventory - -DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus( - void* self, - const SteamInventoryResult_t resultHandle -) { - return smoke_api::steam_inventory::GetResultStatus( - __func__, - resultHandle, - MODULE_CALL_CLOSURE(SteamAPI_ISteamInventory_GetResultStatus, self, resultHandle) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs( - void* self, - SteamItemDef_t* pItemDefIDs, - uint32_t* punItemDefIDsArraySize -) { - return smoke_api::steam_inventory::GetItemDefinitionIDs( - __func__, - pItemDefIDs, - punItemDefIDsArraySize, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_GetItemDefinitionIDs, - self, - pItemDefIDs, - punItemDefIDsArraySize - ) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems( - void* self, - const SteamInventoryResult_t resultHandle, - SteamItemDetails_t* pOutItemsArray, - uint32_t* punOutItemsArraySize -) { - return smoke_api::steam_inventory::GetResultItems( - __func__, - resultHandle, - pOutItemsArray, - punOutItemsArraySize, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_GetResultItems, - self, - resultHandle, - pOutItemsArray, - punOutItemsArraySize - ), - [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { - MODULE_CALL( - SteamAPI_ISteamInventory_GetItemDefinitionIDs, - self, - pItemDefIDs, - punItemDefIDsArraySize - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty( - void* self, - const SteamInventoryResult_t resultHandle, - const uint32_t unItemIndex, - const char* pchPropertyName, - char* pchValueBuffer, - uint32_t* punValueBufferSizeOut -) { - return smoke_api::steam_inventory::GetResultItemProperty( - __func__, - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_GetResultItemProperty, - self, - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut - ) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID( - void* self, - const SteamInventoryResult_t resultHandle, - const CSteamID steamIDExpected -) { - return smoke_api::steam_inventory::CheckResultSteamID( - __func__, - resultHandle, - steamIDExpected, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_CheckResultSteamID, - self, - resultHandle, - steamIDExpected - ) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems( - void* self, - SteamInventoryResult_t* pResultHandle -) { - return smoke_api::steam_inventory::GetAllItems( - __func__, - pResultHandle, - MODULE_CALL_CLOSURE(SteamAPI_ISteamInventory_GetAllItems, self, pResultHandle) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID( - void* self, - SteamInventoryResult_t* pResultHandle, - const SteamItemInstanceID_t* pInstanceIDs, - const uint32_t unCountInstanceIDs -) { - return smoke_api::steam_inventory::GetItemsByID( - __func__, - pResultHandle, - pInstanceIDs, - unCountInstanceIDs, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_GetItemsByID, - self, - pResultHandle, - pInstanceIDs, - unCountInstanceIDs - ) - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult( - void* self, - const SteamInventoryResult_t resultHandle, - void* pOutBuffer, - uint32_t* punOutBufferSize -) { - return smoke_api::steam_inventory::SerializeResult( - __func__, - resultHandle, - pOutBuffer, - punOutBufferSize, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamInventory_SerializeResult, - self, - resultHandle, - pOutBuffer, - punOutBufferSize - ) - ); -} - -// ISteamUser - -DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp( - void* self, - const CSteamID steamID, - const AppId_t dlcID -) { - try { - return smoke_api::steam_user::UserHasLicenseForApp( - __func__, - steam_interface::get_app_id(), - dlcID, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamUser_UserHasLicenseForApp, - self, - steamID, - dlcID - ) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } -} - -// ISteamGameServer - -DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamGameServer_UserHasLicenseForApp( - void* self, - const CSteamID steamID, - const AppId_t dlcID -) { - try { - return smoke_api::steam_user::UserHasLicenseForApp( - __func__, - steam_interface::get_app_id(), - dlcID, - MODULE_CALL_CLOSURE( - SteamAPI_ISteamGameServer_UserHasLicenseForApp, - self, - steamID, - dlcID - ) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } -} diff --git a/src/steam_api/exports/steam_api_internal.cpp b/src/steam_api/exports/steam_api_internal.cpp deleted file mode 100644 index 964eb6c..0000000 --- a/src/steam_api/exports/steam_api_internal.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "smoke_api.hpp" -#include "smoke_api/types.hpp" -#include "steam_api/steam_client.hpp" - -DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface( - const HSteamUser hSteamUser, - const char* version -) { - return steam_client::GetGenericInterface( - __func__, - version, - MODULE_CALL_CLOSURE(SteamInternal_FindOrCreateUserInterface, hSteamUser, version) - ); -} - -DLL_EXPORT(void*) SteamInternal_CreateInterface(const char* version) { - return steam_client::GetGenericInterface( - __func__, - version, - MODULE_CALL_CLOSURE(SteamInternal_CreateInterface, version) - ); -} diff --git a/src/steam_api/exports/steam_api_unversioned.cpp b/src/steam_api/exports/steam_api_unversioned.cpp index f83e248..ce31764 100644 --- a/src/steam_api/exports/steam_api_unversioned.cpp +++ b/src/steam_api/exports/steam_api_unversioned.cpp @@ -22,10 +22,14 @@ namespace { if(not version_map.contains(version_prefix)) { try { - const std::string rdata = kb::win::get_pe_section_data_or_throw( + const auto section = kb::win::get_pe_section_or_throw( smoke_api::steamapi_module, ".rdata" ); + const auto rdata = std::string( + reinterpret_cast(section.start_address), + section.size + ); const std::regex regex(version_prefix + "\\d{3}"); if(std::smatch match; std::regex_search(rdata, match, regex)) { @@ -50,15 +54,7 @@ namespace { } } -DLL_EXPORT(void*) SteamClient() { - static auto version = get_versioned_interface(STEAM_CLIENT, "006"); - - return steam_client::GetGenericInterface( - __func__, - version, - MODULE_CALL_CLOSURE(SteamClient) - ); -} +// TODO: Do we really need to proxy them? DLL_EXPORT(void*) SteamApps() { static auto version = get_versioned_interface(STEAM_APPS, "002"); @@ -70,13 +66,23 @@ DLL_EXPORT(void*) SteamApps() { ); } -DLL_EXPORT(void*) SteamUser() { - static auto version = get_versioned_interface(STEAM_USER, "012"); +DLL_EXPORT(void*) SteamClient() { + static auto version = get_versioned_interface(STEAM_CLIENT, "006"); return steam_client::GetGenericInterface( __func__, version, - MODULE_CALL_CLOSURE(SteamUser) + MODULE_CALL_CLOSURE(SteamClient) + ); +} + +DLL_EXPORT(void*) SteamHTTP() { + static auto version = get_versioned_interface(STEAM_HTTP, "003"); + + return steam_client::GetGenericInterface( + __func__, + version, + MODULE_CALL_CLOSURE(SteamHTTP) ); } @@ -89,3 +95,13 @@ DLL_EXPORT(void*) SteamInventory() { MODULE_CALL_CLOSURE(SteamInventory) ); } + +DLL_EXPORT(void*) SteamUser() { + static auto version = get_versioned_interface(STEAM_USER, "012"); + + return steam_client::GetGenericInterface( + __func__, + version, + MODULE_CALL_CLOSURE(SteamUser) + ); +} diff --git a/src/steam_api/steam_client.cpp b/src/steam_api/steam_client.cpp index 5cfafa1..7be192c 100644 --- a/src/steam_api/steam_client.cpp +++ b/src/steam_api/steam_client.cpp @@ -7,13 +7,18 @@ namespace steam_client { const std::string& function_name, const std::string& interface_version, const std::function& original_function - ) { - auto* const interface = original_function(); + ) noexcept { + try { + auto* const interface = original_function(); - LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface); + LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface); - steam_interface::hook_virtuals(interface, interface_version); + steam_interface::hook_virtuals(interface, interface_version); - return interface; + return interface; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: '{}' @ {}", function_name, interface_version, e.what()); + return nullptr; + } } } diff --git a/src/steam_api/steam_client.hpp b/src/steam_api/steam_client.hpp index 75ae03d..61026f6 100644 --- a/src/steam_api/steam_client.hpp +++ b/src/steam_api/steam_client.hpp @@ -7,5 +7,5 @@ namespace steam_client { const std::string& function_name, const std::string& interface_version, const std::function& original_function - ); + ) noexcept; } diff --git a/src/steam_api/steam_interface.cpp b/src/steam_api/steam_interface.cpp index 17d425e..1abbbdb 100644 --- a/src/steam_api/steam_interface.cpp +++ b/src/steam_api/steam_interface.cpp @@ -25,11 +25,11 @@ namespace { std::map get_virtual_hook_map() { #define ENTRY(INTERFACE, FUNC) \ - { \ - #FUNC, { \ - #INTERFACE "_" #FUNC, reinterpret_cast(INTERFACE##_##FUNC) \ - } \ - } + { \ + #FUNC, { \ + #INTERFACE "_" #FUNC, reinterpret_cast(INTERFACE##_##FUNC) \ + } \ + } return { { @@ -56,6 +56,17 @@ namespace { } } }, + { + STEAM_HTTP, + interface_data{ + .fallback_version = "STEAMHTTP_INTERFACE_VERSION003", + .entry_map = { + ENTRY(ISteamHTTP, GetHTTPResponseBodyData), + ENTRY(ISteamHTTP, GetHTTPStreamingResponseBodyData), + ENTRY(ISteamHTTP, SetHTTPRequestRawPostBody), + } + } + }, { STEAM_USER, interface_data{ @@ -129,7 +140,11 @@ namespace steam_interface { static std::set processed_interfaces; if(processed_interfaces.contains(interface)) { - LOG_DEBUG("Interface {} at {} has already been processed.", version_string, interface); + LOG_DEBUG( + "Interface '{}' at {} has already been processed.", + version_string, + interface + ); return; } diff --git a/src/steam_api/virtuals/isteamapps.cpp b/src/steam_api/virtuals/isteamapps.cpp index e9905bc..26a88f5 100644 --- a/src/steam_api/virtuals/isteamapps.cpp +++ b/src/steam_api/virtuals/isteamapps.cpp @@ -4,45 +4,30 @@ #include "steam_api/steam_interface.hpp" #include "steam_api/virtuals/steam_api_virtuals.hpp" -VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(const AppId_t dlc_id)) { - try { - return smoke_api::steam_apps::IsDlcUnlocked( - __func__, - steam_interface::get_app_id(), - dlc_id, - HOOKED_CALL_CLOSURE(ISteamApps_BIsSubscribedApp, ARGS(dlc_id)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } +VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(const AppId_t dlc_id)) noexcept { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamApps_BIsSubscribedApp, ARGS(dlc_id)) + ); } -VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(const AppId_t dlc_id)) { - try { - return smoke_api::steam_apps::IsDlcUnlocked( - __func__, - steam_interface::get_app_id(), - dlc_id, - HOOKED_CALL_CLOSURE(ISteamApps_BIsDlcInstalled, ARGS(dlc_id)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } +VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(const AppId_t dlc_id)) noexcept { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamApps_BIsDlcInstalled, ARGS(dlc_id)) + ); } -VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) { - try { - return smoke_api::steam_apps::GetDLCCount( - __func__, - steam_interface::get_app_id(), - HOOKED_CALL_CLOSURE(ISteamApps_GetDLCCount, ARGS()) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return 0; - } +VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) noexcept { + return smoke_api::steam_apps::GetDLCCount( + __func__, + steam_interface::get_app_id(), + HOOKED_CALL_CLOSURE(ISteamApps_GetDLCCount, ARGS()) + ); } VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex( @@ -53,26 +38,22 @@ VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex( char* pchName, const int cchNameBufferSize ) -) { - try { - return smoke_api::steam_apps::GetDLCDataByIndex( - __func__, - steam_interface::get_app_id(), - iDLC, - p_dlc_id, - pbAvailable, - pchName, - cchNameBufferSize, - HOOKED_CALL_CLOSURE( - ISteamApps_BGetDLCDataByIndex, - ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize) - ), - [&](const AppId_t dlc_id) { - return ISteamApps_BIsDlcInstalled(ARGS(dlc_id)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } +) noexcept { + return smoke_api::steam_apps::GetDLCDataByIndex( + __func__, + steam_interface::get_app_id(), + iDLC, + p_dlc_id, + pbAvailable, + pchName, + cchNameBufferSize, + HOOKED_CALL_CLOSURE( + ISteamApps_BGetDLCDataByIndex, + ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize) + ), + HOOKED_CALL_CLOSURE( + ISteamApps_BIsSubscribedApp, + ARGS(*p_dlc_id) + ) + ); } diff --git a/src/steam_api/virtuals/isteamclient.cpp b/src/steam_api/virtuals/isteamclient.cpp index 4bc6aff..59fbf3c 100644 --- a/src/steam_api/virtuals/isteamclient.cpp +++ b/src/steam_api/virtuals/isteamclient.cpp @@ -9,17 +9,12 @@ VIRTUAL(void*) ISteamClient_GetISteamApps( const HSteamPipe hSteamPipe, const char* version ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - version, - HOOKED_CALL_CLOSURE(ISteamClient_GetISteamApps, ARGS(hSteamUser, hSteamPipe, version)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } +) noexcept { + return steam_client::GetGenericInterface( + __func__, + version, + HOOKED_CALL_CLOSURE(ISteamClient_GetISteamApps, ARGS(hSteamUser, hSteamPipe, version)) + ); } VIRTUAL(void*) ISteamClient_GetISteamUser( @@ -28,17 +23,12 @@ VIRTUAL(void*) ISteamClient_GetISteamUser( const HSteamPipe hSteamPipe, const char* version ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - version, - HOOKED_CALL_CLOSURE(ISteamClient_GetISteamUser, ARGS(hSteamUser, hSteamPipe, version)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } +) noexcept { + return steam_client::GetGenericInterface( + __func__, + version, + HOOKED_CALL_CLOSURE(ISteamClient_GetISteamUser, ARGS(hSteamUser, hSteamPipe, version)) + ); } VIRTUAL(void*) ISteamClient_GetISteamGenericInterface( @@ -47,20 +37,15 @@ VIRTUAL(void*) ISteamClient_GetISteamGenericInterface( HSteamPipe hSteamPipe, const char* pchVersion ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - HOOKED_CALL_CLOSURE( - ISteamClient_GetISteamGenericInterface, - ARGS(hSteamUser, hSteamPipe, pchVersion) - ) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } +) noexcept { + return steam_client::GetGenericInterface( + __func__, + pchVersion, + HOOKED_CALL_CLOSURE( + ISteamClient_GetISteamGenericInterface, + ARGS(hSteamUser, hSteamPipe, pchVersion) + ) + ); } VIRTUAL(void*) ISteamClient_GetISteamInventory( @@ -69,18 +54,13 @@ VIRTUAL(void*) ISteamClient_GetISteamInventory( const HSteamPipe hSteamPipe, const char* pchVersion ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - HOOKED_CALL_CLOSURE( - ISteamClient_GetISteamInventory, - ARGS(hSteamUser, hSteamPipe, pchVersion) - ) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } +) noexcept { + return steam_client::GetGenericInterface( + __func__, + pchVersion, + HOOKED_CALL_CLOSURE( + ISteamClient_GetISteamInventory, + ARGS(hSteamUser, hSteamPipe, pchVersion) + ) + ); } diff --git a/src/steam_api/virtuals/isteamgameserver.cpp b/src/steam_api/virtuals/isteamgameserver.cpp index 32af7a8..2c1e7d0 100644 --- a/src/steam_api/virtuals/isteamgameserver.cpp +++ b/src/steam_api/virtuals/isteamgameserver.cpp @@ -6,16 +6,11 @@ VIRTUAL(EUserHasLicenseForAppResult) ISteamGameServer_UserHasLicenseForApp( PARAMS(const CSteamID steamID, const AppId_t dlc_id) -) { - try { - return smoke_api::steam_user::UserHasLicenseForApp( - __func__, - steam_interface::get_app_id(), - dlc_id, - HOOKED_CALL_CLOSURE(ISteamGameServer_UserHasLicenseForApp, ARGS(steamID, dlc_id)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } +) noexcept { + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamGameServer_UserHasLicenseForApp, ARGS(steamID, dlc_id)) + ); } diff --git a/src/steam_api/virtuals/isteamhttp.cpp b/src/steam_api/virtuals/isteamhttp.cpp new file mode 100644 index 0000000..944316d --- /dev/null +++ b/src/steam_api/virtuals/isteamhttp.cpp @@ -0,0 +1,66 @@ +#include + +#include "smoke_api/interfaces/steam_http.hpp" +#include "steam_api/steam_interface.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(bool) ISteamHTTP_GetHTTPResponseBodyData( + PARAMS( + const HTTPRequestHandle hRequest, + const uint8_t* pBodyDataBuffer, + const uint32_t unBufferSize + ) +) noexcept { + return smoke_api::steam_http::GetHTTPResponseBodyData( + __func__, + hRequest, + pBodyDataBuffer, + unBufferSize, + HOOKED_CALL_CLOSURE( + ISteamHTTP_GetHTTPResponseBodyData, + ARGS(hRequest, pBodyDataBuffer, unBufferSize) + ) + ); +} + +VIRTUAL(bool) ISteamHTTP_GetHTTPStreamingResponseBodyData( + PARAMS( + const HTTPRequestHandle hRequest, + const uint32_t cOffset, + const uint8_t* pBodyDataBuffer, + const uint32_t unBufferSize + ) +) noexcept { + return smoke_api::steam_http::GetHTTPStreamingResponseBodyData( + __func__, + hRequest, + cOffset, + pBodyDataBuffer, + unBufferSize, + HOOKED_CALL_CLOSURE( + ISteamHTTP_GetHTTPStreamingResponseBodyData, + ARGS(hRequest, cOffset, pBodyDataBuffer, unBufferSize) + ) + ); +} + +VIRTUAL(bool) ISteamHTTP_SetHTTPRequestRawPostBody( + PARAMS( + const HTTPRequestHandle hRequest, + const char* pchContentType, + const uint8_t* pubBody, + const uint32_t unBodyLen + ) +) noexcept { + return smoke_api::steam_http::SetHTTPRequestRawPostBody( + __func__, + hRequest, + pchContentType, + pubBody, + unBodyLen, + HOOKED_CALL_CLOSURE( + ISteamHTTP_SetHTTPRequestRawPostBody, + ARGS(hRequest, pchContentType, pubBody, unBodyLen) + ) + ); +} diff --git a/src/steam_api/virtuals/isteaminventory.cpp b/src/steam_api/virtuals/isteaminventory.cpp index d1c32b2..6978197 100644 --- a/src/steam_api/virtuals/isteaminventory.cpp +++ b/src/steam_api/virtuals/isteaminventory.cpp @@ -3,7 +3,7 @@ VIRTUAL(EResult) ISteamInventory_GetResultStatus( PARAMS(const SteamInventoryResult_t resultHandle) -) { +) noexcept { return smoke_api::steam_inventory::GetResultStatus( __func__, resultHandle, @@ -17,7 +17,7 @@ VIRTUAL(bool) ISteamInventory_GetResultItems( SteamItemDetails_t* pOutItemsArray, uint32_t* punOutItemsArraySize ) -) { +) noexcept { return smoke_api::steam_inventory::GetResultItems( __func__, resultHandle, @@ -44,7 +44,7 @@ VIRTUAL(bool) ISteamInventory_GetResultItemProperty( char* pchValueBuffer, uint32_t* punValueBufferSizeOut ) -) { +) noexcept { return smoke_api::steam_inventory::GetResultItemProperty( __func__, resultHandle, @@ -65,7 +65,7 @@ VIRTUAL(bool) ISteamInventory_GetResultItemProperty( ); } -VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) { +VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) noexcept { return smoke_api::steam_inventory::GetAllItems( __func__, pResultHandle, @@ -79,7 +79,7 @@ VIRTUAL(bool) ISteamInventory_GetItemsByID( const SteamItemInstanceID_t* pInstanceIDs, const uint32_t unCountInstanceIDs ) -) { +) noexcept { return smoke_api::steam_inventory::GetItemsByID( __func__, pResultHandle, @@ -98,7 +98,7 @@ VIRTUAL(bool) ISteamInventory_SerializeResult( void* pOutBuffer, uint32_t* punOutBufferSize ) -) { +) noexcept { return smoke_api::steam_inventory::SerializeResult( __func__, resultHandle, @@ -116,7 +116,7 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( SteamItemDef_t*pItemDefIDs, uint32_t* punItemDefIDsArraySize ) -) { +) noexcept { return smoke_api::steam_inventory::GetItemDefinitionIDs( __func__, pItemDefIDs, @@ -130,14 +130,11 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( VIRTUAL(bool) ISteamInventory_CheckResultSteamID( PARAMS(const SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) -) { +) noexcept { return smoke_api::steam_inventory::CheckResultSteamID( __func__, resultHandle, steamIDExpected, - HOOKED_CALL_CLOSURE( - ISteamInventory_CheckResultSteamID, - ARGS(resultHandle, steamIDExpected) - ) + HOOKED_CALL_CLOSURE(ISteamInventory_CheckResultSteamID, ARGS(resultHandle, steamIDExpected)) ); } diff --git a/src/steam_api/virtuals/isteamuser.cpp b/src/steam_api/virtuals/isteamuser.cpp index a15412d..ab4162e 100644 --- a/src/steam_api/virtuals/isteamuser.cpp +++ b/src/steam_api/virtuals/isteamuser.cpp @@ -6,17 +6,11 @@ VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp( PARAMS(const CSteamID steamID, const AppId_t dlc_id) -) { - try { - static const auto app_id = steam_interface::get_app_id(); - return smoke_api::steam_user::UserHasLicenseForApp( - __func__, - app_id, - dlc_id, - HOOKED_CALL_CLOSURE(ISteamUser_UserHasLicenseForApp, ARGS(steamID, dlc_id)) - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } +) noexcept { + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamUser_UserHasLicenseForApp, ARGS(steamID, dlc_id)) + ); } diff --git a/src/steam_api/virtuals/steam_api_virtuals.hpp b/src/steam_api/virtuals/steam_api_virtuals.hpp index 8a2338f..a764ff7 100644 --- a/src/steam_api/virtuals/steam_api_virtuals.hpp +++ b/src/steam_api/virtuals/steam_api_virtuals.hpp @@ -3,38 +3,60 @@ #include "smoke_api/types.hpp" // ISteamApps -VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t)); -VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t)); -VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()); -VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*, int)); +VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t)) noexcept; +VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t)) noexcept; +VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) noexcept; +VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*, int)) noexcept; // ISteamClient -VIRTUAL(void*) ISteamClient_GetISteamApps(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamUser(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamInventory(PARAMS(HSteamUser, HSteamPipe, const char*)); +VIRTUAL(void*) ISteamClient_GetISteamApps(PARAMS(HSteamUser, HSteamPipe, const char*)) noexcept; +VIRTUAL(void*) ISteamClient_GetISteamUser(PARAMS(HSteamUser, HSteamPipe, const char*)) noexcept; +VIRTUAL(void*) ISteamClient_GetISteamGenericInterface( + PARAMS(HSteamUser, HSteamPipe, const char*) + +) noexcept; +VIRTUAL(void*) ISteamClient_GetISteamInventory( + PARAMS(HSteamUser, HSteamPipe, const char*) + +) noexcept; + +// ISteamHTTP +VIRTUAL(bool) ISteamHTTP_GetHTTPResponseBodyData( + PARAMS(HTTPRequestHandle, const uint8_t*, uint32_t) +) noexcept; +VIRTUAL(bool) ISteamHTTP_GetHTTPStreamingResponseBodyData( + PARAMS(HTTPRequestHandle, uint32_t, const uint8_t*, uint32_t) +) noexcept; +VIRTUAL(bool) ISteamHTTP_SetHTTPRequestRawPostBody( + PARAMS(HTTPRequestHandle, const char*, const uint8_t*, uint32_t) +) noexcept; // ISteamInventory -VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t)); +VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t)) noexcept; VIRTUAL(bool) ISteamInventory_GetResultItems( PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*) // @formatter:off -); // @formatter:on +) noexcept; // @formatter:on VIRTUAL(bool) ISteamInventory_GetResultItemProperty( PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*) // @formatter:off -); // @formatter:on -VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t*)); +) noexcept; // @formatter:on +VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t*)) noexcept; VIRTUAL(bool) ISteamInventory_GetItemsByID( PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t) -); -VIRTUAL(bool) ISteamInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t*)); -VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t*)); -VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID)); +) noexcept; +VIRTUAL(bool) ISteamInventory_SerializeResult( + PARAMS(SteamInventoryResult_t, void*, uint32_t*) + +) noexcept; +VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t*)) noexcept; +VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID)) noexcept; // ISteamUser -VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t)); +VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp( + PARAMS(CSteamID, AppId_t) +) noexcept; // ISteamGameServer VIRTUAL(EUserHasLicenseForAppResult) ISteamGameServer_UserHasLicenseForApp( PARAMS(CSteamID, AppId_t) -); +) noexcept; diff --git a/src/steamclient.cpp b/src/steamclient/steamclient.cpp similarity index 84% rename from src/steamclient.cpp rename to src/steamclient/steamclient.cpp index 58b6ef6..c859bf1 100644 --- a/src/steamclient.cpp +++ b/src/steamclient/steamclient.cpp @@ -1,8 +1,8 @@ #include "smoke_api/steamclient/steamclient.hpp" -#include "smoke_api.hpp" +#include "../smoke_api.hpp" #include "smoke_api/types.hpp" -#include "steam_api/steam_client.hpp" +#include "../steam_api/steam_client.hpp" /** * SmokeAPI implementation diff --git a/static/smoke_api/config.hpp b/static/smoke_api/config.hpp index c73bfb6..0c81c8e 100644 --- a/static/smoke_api/config.hpp +++ b/static/smoke_api/config.hpp @@ -23,8 +23,9 @@ namespace smoke_api::config { ) struct Config { - uint32_t $version = 3; + uint32_t $version = 4; bool logging = false; + bool log_steam_http = false; AppStatus default_app_status = AppStatus::UNLOCKED; std::map override_app_status; std::map override_dlc_status; @@ -32,7 +33,7 @@ namespace smoke_api::config { bool auto_inject_inventory = true; std::vector extra_inventory_items; - NLOHMANN_DEFINE_TYPE_INTRUSIVE( + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( Config, $version, logging, diff --git a/static/smoke_api/interfaces/steam_apps.cpp b/static/smoke_api/interfaces/steam_apps.cpp index 9fedfc3..c233aa0 100644 --- a/static/smoke_api/interfaces/steam_apps.cpp +++ b/static/smoke_api/interfaces/steam_apps.cpp @@ -85,7 +85,7 @@ namespace smoke_api::steam_apps { const AppId_t app_id, const AppId_t dlc_id, const std::function& original_function - ) { + ) noexcept { try { const auto unlocked = config::is_dlc_unlocked( app_id, @@ -103,7 +103,7 @@ namespace smoke_api::steam_apps { return unlocked; } catch(const std::exception& e) { - LOG_ERROR("Uncaught exception: {}", e.what()); + LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what()); return false; } } @@ -112,7 +112,7 @@ namespace smoke_api::steam_apps { const std::string& function_name, const AppId_t app_id, const std::function& original_function - ) { + ) noexcept { try { const auto total_count = [&](int count) { LOG_INFO("{} -> Responding with DLC count: {}", function_name, count); @@ -139,7 +139,7 @@ namespace smoke_api::steam_apps { return total_count(static_cast(app_dlcs[app_id].size())); } catch(const std::exception& e) { - LOG_ERROR("Uncaught exception: {}", function_name, e.what()); + LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what()); return 0; } } @@ -153,8 +153,8 @@ namespace smoke_api::steam_apps { char* pchName, const int cchNameBufferSize, const std::function& original_function, - const std::function& is_originally_unlocked - ) { + const std::function& is_originally_unlocked + ) noexcept { try { LOG_DEBUG("{} -> {}index: {:>3}", function_name, get_app_id_log(app_id), iDLC); @@ -174,13 +174,7 @@ namespace smoke_api::steam_apps { const auto output_dlc = [&](const DLC& dlc) { // Fill the output pointers *pDlcId = dlc.get_id(); - *pbAvailable = config::is_dlc_unlocked( - app_id, - *pDlcId, - [&] { - return is_originally_unlocked(*pDlcId); - } - ); + *pbAvailable = config::is_dlc_unlocked(app_id, *pDlcId, is_originally_unlocked); auto name = dlc.get_name(); name = name.substr(0, cchNameBufferSize + 1); diff --git a/static/smoke_api/interfaces/steam_apps.hpp b/static/smoke_api/interfaces/steam_apps.hpp index f50e1e5..29079df 100644 --- a/static/smoke_api/interfaces/steam_apps.hpp +++ b/static/smoke_api/interfaces/steam_apps.hpp @@ -2,19 +2,21 @@ #include "smoke_api/types.hpp" +// TODO: Make them all noexcept + namespace smoke_api::steam_apps { bool IsDlcUnlocked( const std::string& function_name, AppId_t app_id, AppId_t dlc_id, const std::function& original_function - ); + ) noexcept; int GetDLCCount( const std::string& function_name, AppId_t app_id, const std::function& original_function - ); + ) noexcept; bool GetDLCDataByIndex( const std::string& function_name, @@ -25,6 +27,6 @@ namespace smoke_api::steam_apps { char* pchName, int cchNameBufferSize, const std::function& original_function, - const std::function& is_originally_unlocked - ); + const std::function& is_originally_unlocked + ) noexcept; } diff --git a/static/smoke_api/interfaces/steam_http.cpp b/static/smoke_api/interfaces/steam_http.cpp new file mode 100644 index 0000000..6315abf --- /dev/null +++ b/static/smoke_api/interfaces/steam_http.cpp @@ -0,0 +1,115 @@ +#include + +#include "smoke_api/interfaces/steam_http.hpp" +#include "smoke_api/config.hpp" + +namespace smoke_api::steam_http { + bool GetHTTPResponseBodyData( + const std::string& function_name, + const HTTPRequestHandle hRequest, + const uint8_t* pBodyDataBuffer, + const uint32_t unBufferSize, + const std::function& original_function + ) noexcept { + try { + const auto result = original_function(); + + if(config::instance.log_steam_http) { + const std::string_view buffer = + pBodyDataBuffer && unBufferSize + ? std::string_view( + reinterpret_cast(pBodyDataBuffer), + unBufferSize + ) + : ""; + + LOG_INFO( + "{} -> handle: {}, size: {}, buffer:\n{}", + function_name, + hRequest, + unBufferSize, + buffer + ); + } + + return result; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } + } + + bool GetHTTPStreamingResponseBodyData( + const std::string& function_name, + const HTTPRequestHandle hRequest, + const uint32_t cOffset, + const uint8_t* pBodyDataBuffer, + const uint32_t unBufferSize, + const std::function& original_function + ) noexcept { + try { + const auto result = original_function(); + + if(config::instance.log_steam_http) { + const std::string_view buffer = + pBodyDataBuffer && unBufferSize + ? std::string_view( + reinterpret_cast(pBodyDataBuffer), + unBufferSize + ) + : ""; + + LOG_INFO( + "{} -> handle: {}, offset: {}, size: {}, buffer:\n{}", + function_name, + hRequest, + cOffset, + unBufferSize, + buffer + ); + } + + return result; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } + } + + bool SetHTTPRequestRawPostBody( + const std::string& function_name, + const HTTPRequestHandle hRequest, + const char* pchContentType, + const uint8_t* pubBody, + const uint32_t unBodyLen, + const std::function& original_function + ) noexcept { + try { + const auto result = original_function(); + + if(config::instance.log_steam_http) { + const std::string_view content_type = + pchContentType ? pchContentType : "smoke_api::N/A"; + + const std::string_view buffer = + pubBody && unBodyLen + ? std::string_view(reinterpret_cast(pubBody), unBodyLen) + : ""; + + LOG_INFO( + "{} -> handle: {}, content-type: {}, size: {}, buffer:\n{}", + function_name, + hRequest, + content_type, + unBodyLen, + buffer + ); + } + + return result; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } + } +} diff --git a/static/smoke_api/interfaces/steam_http.hpp b/static/smoke_api/interfaces/steam_http.hpp new file mode 100644 index 0000000..2b1f725 --- /dev/null +++ b/static/smoke_api/interfaces/steam_http.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "smoke_api/types.hpp" + +namespace smoke_api::steam_http { + bool GetHTTPResponseBodyData( + const std::string& function_name, + HTTPRequestHandle hRequest, + const uint8_t* pBodyDataBuffer, + uint32_t unBufferSize, + const std::function& original_function + ) noexcept; + + bool GetHTTPStreamingResponseBodyData( + const std::string& function_name, + HTTPRequestHandle hRequest, + uint32_t cOffset, + const uint8_t* pBodyDataBuffer, + uint32_t unBufferSize, + const std::function& original_function + ) noexcept; + + bool SetHTTPRequestRawPostBody( + const std::string& function_name, + HTTPRequestHandle hRequest, + const char* pchContentType, + const uint8_t* pubBody, + uint32_t unBodyLen, + const std::function& original_function + ) noexcept; +} diff --git a/static/smoke_api/interfaces/steam_inventory.cpp b/static/smoke_api/interfaces/steam_inventory.cpp index 1e121a5..df98c24 100644 --- a/static/smoke_api/interfaces/steam_inventory.cpp +++ b/static/smoke_api/interfaces/steam_inventory.cpp @@ -8,17 +8,22 @@ namespace smoke_api::steam_inventory { const std::string& function_name, const SteamInventoryResult_t resultHandle, const std::function& original_function - ) { - const auto status = original_function(); + ) noexcept { + try { + const auto status = original_function(); - LOG_DEBUG( - "{} -> handle: {}, status: {}", - function_name, - resultHandle, - static_cast(status) - ); + LOG_DEBUG( + "{} -> handle: {}, status: {}", + function_name, + resultHandle, + static_cast(status) + ); - return status; + return status; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return EResult::k_EResultFail; + } } bool GetResultItems( @@ -28,107 +33,112 @@ namespace smoke_api::steam_inventory { uint32_t* punOutItemsArraySize, const std::function& original_function, const std::function& get_item_definition_ids - ) { - static std::mutex section; - const std::lock_guard guard(section); + ) noexcept { + try { + static std::mutex section; + const std::lock_guard guard(section); - const auto success = original_function(); + const auto success = original_function(); - auto print_item = [](const std::string& tag, const SteamItemDetails_t& item) { - LOG_DEBUG( - " [{}] definitionId: {}, itemId: {}, quantity: {}, flags: {}", - tag, - item.m_iDefinition, - item.m_itemId, - item.m_unQuantity, - item.m_unFlags - ); - }; - - if(not success) { - LOG_DEBUG("{} -> original result is false", function_name); - return success; - } - - if(punOutItemsArraySize == nullptr) { - LOG_ERROR("{} -> arraySize pointer is null", function_name); - return success; - } - - LOG_DEBUG( - "{} -> handle: {}, pOutItemsArray: {}, arraySize: {}", - function_name, - resultHandle, - reinterpret_cast(pOutItemsArray), - *punOutItemsArraySize - ); - - static uint32_t original_count = 0; - const auto injected_count = config::instance.extra_inventory_items.size(); - - // Automatically get inventory items from steam - static std::vector auto_inventory_items; - if(config::instance.auto_inject_inventory) { - static std::once_flag inventory_inject_flag; - std::call_once( - inventory_inject_flag, - [&] { - uint32_t count = 0; - if(get_item_definition_ids(nullptr, &count)) { - auto_inventory_items.resize(count); - get_item_definition_ids(auto_inventory_items.data(), &count); - } - } - ); - } - - const auto auto_injected_count = auto_inventory_items.size(); - - if(not pOutItemsArray) { - // If pOutItemsArray is NULL then we must set the array size. - original_count = *punOutItemsArraySize; - *punOutItemsArraySize += auto_injected_count + injected_count; - LOG_DEBUG( - "{} -> Original count: {}, Total count: {}", - function_name, - original_count, - *punOutItemsArraySize - ); - } else { - // Otherwise, we modify the array - for(int i = 0; i < original_count; i++) { - print_item("original", pOutItemsArray[i]); - } - - static auto new_item = [](SteamItemDef_t id) { - return SteamItemDetails_t{ - .m_itemId = id, - .m_iDefinition = id, - .m_unQuantity = 1, - .m_unFlags = 0, - }; + auto print_item = [](const std::string& tag, const SteamItemDetails_t& item) { + LOG_DEBUG( + " [{}] definitionId: {}, itemId: {}, quantity: {}, flags: {}", + tag, + item.m_iDefinition, + item.m_itemId, + item.m_unQuantity, + item.m_unFlags + ); }; - for(int i = 0; i < auto_injected_count; i++) { - auto& item = pOutItemsArray[original_count + i]; - const auto item_def_id = auto_inventory_items[i]; - - item = new_item(item_def_id); - - print_item("auto-injected", item); + if(not success) { + LOG_DEBUG("{} -> original result is false", function_name); + return success; } - for(int i = 0; i < injected_count; i++) { - auto& item = pOutItemsArray[original_count + auto_injected_count + i]; - const auto item_def_id = config::instance.extra_inventory_items[i]; - - item = new_item(item_def_id); - - print_item("injected", item); + if(punOutItemsArraySize == nullptr) { + LOG_ERROR("{} -> arraySize pointer is null", function_name); + return success; } + + LOG_DEBUG( + "{} -> handle: {}, pOutItemsArray: {}, arraySize: {}", + function_name, + resultHandle, + reinterpret_cast(pOutItemsArray), + *punOutItemsArraySize + ); + + static uint32_t original_count = 0; + const auto injected_count = config::instance.extra_inventory_items.size(); + + // Automatically get inventory items from steam + static std::vector auto_inventory_items; + if(config::instance.auto_inject_inventory) { + static std::once_flag inventory_inject_flag; + std::call_once( + inventory_inject_flag, + [&] { + uint32_t count = 0; + if(get_item_definition_ids(nullptr, &count)) { + auto_inventory_items.resize(count); + get_item_definition_ids(auto_inventory_items.data(), &count); + } + } + ); + } + + const auto auto_injected_count = auto_inventory_items.size(); + + if(not pOutItemsArray) { + // If pOutItemsArray is NULL then we must set the array size. + original_count = *punOutItemsArraySize; + *punOutItemsArraySize += auto_injected_count + injected_count; + LOG_DEBUG( + "{} -> Original count: {}, Total count: {}", + function_name, + original_count, + *punOutItemsArraySize + ); + } else { + // Otherwise, we modify the array + for(int i = 0; i < original_count; i++) { + print_item("original", pOutItemsArray[i]); + } + + static auto new_item = [](SteamItemDef_t id) { + return SteamItemDetails_t{ + .m_itemId = id, + .m_iDefinition = id, + .m_unQuantity = 1, + .m_unFlags = 0, + }; + }; + + for(int i = 0; i < auto_injected_count; i++) { + auto& item = pOutItemsArray[original_count + i]; + const auto item_def_id = auto_inventory_items[i]; + + item = new_item(item_def_id); + + print_item("auto-injected", item); + } + + for(int i = 0; i < injected_count; i++) { + auto& item = pOutItemsArray[original_count + auto_injected_count + i]; + const auto item_def_id = config::instance.extra_inventory_items[i]; + + item = new_item(item_def_id); + + print_item("injected", item); + } + } + + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return false; } - - return success; } bool GetResultItemProperty( @@ -139,47 +149,61 @@ namespace smoke_api::steam_inventory { const char* pchValueBuffer, const uint32_t* punValueBufferSizeOut, const std::function& original_function - ) { - LOG_DEBUG( - "{} -> Handle: {}, Index: {}, Name: '{}'", - function_name, - resultHandle, - unItemIndex, - // can be empty, in which case steam responds with property list in csv format - pchPropertyName ? pchPropertyName : "nullptr" - ); + ) noexcept { + try { + LOG_DEBUG( + "{} -> Handle: {}, Index: {}, Name: '{}'", + function_name, + resultHandle, + unItemIndex, + // can be empty, in which case steam responds with property list in csv format + pchPropertyName ? pchPropertyName : "nullptr" + ); - const auto success = original_function(); + const auto success = original_function(); - if(!success) { - LOG_WARN("{} -> Result is false", function_name); + if(!success) { + LOG_WARN("{} -> Result is false", function_name); + return false; + } + + if( + pchValueBuffer && *pchValueBuffer && + punValueBufferSizeOut && *punValueBufferSizeOut > 0 + ) { + LOG_DEBUG( + R"({} -> Buffer: "{}")", + function_name, + std::string(pchValueBuffer, *punValueBufferSizeOut - 1) + ); + } + + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); return false; } - - if( - pchValueBuffer && *pchValueBuffer && - punValueBufferSizeOut && *punValueBufferSizeOut > 0 - ) { - LOG_DEBUG( - R"({} -> Buffer: "{}")", - function_name, - std::string(pchValueBuffer, *punValueBufferSizeOut - 1) - ); - } - - return success; } bool GetAllItems( const std::string& function_name, const SteamInventoryResult_t* pResultHandle, const std::function& original_function - ) { - const auto success = original_function(); + ) noexcept { + try { + const auto success = original_function(); - LOG_DEBUG("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle)); + LOG_DEBUG( + "{} -> Handle: {}", + function_name, + reinterpret_cast(pResultHandle) + ); - return success; + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return false; + } } bool GetItemsByID( @@ -188,18 +212,23 @@ namespace smoke_api::steam_inventory { const SteamItemInstanceID_t* pInstanceIDs, const uint32_t unCountInstanceIDs, const std::function& original_function - ) { - const auto success = original_function(); + ) noexcept { + try { + const auto success = original_function(); - LOG_DEBUG("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle)); + LOG_DEBUG("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle)); - if(success && pInstanceIDs != nullptr) { - for(int i = 0; i < unCountInstanceIDs; i++) { - LOG_DEBUG(" Index: {}, ItemId: {}", i, pInstanceIDs[i]); + if(success && pInstanceIDs != nullptr) { + for(int i = 0; i < unCountInstanceIDs; i++) { + LOG_DEBUG(" Index: {}, ItemId: {}", i, pInstanceIDs[i]); + } } - } - return success; + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return false; + } } bool SerializeResult( @@ -208,22 +237,27 @@ namespace smoke_api::steam_inventory { void* pOutBuffer, uint32_t* punOutBufferSize, const std::function& original_function - ) { - const auto success = original_function(); + ) noexcept { + try { + const auto success = original_function(); - if(pOutBuffer != nullptr) { - std::string buffer(static_cast(pOutBuffer), *punOutBufferSize); - LOG_DEBUG("{} -> Handle: {}, Buffer: '{}'", function_name, resultHandle, buffer); - } else { - LOG_DEBUG( - "{} -> Handle: {}, Size: '{}'", - function_name, - resultHandle, - *punOutBufferSize - ); + if(pOutBuffer != nullptr) { + std::string buffer(static_cast(pOutBuffer), *punOutBufferSize); + LOG_DEBUG("{} -> Handle: {}, Buffer: '{}'", function_name, resultHandle, buffer); + } else { + LOG_DEBUG( + "{} -> Handle: {}, Size: '{}'", + function_name, + resultHandle, + *punOutBufferSize + ); + } + + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return false; } - - return success; } bool GetItemDefinitionIDs( @@ -231,28 +265,33 @@ namespace smoke_api::steam_inventory { const SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize, const std::function& original_function - ) { - const auto success = original_function(); + ) noexcept { + try { + const auto success = original_function(); - if(!success) { - LOG_WARN("{} -> Result is false", function_name); + if(!success) { + LOG_WARN("{} -> Result is false", function_name); + return false; + } + + if(punItemDefIDsArraySize) { + LOG_DEBUG("{} -> Size: {}", function_name, *punItemDefIDsArraySize); + } else { + return success; + } + + if(pItemDefIDs) { // Definitions were copied + for(int i = 0; i < *punItemDefIDsArraySize; i++) { + const auto& def = pItemDefIDs[i]; + LOG_DEBUG(" Index: {}, ID: {}", i, def); + } + } + + return success; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); return false; } - - if(punItemDefIDsArraySize) { - LOG_DEBUG("{} -> Size: {}", function_name, *punItemDefIDsArraySize); - } else { - return success; - } - - if(pItemDefIDs) { // Definitions were copied - for(int i = 0; i < *punItemDefIDsArraySize; i++) { - const auto& def = pItemDefIDs[i]; - LOG_DEBUG(" Index: {}, ID: {}", i, def); - } - } - - return success; } bool CheckResultSteamID( @@ -260,17 +299,22 @@ namespace smoke_api::steam_inventory { SteamInventoryResult_t resultHandle, CSteamID steamIDExpected, const std::function& original_function - ) { - const auto result = original_function(); + ) noexcept { + try { + const auto result = original_function(); - LOG_DEBUG( - "{} -> handle: {}, steamID: {}, original result: {}", - function_name, - resultHandle, - steamIDExpected, - result - ); + LOG_DEBUG( + "{} -> handle: {}, steamID: {}, original result: {}", + function_name, + resultHandle, + steamIDExpected, + result + ); - return true; + return true; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return false; + } } } diff --git a/static/smoke_api/interfaces/steam_inventory.hpp b/static/smoke_api/interfaces/steam_inventory.hpp index cbaf351..2eec034 100644 --- a/static/smoke_api/interfaces/steam_inventory.hpp +++ b/static/smoke_api/interfaces/steam_inventory.hpp @@ -7,7 +7,7 @@ namespace smoke_api::steam_inventory { const std::string& function_name, SteamInventoryResult_t resultHandle, const std::function& original_function - ); + ) noexcept; bool GetResultItems( const std::string& function_name, @@ -16,7 +16,7 @@ namespace smoke_api::steam_inventory { uint32_t* punOutItemsArraySize, const std::function& original_function, const std::function& get_item_definition_ids - ); + ) noexcept; bool GetResultItemProperty( const std::string& function_name, @@ -26,13 +26,13 @@ namespace smoke_api::steam_inventory { const char* pchValueBuffer, const uint32_t* punValueBufferSizeOut, const std::function& original_function - ); + ) noexcept; bool GetAllItems( const std::string& function_name, const SteamInventoryResult_t* pResultHandle, const std::function& original_function - ); + ) noexcept; bool GetItemsByID( const std::string& function_name, @@ -40,7 +40,7 @@ namespace smoke_api::steam_inventory { const SteamItemInstanceID_t* pInstanceIDs, uint32_t unCountInstanceIDs, const std::function& original_function - ); + ) noexcept; bool SerializeResult( const std::string& function_name, @@ -48,19 +48,19 @@ namespace smoke_api::steam_inventory { void* pOutBuffer, uint32_t* punOutBufferSize, const std::function& original_function - ); + ) noexcept; bool GetItemDefinitionIDs( const std::string& function_name, const SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize, const std::function& original_function - ); + ) noexcept; bool CheckResultSteamID( const std::string& function_name, SteamInventoryResult_t resultHandle, CSteamID steamIDExpected, const std::function& original_function - ); + ) noexcept; } diff --git a/static/smoke_api/interfaces/steam_user.cpp b/static/smoke_api/interfaces/steam_user.cpp index 5a0c1c0..5bd80dd 100644 --- a/static/smoke_api/interfaces/steam_user.cpp +++ b/static/smoke_api/interfaces/steam_user.cpp @@ -9,26 +9,31 @@ namespace smoke_api::steam_user { const AppId_t appId, const AppId_t dlcId, const std::function& original_function - ) { - const auto result = original_function(); + ) noexcept { + try { + const auto result = original_function(); - if(result == k_EUserHasLicenseResultNoAuth) { - LOG_WARN("{} -> App ID: {:>8}, Result: NoAuth", function_name, dlcId); - return result; - } - - const auto has_license = config::is_dlc_unlocked( - appId, - dlcId, - [&] { - return result == k_EUserHasLicenseResultHasLicense; + if(result == k_EUserHasLicenseResultNoAuth) { + LOG_WARN("{} -> App ID: {:>8}, Result: NoAuth", function_name, dlcId); + return result; } - ); - LOG_INFO("{} -> App ID: {:>8}, HasLicense: {}", function_name, dlcId, has_license); + const auto has_license = config::is_dlc_unlocked( + appId, + dlcId, + [&] { + return result == k_EUserHasLicenseResultHasLicense; + } + ); - return has_license - ? k_EUserHasLicenseResultHasLicense - : k_EUserHasLicenseResultDoesNotHaveLicense; + LOG_INFO("{} -> App ID: {:>8}, HasLicense: {}", function_name, dlcId, has_license); + + return has_license + ? k_EUserHasLicenseResultHasLicense + : k_EUserHasLicenseResultDoesNotHaveLicense; + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", function_name, e.what()); + return k_EUserHasLicenseResultDoesNotHaveLicense; + } } } diff --git a/static/smoke_api/interfaces/steam_user.hpp b/static/smoke_api/interfaces/steam_user.hpp index 57b790e..8ce5165 100644 --- a/static/smoke_api/interfaces/steam_user.hpp +++ b/static/smoke_api/interfaces/steam_user.hpp @@ -8,5 +8,5 @@ namespace smoke_api::steam_user { AppId_t appId, AppId_t dlcId, const std::function& original_function - ); + ) noexcept; } diff --git a/static/smoke_api/types.hpp b/static/smoke_api/types.hpp index fc671d2..2097c40 100644 --- a/static/smoke_api/types.hpp +++ b/static/smoke_api/types.hpp @@ -14,11 +14,15 @@ // These macros are meant to be used for callbacks that should return original result #define HOOKED_CALL(FUNC, ...) \ -static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(FUNC); \ -return _##FUNC(__VA_ARGS__) + static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(FUNC); \ + return _##FUNC(__VA_ARGS__) #define HOOKED_CALL_CLOSURE(FUNC, ...) \ -[&] { HOOKED_CALL(FUNC, __VA_ARGS__); } + [&] { HOOKED_CALL(FUNC, __VA_ARGS__); } + +#define HOOKED_CALL_RESULT(FUNC, ...) \ + static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(FUNC); \ + const auto result = _##FUNC(__VA_ARGS__) /** * By default, virtual functions are declared with __thiscall @@ -55,12 +59,19 @@ return _##FUNC(__VA_ARGS__) using AppId_t = uint32_t; using HSteamPipe = uint32_t; -using EResult = uint32_t; using HSteamUser = uint32_t; using SteamInventoryResult_t = uint32_t; using SteamItemInstanceID_t = uint64_t; using SteamItemDef_t = uint32_t; using CSteamID = uint64_t; +using HTTPRequestHandle = uint32_t; + +enum class EResult { + k_EResultNone = 0, + k_EResultOK = 1, + k_EResultFail = 2, + // See all at steamclientpublic.h +}; struct SteamItemDetails_t { SteamItemInstanceID_t m_itemId; @@ -71,10 +82,12 @@ struct SteamItemDetails_t { // results from UserHasLicenseForApp enum EUserHasLicenseForAppResult { - k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app - k_EUserHasLicenseResultDoesNotHaveLicense = 1, + // User has a license for specified app + k_EUserHasLicenseResultHasLicense = 0, // User does not have a license for the specified app - k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated + k_EUserHasLicenseResultDoesNotHaveLicense = 1, + // User has not been authenticated + k_EUserHasLicenseResultNoAuth = 2, }; // These aliases exist solely to increase code readability @@ -87,7 +100,7 @@ using DlcNameMap = std::map; struct App { DlcNameMap dlcs; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(App, dlcs) // NOLINT(misc-const-correctness) + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(App, dlcs) }; using AppDlcNameMap = std::map; @@ -98,6 +111,8 @@ class DLC { std::string name; public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(DLC, appid, name) + explicit DLC() = default; explicit DLC(std::string appid, std::string name) : appid{std::move(appid)}, @@ -115,8 +130,6 @@ public: return name; } - NLOHMANN_DEFINE_TYPE_INTRUSIVE(DLC, appid, name) - static std::vector get_dlcs_from_apps(const AppDlcNameMap& apps, AppId_t app_id); static DlcNameMap get_dlc_map_from_vector(const std::vector& dlcs);