Add ugc support

This commit is contained in:
momo5502 2022-09-30 19:19:58 +02:00
parent b74dfef65e
commit 0b58d406dd
4 changed files with 159 additions and 5 deletions

View File

@ -6,6 +6,8 @@
#include <utils/nt.hpp>
#include <utils/flags.hpp>
#include <utils/string.hpp>
#include <utils/finally.hpp>
#include <utils/concurrency.hpp>
#include <utils/binary_resource.hpp>
#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<const char*>("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<uint32_t>("GetNumSubscribedItems", app_id);
if (!num_items)
{
return;
}
std::vector<uint64_t> ids;
ids.resize(num_items);
auto result = this->client_ugc_.invoke<uint32_t>("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<uint32_t>("GetItemState", app_id, ids[i]);
item.available = this->client_ugc_.invoke<bool>("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<void(const subscribed_item_map&)>& 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_item_map> subscribed_items_;
void* steam_pipe_ = nullptr;
void* global_user_ = nullptr;
@ -150,7 +223,10 @@ namespace steam_proxy
this->client_user_ = this->client_engine_.invoke<void*>(8, this->global_user_, this->steam_pipe_);
// GetIClientUser
this->client_utils_ = this->client_engine_.invoke<void*>(14, this->steam_pipe_); // GetIClientUtils
this->client_friends_ = this->client_engine_.invoke<void*>(13, this->global_user_, this->steam_pipe_); // GetIClientFriends
this->client_friends_ = this->client_engine_.invoke<void*>(13, this->global_user_, this->steam_pipe_);
// GetIClientFriends
this->client_ugc_ = this->client_engine_.invoke<void*>(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<component>()->get_player_name();
return name.data();
}
void update_subscribed_items()
{
component_loader::get<component>()->update_subscribed_items();
}
void access_subscribed_items(const std::function<void(const subscribed_item_map&)>& callback)
{
component_loader::get<component>()->access_subscribed_items(callback);
}
}
REGISTER_COMPONENT(steam_proxy::component)

View File

@ -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<uint64_t, subscribed_item>;
void update_subscribed_items();
void access_subscribed_items(const std::function<void(const subscribed_item_map&)>& callback);
}

View File

@ -1,6 +1,6 @@
#include <std_include.hpp>
#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<uint32_t>(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<size_t>(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,

View File

@ -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);