From 9443afbd00ce5c8846ef86ad03de4188af7a0d79 Mon Sep 17 00:00:00 2001 From: otavepto <153766569+otavepto@users.noreply.github.com> Date: Wed, 3 Jul 2024 01:35:07 +0300 Subject: [PATCH] * add 2 new properties to mods.json `min_game_branch` and `max_game_branch` according to sdk v1.60, no idea what they do * make sure buffer is null terminated in `Steam_UGC::GetQueryUGCPreviewURL()` * implement 2 new useless ugc stuff + use an already made function to check for handle validity --- dll/dll/settings.h | 2 + dll/dll/steam_ugc.h | 6 ++ dll/settings_parser.cpp | 6 ++ dll/steam_ugc.cpp | 55 ++++++++++++++----- .../steam_settings.EXAMPLE/mods.EXAMPLE.json | 2 + sdk/steam/isteamugc.h | 3 +- 6 files changed, 58 insertions(+), 16 deletions(-) diff --git a/dll/dll/settings.h b/dll/dll/settings.h index 33d14fa9..4bdc4df9 100644 --- a/dll/dll/settings.h +++ b/dll/dll/settings.h @@ -56,6 +56,8 @@ struct Mod_entry { int32 previewFileSize{}; uint64 total_files_sizes{}; // added in sdk 1.60, "Total size of all files (non-legacy), excluding the preview file" + std::string min_game_branch{}; // added in sdk 1.60 + std::string max_game_branch{}; // added in sdk 1.60 std::string workshopItemURL{}; diff --git a/dll/dll/steam_ugc.h b/dll/dll/steam_ugc.h index dce274aa..ac8cf6ac 100644 --- a/dll/dll/steam_ugc.h +++ b/dll/dll/steam_ugc.h @@ -27,6 +27,10 @@ struct UGC_query { bool return_all_subscribed{}; std::set results{}; + + bool admin_query = false; // added in sdk 1.60 (currently unused) + std::string min_branch{}; // added in sdk 1.60 (currently unused) + std::string max_branch{}; // added in sdk 1.60 (currently unused) }; class Steam_UGC : @@ -135,6 +139,7 @@ public: bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, const char *pchKey, STEAM_OUT_STRING_COUNT(cchValueSize) char *pchValue, uint32 cchValueSize ); + // Some items can specify that they have a version that is valid for a range of game versions (Steam branch) uint32 GetNumSupportedGameVersions( UGCQueryHandle_t handle, uint32 index ); bool GetSupportedGameVersionData( UGCQueryHandle_t handle, uint32 index, uint32 versionIndex, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMin, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMax, uint32 cchGameBranchSize ); @@ -172,6 +177,7 @@ public: bool SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAgeSeconds ); + // allow ISteamUGC to be used in a tools like environment for users who have the appropriate privileges for the calling appid bool SetAdminQuery( UGCUpdateHandle_t handle, bool bAdminQuery ); // Options only for querying user UGC diff --git a/dll/settings_parser.cpp b/dll/settings_parser.cpp index 21ce4472..b8e70c4d 100644 --- a/dll/settings_parser.cpp +++ b/dll/settings_parser.cpp @@ -1016,6 +1016,8 @@ static void try_parse_mods_file(class Settings *settings_client, Settings *setti newMod.previewFileSize = mod.value().value("preview_filesize", preview_filesize); newMod.total_files_sizes = mod.value().value("total_files_sizes", primary_filesize); + newMod.min_game_branch = mod.value().value("min_game_branch", ""); + newMod.max_game_branch = mod.value().value("max_game_branch", ""); newMod.workshopItemURL = mod.value().value("workshop_item_url", "https://steamcommunity.com/sharedfiles/filedetails/?id=" + std::string(mod.key())); newMod.votesUp = mod.value().value("upvotes", (uint32)500); @@ -1046,6 +1048,8 @@ static void try_parse_mods_file(class Settings *settings_client, Settings *setti PRINT_DEBUG(" preview_filesize: %i bytes", newMod.previewFileSize); PRINT_DEBUG(" preview file handle: %llu", settings_client->getMod(newMod.id).handlePreviewFile); PRINT_DEBUG(" total_files_sizes: %llu", settings_client->getMod(newMod.id).total_files_sizes); + PRINT_DEBUG(" min_game_branch: '%s'", settings_client->getMod(newMod.id).min_game_branch.c_str()); + PRINT_DEBUG(" max_game_branch: '%s'", settings_client->getMod(newMod.id).max_game_branch.c_str()); PRINT_DEBUG(" workshop_item_url: '%s'", newMod.workshopItemURL.c_str()); PRINT_DEBUG(" preview_url: '%s'", newMod.previewURL.c_str()); } catch (std::exception& e) { @@ -1111,6 +1115,8 @@ static void try_detect_mods_folder(class Settings *settings_client, Settings *se PRINT_DEBUG(" preview_filesize: %i bytes", newMod.previewFileSize); PRINT_DEBUG(" preview file handle: %llu", settings_client->getMod(newMod.id).handlePreviewFile); PRINT_DEBUG(" total_files_sizes: '%s'", newMod.total_files_sizes); + PRINT_DEBUG(" min_game_branch: '%s'", newMod.min_game_branch.c_str()); + PRINT_DEBUG(" max_game_branch: '%s'", newMod.max_game_branch.c_str()); PRINT_DEBUG(" workshop_item_url: '%s'", newMod.workshopItemURL.c_str()); PRINT_DEBUG(" preview_url: '%s'", newMod.previewURL.c_str()); } catch (...) {} diff --git a/dll/steam_ugc.cpp b/dll/steam_ugc.cpp index e498630a..3ebe733c 100644 --- a/dll/steam_ugc.cpp +++ b/dll/steam_ugc.cpp @@ -106,7 +106,7 @@ void Steam_UGC::set_details(PublishedFileId_t id, SteamUGCDetails_t *pDetails) // TODO should we enable this? // pDetails->m_unNumChildren = mod.numChildren; - // TODO make the filesize is good + // TODO make sure the filesize is good pDetails->m_ulTotalFilesSize = mod.total_files_sizes; } else { PRINT_DEBUG(" mod isn't installed, returning failure"); @@ -364,8 +364,9 @@ bool Steam_UGC::GetQueryUGCPreviewURL( UGCQueryHandle_t handle, uint32 index, ST auto res = get_query_ugc(handle, index); if (!res.has_value()) return false; - auto mod = res.value(); + auto &mod = res.value(); PRINT_DEBUG("Steam_UGC:GetQueryUGCPreviewURL: '%s'", mod.previewURL.c_str()); + memset(pchURL, 0, cchURLSize); mod.previewURL.copy(pchURL, cchURLSize - 1); return true; } @@ -495,29 +496,47 @@ bool Steam_UGC::GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, c return false; } +// TODO no public docs +// Some items can specify that they have a version that is valid for a range of game versions (Steam branch) uint32 Steam_UGC::GetNumSupportedGameVersions( UGCQueryHandle_t handle, uint32 index ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG("%llu %u // TODO", handle, index); std::lock_guard lock(global_mutex); if (handle == k_UGCQueryHandleInvalid) return 0; - auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); - if (ugc_queries.end() == request) return 0; + auto res = get_query_ugc(handle, index); + if (!res.has_value()) return 0; return 1; } +// TODO no public docs bool Steam_UGC::GetSupportedGameVersionData( UGCQueryHandle_t handle, uint32 index, uint32 versionIndex, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMin, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMax, uint32 cchGameBranchSize ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG("%llu %u %u // TODO", handle, index, versionIndex); std::lock_guard lock(global_mutex); if (handle == k_UGCQueryHandleInvalid) return false; - if (index != 0) return false; // TODO ?? - auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); - if (ugc_queries.end() == request) return false; + if (versionIndex != 0) { // TODO I assume this is supposed to be an index in the range [ 0, GetNumSupportedGameVersions() ) + return false; + } - return false; // TODO ?? + auto res = get_query_ugc(handle, index); + if (!res.has_value()) return false; + + auto &mod = res.value(); + + // TODO I assume each mod/workshop item has a min version and max version for the game + if (pchGameBranchMin && static_cast(cchGameBranchSize) > mod.min_game_branch.size()) { + memset(pchGameBranchMin, 0, cchGameBranchSize); + memcpy(pchGameBranchMin, mod.min_game_branch.c_str(), mod.min_game_branch.size()); + } + if (pchGameBranchMax && static_cast(cchGameBranchSize) > mod.max_game_branch.size()) { + memset(pchGameBranchMax, 0, cchGameBranchSize); + memcpy(pchGameBranchMax, mod.max_game_branch.c_str(), mod.max_game_branch.size()); + } + + return true; } uint32 Steam_UGC::GetQueryUGCContentDescriptors( UGCQueryHandle_t handle, uint32 index, EUGCContentDescriptorID *pvecDescriptors, uint32 cMaxEntries ) @@ -526,9 +545,9 @@ uint32 Steam_UGC::GetQueryUGCContentDescriptors( UGCQueryHandle_t handle, uint32 std::lock_guard lock(global_mutex); if (handle == k_UGCQueryHandleInvalid) return 0; - auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); - if (ugc_queries.end() == request) return 0; - + auto res = get_query_ugc(handle, index); + if (!res.has_value()) return 0; + return 0; } @@ -712,15 +731,18 @@ bool Steam_UGC::SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAge return true; } +// TODO no public docs +// allow ISteamUGC to be used in a tools like environment for users who have the appropriate privileges for the calling appid bool Steam_UGC::SetAdminQuery( UGCUpdateHandle_t handle, bool bAdminQuery ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG("%llu %i // TODO", handle, (int)bAdminQuery); std::lock_guard lock(global_mutex); if (handle == k_UGCQueryHandleInvalid) return false; auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); if (ugc_queries.end() == request) return false; + request->admin_query = bAdminQuery; return true; } @@ -1046,6 +1068,7 @@ bool Steam_UGC::RemoveContentDescriptor( UGCUpdateHandle_t handle, EUGCContentDe return false; } +// TODO no public docs bool Steam_UGC::SetRequiredGameVersions( UGCUpdateHandle_t handle, const char *pszGameBranchMin, const char *pszGameBranchMax ) { PRINT_DEBUG("%llu '%s' '%s' // TODO", handle, pszGameBranchMin, pszGameBranchMax); @@ -1056,7 +1079,9 @@ bool Steam_UGC::SetRequiredGameVersions( UGCUpdateHandle_t handle, const char *p auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); if (ugc_queries.end() == request) return false; - return false; + if (pszGameBranchMin) request->min_branch = pszGameBranchMin; + if (pszGameBranchMax) request->max_branch = pszGameBranchMax; + return true; } STEAM_CALL_RESULT( SubmitItemUpdateResult_t ) diff --git a/post_build/steam_settings.EXAMPLE/mods.EXAMPLE.json b/post_build/steam_settings.EXAMPLE/mods.EXAMPLE.json index 0e0b9083..2ffe5472 100644 --- a/post_build/steam_settings.EXAMPLE/mods.EXAMPLE.json +++ b/post_build/steam_settings.EXAMPLE/mods.EXAMPLE.json @@ -19,6 +19,8 @@ "preview_filename": "test.png", "preview_filesize": 1000000, "total_files_sizes": 9977664411, + "min_game_branch": "1.4.2", + "max_game_branch": "1.5.0", "workshop_item_url": "https://steamcommunity.com/sharedfiles/filedetails/?id=111111111", "upvotes": 10, "downvotes": 1, diff --git a/sdk/steam/isteamugc.h b/sdk/steam/isteamugc.h index c54a5b76..f923e2a4 100644 --- a/sdk/steam/isteamugc.h +++ b/sdk/steam/isteamugc.h @@ -249,9 +249,9 @@ public: STEAM_FLAT_NAME( GetQueryFirstUGCKeyValueTag ) virtual bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, const char *pchKey, STEAM_OUT_STRING_COUNT(cchValueSize) char *pchValue, uint32 cchValueSize ) = 0; - // Some items can specify that they have a version that is valid for a range of game versions (Steam branch) virtual uint32 GetNumSupportedGameVersions( UGCQueryHandle_t handle, uint32 index ) = 0; + virtual bool GetSupportedGameVersionData( UGCQueryHandle_t handle, uint32 index, uint32 versionIndex, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMin, STEAM_OUT_STRING_COUNT( cchGameBranchSize ) char *pchGameBranchMax, uint32 cchGameBranchSize ) = 0; virtual uint32 GetQueryUGCContentDescriptors( UGCQueryHandle_t handle, uint32 index, EUGCContentDescriptorID *pvecDescriptors, uint32 cMaxEntries ) = 0; @@ -273,6 +273,7 @@ public: virtual bool SetReturnPlaytimeStats( UGCQueryHandle_t handle, uint32 unDays ) = 0; virtual bool SetLanguage( UGCQueryHandle_t handle, const char *pchLanguage ) = 0; virtual bool SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAgeSeconds ) = 0; + // allow ISteamUGC to be used in a tools like environment for users who have the appropriate privileges for the calling appid virtual bool SetAdminQuery( UGCUpdateHandle_t handle, bool bAdminQuery ) = 0; // admin queries return hidden items // Options only for querying user UGC