diff --git a/Data/ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml index f275ffa34..a7082fb6f 100644 --- a/Data/ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml +++ b/Data/ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -1,44 +1,44 @@ - - - - Mimic - Greater Mimic + + + + Mimic + Greater Mimic - - Normal - Thermal - Etheric - Voltaic + + Normal + Thermal + Etheric + Voltaic - Nightmare - Poltergeist - Telepath - Technopath + Nightmare + Poltergeist + Telepath + Technopath - - Medical - Engineering - Science - Military + + Medical + Engineering + Science + Military - Turret + Turret - - Wrench - Shotgun - Shotgun Ammo - Pistol - Pistol Ammo - Gloo Gun - Gloo Gun Ammo - Q Beam - Q Beam Ammo - Stun Gun - Stun Gun Ammo + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo diff --git a/Data/MergingLibrary/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/MergingLibrary/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..708ea66e3 --- /dev/null +++ b/Data/MergingLibrary/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,7 @@ + + + + diff --git a/Data/Testing/ChairMerger/FullTestCustomFileMerge/Configs/Mod1.xml b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Configs/Mod1.xml new file mode 100644 index 000000000..f9fdd14c9 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Configs/Mod1.xml @@ -0,0 +1,4 @@ + + + String from mod 1 + diff --git a/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/.chairloader b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/.chairloader new file mode 100644 index 000000000..e69de29bb diff --git a/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..7b7062e5f --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,55 @@ + + + + + Mimic + Greater Mimic + + + + Beanie + Bucket + Crown + Rice + Sombrero + Striped Hat + Top Hat + Witch Hat + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/UI/texture.dds b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/UI/texture.dds new file mode 100644 index 000000000..e59d0d101 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Expected/Main/UI/texture.dds @@ -0,0 +1 @@ +I'm a texture! \ No newline at end of file diff --git a/Data/Testing/ChairMerger/FullTestCustomFileMerge/Mod1/Data/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Mod1/Data/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..5f19f6b9a --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestCustomFileMerge/Mod1/Data/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,15 @@ + + + + + Beanie + Bucket + Crown + Rice + Sombrero + Striped Hat + Top Hat + Witch Hat + + + diff --git a/Data/Testing/ChairMerger/FullTestDllOnly/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestDllOnly/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..64a92d352 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestDllOnly/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/FullTestEverything/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestEverything/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..64a92d352 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestEverything/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/FullTestLevels/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestLevels/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..64a92d352 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestLevels/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/FullTestLocalization/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestLocalization/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..64a92d352 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestLocalization/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/FullTestMain/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/FullTestMain/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..64a92d352 --- /dev/null +++ b/Data/Testing/ChairMerger/FullTestMain/Expected/Main/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/Testing/ChairMerger/_ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml b/Data/Testing/ChairMerger/_ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml new file mode 100644 index 000000000..a7082fb6f --- /dev/null +++ b/Data/Testing/ChairMerger/_ChairloaderPatch/Libs/Chairloader/Trainer/EntitySpawnList.xml @@ -0,0 +1,44 @@ + + + + + Mimic + Greater Mimic + + + + Normal + Thermal + Etheric + Voltaic + + + Nightmare + Poltergeist + Telepath + Technopath + + + + Medical + Engineering + Science + Military + + + Turret + + + Wrench + Shotgun + Shotgun Ammo + Pistol + Pistol Ammo + Gloo Gun + Gloo Gun Ammo + Q Beam + Q Beam Ammo + Stun Gun + Stun Gun Ammo + + diff --git a/Data/XmlTypeLibrary.xml b/Data/XmlTypeLibrary.xml index a744253bc..539e2b62a 100644 --- a/Data/XmlTypeLibrary.xml +++ b/Data/XmlTypeLibrary.xml @@ -1826,5 +1826,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Src/ChairManager/ChairManager.cpp b/Src/ChairManager/ChairManager.cpp index 88bde3250..4d91a1e51 100644 --- a/Src/ChairManager/ChairManager.cpp +++ b/Src/ChairManager/ChairManager.cpp @@ -1024,6 +1024,15 @@ fs::path ChairManager::getConfigPath(std::string &modName) { fs::path ChairManager::getDefaultConfigPath(std::string &modName) { return GetGamePath() / "Mods" / modName / fs::u8path(modName + "_default.xml"); } + +void ChairManager::saveChairloaderConfigFile() +{ + bool result = ChairloaderConfigFile.save_file((GetGamePath().wstring() + L"/Mods/config/Chairloader.xml").c_str()); + + if (!result) + log(severityLevel::error, "Failed to save Chairloader config"); +} + bool ChairManager::LoadModInfoFile(fs::path directory, Mod *mod, bool allowDifferentDirectory) { std::string directoryName = directory.filename().u8string(); pugi::xml_document result; @@ -2625,7 +2634,13 @@ fs::path ChairManager::GetConfigPath() fs::path ChairManager::GetModPath(const std::string& modName) { - return GetGamePath() / "Mods" / fs::u8path(modName); + for (const auto& i : GetMods()) + { + if (i.modName == modName) + return i.path; + } + + return std::string(); } std::vector ChairManager::GetModNames() diff --git a/Src/ChairManager/ChairManager.h b/Src/ChairManager/ChairManager.h index b77fe85a0..d5a431fef 100644 --- a/Src/ChairManager/ChairManager.h +++ b/Src/ChairManager/ChairManager.h @@ -176,9 +176,7 @@ class ChairManager final : public IChairManager { fs::path getDefaultConfigPath(std::string &modName); pugi::xml_document ChairloaderConfigFile, ChairManagerConfigFile; pugi::xml_node ModListNode; - inline bool saveChairloaderConfigFile() { - return ChairloaderConfigFile.save_file((GetGamePath().wstring() + L"/Mods/config/Chairloader.xml").c_str()); - }; + void saveChairloaderConfigFile(); inline bool saveModManagerConfigFile(){ return ChairManagerConfigFile.save_file(ChairManagerConfigPath.string().c_str()); } diff --git a/Src/ChairMerger/Private/ChairMerger.cpp b/Src/ChairMerger/Private/ChairMerger.cpp index 63155354b..628e96399 100644 --- a/Src/ChairMerger/Private/ChairMerger.cpp +++ b/Src/ChairMerger/Private/ChairMerger.cpp @@ -322,23 +322,41 @@ void ChairMerger::Merge() SetDeployPhase(DeployPhase::Merge); SetDeployStep(DeployStep::MergingMods); - m_pBaseFileCache = std::make_unique(); - m_pBaseFileCache->SetRootDir(m_PreyFilesPath); - - for (size_t i = 0; i < m_Mods.size(); i++) + try { - if (!m_ModXmlCaches[i]) + m_pBaseFileCache = std::make_unique(); + m_pBaseFileCache->SetRootDir(m_PreyFilesPath); + + for (size_t i = 0; i < m_Mods.size(); i++) { - m_pLog->Log(severityLevel::debug, "Skipping mod without Data: %s", m_Mods[i].modName); - continue; + if (!m_ModXmlCaches[i]) + { + m_pLog->Log(severityLevel::debug, "Skipping mod without Data: %s", m_Mods[i].modName); + continue; + } + + ProcessMod(i); + WaitForPendingTasks(); + m_pLog->Log(severityLevel::trace, "Finished merging mod: %s", m_Mods[i].modName); } - ProcessMod(i); - WaitForPendingTasks(); - m_pLog->Log(severityLevel::trace, "Finished merging mod: %s", m_Mods[i].modName); + FinalizeFiles(); + } + catch (const std::exception&) + { + // Save files to disk for debugging + try + { + m_pBaseFileCache->ExportModifiedFiles(m_OutputPath); + m_pBaseFileCache.reset(); + } + catch (const std::exception& e) + { + m_pLog->Log(severityLevel::error, "Failed to save modified files: %s", e.what()); + } + + throw; } - - FinalizeFiles(); // Save files to disk m_pBaseFileCache->ExportModifiedFiles(m_OutputPath); @@ -494,17 +512,6 @@ void ChairMerger::ProcessXMLFile( if (mod.type == EModType::Native) ResolveFileWildcards(mod, modDoc.first_child()); - // Load the original file - IXmlCache::ReadLock originalXmlLock; - const pugi::xml_document* originalDoc = nullptr; - - { - IXmlCache::EOpenResult result = m_pOriginalFileCache->TryOpenXmlForReading(relativePath, &originalDoc, originalXmlLock, parseTags); - - if (result != IXmlCache::EOpenResult::NotFound) - IXmlCache::ThrowForResult(result); - } - // if we have an original result, we can actually do some merging if (fileMergingPolicy.GetMethod() == FileMergingPolicy3::EMethod::Replace) { @@ -519,6 +526,17 @@ void ChairMerger::ProcessXMLFile( // Convert legacy mod into a Chairloader mod if (mod.type == EModType::Legacy) { + // Load the original file + IXmlCache::ReadLock originalXmlLock; + const pugi::xml_document* originalDoc = nullptr; + + { + IXmlCache::EOpenResult result = m_pOriginalFileCache->TryOpenXmlForReading(relativePath, &originalDoc, originalXmlLock, parseTags); + + if (result != IXmlCache::EOpenResult::NotFound) + IXmlCache::ThrowForResult(result); + } + // Move mod into a temp doc // modDoc will be replaced with converted mod pugi::xml_document legacyModDoc = std::move(modDoc); @@ -621,8 +639,8 @@ void ChairMerger::ProcessXMLFile( modDoc = std::move(legacyModDoc); } - // If original file doesn't exist, overwrite the base file. - if (!originalDoc) + // If base file is empty, overwrite the base file. + if (!baseDoc.first_child()) { // Replace the entire file baseDoc = std::move(modDoc); diff --git a/Src/ChairMerger/Private/XmlFinalizer3.cpp b/Src/ChairMerger/Private/XmlFinalizer3.cpp index b542546ef..c02a20056 100644 --- a/Src/ChairMerger/Private/XmlFinalizer3.cpp +++ b/Src/ChairMerger/Private/XmlFinalizer3.cpp @@ -143,6 +143,9 @@ void XmlFinalizer3::FinalizeNode( for (pugi::xml_node childNode : node.children()) { + if (childNode.type() != pugi::node_element) + continue; + XmlErrorStack childErrorStack = errorStack.GetChild(childNode); childErrorStack.SetIndex(i); diff --git a/Src/ChairMerger/Tests/ModMerging.cpp b/Src/ChairMerger/Tests/ModMerging.cpp index 32427f9c3..e47238af9 100644 --- a/Src/ChairMerger/Tests/ModMerging.cpp +++ b/Src/ChairMerger/Tests/ModMerging.cpp @@ -115,6 +115,7 @@ class ChairMergerTestFullMerging TEST_P(ChairMergerTestFullMerging, FullTest) { + CrySleep(5000); InitTest(GetParam()); LoadMods(); CreateMerger(); @@ -168,6 +169,7 @@ TEST_P(ChairMergerTestFullMerging, FullTest) } const auto FULL_TEST_NAMES = testing::Values( + "FullTestCustomFileMerge", "FullTestDllOnly", "FullTestMain", "FullTestLocalization", diff --git a/Src/Preditor/Assets/Merging/Mergers/XmlAssetMerger.cpp b/Src/Preditor/Assets/Merging/Mergers/XmlAssetMerger.cpp index 745a427db..12a5b3140 100644 --- a/Src/Preditor/Assets/Merging/Mergers/XmlAssetMerger.cpp +++ b/Src/Preditor/Assets/Merging/Mergers/XmlAssetMerger.cpp @@ -97,7 +97,7 @@ void Assets::XmlAssetMerger::DoMerge(const std::vector& inputFiles) CRY_ASSERT(!inputFiles.empty()); // First file is the base - baseDoc = ReadFile(*inputFiles.rbegin()); + baseDoc = ReadFile(*inputFiles.begin()); // Since it's already "merged", skip it inputFileIdx = 1;