From 0b58d406dd4065e115c35e2a225024bc6c945a5c Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 30 Sep 2022 19:19:58 +0200 Subject: [PATCH] Add ugc support --- src/client/component/steam_proxy.cpp | 88 +++++++++++++++++++++++++++- src/client/component/steam_proxy.hpp | 14 +++++ src/client/steam/interfaces/ugc.cpp | 61 +++++++++++++++++-- src/client/steam/interfaces/ugc.hpp | 1 + 4 files changed, 159 insertions(+), 5 deletions(-) diff --git a/src/client/component/steam_proxy.cpp b/src/client/component/steam_proxy.cpp index 13d38bc0..133525e5 100644 --- a/src/client/component/steam_proxy.cpp +++ b/src/client/component/steam_proxy.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include "resource.hpp" @@ -45,6 +47,7 @@ namespace steam_proxy }*/ this->load_client(); + update_subscribed_items(); this->clean_up_on_error(); } @@ -103,6 +106,73 @@ namespace steam_proxy return this->client_friends_.invoke("GetPersonaName"); } + void update_subscribed_items() + { + subscribed_item_map map{}; + + const auto _ = utils::finally([&] + { + this->subscribed_items_.access([&](subscribed_item_map& items) + { + items = std::move(map); + }); + }); + + if (!this->client_ugc_) + { + return; + } + + try + { + const auto app_id = steam::SteamUtils()->GetAppID(); + const auto num_items = this->client_ugc_.invoke("GetNumSubscribedItems", app_id); + + if (!num_items) + { + return; + } + + std::vector ids; + ids.resize(num_items); + + auto result = this->client_ugc_.invoke("GetSubscribedItems", app_id, ids.data(), + num_items); + result = std::min(num_items, result); + + for (uint32_t i = 0; i < result; ++i) + { + char buffer[0x1000] = {0}; + subscribed_item item{}; + + item.state = this->client_ugc_.invoke("GetItemState", app_id, ids[i]); + item.available = this->client_ugc_.invoke("GetItemInstallInfo", app_id, ids[i], + &item.size_on_disk, + buffer, + sizeof(buffer), &item.time_stamp); + item.path = buffer; + + map[ids[i]] = std::move(item); + } + } + catch (std::exception& e) + { + OutputDebugStringA(e.what()); + this->client_ugc_ = {}; + } + catch (...) + { + OutputDebugStringA("Unk exc"); + this->client_ugc_ = {}; + } + } + + void access_subscribed_items( + const std::function& callback) + { + this->subscribed_items_.access(callback); + } + private: utils::nt::library steam_client_module_{}; utils::nt::library steam_overlay_module_{}; @@ -111,6 +181,9 @@ namespace steam_proxy steam::interface client_user_{}; steam::interface client_utils_{}; steam::interface client_friends_{}; + steam::interface client_ugc_{}; + + utils::concurrency::container subscribed_items_; void* steam_pipe_ = nullptr; void* global_user_ = nullptr; @@ -150,7 +223,10 @@ namespace steam_proxy this->client_user_ = this->client_engine_.invoke(8, this->global_user_, this->steam_pipe_); // GetIClientUser this->client_utils_ = this->client_engine_.invoke(14, this->steam_pipe_); // GetIClientUtils - this->client_friends_ = this->client_engine_.invoke(13, this->global_user_, this->steam_pipe_); // GetIClientFriends + this->client_friends_ = this->client_engine_.invoke(13, this->global_user_, this->steam_pipe_); + // GetIClientFriends + this->client_ugc_ = this->client_engine_.invoke(61, this->global_user_, this->steam_pipe_); + // GetIClientUGC } ownership_state start_mod(const std::string& title, const size_t app_id) @@ -249,6 +325,16 @@ namespace steam_proxy static std::string name = component_loader::get()->get_player_name(); return name.data(); } + + void update_subscribed_items() + { + component_loader::get()->update_subscribed_items(); + } + + void access_subscribed_items(const std::function& callback) + { + component_loader::get()->access_subscribed_items(callback); + } } REGISTER_COMPONENT(steam_proxy::component) diff --git a/src/client/component/steam_proxy.hpp b/src/client/component/steam_proxy.hpp index c5787cd1..b9709aab 100644 --- a/src/client/component/steam_proxy.hpp +++ b/src/client/component/steam_proxy.hpp @@ -5,4 +5,18 @@ namespace steam_proxy { const utils::nt::library& get_overlay_module(); const char* get_player_name(); + + struct subscribed_item + { + bool available; + std::string path; + uint32_t state; + uint32_t time_stamp; + uint64_t size_on_disk; + }; + + using subscribed_item_map = std::unordered_map; + + void update_subscribed_items(); + void access_subscribed_items(const std::function& callback); } diff --git a/src/client/steam/interfaces/ugc.cpp b/src/client/steam/interfaces/ugc.cpp index bc72abbd..eaacb52a 100644 --- a/src/client/steam/interfaces/ugc.cpp +++ b/src/client/steam/interfaces/ugc.cpp @@ -1,6 +1,6 @@ #include #include "../steam.hpp" - +#include "component/steam_proxy.hpp" namespace steam { @@ -294,20 +294,73 @@ namespace steam return 0; } + uint32_t ugc::GetNumSubscribedItems() + { + ::steam_proxy::update_subscribed_items(); + + uint32_t count = 0; + ::steam_proxy::access_subscribed_items([&](const steam_proxy::subscribed_item_map& items) + { + count = static_cast(items.size()); + }); + + return count; + } + uint32_t ugc::GetSubscribedItems(uint64_t* pvecPublishedFileID, uint32_t cMaxEntries) { - return 0; + uint32_t count = 0; + ::steam_proxy::access_subscribed_items([&](const steam_proxy::subscribed_item_map& items) + { + for (const auto& item : items) + { + if (count < cMaxEntries) + { + pvecPublishedFileID[count] = item.first; + ++count; + } + } + }); + + return count; } uint32_t ugc::GetItemState(uint64_t nPublishedFileID) { - return 0; + uint32_t state = 0; + ::steam_proxy::access_subscribed_items([&](const steam_proxy::subscribed_item_map& items) + { + const auto entry = items.find(nPublishedFileID); + if (entry != items.end()) + { + state = entry->second.state; + } + }); + + return state; } bool ugc::GetItemInstallInfo(uint64_t nPublishedFileID, uint64_t* punSizeOnDisk, char* pchFolder, uint32_t cchFolderSize, uint32_t* punTimeStamp) { - return false; + bool found = false; + ::steam_proxy::access_subscribed_items([&](const steam_proxy::subscribed_item_map& items) + { + const auto entry = items.find(nPublishedFileID); + if (entry != items.end()) + { + const auto& item = entry->second; + found = item.available; + memcpy(pchFolder, item.path.data(), + std::min(item.path.size() + 1, static_cast(cchFolderSize))); + pchFolder[cchFolderSize - 1] = 0; + + *punSizeOnDisk = item.size_on_disk; + *punTimeStamp = item.time_stamp; + } + }); + + return found; } bool ugc::GetItemDownloadInfo(uint64_t nPublishedFileID, uint64_t* punBytesDownloaded, diff --git a/src/client/steam/interfaces/ugc.hpp b/src/client/steam/interfaces/ugc.hpp index 478c5714..a483d4ff 100644 --- a/src/client/steam/interfaces/ugc.hpp +++ b/src/client/steam/interfaces/ugc.hpp @@ -95,6 +95,7 @@ namespace steam virtual uint64_t SubscribeItem(uint64_t nPublishedFileID); virtual uint64_t UnsubscribeItem(uint64_t nPublishedFileID); + virtual uint32_t GetNumSubscribedItems(); virtual uint32_t GetSubscribedItems(uint64_t* pvecPublishedFileID, uint32_t cMaxEntries); virtual uint32_t GetItemState(uint64_t nPublishedFileID);