* attempt to auto detect mods with the same behavior as if they were defined in mods.json, for an easier config

* new function in local storage to get list of folders at root level, given some path

* use last week epoch as the default time for mods dates (created, added, etc...)

* UGC: some params checks according to SDK docs for CreateQueryXXX() functions

* fixed some mistakes
This commit is contained in:
otavepto 2024-01-20 17:50:16 +02:00
parent 45d76fbc31
commit 6249d7ca4d
7 changed files with 246 additions and 150 deletions

View File

@ -479,7 +479,7 @@ echo: & echo:
if %last_code% equ 0 ( if %last_code% equ 0 (
echo // copying readmes + files examples echo // copying readmes + files examples
xcopy /y /s /e /r "post_build\steam_settings.EXAMPLE\" "%build_root_dir%\steam_settings.EXAMPLE\" xcopy /y /s /e /r "post_build\steam_settings.EXAMPLE\" "%build_root_dir%\steam_settings.EXAMPLE\"
xcopy /y /s /e /r "post_build\win\ColdClientLoader.EXAMPLE\" "%steamclient_dir%\EXAMPLE\" xcopy /y /s /e /r "post_build\win\ColdClientLoader.EXAMPLE\" "%steamclient_dir%\dll_injection.EXAMPLE\"
copy /y "%tools_src_dir%\steamclient_loader\win\ColdClientLoader.ini" "%steamclient_dir%\" copy /y "%tools_src_dir%\steamclient_loader\win\ColdClientLoader.ini" "%steamclient_dir%\"
copy /y "post_build\README.release.md" "%build_root_dir%\" copy /y "post_build\README.release.md" "%build_root_dir%\"
copy /y "CHANGELOG.md" "%build_root_dir%\" copy /y "CHANGELOG.md" "%build_root_dir%\"

View File

@ -64,6 +64,7 @@ public:
void setAppId(uint32 appid); void setAppId(uint32 appid);
static int store_file_data(std::string folder, std::string file, char *data, unsigned int length); static int store_file_data(std::string folder, std::string file, char *data, unsigned int length);
static std::vector<std::string> get_filenames_path(std::string path); static std::vector<std::string> get_filenames_path(std::string path);
static std::vector<std::string> get_folders_path(std::string path);
int store_data(std::string folder, std::string file, char *data, unsigned int length); int store_data(std::string folder, std::string file, char *data, unsigned int length);
int store_data_settings(std::string file, char *data, unsigned int length); int store_data_settings(std::string file, char *data, unsigned int length);

View File

@ -171,7 +171,14 @@ Steam_UGC(class Settings *settings, class Ugc_Remote_Storage_Bridge *ugc_bridge,
UGCQueryHandle_t CreateQueryUserUGCRequest( AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage ) UGCQueryHandle_t CreateQueryUserUGCRequest( AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage )
{ {
PRINT_DEBUG("Steam_UGC::CreateQueryUserUGCRequest %u %i %i %i %u %u %u\n", unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage); PRINT_DEBUG("Steam_UGC::CreateQueryUserUGCRequest %u %i %i %i %u %u %u\n", unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage);
//TODO std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (nCreatorAppID != settings->get_local_game_id().AppID() || nConsumerAppID != settings->get_local_game_id().AppID()) return k_UGCQueryHandleInvalid;
if (unPage < 1) return k_UGCQueryHandleInvalid;
if (eListType < 0) return k_UGCQueryHandleInvalid;
if (unAccountID != settings->get_local_steam_id().GetAccountID()) return k_UGCQueryHandleInvalid;
// TODO
return new_ugc_query(eListType == k_EUserUGCList_Subscribed || eListType == k_EUserUGCList_Published); return new_ugc_query(eListType == k_EUserUGCList_Subscribed || eListType == k_EUserUGCList_Published);
} }
@ -180,7 +187,13 @@ UGCQueryHandle_t CreateQueryUserUGCRequest( AccountID_t unAccountID, EUserUGCLis
UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage ) UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage )
{ {
PRINT_DEBUG("Steam_UGC::CreateQueryAllUGCRequest\n"); PRINT_DEBUG("Steam_UGC::CreateQueryAllUGCRequest\n");
//TODO std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (nCreatorAppID != settings->get_local_game_id().AppID() || nConsumerAppID != settings->get_local_game_id().AppID()) return k_UGCQueryHandleInvalid;
if (unPage < 1) return k_UGCQueryHandleInvalid;
if (eQueryType < 0) return k_UGCQueryHandleInvalid;
// TODO
return new_ugc_query(); return new_ugc_query();
} }
@ -188,7 +201,12 @@ UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGC
UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, const char *pchCursor = NULL ) UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, const char *pchCursor = NULL )
{ {
PRINT_DEBUG("Steam_UGC::CreateQueryAllUGCRequest other\n"); PRINT_DEBUG("Steam_UGC::CreateQueryAllUGCRequest other\n");
//TODO std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (nCreatorAppID != settings->get_local_game_id().AppID() || nConsumerAppID != settings->get_local_game_id().AppID()) return k_UGCQueryHandleInvalid;
if (eQueryType < 0) return k_UGCQueryHandleInvalid;
// TODO
return new_ugc_query(); return new_ugc_query();
} }
@ -196,6 +214,12 @@ UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGC
UGCQueryHandle_t CreateQueryUGCDetailsRequest( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs ) UGCQueryHandle_t CreateQueryUGCDetailsRequest( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs )
{ {
PRINT_DEBUG("Steam_UGC::CreateQueryUGCDetailsRequest\n"); PRINT_DEBUG("Steam_UGC::CreateQueryUGCDetailsRequest\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pvecPublishedFileID) return k_UGCQueryHandleInvalid;
if (unNumPublishedFileIDs < 1) return k_UGCQueryHandleInvalid;
// TODO
std::set<PublishedFileId_t> only(pvecPublishedFileID, pvecPublishedFileID + unNumPublishedFileIDs); std::set<PublishedFileId_t> only(pvecPublishedFileID, pvecPublishedFileID + unNumPublishedFileIDs);
return new_ugc_query(false, only); return new_ugc_query(false, only);
} }
@ -248,10 +272,7 @@ bool GetQueryUGCResult( UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t
{ {
PRINT_DEBUG("Steam_UGC::GetQueryUGCResult %llu %u %p\n", handle, index, pDetails); PRINT_DEBUG("Steam_UGC::GetQueryUGCResult %llu %u %p\n", handle, index, pDetails);
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (pDetails) { if (handle == k_UGCQueryHandleInvalid) return false;
memset(pDetails, 0, sizeof(SteamUGCDetails_t));
pDetails->m_eResult = k_EResultFail;
}
auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); 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) { if (ugc_queries.end() == request) {
@ -262,6 +283,11 @@ bool GetQueryUGCResult( UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t
return false; return false;
} }
if (pDetails) {
memset(pDetails, 0, sizeof(SteamUGCDetails_t));
pDetails->m_eResult = k_EResultFail;
}
auto it = request->results.begin(); auto it = request->results.begin();
std::advance(it, index); std::advance(it, index);
PublishedFileId_t file_id = *it; PublishedFileId_t file_id = *it;
@ -530,9 +556,11 @@ bool SetReturnLongDescription( UGCQueryHandle_t handle, bool bReturnLongDescript
bool SetReturnMetadata( UGCQueryHandle_t handle, bool bReturnMetadata ) bool SetReturnMetadata( UGCQueryHandle_t handle, bool bReturnMetadata )
{ {
PRINT_DEBUG("TODO Steam_UGC::SetReturnMetadata\n"); PRINT_DEBUG("TODO Steam_UGC::SetReturnMetadata %i\n", (int)bReturnMetadata);
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (handle == k_UGCQueryHandleInvalid) return false;
return true; return true;
} }
@ -1086,7 +1114,7 @@ bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDi
if (punTimeStamp) *punTimeStamp = mod.timeUpdated; if (punTimeStamp) *punTimeStamp = mod.timeUpdated;
if (pchFolder && cchFolderSize) { if (pchFolder && cchFolderSize) {
PRINT_DEBUG(" mod path: '%s'\n", mod.path.c_str()); PRINT_DEBUG(" mod path: '%s'\n", mod.path.c_str());
memset(pchFolder, cchFolderSize, 0); memset(pchFolder, 0, cchFolderSize);
mod.path.copy(pchFolder, cchFolderSize - 1); mod.path.copy(pchFolder, cchFolderSize - 1);
} }

View File

@ -159,6 +159,11 @@ std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
return std::vector<std::string>(); return std::vector<std::string>();
} }
std::vector<std::string> Local_Storage::get_folders_path(std::string path)
{
return std::vector<std::string>();
}
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path) std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
{ {
return std::vector<image_pixel_t>(); return std::vector<image_pixel_t>();
@ -185,6 +190,7 @@ std::string Local_Storage::desanitize_string(std::string name)
} }
#else #else
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
static BOOL DirectoryExists(LPCWSTR szPath) static BOOL DirectoryExists(LPCWSTR szPath)
@ -559,6 +565,7 @@ std::string Local_Storage::get_global_settings_path()
std::vector<std::string> Local_Storage::get_filenames_path(std::string path) std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
{ {
if (path.empty()) return {};
if (path.back() != *PATH_SEPARATOR) { if (path.back() != *PATH_SEPARATOR) {
path.append(PATH_SEPARATOR); path.append(PATH_SEPARATOR);
} }
@ -569,6 +576,30 @@ std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
return output; return output;
} }
std::vector<std::string> Local_Storage::get_folders_path(std::string path)
{
if (path.empty()) return {};
if (path.back() != *PATH_SEPARATOR) {
path.append(PATH_SEPARATOR);
}
std::vector<std::string> output{};
try
{
const auto path_p = std::filesystem::path(path);
if (!std::filesystem::is_directory(path_p)) return output;
for (const auto &dir_entry :
std::filesystem::directory_iterator(path_p, std::filesystem::directory_options::follow_directory_symlink)) {
if (std::filesystem::is_directory(dir_entry)) {
output.push_back(dir_entry.path().filename().u8string());
}
}
} catch(...) { }
return output;
}
int Local_Storage::store_data(std::string folder, std::string file, char *data, unsigned int length) int Local_Storage::store_data(std::string folder, std::string file, char *data, unsigned int length)
{ {
if (folder.size() && folder.back() != *PATH_SEPARATOR) { if (folder.size() && folder.back() != *PATH_SEPARATOR) {

View File

@ -777,151 +777,187 @@ static void parse_force_branch_name(class Settings *settings_client, Settings *s
} }
// steam_settings/mods // steam_settings/mods
static const auto one_week_ago_epoch = std::chrono::duration_cast<std::chrono::seconds>(
( startup_time - std::chrono::hours(24 * 7) ).time_since_epoch()
).count();
static size_t get_file_size_safe(const std::string &filepath, const std::string &basepath, int32 default_val = 0)
{
try
{
const auto file_p = common_helpers::to_absolute(filepath, basepath);
if (file_p.empty()) return default_val;
size_t size = 0;
if (common_helpers::file_size(file_p, size)) {
return size;
}
} catch(...) {}
return default_val;
}
static std::string get_mod_preview_url(const std::string &previewFileName, const std::string &mod_id)
{
if (previewFileName.empty()) {
return std::string();
} else {
auto settings_folder = std::string(Local_Storage::get_game_settings_path());
std::replace(settings_folder.begin(), settings_folder.end(), '\\', '/');
return "file://" + settings_folder + "mod_images/" + mod_id + "/" + previewFileName;
}
}
static void try_parse_mods_file(class Settings *settings_client, Settings *settings_server, nlohmann::json &mod_items, const std::string &mods_folder)
{
for (auto mod = mod_items.begin(); mod != mod_items.end(); ++mod) {
try {
std::string mod_images_fullpath = Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + std::string(mod.key());
Mod_entry newMod;
newMod.id = std::stoull(mod.key());
newMod.title = mod.value().value("title", std::string(mod.key()));
// make sure this is never empty
newMod.path = mod.value().value("path", std::string(""));
if (newMod.path.empty()) {
newMod.path = mods_folder + PATH_SEPARATOR + std::string(mod.key());
}
newMod.fileType = k_EWorkshopFileTypeCommunity;
newMod.description = mod.value().value("description", std::string(""));
newMod.steamIDOwner = mod.value().value("steam_id_owner", settings_client->get_local_steam_id().ConvertToUint64());
newMod.timeCreated = mod.value().value("time_created", (uint32)one_week_ago_epoch);
newMod.timeUpdated = mod.value().value("time_updated", (uint32)one_week_ago_epoch);
newMod.timeAddedToUserList = mod.value().value("time_added", (uint32)one_week_ago_epoch);
newMod.visibility = k_ERemoteStoragePublishedFileVisibilityPublic;
newMod.banned = false;
newMod.acceptedForUse = true;
newMod.tagsTruncated = false;
newMod.tags = mod.value().value("tags", std::string(""));
newMod.primaryFileName = mod.value().value("primary_filename", std::string(""));
int32 primary_filesize = 0;
if (!newMod.primaryFileName.empty()) {
primary_filesize = (int32)get_file_size_safe(newMod.primaryFileName, newMod.path, primary_filesize);
}
newMod.primaryFileSize = mod.value().value("primary_filesize", primary_filesize);
newMod.previewFileName = mod.value().value("preview_filename", std::string(""));
int32 preview_filesize = 0;
if (!newMod.previewFileName.empty()) {
preview_filesize = (int32)get_file_size_safe(newMod.previewFileName, mod_images_fullpath, preview_filesize);
}
newMod.previewFileSize = mod.value().value("preview_filesize", preview_filesize);
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);
newMod.votesDown = mod.value().value("downvotes", (uint32)12);
float score = 0.97f;
try
{
score = newMod.votesUp / (float)(newMod.votesUp + newMod.votesDown);
} catch(...) {}
newMod.score = mod.value().value("score", score);
newMod.numChildren = mod.value().value("num_children", (uint32)0);
newMod.previewURL = mod.value().value("preview_url", get_mod_preview_url(newMod.previewFileName, std::string(mod.key())));
settings_client->addMod(newMod.id, newMod.title, newMod.path);
settings_server->addMod(newMod.id, newMod.title, newMod.path);
settings_client->addModDetails(newMod.id, newMod);
settings_server->addModDetails(newMod.id, newMod);
PRINT_DEBUG(" parsed mod '%s':\n", std::string(mod.key()).c_str());
PRINT_DEBUG(" path (will be used for primary file): '%s'\n", newMod.path.c_str());
PRINT_DEBUG(" images path (will be used for preview file): '%s'\n", mod_images_fullpath.c_str());
PRINT_DEBUG(" primary_filename: '%s'\n", newMod.primaryFileName.c_str());
PRINT_DEBUG(" primary_filesize: %i bytes\n", newMod.primaryFileSize);
PRINT_DEBUG(" primary file handle: %llu\n", settings_client->getMod(newMod.id).handleFile);
PRINT_DEBUG(" preview_filename: '%s'\n", newMod.previewFileName.c_str());
PRINT_DEBUG(" preview_filesize: %i bytes\n", newMod.previewFileSize);
PRINT_DEBUG(" preview file handle: %llu\n", settings_client->getMod(newMod.id).handlePreviewFile);
PRINT_DEBUG(" workshop_item_url: '%s'\n", newMod.workshopItemURL.c_str());
PRINT_DEBUG(" preview_url: '%s'\n", newMod.previewURL.c_str());
} catch (std::exception& e) {
PRINT_DEBUG("MODLOADER ERROR: %s\n", e.what());
}
}
}
// called if mods.json doesn't exist or invalid
static void try_detect_mods_folder(class Settings *settings_client, Settings *settings_server, const std::string &mods_folder)
{
std::vector<std::string> all_mods = Local_Storage::get_folders_path(mods_folder);
for (auto & mod_folder: all_mods) {
std::string mod_images_fullpath = Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + mod_folder;
try {
Mod_entry newMod;
newMod.id = std::stoull(mod_folder);
newMod.title = mod_folder;
// make sure this is never empty
newMod.path = mods_folder + PATH_SEPARATOR + mod_folder;
newMod.fileType = k_EWorkshopFileTypeCommunity;
newMod.description = "mod #" + mod_folder;
newMod.steamIDOwner = settings_client->get_local_steam_id().ConvertToUint64();
newMod.timeCreated = (uint32)one_week_ago_epoch;
newMod.timeUpdated = (uint32)one_week_ago_epoch;
newMod.timeAddedToUserList = (uint32)one_week_ago_epoch;
newMod.visibility = k_ERemoteStoragePublishedFileVisibilityPublic;
newMod.banned = false;
newMod.acceptedForUse = true;
newMod.tagsTruncated = false;
newMod.tags = "";
std::vector<std::string> mod_primary_files = Local_Storage::get_filenames_path(newMod.path);
newMod.primaryFileName = mod_primary_files.size() ? mod_primary_files[0] : "";
newMod.primaryFileSize = (int32)get_file_size_safe(newMod.primaryFileName, newMod.path);
std::vector<std::string> mod_preview_files = Local_Storage::get_filenames_path(mod_images_fullpath);
newMod.previewFileName = mod_preview_files.size() ? mod_preview_files[0] : "";
newMod.previewFileSize = (int32)get_file_size_safe(newMod.previewFileName, mod_images_fullpath);
newMod.workshopItemURL = "https://steamcommunity.com/sharedfiles/filedetails/?id=" + mod_folder;
newMod.votesUp = (uint32)500;
newMod.votesDown = (uint32)12;
newMod.score = 0.97f;
newMod.numChildren = (uint32)0;
newMod.previewURL = get_mod_preview_url(newMod.previewFileName, mod_folder);
settings_client->addMod(newMod.id, newMod.title, newMod.path);
settings_server->addMod(newMod.id, newMod.title, newMod.path);
settings_client->addModDetails(newMod.id, newMod);
settings_server->addModDetails(newMod.id, newMod);
PRINT_DEBUG(" detected mod '%s':\n", mod_folder.c_str());
PRINT_DEBUG(" path (will be used for primary file): '%s'\n", newMod.path.c_str());
PRINT_DEBUG(" images path (will be used for preview file): '%s'\n", mod_images_fullpath.c_str());
PRINT_DEBUG(" primary_filename: '%s'\n", newMod.primaryFileName.c_str());
PRINT_DEBUG(" primary_filesize: %i bytes\n", newMod.primaryFileSize);
PRINT_DEBUG(" primary file handle: %llu\n", settings_client->getMod(newMod.id).handleFile);
PRINT_DEBUG(" preview_filename: '%s'\n", newMod.previewFileName.c_str());
PRINT_DEBUG(" preview_filesize: %i bytes\n", newMod.previewFileSize);
PRINT_DEBUG(" preview file handle: %llu\n", settings_client->getMod(newMod.id).handlePreviewFile);
PRINT_DEBUG(" workshop_item_url: '%s'\n", newMod.workshopItemURL.c_str());
PRINT_DEBUG(" preview_url: '%s'\n", newMod.previewURL.c_str());
} catch (...) {}
}
}
static void parse_mods_folder(class Settings *settings_client, Settings *settings_server, class Local_Storage *local_storage) static void parse_mods_folder(class Settings *settings_client, Settings *settings_server, class Local_Storage *local_storage)
{ {
std::chrono::system_clock::time_point one_week_ago = std::chrono::system_clock::now() - std::chrono::hours(24 * 7); std::string mods_folder = Local_Storage::get_game_settings_path() + "mods";
auto one_week_ago_epoch = std::chrono::duration_cast<std::chrono::seconds>(one_week_ago.time_since_epoch()).count();
std::string mod_path = Local_Storage::get_game_settings_path() + "mods";
nlohmann::json mod_items = nlohmann::json::object(); nlohmann::json mod_items = nlohmann::json::object();
static constexpr auto mods_json_file = "mods.json"; static constexpr auto mods_json_file = "mods.json";
std::string mods_json_path = Local_Storage::get_game_settings_path() + mods_json_file; std::string mods_json_path = Local_Storage::get_game_settings_path() + mods_json_file;
if (local_storage->load_json(mods_json_path, mod_items)) { if (local_storage->load_json(mods_json_path, mod_items)) {
for (auto mod = mod_items.begin(); mod != mod_items.end(); ++mod) { PRINT_DEBUG("Attempting to parse mods.json\n");
try { try_parse_mods_file(settings_client, settings_server, mod_items, mods_folder);
std::string mod_images_folder = Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + std::string(mod.key());
Mod_entry newMod;
newMod.id = std::stoull(mod.key());
newMod.title = mod.value().value("title", std::string(mod.key()));
newMod.path = mod.value().value("path", std::string(""));
if (newMod.path.empty()) {
newMod.path = mod_path + PATH_SEPARATOR + std::string(mod.key());
}
newMod.fileType = k_EWorkshopFileTypeCommunity;
newMod.description = mod.value().value("description", std::string(""));
newMod.steamIDOwner = mod.value().value("steam_id_owner", settings_client->get_local_steam_id().ConvertToUint64());
newMod.timeCreated = mod.value().value("time_created", (uint32)std::chrono::system_clock::now().time_since_epoch().count());
newMod.timeUpdated = mod.value().value("time_updated", (uint32)one_week_ago.time_since_epoch().count());
newMod.timeAddedToUserList = mod.value().value("time_added", (uint32)one_week_ago_epoch);
newMod.visibility = k_ERemoteStoragePublishedFileVisibilityPublic;
newMod.banned = false;
newMod.acceptedForUse = true;
newMod.tagsTruncated = false;
newMod.tags = mod.value().value("tags", std::string(""));
constexpr static auto get_file_size = [](
const std::string &filepath,
const std::string &basepath,
int32 default_val = 0) -> size_t {
try
{
const auto file_p = common_helpers::to_absolute(filepath, basepath);
if (file_p.empty()) return default_val;
size_t size = 0;
if (common_helpers::file_size(file_p, size)) {
return size;
}
} catch(...) {}
return default_val;
};
newMod.primaryFileName = mod.value().value("primary_filename", std::string(""));
int32 primary_filesize = 0;
if (!newMod.primaryFileName.empty()) {
primary_filesize = (int32)get_file_size(newMod.primaryFileName, newMod.path, primary_filesize);
}
newMod.primaryFileSize = mod.value().value("primary_filesize", primary_filesize);
newMod.previewFileName = mod.value().value("preview_filename", std::string(""));
int32 preview_filesize = 0;
if (!newMod.previewFileName.empty()) {
preview_filesize = (int32)get_file_size(
newMod.previewFileName,
mod_images_folder,
preview_filesize);
}
newMod.previewFileSize = mod.value().value("preview_filesize", preview_filesize);
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)1);
newMod.votesDown = mod.value().value("downvotes", (uint32)0);
float score = 1.0f;
try
{
score = newMod.votesUp / (float)(newMod.votesUp + newMod.votesDown);
} catch(...) {}
newMod.score = mod.value().value("score", score);
newMod.numChildren = mod.value().value("num_children", (uint32)0);
newMod.previewURL = mod.value().value("preview_url", std::string(""));
if (newMod.previewURL.empty()) {
if (newMod.previewFileName.empty()) {
newMod.previewURL = std::string();
} else {
auto settings_folder = std::string(Local_Storage::get_game_settings_path());
std::replace(settings_folder.begin(), settings_folder.end(), '\\', '/');
newMod.previewURL = "file://" + settings_folder + "mod_images/" + std::string(mod.key()) + "/" + newMod.previewFileName;
}
}
settings_client->addMod(newMod.id, newMod.title, newMod.path);
settings_server->addMod(newMod.id, newMod.title, newMod.path);
settings_client->addModDetails(newMod.id, newMod);
settings_server->addModDetails(newMod.id, newMod);
PRINT_DEBUG(" parsed mod '%s':\n", std::string(mod.key()).c_str());
PRINT_DEBUG(" path (will be used for primary file): '%s'\n", newMod.path.c_str());
PRINT_DEBUG(" images path (will be used for preview file): '%s'\n", mod_images_folder.c_str());
PRINT_DEBUG(" primary_filename: '%s'\n", newMod.primaryFileName.c_str());
PRINT_DEBUG(" primary_filesize: %i bytes\n", newMod.primaryFileSize);
PRINT_DEBUG(" primary file handle: %llu\n", settings_client->getMod(newMod.id).handleFile);
PRINT_DEBUG(" preview_filename: '%s'\n", newMod.previewFileName.c_str());
PRINT_DEBUG(" preview_filesize: %i bytes\n", newMod.previewFileSize);
PRINT_DEBUG(" preview file handle: %llu\n", settings_client->getMod(newMod.id).handlePreviewFile);
PRINT_DEBUG(" workshop_item_url: '%s'\n", newMod.workshopItemURL.c_str());
PRINT_DEBUG(" preview_url: '%s'\n", newMod.previewURL.c_str());
} catch (std::exception& e) {
PRINT_DEBUG("MODLOADER ERROR: %s\n", e.what());
}
}
} else { // invalid mods.json or doesn't exist } else { // invalid mods.json or doesn't exist
std::vector<std::string> paths = Local_Storage::get_filenames_path(mod_path); PRINT_DEBUG("Failed to load mods.json, attempting to auto detect mods folder\n");
for (auto & p: paths) { try_detect_mods_folder(settings_client, settings_server, mods_folder);
PRINT_DEBUG("mod directory %s\n", p.c_str());
try {
Mod_entry newMod;
newMod.id = std::stoull(p);
newMod.title = p;
newMod.path = mod_path + PATH_SEPARATOR + p;
newMod.fileType = k_EWorkshopFileTypeCommunity;
newMod.description = "";
newMod.steamIDOwner = (uint64)0;
newMod.timeCreated = (uint32)one_week_ago_epoch;
newMod.timeUpdated = (uint32)one_week_ago_epoch;
newMod.timeAddedToUserList = (uint32)one_week_ago_epoch;
newMod.visibility = k_ERemoteStoragePublishedFileVisibilityPublic;
newMod.banned = false;
newMod.acceptedForUse = true;
newMod.tagsTruncated = false;
newMod.tags = "";
newMod.primaryFileName = "";
newMod.primaryFileSize = (int32)0;
newMod.previewFileName = "";
newMod.previewFileSize = (int32)0;
newMod.workshopItemURL = "";
newMod.votesUp = (uint32)1;
newMod.votesDown = (uint32)0;
newMod.score = 1.0f;
newMod.numChildren = (uint32)0;
newMod.previewURL = "";
settings_client->addMod(newMod.id, newMod.title, newMod.path);
settings_server->addMod(newMod.id, newMod.title, newMod.path);
settings_client->addModDetails(newMod.id, newMod);
settings_server->addModDetails(newMod.id, newMod);
} catch (...) {}
}
} }
} }

View File

@ -134,7 +134,7 @@ std::wstring common_helpers::to_upper(std::wstring wstr)
return _wstr; return _wstr;
} }
std::filesystem::path to_absolute_impl(const std::filesystem::path &path, const std::filesystem::path &base) static std::filesystem::path to_absolute_impl(const std::filesystem::path &path, const std::filesystem::path &base)
{ {
if (path.is_absolute()) { if (path.is_absolute()) {
return path; return path;

View File

@ -15,7 +15,7 @@ static std::recursive_mutex f_mtx{};
bool dbg_log::init(const wchar_t *path) bool dbg_log::init(const wchar_t *path)
{ {
auto p = std::filesystem::path(path).string(); auto p = std::filesystem::path(path).u8string();
return init(p.c_str()); return init(p.c_str());
} }