Skip to content

Commit 09a8d75

Browse files
committed
fix: Not parsing mods.txt from all available mods paths
Toggleable by 'ParseModsFromAdditionalPaths' in the Overrides section in UE4SS-settings.ini Defaults to being enabled.
1 parent c4b5add commit 09a8d75

File tree

18 files changed

+164
-89
lines changed

18 files changed

+164
-89
lines changed

UE4SS/include/SettingsManager.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace RC
1616
struct SectionOverrides
1717
{
1818
File::StringType ModsFolderPath{};
19-
std::vector<File::StringType> ModsFolderPaths{};
19+
bool ParseModsFromAdditionalPaths{true};
2020
} Overrides;
2121

2222
struct SectionGeneral

UE4SS/src/SettingsManager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ namespace RC
6868
}
6969
});
7070

71+
REGISTER_BOOL_SETTING(Overrides.ParseModsFromAdditionalPaths, section_overrides, ParseModsFromAdditionalPaths)
72+
7173
constexpr static File::CharType section_general[] = STR("General");
7274
REGISTER_BOOL_SETTING(General.EnableHotReloadSystem, section_general, EnableHotReloadSystem)
7375
StringType hot_reload_key{};

UE4SS/src/UE4SSProgram.cpp

Lines changed: 101 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,119 +1304,132 @@ namespace RC
13041304
auto start_mods() -> std::string
13051305
{
13061306
ProfilerScope();
1307-
// Part #1: Start all mods that are enabled in mods.txt.
1308-
Output::send(STR("Starting mods (from mods.txt load order)...\n"));
13091307

1310-
std::filesystem::path mods_directory = UE4SSProgram::get_program().get_mods_directory();
1311-
std::wstring enabled_mods_file{mods_directory / "mods.txt"};
1312-
if (!std::filesystem::exists(enabled_mods_file))
1308+
const auto& main_mods_directory = UE4SSProgram::get_program().get_mods_directory();
1309+
for (const auto& mods_directory : std::ranges::reverse_view(UE4SSProgram::get_program().get_mods_directories()))
13131310
{
1314-
Output::send(STR("No mods.txt file found...\n"));
1315-
}
1316-
else
1317-
{
1318-
// 'mods.txt' exists, lets parse it
1311+
if (!std::filesystem::exists(mods_directory))
1312+
{
1313+
continue;
1314+
}
1315+
1316+
// Only parse mods.txt from allowed directories.
1317+
if (UE4SSProgram::settings_manager.Overrides.ParseModsFromAdditionalPaths || mods_directory == main_mods_directory)
1318+
{
1319+
// Part #1: Start all mods that are enabled in mods.txt.
1320+
std::wstring enabled_mods_file{mods_directory / "mods.txt"};
1321+
if (!std::filesystem::exists(enabled_mods_file))
1322+
{
1323+
Output::send(STR("No mods.txt file found...\n"));
1324+
}
1325+
else
1326+
{
1327+
// 'mods.txt' exists, lets parse it
1328+
Output::send(STR("Starting mods (from mods.txt ({}) load order)...\n"), ensure_str(enabled_mods_file));
1329+
1330+
// First, check for BOM using a byte stream
1331+
std::ifstream bom_check(enabled_mods_file, std::ios::binary);
1332+
char bom[3] = {0};
1333+
bom_check.read(bom, 3);
1334+
bool has_bom = (bom[0] == '\xEF' && bom[1] == '\xBB' && bom[2] == '\xBF');
1335+
bom_check.close();
1336+
1337+
// Now open the actual stream
1338+
StreamIType mods_stream{enabled_mods_file};
1339+
1340+
// If BOM was detected, skip the first "character" (which will be the BOM interpreted as a wide char)
1341+
if (has_bom)
1342+
{
1343+
wchar_t discard;
1344+
mods_stream.get(discard);
1345+
}
1346+
1347+
StringType current_line;
1348+
while (std::getline(mods_stream, current_line))
1349+
{
1350+
// Don't parse any lines with ';'
1351+
if (current_line.find(STR(";")) != current_line.npos)
1352+
{
1353+
continue;
1354+
}
1355+
1356+
// Don't parse if the line is impossibly short (empty lines for example)
1357+
if (current_line.size() <= 4)
1358+
{
1359+
continue;
1360+
}
13191361

1320-
// First, check for BOM using a byte stream
1321-
std::ifstream bom_check(enabled_mods_file, std::ios::binary);
1322-
char bom[3] = {0};
1323-
bom_check.read(bom, 3);
1324-
bool has_bom = (bom[0] == '\xEF' && bom[1] == '\xBB' && bom[2] == '\xBF');
1325-
bom_check.close();
1362+
// Remove all spaces
1363+
auto end = std::remove(current_line.begin(), current_line.end(), STR(' '));
1364+
current_line.erase(end, current_line.end());
13261365

1327-
// Now open the actual stream
1328-
StreamIType mods_stream{enabled_mods_file};
1366+
// Parse the line into something that can be converted into proper data
1367+
StringType mod_name = explode_by_occurrence(current_line, STR(':'), 1);
1368+
StringType mod_enabled = explode_by_occurrence(current_line, STR(':'), ExplodeType::FromEnd);
13291369

1330-
// If BOM was detected, skip the first "character" (which will be the BOM interpreted as a wide char)
1331-
if (has_bom) {
1332-
wchar_t discard;
1333-
mods_stream.get(discard);
1370+
auto mod = UE4SSProgram::find_mod_by_name<ModType>(mod_name, UE4SSProgram::IsInstalled::Yes);
1371+
if (!mod || !dynamic_cast<ModType*>(mod) || mod->is_started())
1372+
{
1373+
continue;
1374+
}
1375+
1376+
if (!mod_enabled.empty() && mod_enabled[0] == STR('1'))
1377+
{
1378+
Output::send(STR("Starting {} mod '{}'\n"), std::is_same_v<ModType, LuaMod> ? STR("Lua") : STR("C++"), mod->get_name().data());
1379+
mod->start_mod();
1380+
}
1381+
else
1382+
{
1383+
Output::send(STR("Mod '{}' disabled in mods.txt.\n"), mod_name);
1384+
}
1385+
}
1386+
}
13341387
}
13351388

1336-
StringType current_line;
1337-
while (std::getline(mods_stream, current_line))
1389+
// Part #2: Start all mods that have enabled.txt present in the mod directory.
1390+
Output::send(STR("Starting mods (from enabled.txt ({}), no defined load order)...\n"), ensure_str(mods_directory));
1391+
1392+
for (const auto& mod_directory : std::filesystem::directory_iterator(mods_directory))
13381393
{
1339-
// Don't parse any lines with ';'
1340-
if (current_line.find(STR(";")) != current_line.npos)
1394+
std::error_code ec{};
1395+
1396+
if (!mod_directory.is_directory(ec))
13411397
{
13421398
continue;
13431399
}
1344-
1345-
// Don't parse if the line is impossibly short (empty lines for example)
1346-
if (current_line.size() <= 4)
1400+
if (ec.value() != 0)
13471401
{
1348-
continue;
1402+
return fmt::format("is_directory ran into error {}", ec.value());
13491403
}
13501404

1351-
// Remove all spaces
1352-
auto end = std::remove(current_line.begin(), current_line.end(), STR(' '));
1353-
current_line.erase(end, current_line.end());
1354-
1355-
// Parse the line into something that can be converted into proper data
1356-
StringType mod_name = explode_by_occurrence(current_line, STR(':'), 1);
1357-
StringType mod_enabled = explode_by_occurrence(current_line, STR(':'), ExplodeType::FromEnd);
1358-
1359-
auto mod = UE4SSProgram::find_mod_by_name<ModType>(mod_name, UE4SSProgram::IsInstalled::Yes);
1360-
if (!mod || !dynamic_cast<ModType*>(mod))
1405+
if (!std::filesystem::exists(mod_directory.path() / "enabled.txt", ec))
13611406
{
13621407
continue;
13631408
}
1409+
if (ec.value() != 0)
1410+
{
1411+
return fmt::format("exists ran into error {}", ec.value());
1412+
}
13641413

1365-
if (!mod_enabled.empty() && mod_enabled[0] == STR('1'))
1414+
auto mod = UE4SSProgram::find_mod_by_name<ModType>(ensure_str(mod_directory.path().stem()), UE4SSProgram::IsInstalled::Yes);
1415+
if (!dynamic_cast<ModType*>(mod))
13661416
{
1367-
Output::send(STR("Starting {} mod '{}'\n"), std::is_same_v<ModType, LuaMod> ? STR("Lua") : STR("C++"), mod->get_name().data());
1368-
mod->start_mod();
1417+
continue;
13691418
}
1370-
else
1419+
if (!mod)
13711420
{
1372-
Output::send(STR("Mod '{}' disabled in mods.txt.\n"), mod_name);
1421+
Output::send<LogLevel::Warning>(STR("Found a mod with enabled.txt but mod has not been installed properly.\n"));
1422+
continue;
13731423
}
1374-
}
1375-
}
1376-
1377-
// Part #2: Start all mods that have enabled.txt present in the mod directory.
1378-
Output::send(STR("Starting mods (from enabled.txt, no defined load order)...\n"));
1379-
1380-
for (const auto& mod_directory : std::filesystem::directory_iterator(mods_directory))
1381-
{
1382-
std::error_code ec{};
1383-
1384-
if (!mod_directory.is_directory(ec))
1385-
{
1386-
continue;
1387-
}
1388-
if (ec.value() != 0)
1389-
{
1390-
return fmt::format("is_directory ran into error {}", ec.value());
1391-
}
1392-
1393-
if (!std::filesystem::exists(mod_directory.path() / "enabled.txt", ec))
1394-
{
1395-
continue;
1396-
}
1397-
if (ec.value() != 0)
1398-
{
1399-
return fmt::format("exists ran into error {}", ec.value());
1400-
}
14011424

1402-
auto mod = UE4SSProgram::find_mod_by_name<ModType>(ensure_str(mod_directory.path().stem()), UE4SSProgram::IsInstalled::Yes);
1403-
if (!dynamic_cast<ModType*>(mod))
1404-
{
1405-
continue;
1406-
}
1407-
if (!mod)
1408-
{
1409-
Output::send<LogLevel::Warning>(STR("Found a mod with enabled.txt but mod has not been installed properly.\n"));
1410-
continue;
1411-
}
1425+
if (mod->is_started())
1426+
{
1427+
continue;
1428+
}
14121429

1413-
if (mod->is_started())
1414-
{
1415-
continue;
1430+
Output::send(STR("Mod '{}' has enabled.txt, starting mod.\n"), mod->get_name().data());
1431+
mod->start_mod();
14161432
}
1417-
1418-
Output::send(STR("Mod '{}' has enabled.txt, starting mod.\n"), mod->get_name().data());
1419-
mod->start_mod();
14201433
}
14211434

14221435
return {};

assets/Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ Fixed `LoadMod` function issue that variables would go out-of-scope in the `Exec
444444
; -ModsFolderPaths = ../SharedMods
445445
; Default: none
446446

447+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
448+
; Default: 1
449+
ParseModsFromAdditionalPaths =
450+
447451
[General]
448452
; The key that will trigger a reload of all mods.
449453
; The CTRL key is always required.

assets/CustomGameConfigs/Atomic Heart/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

assets/CustomGameConfigs/Borderlands 3/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

assets/CustomGameConfigs/Deadly Days Roadtrip/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

assets/CustomGameConfigs/Final Fantasy 7 Rebirth/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

assets/CustomGameConfigs/Final Fantasy 7 Remake/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

assets/CustomGameConfigs/Kingdom Hearts 3/UE4SS-settings.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ ModsFolderPath =
1313
; -ModsFolderPaths = ../SharedMods
1414
; Default: None
1515

16+
; Whether to parse 'mods.txt' from the additional paths set by 'ModsFolderPath', and 'ModsFolderPaths' options.
17+
; Default: 1
18+
ParseModsFromAdditionalPaths =
19+
1620
[General]
1721
; Whether to reload all mods when the key defined by HotReloadKey is hit.
1822
; Default: 1

0 commit comments

Comments
 (0)