Support UGC on steam deck
This commit is contained in:
parent
bf9a3336d0
commit
5532980cc6
@ -7,8 +7,6 @@
|
|||||||
#include <utils/finally.hpp>
|
#include <utils/finally.hpp>
|
||||||
#include <utils/concurrency.hpp>
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
#include "game/utils.hpp"
|
|
||||||
|
|
||||||
#include "steam/interface.hpp"
|
#include "steam/interface.hpp"
|
||||||
#include "steam/steam.hpp"
|
#include "steam/steam.hpp"
|
||||||
|
|
||||||
@ -22,8 +20,8 @@ namespace steam_proxy
|
|||||||
utils::nt::library steam_client_module{};
|
utils::nt::library steam_client_module{};
|
||||||
utils::nt::library steam_overlay_module{};
|
utils::nt::library steam_overlay_module{};
|
||||||
|
|
||||||
void* steam_pipe = nullptr;
|
steam::HSteamPipe steam_pipe = 0;
|
||||||
void* global_user = nullptr;
|
steam::HSteamUser global_user = 0;
|
||||||
|
|
||||||
steam::interface client_engine{};
|
steam::interface client_engine{};
|
||||||
steam::interface client_user{};
|
steam::interface client_user{};
|
||||||
@ -31,6 +29,9 @@ namespace steam_proxy
|
|||||||
steam::interface client_friends{};
|
steam::interface client_friends{};
|
||||||
steam::interface client_ugc{};
|
steam::interface client_ugc{};
|
||||||
|
|
||||||
|
steam::client* steam_client{};
|
||||||
|
steam::ugc* steam_ugc{};
|
||||||
|
|
||||||
utils::concurrency::container<subscribed_item_map> subscribed_items;
|
utils::concurrency::container<subscribed_item_map> subscribed_items;
|
||||||
|
|
||||||
enum class ownership_state
|
enum class ownership_state
|
||||||
@ -64,6 +65,8 @@ namespace steam_proxy
|
|||||||
|
|
||||||
void load_client()
|
void load_client()
|
||||||
{
|
{
|
||||||
|
SetEnvironmentVariableA("SteamAppId", std::to_string(steam::SteamUtils()->GetAppID()).data());
|
||||||
|
|
||||||
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
|
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
|
||||||
if (steam_path.empty()) return;
|
if (steam_path.empty()) return;
|
||||||
|
|
||||||
@ -76,8 +79,8 @@ namespace steam_proxy
|
|||||||
client_engine = load_client_engine();
|
client_engine = load_client_engine();
|
||||||
if (!client_engine) return;
|
if (!client_engine) return;
|
||||||
|
|
||||||
steam_pipe = steam_client_module.invoke<void*>("Steam_CreateSteamPipe");
|
steam_pipe = steam_client_module.invoke<steam::HSteamPipe>("Steam_CreateSteamPipe");
|
||||||
global_user = steam_client_module.invoke<void*>(
|
global_user = steam_client_module.invoke<steam::HSteamUser>(
|
||||||
"Steam_ConnectToGlobalUser", steam_pipe);
|
"Steam_ConnectToGlobalUser", steam_pipe);
|
||||||
|
|
||||||
client_user = client_engine.invoke<void*>(8, global_user, steam_pipe);
|
client_user = client_engine.invoke<void*>(8, global_user, steam_pipe);
|
||||||
@ -94,19 +97,21 @@ namespace steam_proxy
|
|||||||
client_friends = nullptr;
|
client_friends = nullptr;
|
||||||
client_ugc = nullptr;
|
client_ugc = nullptr;
|
||||||
|
|
||||||
steam_pipe = nullptr;
|
steam_pipe = 0;
|
||||||
global_user = nullptr;
|
global_user = 0;
|
||||||
|
|
||||||
steam_client_module = utils::nt::library{nullptr};
|
steam_client = nullptr;
|
||||||
|
steam_ugc = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool perform_cleanup_if_needed()
|
bool perform_cleanup_if_needed()
|
||||||
{
|
{
|
||||||
|
if (steam_client) return true;
|
||||||
|
|
||||||
if (steam_client_module
|
if (steam_client_module
|
||||||
&& steam_pipe
|
&& steam_pipe
|
||||||
&& global_user
|
&& global_user
|
||||||
&& steam_client_module.invoke<bool>("Steam_BConnected", global_user,
|
&& steam_client_module.invoke<bool>("Steam_BConnected", global_user, steam_pipe)
|
||||||
steam_pipe)
|
|
||||||
&& steam_client_module.invoke<bool>("Steam_BLoggedOn", global_user, steam_pipe)
|
&& steam_client_module.invoke<bool>("Steam_BLoggedOn", global_user, steam_pipe)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -224,7 +229,16 @@ namespace steam_proxy
|
|||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
{
|
{
|
||||||
if (steam_client_module && steam_pipe)
|
if (steam_client)
|
||||||
|
{
|
||||||
|
if (global_user)
|
||||||
|
{
|
||||||
|
steam_client->ReleaseUser(steam_pipe, global_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
steam_client->BReleaseSteamPipe(steam_pipe);
|
||||||
|
}
|
||||||
|
else if (steam_client_module && steam_pipe)
|
||||||
{
|
{
|
||||||
if (global_user)
|
if (global_user)
|
||||||
{
|
{
|
||||||
@ -232,7 +246,7 @@ namespace steam_proxy
|
|||||||
global_user);
|
global_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
steam_client_module.invoke<bool>("Steam_BReleaseSteamPipe", steam_pipe);
|
(void)steam_client_module.invoke<bool>("Steam_BReleaseSteamPipe", steam_pipe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,6 +271,87 @@ namespace steam_proxy
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
if (client_engine || !steam_client_module) return;
|
||||||
|
|
||||||
|
steam_client = steam_client_module.invoke<steam::client*>("CreateInterface", "SteamClient017", nullptr);
|
||||||
|
if (!steam_client) return;
|
||||||
|
|
||||||
|
steam_pipe = steam_client->CreateSteamPipe();
|
||||||
|
global_user = steam_client->ConnectToGlobalUser(steam_pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_ugc()
|
||||||
|
{
|
||||||
|
if (!steam_client) return;
|
||||||
|
|
||||||
|
auto* ugc = steam_client->GetISteamUGC(global_user, steam_pipe, "STEAMUGC_INTERFACE_VERSION008");
|
||||||
|
steam_ugc = static_cast<steam::ugc*>(ugc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_map_client(subscribed_item_map& map)
|
||||||
|
{
|
||||||
|
const auto app_id = steam::SteamUtils()->GetAppID();
|
||||||
|
const auto num_items = client_ugc.invoke<uint32_t>("GetNumSubscribedItems", app_id);
|
||||||
|
|
||||||
|
if (!num_items)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> ids;
|
||||||
|
ids.resize(num_items);
|
||||||
|
|
||||||
|
auto result = 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 = client_ugc.invoke<uint32_t>("GetItemState", app_id, ids[i]);
|
||||||
|
item.available = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_map_steam(subscribed_item_map& map)
|
||||||
|
{
|
||||||
|
const auto num_items = steam_ugc->GetNumSubscribedItems();
|
||||||
|
|
||||||
|
if (!num_items)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> ids;
|
||||||
|
ids.resize(num_items);
|
||||||
|
|
||||||
|
auto result = steam_ugc->GetSubscribedItems(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 = steam_ugc->GetItemState(ids[i]);
|
||||||
|
item.available = steam_ugc->GetItemInstallInfo(ids[i], &item.size_on_disk, buffer, sizeof(buffer),
|
||||||
|
&item.time_stamp);
|
||||||
|
item.path = buffer;
|
||||||
|
|
||||||
|
map[ids[i]] = std::move(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update_subscribed_items()
|
void update_subscribed_items()
|
||||||
{
|
{
|
||||||
subscribed_item_map map{};
|
subscribed_item_map map{};
|
||||||
@ -269,41 +364,15 @@ namespace steam_proxy
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!client_ugc)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto app_id = steam::SteamUtils()->GetAppID();
|
if (client_ugc)
|
||||||
const auto num_items = client_ugc.invoke<uint32_t>("GetNumSubscribedItems", app_id);
|
|
||||||
|
|
||||||
if (!num_items)
|
|
||||||
{
|
{
|
||||||
return;
|
update_map_client(map);
|
||||||
}
|
}
|
||||||
|
else if (steam_ugc)
|
||||||
std::vector<uint64_t> ids;
|
|
||||||
ids.resize(num_items);
|
|
||||||
|
|
||||||
auto result = 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};
|
update_map_steam(map);
|
||||||
subscribed_item item{};
|
|
||||||
|
|
||||||
item.state = client_ugc.invoke<uint32_t>("GetItemState", app_id, ids[i]);
|
|
||||||
item.available = 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 (...)
|
catch (...)
|
||||||
|
@ -18,6 +18,9 @@ namespace steam_proxy
|
|||||||
|
|
||||||
using subscribed_item_map = std::unordered_map<uint64_t, subscribed_item>;
|
using subscribed_item_map = std::unordered_map<uint64_t, subscribed_item>;
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void create_ugc();
|
||||||
|
|
||||||
void update_subscribed_items();
|
void update_subscribed_items();
|
||||||
void access_subscribed_items(const std::function<void(const subscribed_item_map&)>& callback);
|
void access_subscribed_items(const std::function<void(const subscribed_item_map&)>& callback);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "../steam.hpp"
|
#include "../steam.hpp"
|
||||||
|
#include "../../component/steam_proxy.hpp"
|
||||||
|
|
||||||
namespace steam
|
namespace steam
|
||||||
{
|
{
|
||||||
@ -225,6 +226,13 @@ namespace steam
|
|||||||
|
|
||||||
void* client::GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char* pchVersion)
|
void* client::GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char* pchVersion)
|
||||||
{
|
{
|
||||||
|
static auto x = []
|
||||||
|
{
|
||||||
|
steam_proxy::create_ugc();
|
||||||
|
return 0;
|
||||||
|
}();
|
||||||
|
(void)x;
|
||||||
|
|
||||||
static ugc u;
|
static ugc u;
|
||||||
return &u;
|
return &u;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <utils/nt.hpp>
|
#include <utils/nt.hpp>
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "../component/steam_proxy.hpp"
|
||||||
|
|
||||||
namespace steam
|
namespace steam
|
||||||
{
|
{
|
||||||
@ -118,6 +118,9 @@ namespace steam
|
|||||||
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
||||||
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
||||||
::utils::nt::library::load(steam_path / "steamclient64.dll");
|
::utils::nt::library::load(steam_path / "steamclient64.dll");
|
||||||
|
|
||||||
|
steam_proxy::initialize();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user