mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2026-01-24 21:42:53 -05:00
Compare commits
9 Commits
v2.0.0-rc0
...
v2.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9f477898c | ||
|
|
3c707f2474 | ||
|
|
e1987515d8 | ||
|
|
feb212e841 | ||
|
|
98c61f6e46 | ||
|
|
6b9cb115c3 | ||
|
|
73a05f1d91 | ||
|
|
95ceac3d47 | ||
|
|
aa23be373d |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -4,7 +4,7 @@ on: push
|
|||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
name: CI
|
name: CI
|
||||||
uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@15d5cfc2e515bc72e47da6c0c563820cff98551f
|
uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@acac7a4450414784f441dc55c52758f550f182ab
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.24)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
|
||||||
project(SmokeAPI VERSION 2.0.0)
|
project(SmokeAPI VERSION 2.0.3)
|
||||||
|
|
||||||
include(KoalaBox/cmake/KoalaBox.cmake)
|
include(KoalaBox/cmake/KoalaBox.cmake)
|
||||||
|
|
||||||
|
|||||||
2
KoalaBox
2
KoalaBox
Submodule KoalaBox updated: fe45f9c61c...acac7a4450
@@ -61,7 +61,7 @@ Usage of this unlocker entails breaking one or more terms of service, which migh
|
|||||||
SmokeAPI supports 2 main modes of installation: *Store* mode and *Game* mode, which are described in the next section.
|
SmokeAPI supports 2 main modes of installation: *Store* mode and *Game* mode, which are described in the next section.
|
||||||
|
|
||||||
NOTE: It is worth noting that the following instructions describe a _manual_ installation method.
|
NOTE: It is worth noting that the following instructions describe a _manual_ installation method.
|
||||||
You can benefit from _automatic_ installation and GUI configuration by using Koalageddon v2 (Coming soon).
|
You can benefit from _automatic_ installation and GUI configuration by using https://github.com/acidicoala/Koalageddon2#readme[Koalageddon v2].
|
||||||
|
|
||||||
=== 🛍️ Store mode
|
=== 🛍️ Store mode
|
||||||
|
|
||||||
@@ -140,7 +140,8 @@ The configuration file is expected to conform to the Json standard.
|
|||||||
Type::: Boolean
|
Type::: Boolean
|
||||||
Default::: `false`
|
Default::: `false`
|
||||||
|
|
||||||
`unlock_family_sharing`:: Toggles Family Sharing bypass, which enables the borrower of a shared library to start and continue playing games when library owner is playing as well.
|
`unlock_family_sharing`:: *_Store mode only_*.
|
||||||
|
Toggles Family Sharing bypass, which enables the borrower of a shared library to start and continue playing games when library owner is playing as well.
|
||||||
+
|
+
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Type::: Boolean
|
Type::: Boolean
|
||||||
@@ -203,7 +204,8 @@ The format is the same as in the aforementioned GitHub config.
|
|||||||
Type::: Object (Map of String to Object)
|
Type::: Object (Map of String to Object)
|
||||||
Default::: `{}`
|
Default::: `{}`
|
||||||
|
|
||||||
`store_config`:: An object that specifies offsets required for store mode operation.
|
`store_config`:: *_Store mode only_*.
|
||||||
|
An object that specifies offsets required for store mode operation.
|
||||||
It will override the config fetched from {steam_config}[remote source] or local cache.
|
It will override the config fetched from {steam_config}[remote source] or local cache.
|
||||||
Do not modify this value unless you know what you are doing.
|
Do not modify this value unless you know what you are doing.
|
||||||
+
|
+
|
||||||
|
|||||||
@@ -7,12 +7,9 @@ constexpr auto KEY_APPS = "apps";
|
|||||||
|
|
||||||
AppDlcNameMap get_cached_apps() noexcept {
|
AppDlcNameMap get_cached_apps() noexcept {
|
||||||
try {
|
try {
|
||||||
const auto cache = koalabox::cache::read_from_cache(KEY_APPS);
|
return koalabox::cache::get(KEY_APPS).get<AppDlcNameMap>();
|
||||||
|
|
||||||
return cache.get<AppDlcNameMap>();
|
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_WARN("Failed to get cached apps: {}", e.what())
|
LOG_WARN("Failed to get cached apps: {}", e.what())
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +38,7 @@ namespace smoke_api::app_cache {
|
|||||||
|
|
||||||
apps[std::to_string(app_id)] = App{.dlcs=DLC::get_dlc_map_from_vector(dlcs)};
|
apps[std::to_string(app_id)] = App{.dlcs=DLC::get_dlc_map_from_vector(dlcs)};
|
||||||
|
|
||||||
return koalabox::cache::save_to_cache(KEY_APPS, Json(apps));
|
return koalabox::cache::put(KEY_APPS, Json(apps));
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_ERROR("Error saving DLCs to disk cache: {}", e.what())
|
LOG_ERROR("Error saving DLCs to disk cache: {}", e.what())
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace api {
|
|||||||
try {
|
try {
|
||||||
const auto* url =
|
const auto* url =
|
||||||
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/dlc.json";
|
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/dlc.json";
|
||||||
const auto json = koalabox::http_client::fetch_json(url);
|
const auto json = koalabox::http_client::get_json(url);
|
||||||
const auto response = json.get<AppDlcNameMap>();
|
const auto response = json.get<AppDlcNameMap>();
|
||||||
|
|
||||||
return DLC::get_dlcs_from_apps(response, app_id);
|
return DLC::get_dlcs_from_apps(response, app_id);
|
||||||
@@ -27,8 +27,10 @@ namespace api {
|
|||||||
|
|
||||||
std::optional<Vector<DLC>> fetch_dlcs_from_steam(AppId_t app_id) noexcept {
|
std::optional<Vector<DLC>> fetch_dlcs_from_steam(AppId_t app_id) noexcept {
|
||||||
try {
|
try {
|
||||||
const auto url = fmt::format("https://store_mode.steampowered.com/dlc/{}/ajaxgetdlclist", app_id);
|
// TODO: Communicate directly with Steam servers.
|
||||||
const auto json = koalabox::http_client::fetch_json(url);
|
// ref.: https://github.com/SteamRE/SteamKit
|
||||||
|
const auto url = fmt::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id);
|
||||||
|
const auto json = koalabox::http_client::get_json(url);
|
||||||
|
|
||||||
const auto response = json.get<SteamResponse>();
|
const auto response = json.get<SteamResponse>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
#include <core/globals.hpp>
|
|
||||||
|
|
||||||
namespace globals {
|
namespace globals {
|
||||||
|
|
||||||
HMODULE smokeapi_handle = nullptr;
|
HMODULE smokeapi_handle = nullptr;
|
||||||
HMODULE steamapi_module = nullptr;
|
HMODULE steamapi_module = nullptr;
|
||||||
HMODULE vstdlib_module = nullptr;
|
HMODULE vstdlib_module = nullptr;
|
||||||
HMODULE steamclient_module = nullptr;
|
HMODULE steamclient_module = nullptr;
|
||||||
Map<String, uintptr_t> address_map; // NOLINT(cert-err58-cpp)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ namespace globals {
|
|||||||
extern HMODULE steamclient_module;
|
extern HMODULE steamclient_module;
|
||||||
extern HMODULE steamapi_module;
|
extern HMODULE steamapi_module;
|
||||||
extern HMODULE vstdlib_module;
|
extern HMODULE vstdlib_module;
|
||||||
extern Map<String, uintptr_t> address_map;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <core/globals.hpp>
|
#include <core/globals.hpp>
|
||||||
#include <koalabox/loader.hpp>
|
#include <koalabox/loader.hpp>
|
||||||
|
|
||||||
|
// TODO: Refactor to KoalaBox
|
||||||
namespace paths {
|
namespace paths {
|
||||||
|
|
||||||
Path get_self_path() {
|
Path get_self_path() {
|
||||||
|
|||||||
@@ -45,17 +45,17 @@
|
|||||||
#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall
|
#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall
|
||||||
|
|
||||||
#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \
|
#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \
|
||||||
static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(globals::address_map, #FUNC, FUNC);
|
static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(#FUNC, FUNC);
|
||||||
|
|
||||||
#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \
|
#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \
|
||||||
static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC);
|
static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC);
|
||||||
|
|
||||||
|
|
||||||
#define DETOUR_ADDRESS(FUNC, ADDRESS) \
|
#define DETOUR_ADDRESS(FUNC, ADDRESS) \
|
||||||
koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast<uintptr_t>(FUNC));
|
koalabox::hook::detour_or_warn(ADDRESS, #FUNC, reinterpret_cast<uintptr_t>(FUNC));
|
||||||
|
|
||||||
#define $DETOUR(FUNC, NAME, MODULE_HANDLE) \
|
#define $DETOUR(FUNC, NAME, MODULE_HANDLE) \
|
||||||
koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, NAME, reinterpret_cast<uintptr_t>(FUNC));
|
koalabox::hook::detour_or_warn(MODULE_HANDLE, NAME, reinterpret_cast<uintptr_t>(FUNC));
|
||||||
|
|
||||||
#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, #FUNC, globals::steamclient_module)
|
#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, #FUNC, globals::steamclient_module)
|
||||||
#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
|
#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
|
||||||
|
|||||||
@@ -8,33 +8,51 @@
|
|||||||
// ISteamApps
|
// ISteamApps
|
||||||
|
|
||||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) {
|
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) {
|
||||||
return steam_apps::IsDlcUnlocked(
|
try {
|
||||||
__func__, 0, dlcID, [&]() {
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp)
|
return steam_apps::IsDlcUnlocked(
|
||||||
|
__func__, app_id, dlcID, [&]() {
|
||||||
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp)
|
||||||
|
|
||||||
return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, dlcID);
|
return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, dlcID);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, AppId_t dlcID) {
|
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, AppId_t dlcID) {
|
||||||
return steam_apps::IsDlcUnlocked(
|
try {
|
||||||
__func__, 0, dlcID, [&]() {
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled)
|
return steam_apps::IsDlcUnlocked(
|
||||||
|
__func__, app_id, dlcID, [&]() {
|
||||||
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled)
|
||||||
|
|
||||||
return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, dlcID);
|
return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, dlcID);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void* self) {
|
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void* self) {
|
||||||
return steam_apps::GetDLCCount(
|
try {
|
||||||
__func__, 0, [&]() {
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount)
|
return steam_apps::GetDLCCount(
|
||||||
|
__func__, app_id, [&]() {
|
||||||
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount)
|
||||||
|
|
||||||
return SteamAPI_ISteamApps_GetDLCCount_o(self);
|
return SteamAPI_ISteamApps_GetDLCCount_o(self);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
|
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
|
||||||
@@ -45,19 +63,24 @@ DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
|
|||||||
char* pchName,
|
char* pchName,
|
||||||
int cchNameBufferSize
|
int cchNameBufferSize
|
||||||
) {
|
) {
|
||||||
return steam_apps::GetDLCDataByIndex(
|
try {
|
||||||
__func__, 0, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize,
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
[&]() {
|
return steam_apps::GetDLCDataByIndex(
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BGetDLCDataByIndex)
|
__func__, app_id, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize,
|
||||||
|
[&]() {
|
||||||
return SteamAPI_ISteamApps_BGetDLCDataByIndex_o(
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BGetDLCDataByIndex)
|
||||||
self, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize
|
return SteamAPI_ISteamApps_BGetDLCDataByIndex_o(
|
||||||
);
|
self, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize
|
||||||
},
|
);
|
||||||
[&](AppId_t dlc_id) {
|
},
|
||||||
return SteamAPI_ISteamApps_BIsDlcInstalled(self, dlc_id);
|
[&](AppId_t dlc_id) {
|
||||||
}
|
return SteamAPI_ISteamApps_BIsDlcInstalled(self, dlc_id);
|
||||||
);
|
}
|
||||||
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISteamClient
|
// ISteamClient
|
||||||
@@ -68,13 +91,17 @@ DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(
|
|||||||
HSteamPipe hSteamPipe,
|
HSteamPipe hSteamPipe,
|
||||||
const char* pchVersion
|
const char* pchVersion
|
||||||
) {
|
) {
|
||||||
return steam_client::GetGenericInterface(
|
try {
|
||||||
__func__, pchVersion, [&]() {
|
return steam_client::GetGenericInterface(
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamClient_GetISteamGenericInterface)
|
__func__, pchVersion, [&]() {
|
||||||
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamClient_GetISteamGenericInterface)
|
||||||
return SteamAPI_ISteamClient_GetISteamGenericInterface_o(self, hSteamUser, hSteamPipe, pchVersion);
|
return SteamAPI_ISteamClient_GetISteamGenericInterface_o(self, hSteamUser, hSteamPipe, pchVersion);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISteamInventory
|
// ISteamInventory
|
||||||
@@ -210,18 +237,18 @@ DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp
|
|||||||
CSteamID steamID,
|
CSteamID steamID,
|
||||||
AppId_t dlcID
|
AppId_t dlcID
|
||||||
) {
|
) {
|
||||||
AppId_t app_id;
|
|
||||||
try {
|
try {
|
||||||
app_id = steam_impl::get_app_id_or_throw();
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
|
return steam_user::UserHasLicenseForApp(
|
||||||
|
__func__, app_id, dlcID, [&]() {
|
||||||
|
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
|
||||||
|
|
||||||
|
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, dlcID);
|
||||||
|
}
|
||||||
|
);
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_ERROR("{} -> Error getting app id: {}", __func__, e.what())
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return k_EUserHasLicenseResultDoesNotHaveLicense;
|
||||||
}
|
}
|
||||||
|
|
||||||
return steam_user::UserHasLicenseForApp(
|
|
||||||
__func__, app_id, dlcID, [&]() {
|
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
|
|
||||||
|
|
||||||
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, dlcID);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,81 @@
|
|||||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||||
|
#include <koalabox/util.hpp>
|
||||||
#include <steam_impl/steam_apps.hpp>
|
#include <steam_impl/steam_apps.hpp>
|
||||||
|
#include <steam_impl/steam_impl.hpp>
|
||||||
|
|
||||||
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t appID)) {
|
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) {
|
||||||
return steam_apps::IsDlcUnlocked(
|
try {
|
||||||
__func__, 0, appID, [&]() {
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsSubscribedApp)
|
return steam_apps::IsDlcUnlocked(
|
||||||
|
__func__, app_id, dlc_id, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BIsSubscribedApp)
|
||||||
|
return ISteamApps_BIsSubscribedApp_o(ARGS(dlc_id));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
|
||||||
return ISteamApps_BIsSubscribedApp_o(ARGS(appID));
|
return false;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t appID)) {
|
VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t dlc_id)) {
|
||||||
return steam_apps::IsDlcUnlocked(
|
try {
|
||||||
__func__, 0, appID, [&]() {
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsDlcInstalled)
|
return steam_apps::IsDlcUnlocked(
|
||||||
|
__func__, app_id, dlc_id, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BIsDlcInstalled)
|
||||||
|
return ISteamApps_BIsDlcInstalled_o(ARGS(dlc_id));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
|
||||||
return ISteamApps_BIsDlcInstalled_o(ARGS(appID));
|
return false;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) {
|
VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) {
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_GetDLCCount)
|
try {
|
||||||
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
|
return steam_apps::GetDLCCount(
|
||||||
|
__func__, app_id, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_GetDLCCount)
|
||||||
|
return ISteamApps_GetDLCCount_o(ARGS());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
|
||||||
return steam_apps::GetDLCCount(
|
return 0;
|
||||||
__func__, 0, [&]() {
|
}
|
||||||
return ISteamApps_GetDLCCount_o(ARGS());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(
|
VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(
|
||||||
PARAMS(
|
PARAMS(
|
||||||
int iDLC,
|
int iDLC,
|
||||||
AppId_t* pAppID,
|
AppId_t* p_dlc_id,
|
||||||
bool* pbAvailable,
|
bool* pbAvailable,
|
||||||
char* pchName,
|
char* pchName,
|
||||||
int cchNameBufferSize
|
int cchNameBufferSize
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_apps::GetDLCDataByIndex(
|
try {
|
||||||
__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize,
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
[&]() {
|
return steam_apps::GetDLCDataByIndex(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex)
|
__func__, app_id, iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize,
|
||||||
|
[&]() {
|
||||||
return ISteamApps_BGetDLCDataByIndex_o(
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex)
|
||||||
ARGS(iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize)
|
return ISteamApps_BGetDLCDataByIndex_o(
|
||||||
);
|
ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize)
|
||||||
},
|
);
|
||||||
[&](AppId_t dlc_id) {
|
},
|
||||||
return ISteamApps_BIsDlcInstalled(ARGS(dlc_id));
|
[&](AppId_t dlc_id) {
|
||||||
}
|
return ISteamApps_BIsDlcInstalled(ARGS(dlc_id));
|
||||||
);
|
}
|
||||||
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,17 @@ VIRTUAL(void*) ISteamClient_GetISteamApps(
|
|||||||
const char* version
|
const char* version
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_client::GetGenericInterface(
|
try {
|
||||||
__func__, version, [&]() {
|
return steam_client::GetGenericInterface(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps)
|
__func__, version, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps)
|
||||||
return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version));
|
return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(void*) ISteamClient_GetISteamUser(
|
VIRTUAL(void*) ISteamClient_GetISteamUser(
|
||||||
@@ -24,13 +28,18 @@ VIRTUAL(void*) ISteamClient_GetISteamUser(
|
|||||||
const char* version
|
const char* version
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_client::GetGenericInterface(
|
try {
|
||||||
__func__, version, [&]() {
|
return steam_client::GetGenericInterface(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser)
|
__func__, version, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser)
|
||||||
|
|
||||||
return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version));
|
return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
|
VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
|
||||||
@@ -40,13 +49,18 @@ VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
|
|||||||
const char* pchVersion
|
const char* pchVersion
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_client::GetGenericInterface(
|
try {
|
||||||
__func__, pchVersion, [&]() {
|
return steam_client::GetGenericInterface(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface)
|
__func__, pchVersion, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface)
|
||||||
|
|
||||||
return ISteamClient_GetISteamGenericInterface_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
return ISteamClient_GetISteamGenericInterface_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(void*) ISteamClient_GetISteamInventory(
|
VIRTUAL(void*) ISteamClient_GetISteamInventory(
|
||||||
@@ -56,11 +70,16 @@ VIRTUAL(void*) ISteamClient_GetISteamInventory(
|
|||||||
const char* pchVersion
|
const char* pchVersion
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_client::GetGenericInterface(
|
try {
|
||||||
__func__, pchVersion, [&]() {
|
return steam_client::GetGenericInterface(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory)
|
__func__, pchVersion, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory)
|
||||||
|
|
||||||
return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,18 @@
|
|||||||
#include <steam_impl/steam_impl.hpp>
|
#include <steam_impl/steam_impl.hpp>
|
||||||
#include <koalabox/logger.hpp>
|
#include <koalabox/logger.hpp>
|
||||||
|
|
||||||
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t dlcID)) {
|
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t dlc_id)) {
|
||||||
AppId_t app_id = 0;
|
|
||||||
try {
|
try {
|
||||||
app_id = steam_impl::get_app_id_or_throw();
|
static const auto app_id = steam_impl::get_app_id_or_throw();
|
||||||
|
return steam_user::UserHasLicenseForApp(
|
||||||
|
__func__, app_id, dlc_id, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
|
||||||
|
|
||||||
|
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, dlc_id));
|
||||||
|
}
|
||||||
|
);
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_ERROR("{} -> Error getting app id: {}", __func__, e.what())
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return k_EUserHasLicenseResultDoesNotHaveLicense;
|
||||||
}
|
}
|
||||||
|
|
||||||
return steam_user::UserHasLicenseForApp(
|
|
||||||
__func__, app_id, dlcID, [&]() {
|
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
|
|
||||||
|
|
||||||
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, dlcID));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
namespace smoke_api::config {
|
namespace smoke_api::config {
|
||||||
Config instance; // NOLINT(cert-err58-cpp)
|
Config instance; // NOLINT(cert-err58-cpp)
|
||||||
|
|
||||||
|
// TODO: Refactor to Koalabox
|
||||||
void init_config() {
|
void init_config() {
|
||||||
const auto path = paths::get_config_path();
|
const auto path = paths::get_config_path();
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,13 @@
|
|||||||
#include <core/globals.hpp>
|
#include <core/globals.hpp>
|
||||||
#include <core/paths.hpp>
|
#include <core/paths.hpp>
|
||||||
#include <common/steamclient_exports.hpp>
|
#include <common/steamclient_exports.hpp>
|
||||||
|
#include <koalabox/globals.hpp>
|
||||||
#include <koalabox/dll_monitor.hpp>
|
#include <koalabox/dll_monitor.hpp>
|
||||||
#include <koalabox/logger.hpp>
|
#include <koalabox/logger.hpp>
|
||||||
#include <koalabox/hook.hpp>
|
#include <koalabox/hook.hpp>
|
||||||
#include <koalabox/cache.hpp>
|
|
||||||
#include <koalabox/loader.hpp>
|
#include <koalabox/loader.hpp>
|
||||||
#include <koalabox/win_util.hpp>
|
#include <koalabox/win_util.hpp>
|
||||||
#include <koalabox/util.hpp>
|
#include <koalabox/util.hpp>
|
||||||
//#include <steam_api_exports/steam_api_exports.hpp>
|
|
||||||
|
|
||||||
#if COMPILE_STORE_MODE
|
#if COMPILE_STORE_MODE
|
||||||
#include <store_mode/store.hpp>
|
#include <store_mode/store.hpp>
|
||||||
@@ -81,6 +80,8 @@ namespace smoke_api {
|
|||||||
try {
|
try {
|
||||||
DisableThreadLibraryCalls(module_handle);
|
DisableThreadLibraryCalls(module_handle);
|
||||||
|
|
||||||
|
koalabox::globals::init_globals(module_handle, PROJECT_NAME);
|
||||||
|
|
||||||
globals::smokeapi_handle = module_handle;
|
globals::smokeapi_handle = module_handle;
|
||||||
|
|
||||||
config::init_config();
|
config::init_config();
|
||||||
@@ -89,12 +90,10 @@ namespace smoke_api {
|
|||||||
koalabox::logger::init_file_logger(paths::get_log_path());
|
koalabox::logger::init_file_logger(paths::get_log_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This kind of timestamp is reliable on for CI builds, as it will reflect the compilation
|
// This kind of timestamp is reliable only for CI builds, as it will reflect the compilation
|
||||||
// time stamp only when this file gets recompiled.
|
// time stamp only when this file gets recompiled.
|
||||||
LOG_INFO("🐨 {} v{} | Compiled at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__)
|
LOG_INFO("🐨 {} v{} | Compiled at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__)
|
||||||
|
|
||||||
koalabox::cache::init_cache(paths::get_cache_path());
|
|
||||||
|
|
||||||
const auto exe_path = Path(koalabox::win_util::get_module_file_name_or_throw(nullptr));
|
const auto exe_path = Path(koalabox::win_util::get_module_file_name_or_throw(nullptr));
|
||||||
const auto exe_name = exe_path.filename().string();
|
const auto exe_name = exe_path.filename().string();
|
||||||
|
|
||||||
|
|||||||
@@ -25,20 +25,13 @@ namespace steam_apps {
|
|||||||
* @return boolean indicating if the function was able to successfully fetch DLC IDs from all sources.
|
* @return boolean indicating if the function was able to successfully fetch DLC IDs from all sources.
|
||||||
*/
|
*/
|
||||||
void fetch_and_cache_dlcs(AppId_t app_id) {
|
void fetch_and_cache_dlcs(AppId_t app_id) {
|
||||||
static std::mutex mutex;
|
static Mutex mutex;
|
||||||
const std::lock_guard<std::mutex> guard(mutex);
|
const MutexLockGuard guard(mutex);
|
||||||
|
|
||||||
if (not app_id) {
|
if (app_id == 0) {
|
||||||
// No app id means we are operating in game mode.
|
LOG_ERROR("{} -> App ID is 0", __func__)
|
||||||
// Hence, we need to use utility functions to get app id.
|
app_dlcs[app_id] = {}; // Dummy value to avoid checking for presence on each access
|
||||||
try {
|
return;
|
||||||
app_id = steam_impl::get_app_id_or_throw();
|
|
||||||
LOG_INFO("Detected App ID: {}", app_id)
|
|
||||||
} catch (const Exception& ex) {
|
|
||||||
LOG_ERROR("Failed to get app ID: {}", ex.what())
|
|
||||||
app_dlcs[app_id] = {}; // Dummy value to avoid checking for presence on each access
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to fetch data only once. However, if any of the remote sources have failed
|
// We want to fetch data only once. However, if any of the remote sources have failed
|
||||||
@@ -75,7 +68,6 @@ namespace steam_apps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache DLCs in memory and cache for future use
|
// Cache DLCs in memory and cache for future use
|
||||||
|
|
||||||
app_dlcs[app_id] = aggregated_dlcs;
|
app_dlcs[app_id] = aggregated_dlcs;
|
||||||
|
|
||||||
smoke_api::app_cache::save_dlcs(app_id, aggregated_dlcs);
|
smoke_api::app_cache::save_dlcs(app_id, aggregated_dlcs);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ namespace steam_apps {
|
|||||||
);
|
);
|
||||||
|
|
||||||
bool GetDLCDataByIndex(
|
bool GetDLCDataByIndex(
|
||||||
const String& dlc_id,
|
const String& function_name,
|
||||||
AppId_t dlc_ids,
|
AppId_t app_id,
|
||||||
int iDLC,
|
int iDLC,
|
||||||
AppId_t* pDlcId,
|
AppId_t* pDlcId,
|
||||||
bool* pbAvailable,
|
bool* pbAvailable,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
#include <ranges>
|
||||||
#include <steam_impl/steam_impl.hpp>
|
#include <steam_impl/steam_impl.hpp>
|
||||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||||
#include <common/steamclient_exports.hpp>
|
#include <common/steamclient_exports.hpp>
|
||||||
#include <core/globals.hpp>
|
|
||||||
#include <build_config.h>
|
#include <build_config.h>
|
||||||
#include <koalabox/util.hpp>
|
#include <koalabox/util.hpp>
|
||||||
#include <koalabox/win_util.hpp>
|
#include <koalabox/win_util.hpp>
|
||||||
@@ -21,7 +21,7 @@ namespace steam_impl {
|
|||||||
{
|
{
|
||||||
{6, 16},
|
{6, 16},
|
||||||
{7, 18},
|
{7, 18},
|
||||||
{8, 15},
|
{8, 15},
|
||||||
{9, 16},
|
{9, 16},
|
||||||
{12, 15},
|
{12, 15},
|
||||||
}
|
}
|
||||||
@@ -114,9 +114,7 @@ namespace steam_impl {
|
|||||||
int get_ordinal(const FunctionOrdinalMap& ordinal_map, const String& function_name, int interface_version) {
|
int get_ordinal(const FunctionOrdinalMap& ordinal_map, const String& function_name, int interface_version) {
|
||||||
const auto& map = ordinal_map.at(function_name);
|
const auto& map = ordinal_map.at(function_name);
|
||||||
|
|
||||||
for (auto it = map.rbegin(); it != map.rend(); it++) {
|
for (auto [version, ordinal]: std::ranges::reverse_view(map)) {
|
||||||
const auto [version, ordinal] = *it;
|
|
||||||
|
|
||||||
if (interface_version >= version) {
|
if (interface_version >= version) {
|
||||||
return ordinal;
|
return ordinal;
|
||||||
}
|
}
|
||||||
@@ -127,7 +125,6 @@ namespace steam_impl {
|
|||||||
|
|
||||||
#define HOOK_VIRTUALS(MAP, FUNC) \
|
#define HOOK_VIRTUALS(MAP, FUNC) \
|
||||||
koalabox::hook::swap_virtual_func( \
|
koalabox::hook::swap_virtual_func( \
|
||||||
globals::address_map, \
|
|
||||||
interface, \
|
interface, \
|
||||||
#FUNC, \
|
#FUNC, \
|
||||||
get_ordinal(MAP, #FUNC, version_number), \
|
get_ordinal(MAP, #FUNC, version_number), \
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
#include <steam_impl/steam_apps.hpp>
|
#include <steam_impl/steam_apps.hpp>
|
||||||
|
|
||||||
VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) {
|
VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) {
|
||||||
return steam_apps::IsDlcUnlocked(
|
try {
|
||||||
__func__, app_id, dlc_id, [&]() {
|
return steam_apps::IsDlcUnlocked(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_IsAppDlcInstalled)
|
__func__, app_id, dlc_id, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_IsAppDlcInstalled)
|
||||||
|
|
||||||
return IClientAppManager_IsAppDlcInstalled_o(ARGS(app_id, dlc_id));
|
return IClientAppManager_IsAppDlcInstalled_o(ARGS(app_id, dlc_id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,18 @@
|
|||||||
#include <steam_impl/steam_apps.hpp>
|
#include <steam_impl/steam_apps.hpp>
|
||||||
|
|
||||||
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
|
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
|
||||||
return steam_apps::GetDLCCount(
|
try {
|
||||||
__func__, appId, [&]() {
|
return steam_apps::GetDLCCount(
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_GetDLCCount)
|
__func__, appId, [&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_GetDLCCount)
|
||||||
|
|
||||||
return IClientApps_GetDLCCount_o(ARGS(appId));
|
return IClientApps_GetDLCCount_o(ARGS(appId));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
||||||
@@ -21,24 +26,29 @@ VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
|||||||
int cchNameBufferSize
|
int cchNameBufferSize
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return steam_apps::GetDLCDataByIndex(
|
try {
|
||||||
__func__, appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize,
|
return steam_apps::GetDLCDataByIndex(
|
||||||
[&]() {
|
__func__, appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize,
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_BGetDLCDataByIndex)
|
[&]() {
|
||||||
|
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_BGetDLCDataByIndex)
|
||||||
|
|
||||||
return IClientApps_BGetDLCDataByIndex_o(
|
return IClientApps_BGetDLCDataByIndex_o(
|
||||||
ARGS(appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize)
|
ARGS(appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[&](AppId_t dlc_id) {
|
[&](AppId_t dlc_id) {
|
||||||
const auto* app_manager_interface = store::steamclient::interface_name_to_address_map["IClientAppManager"];
|
const auto* app_manager_interface = store::steamclient::interface_name_to_address_map["IClientAppManager"];
|
||||||
if (app_manager_interface) {
|
if (app_manager_interface) {
|
||||||
IClientAppManager_IsAppDlcInstalled(app_manager_interface, EDX, appID, dlc_id);
|
IClientAppManager_IsAppDlcInstalled(app_manager_interface, EDX, appID, dlc_id);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Would never happen in practice, as the interfaces would be instantiated almost simultaneously
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
);
|
||||||
// Would never happen in practice, as the interfaces would be instantiated almost simultaneously
|
} catch (const Exception& e) {
|
||||||
return false;
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
}
|
return false;
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,18 @@
|
|||||||
#include <steam_impl/steam_apps.hpp>
|
#include <steam_impl/steam_apps.hpp>
|
||||||
|
|
||||||
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) {
|
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) {
|
||||||
const auto* utils_interface = store::steamclient::interface_name_to_address_map["IClientUtils"];
|
try {
|
||||||
|
const auto* utils_interface = store::steamclient::interface_name_to_address_map["IClientUtils"];
|
||||||
|
|
||||||
const auto app_id = utils_interface ? IClientUtils_GetAppID(utils_interface, EDX) : 0;
|
const auto app_id = utils_interface ? IClientUtils_GetAppID(utils_interface, EDX) : 0;
|
||||||
|
|
||||||
return steam_apps::IsDlcUnlocked(__func__, app_id, dlc_id, [&]() {
|
return steam_apps::IsDlcUnlocked(__func__, app_id, dlc_id, [&]() {
|
||||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp)
|
GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp)
|
||||||
|
|
||||||
return IClientUser_BIsSubscribedApp_o(ARGS(dlc_id));
|
return IClientUser_BIsSubscribedApp_o(ARGS(dlc_id));
|
||||||
});
|
});
|
||||||
|
} catch (const Exception& e) {
|
||||||
|
LOG_ERROR("{} -> Error: {}", __func__, e.what())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ namespace store::steamclient {
|
|||||||
construct_ordinal_map(#INTERFACE, ordinal_map[#INTERFACE], function_selector_address);
|
construct_ordinal_map(#INTERFACE, ordinal_map[#INTERFACE], function_selector_address);
|
||||||
|
|
||||||
#define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \
|
#define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \
|
||||||
globals::address_map, \
|
|
||||||
interface, \
|
interface, \
|
||||||
#INTERFACE"_"#FUNC, \
|
#INTERFACE"_"#FUNC, \
|
||||||
ordinal_map[#INTERFACE][#FUNC], \
|
ordinal_map[#INTERFACE][#FUNC], \
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace store::api {
|
|||||||
try {
|
try {
|
||||||
const String url =
|
const String url =
|
||||||
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/store_config.json";
|
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/store_config.json";
|
||||||
const auto kg_config_json = koalabox::http_client::fetch_json(url);
|
const auto kg_config_json = koalabox::http_client::get_json(url);
|
||||||
|
|
||||||
return kg_config_json.get<StoreConfig>();
|
return kg_config_json.get<StoreConfig>();
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ namespace store::store_cache {
|
|||||||
|
|
||||||
std::optional<StoreConfig> get_store_config() {
|
std::optional<StoreConfig> get_store_config() {
|
||||||
try {
|
try {
|
||||||
const auto config_json = koalabox::cache::read_from_cache(KEY_KG_CONFIG);
|
return koalabox::cache::get(KEY_KG_CONFIG, Json(nullptr)).get<StoreConfig>();
|
||||||
|
|
||||||
return config_json.get<StoreConfig>();
|
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_ERROR("Failed to get cached store_mode config: {}", e.what())
|
LOG_ERROR("Failed to get cached store_mode config: {}", e.what())
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ namespace store::store_cache {
|
|||||||
try {
|
try {
|
||||||
LOG_DEBUG("Caching store_mode config")
|
LOG_DEBUG("Caching store_mode config")
|
||||||
|
|
||||||
return koalabox::cache::save_to_cache(KEY_KG_CONFIG, Json(config));
|
return koalabox::cache::put(KEY_KG_CONFIG, Json(config));
|
||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
LOG_ERROR("Failed to cache store_mode config: {}", e.what())
|
LOG_ERROR("Failed to cache store_mode config: {}", e.what())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user