Skip to content

Commit

Permalink
🐛 Fixed mods not loading from app_extra_mod_path
Browse files Browse the repository at this point in the history
Fixes #3149

Problem was caused by myself in 74ed108 - apart from fixing the bug, I also made a cosmetic edit of resource group names - Instead of it being 'bundle $FULLPATH', I made it '{bundle $LOCALPATH}'. But I botched the code, causing exception "invalid string position" to be thrown.

Solution: keep pretifying the resource group names, but account for all locations. I added a location-label to the name to avoid RG name clashes.
* prepackaged mods, i.e. {bundle BIN:\content\simple2-terrain.zip}
* extra mod path, i.e. {bundle EXTRA:\DI_SportsCar.zip}
* mod dirs under user profile, i.e. {bundle USER:\mods\vehicles\Desperado.zip}
  • Loading branch information
ohlidalp committed Jun 30, 2024
1 parent d992377 commit 05f71f5
Showing 1 changed file with 50 additions and 8 deletions.
58 changes: 50 additions & 8 deletions source/main/resources/CacheSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,18 +1339,60 @@ bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& gro
return false;
}

static bool CheckAndReplacePathIgnoreCase(const CacheEntryPtr& entry, CVar* dir, const std::string& dir_label, std::string& out_rgname)
{
// Helper for `ComposeResourceGroupName()`
// ---------------------------------------

// Sanity check - assert on Debug, minimize damage on Release
ROR_ASSERT(entry->resource_bundle_path != "");
if (entry->resource_bundle_path == "")
{
LOG(fmt::format("[RoR|CacheSystem] CheckAndReplacePathIgnoreCase(): INTERNAL ERROR - entry '{}' has no bundle path!", entry->fname));
return false;
}

// Lowercase everything
std::string lower_bundlepath = entry->resource_bundle_path;
Ogre::StringUtil::toLowerCase(lower_bundlepath);

std::string lower_dir = dir->getStr();
Ogre::StringUtil::toLowerCase(lower_dir);

// Look for match and replace
if (Ogre::StringUtil::startsWith(lower_bundlepath, lower_dir, /*lowercase:*/true))
{
// Sanity check; Should be guaranteed by the `startsWith()` check, but just to be sure...
ROR_ASSERT(lower_bundlepath.size() > lower_dir.size());
if (lower_bundlepath.size() > lower_dir.size())
{
std::string localpath = entry->resource_bundle_path.substr(lower_dir.length());
out_rgname = fmt::format("{{bundle {}:{}}}", dir_label, localpath);
return true;
}
}
return false;
}

std::string CacheSystem::ComposeResourceGroupName(const CacheEntryPtr& entry)
{
// Compose group name as "{bundle <local path>}",
// where 'local path' means under 'Documenst\My Games\Rigs of Rods'.
// -----------------------------------------------------------------
std::string name = entry->resource_bundle_path; // Start from full path
size_t prefix_pos = name.find_first_not_of(App::sys_user_dir->getStr());
if (prefix_pos != std::string::npos)
// Compose group name as "{bundle <local path>}", where 'local path' means either:
// - under `sys_user_dir` (by default 'Documenst\My Games\Rigs of Rods')
// - under `app_extra_mod_path` (empty by default)
// - under 'sys_process_dir' (autodetected)
// -------------------------------------------------------------------------------

std::string rg_name;
if (CheckAndReplacePathIgnoreCase(entry, App::sys_user_dir, "USER", rg_name) ||
CheckAndReplacePathIgnoreCase(entry, App::sys_process_dir, "BIN", rg_name) ||
CheckAndReplacePathIgnoreCase(entry, App::app_extra_mod_path, "EXTRA", rg_name))
{
return rg_name;
}
else
{
name = name.substr(App::sys_user_dir->getStr().length());
return fmt::format("{{bundle FULL:{}}}", entry->resource_bundle_path);
}
return fmt::format("{{bundle {}}}", name);
}

void CacheSystem::LoadSupplementaryDocuments(CacheEntryPtr& entry)
Expand Down

0 comments on commit 05f71f5

Please sign in to comment.