diff --git a/dll/settings.cpp b/dll/settings.cpp index 95ab05a..48c574b 100644 --- a/dll/settings.cpp +++ b/dll/settings.cpp @@ -128,6 +128,38 @@ void Settings::addMod(PublishedFileId_t id, std::string title, std::string path) mods.push_back(new_entry); } +void Settings::addModDetails(PublishedFileId_t id, std::string previewURL, EWorkshopFileType fileType, std::string description, + uint64 steamIDOwner, uint32 timeCreated, uint32 timeUpdated, uint32 timeAddedToUserList, ERemoteStoragePublishedFileVisibility visibility, bool banned, bool acceptedForUse, bool tagsTruncated, + std::string tags, std::string primaryFileName, int32 primaryFileSize, int32 previewFileSize, std::string workshopItemURL, uint32 votesUp, uint32 votesDown, float score, uint32 numChildren) +{ + auto f = std::find_if(mods.begin(), mods.end(), [&id](Mod_entry const& item) { return item.id == id; }); + if (mods.end() != f) { + f->previewURL = previewURL; + + f->fileType = fileType; + f->description = description; + f->steamIDOwner = steamIDOwner; + f->timeCreated = timeCreated; + f->timeUpdated = timeUpdated; + f->timeAddedToUserList= timeAddedToUserList; + f->visibility = visibility; + f->banned = banned; + f->acceptedForUse = acceptedForUse; + f->tagsTruncated = tagsTruncated; + f->tags = tags; + f->handleFile; + f->handlePreviewFile; + f->primaryFileName = primaryFileName; + f->primaryFileSize = primaryFileSize; + f->previewFileSize = previewFileSize; + f->workshopItemURL = workshopItemURL; + f->votesUp = votesUp; + f->votesDown = votesDown; + f->score = score; + f->numChildren = numChildren; + } +} + Mod_entry Settings::getMod(PublishedFileId_t id) { auto f = std::find_if(mods.begin(), mods.end(), [&id](Mod_entry const& item) { return item.id == id; }); diff --git a/dll/settings.h b/dll/settings.h index b54815e..1713473 100644 --- a/dll/settings.h +++ b/dll/settings.h @@ -32,6 +32,33 @@ struct Mod_entry { PublishedFileId_t id; std::string title; std::string path; + + std::string previewURL; + + EWorkshopFileType fileType = k_EWorkshopFileTypeCommunity; + std::string description; + uint64 steamIDOwner; + uint32 timeCreated = 1554997000; + uint32 timeUpdated = 1554997000; + uint32 timeAddedToUserList = 1554997000; + ERemoteStoragePublishedFileVisibility visibility; + bool banned = false; + bool acceptedForUse = true; + bool tagsTruncated = false; + std::string tags; + // file/url information + UGCHandle_t handleFile = k_UGCHandleInvalid; + UGCHandle_t handlePreviewFile = k_UGCHandleInvalid; + std::string primaryFileName; + int32 primaryFileSize = 1000000; + int32 previewFileSize = 1000000; + std::string workshopItemURL; + // voting information + uint32 votesUp = 1; + uint32 votesDown = 0; + float score = 1.0f; + // collection details + uint32 numChildren; }; struct Leaderboard_config { @@ -116,6 +143,9 @@ public: //mod stuff void addMod(PublishedFileId_t id, std::string title, std::string path); + void addModDetails(PublishedFileId_t id, std::string previewURL, EWorkshopFileType fileType, std::string description, + uint64 steamIDOwner, uint32 timeCreated, uint32 timeUpdated, uint32 timeAddedToUserList, ERemoteStoragePublishedFileVisibility visibility, bool banned, bool acceptedForUse, bool tagsTruncated, + std::string tags, std::string primaryFileName, int32 primaryFileSize, int32 previewFileSize, std::string workshopItemURL, uint32 votesUp, uint32 votesDown, float score, uint32 numChildren); Mod_entry getMod(PublishedFileId_t id); bool isModInstalled(PublishedFileId_t id); std::set modSet(); diff --git a/dll/settings_parser.cpp b/dll/settings_parser.cpp index fb4a6a8..f232969 100644 --- a/dll/settings_parser.cpp +++ b/dll/settings_parser.cpp @@ -552,14 +552,58 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s { std::string mod_path = Local_Storage::get_game_settings_path() + "mods"; - std::vector paths = Local_Storage::get_filenames_path(mod_path); - for (auto & p: paths) { - PRINT_DEBUG("mod directory %s\n", p.c_str()); - try { - PublishedFileId_t id = std::stoull(p); - settings_client->addMod(id, p, mod_path + PATH_SEPARATOR + p); - settings_server->addMod(id, p, mod_path + PATH_SEPARATOR + p); - } catch (...) {} + + //try to load mods.json + nlohmann::json mod_items = nlohmann::json::object(); + static constexpr auto mods_json_file = "mods.json"; + std::string mods_json_path = Local_Storage::get_game_settings_path() + mods_json_file; + if (local_storage->load_json(mods_json_path, mod_items)) { + //iterate over loaded mods + for (auto mod = mod_items.begin(); mod != mod_items.end(); ++mod) { + try { + PublishedFileId_t id = std::stoull(mod.key()); + std::string title = mod.value().value("title", std::string(mod.key())); + std::string path = mod.value().value("path", mod_path + PATH_SEPARATOR + std::string(mod.key())); + std::string previewURL = mod.value().value("preview_url", std::string("")); + EWorkshopFileType fileType = k_EWorkshopFileTypeCommunity; + std::string description = mod.value().value("description", std::string("")); + uint64 steamIDOwner = mod.value().value("steam_id_owner",(uint64) 0); //TODO own id + uint32 timeCreated = mod.value().value("time_created",(uint32) 1554997000); + uint32 timeUpdated = mod.value().value("time_updated",(uint32) 1554997000); + uint32 timeAddedToUserList = mod.value().value("time_added",(uint32) 1554997000); + ERemoteStoragePublishedFileVisibility visibility = k_ERemoteStoragePublishedFileVisibilityPublic; + bool banned = false; + bool acceptedForUse = true; + bool tagsTruncated = false; + std::string tags = mod.value().value("tags", std::string("")); + std::string primaryFileName = mod.value().value("primary_filename", std::string("")); + int32 primaryFileSize = mod.value().value("primary_filesize", (int32) 1000000); + int32 previewFileSize = mod.value().value("preview_filesize", (int32) 1000000); + std::string workshopItemURL = mod.value().value("workshop_item_url", std::string("")); + uint32 votesUp = mod.value().value("upvotes",(uint32) 1); + uint32 votesDown = mod.value().value("downvotes",(uint32) 0); + float score = 1.0; + uint32 numChildren = mod.value().value("num_children",(uint32) 0); + + settings_client->addMod(id, title, path); + settings_client->addModDetails(id, previewURL, fileType, description, steamIDOwner, timeCreated, timeUpdated, + timeAddedToUserList, visibility, banned, acceptedForUse, tagsTruncated, tags, primaryFileName, primaryFileSize, previewFileSize, workshopItemURL, votesUp, votesDown, score, numChildren); + settings_server->addMod(id, title, path); + settings_server->addModDetails(id, previewURL, fileType, description, steamIDOwner, timeCreated, timeUpdated, + timeAddedToUserList, visibility, banned, acceptedForUse, tagsTruncated, tags, primaryFileName, primaryFileSize, previewFileSize, workshopItemURL, votesUp, votesDown, score, numChildren); + } catch (std::exception& e) {PRINT_DEBUG("MODLOADER ERROR: %s\n", e.what());} + } + } else { + //Load mods the old way, if there is no mods.json + std::vector paths = Local_Storage::get_filenames_path(mod_path); + for (auto & p: paths) { + PRINT_DEBUG("mod directory %s\n", p.c_str()); + try { + PublishedFileId_t id = std::stoull(p); + settings_client->addMod(id, p, mod_path + PATH_SEPARATOR + p); + settings_server->addMod(id, p, mod_path + PATH_SEPARATOR + p); + } catch (...) {} + } } } diff --git a/dll/steam_ugc.h b/dll/steam_ugc.h index 3786c36..8042e4a 100644 --- a/dll/steam_ugc.h +++ b/dll/steam_ugc.h @@ -67,11 +67,29 @@ void set_details(PublishedFileId_t id, SteamUGCDetails_t *pDetails) if (settings->isModInstalled(id)) { pDetails->m_eResult = k_EResultOK; pDetails->m_nPublishedFileId = id; - pDetails->m_eFileType = k_EWorkshopFileTypeCommunity; pDetails->m_nCreatorAppID = settings->get_local_game_id().AppID(); pDetails->m_nConsumerAppID = settings->get_local_game_id().AppID(); - snprintf(pDetails->m_rgchTitle, sizeof(pDetails->m_rgchDescription), "%s", settings->getMod(id).title.c_str()); - //TODO + + snprintf(pDetails->m_rgchTitle, k_cchPublishedDocumentTitleMax, "%s", settings->getMod(id).title.c_str()); + pDetails->m_eFileType = settings->getMod(id).fileType; + snprintf(pDetails->m_rgchDescription, k_cchPublishedDocumentDescriptionMax, "%s", settings->getMod(id).description.c_str()); + pDetails->m_ulSteamIDOwner = settings->get_local_steam_id().ConvertToUint64(); + pDetails->m_rtimeCreated = settings->getMod(id).timeCreated; + pDetails->m_rtimeUpdated = settings->getMod(id).timeUpdated; + pDetails->m_rtimeAddedToUserList= settings->getMod(id).timeAddedToUserList; + pDetails->m_eVisibility = settings->getMod(id).visibility; + pDetails->m_bBanned = settings->getMod(id).banned; + pDetails->m_bAcceptedForUse = settings->getMod(id).acceptedForUse; + pDetails->m_bTagsTruncated = settings->getMod(id).tagsTruncated; + snprintf(pDetails->m_rgchTags, k_cchTagListMax, "%s", settings->getMod(id).tags.c_str()); + snprintf(pDetails->m_pchFileName, k_cchFilenameMax, "%s", settings->getMod(id).primaryFileName.c_str()); + pDetails->m_nFileSize = settings->getMod(id).primaryFileSize; + pDetails->m_nPreviewFileSize = settings->getMod(id).previewFileSize; + snprintf(pDetails->m_rgchURL, k_cchPublishedFileURLMax, "%s", settings->getMod(id).workshopItemURL.c_str()); + pDetails->m_unVotesUp = settings->getMod(id).votesUp; + pDetails->m_unVotesDown = settings->getMod(id).votesDown; + pDetails->m_flScore = settings->getMod(id).score; + pDetails->m_unNumChildren = settings->getMod(id).numChildren; } else { pDetails->m_nPublishedFileId = id; pDetails->m_eResult = k_EResultFail; @@ -203,7 +221,23 @@ bool GetQueryUGCTagDisplayName( UGCQueryHandle_t handle, uint32 index, uint32 in bool GetQueryUGCPreviewURL( UGCQueryHandle_t handle, uint32 index, STEAM_OUT_STRING_COUNT(cchURLSize) char *pchURL, uint32 cchURLSize ) { PRINT_DEBUG("Steam_UGC::GetQueryUGCPreviewURL\n"); - return false; + std::lock_guard lock(global_mutex); + + 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 (index >= request->results.size()) { + return false; + } + + auto it = request->results.begin(); + //std::advance(it, index); + PRINT_DEBUG("Steam_UGC::GetQueryUGCPreviewURL: %u %s\n", *it, settings->getMod(*it).previewURL.c_str()); + snprintf(pchURL, cchURLSize, "%s", settings->getMod(*it).previewURL.c_str()); + return true; + // return false; } @@ -713,8 +747,8 @@ bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDi return false; } - if (punSizeOnDisk) *punSizeOnDisk = 1000000; - if (punTimeStamp) *punTimeStamp = 1554997000; + if (punSizeOnDisk) *punSizeOnDisk = settings->getMod(nPublishedFileID).primaryFileSize; + if (punTimeStamp) *punTimeStamp = settings->getMod(nPublishedFileID).timeCreated; if (pchFolder && cchFolderSize) { snprintf(pchFolder, cchFolderSize, "%s", settings->getMod(nPublishedFileID).path.c_str()); } diff --git a/files_example/steam_settings.EXAMPLE/mods.EXAMPLE.json b/files_example/steam_settings.EXAMPLE/mods.EXAMPLE.json new file mode 100644 index 0000000..e375504 --- /dev/null +++ b/files_example/steam_settings.EXAMPLE/mods.EXAMPLE.json @@ -0,0 +1,34 @@ +{ + "111111111": { + "title": "Example Workshop Item", + "path": "C:/Game/steam_settings/mods/111111111", + "preview_url": "file://C:/Game/steam_settings/mods/111111111/test.png", + "description": "Example Workshop Item with all Details", + "steam_id_owner": 11111111111111111, + "time_created": 1554997000, + "time_updated": 1554997000, + "time_added": 1554997000, + "tags": "Maps, exampleTag, exampleTag2", + "primary_filename": "test.sav", + "primary_filesize": 1000000, + "preview_filesize": 1000000, + "workshop_item_url": "https://steamcommunity.com/sharedfiles/filedetails/?id=111111111", + "upvotes": 1, + "downvotes": 0, + "num_children": 0 + }, + + "222222222": { + "title": "Example Workshop Item", + "path": "C:/Game/steam_settings/mods/222222222", + "preview_url": "file://C:/Game/steam_settings/mods/222222222/test.png", + "description": "Example Workshop Item with all Details" + }, + + "333333333": { + "title": "Example Workshop Item" + }, + + "444444444": { + } +} \ No newline at end of file