diff --git a/src/ModMan/Context/FastFileContext.cpp b/src/ModMan/Context/FastFileContext.cpp index 220802f9..c01a1ae3 100644 --- a/src/ModMan/Context/FastFileContext.cpp +++ b/src/ModMan/Context/FastFileContext.cpp @@ -2,9 +2,6 @@ #include "Game/AutoSearchPaths.h" #include "IObjLoader.h" -#include "SearchPath/IWD.h" -#include "SearchPath/SearchPathFilesystem.h" -#include "Utils/StringUtils.h" #include "Web/Binds/ZoneBinds.h" #include "Web/UiCommunication.h" #include "ZoneLoading.h" @@ -41,89 +38,15 @@ namespace std::string m_zone_name; double m_last_progress; }; - - std::unique_ptr CreateSearchPath(const std::string& searchPathStr) - { - auto searchPath = std::make_unique(searchPathStr); - con::debug("Loaded search path \"{}\"", searchPathStr); - - SearchPaths searchPaths; - bool hasIwds = false; - - std::filesystem::directory_iterator iterator(searchPathStr); - const auto end = fs::end(iterator); - for (auto i = fs::begin(iterator); i != end; ++i) - { - if (!i->is_regular_file()) - continue; - - auto extension = i->path().extension().string(); - utils::MakeStringLowerCase(extension); - if (extension == ".iwd") - { - std::string iwdPath = i->path().string(); - auto iwd = iwd::LoadFromFile(iwdPath); - if (iwd) - { - if (!hasIwds) - { - searchPaths.CommitSearchPath(std::move(searchPath)); - hasIwds = true; - } - - searchPaths.CommitSearchPath(std::move(iwd)); - con::debug("Loaded search path \"{}\"", iwdPath); - } - } - } - - if (hasIwds) - return std::make_unique(std::move(searchPaths)); - - return searchPath; - } } // namespace -ContextSearchPath::ContextSearchPath(std::unique_ptr searchPath) - : m_search_path(std::move(searchPath)), - m_ref_count(1) -{ -} - -LoadedZone::LoadedZone(std::unique_ptr zone, std::string filePath, std::vector searchPaths) - : m_zone(std::move(zone)), - m_file_path(std::move(filePath)), - m_search_paths(std::move(searchPaths)) -{ -} - -Zone& LoadedZone::GetZone() -{ - return *m_zone; -} - -const Zone& LoadedZone::GetZone() const -{ - return *m_zone; -} - -const std::string& LoadedZone::GetFilePath() const -{ - return m_file_path; -} - -const std::vector& LoadedZone::GetSearchPaths() const -{ - return m_search_paths; -} - void FastFileContext::Destroy() { // Unload all zones m_loaded_zones.clear(); } -std::expected FastFileContext::LoadFastFile(const std::string& path) +std::expected FastFileContext::LoadFastFile(const std::string& path) { auto zone = ZoneLoading::LoadZone(path, std::make_unique(fs::path(path).filename().replace_extension().string())); if (!zone) @@ -133,24 +56,12 @@ std::expected FastFileContext::LoadFastFile(const std: { std::lock_guard lock(m_search_path_lock); for (const auto& searchPathStr : searchPathsForZone) - { - const auto existingSearchPath = m_context_search_paths.find(searchPathStr); - if (existingSearchPath == m_context_search_paths.end()) - { - auto searchPath = CreateSearchPath(searchPathStr); - m_search_paths.IncludeSearchPath(searchPath.get()); - m_context_search_paths.emplace(searchPathStr, std::make_unique(std::move(searchPath))); - } - else - { - existingSearchPath->second->m_ref_count++; - } - } + m_shared_search_paths.RefSearchPath(searchPathStr); } - auto loadedZone = std::make_unique(std::move(*zone), path, std::move(searchPathsForZone)); + auto loadedZone = std::make_unique(std::move(*zone), path, std::move(searchPathsForZone)); - LoadedZone* loadedZonePtr; + LoadedZoneInformation* loadedZonePtr; { std::lock_guard lock(m_zone_lock); loadedZonePtr = m_loaded_zones.emplace_back(std::move(loadedZone)).get(); @@ -158,7 +69,8 @@ std::expected FastFileContext::LoadFastFile(const std: { std::shared_lock lock(m_search_path_lock); - IObjLoader::GetObjLoaderForGame(loadedZonePtr->GetZone().m_game_id)->LoadReferencedContainersForZone(m_search_paths, loadedZonePtr->GetZone()); + auto* objLoader = IObjLoader::GetObjLoaderForGame(loadedZonePtr->GetZone().m_game_id); + objLoader->LoadReferencedContainersForZone(m_shared_search_paths.GetSearchPath(), loadedZonePtr->GetZone()); } ui::NotifyZoneLoaded(*loadedZonePtr); @@ -168,12 +80,12 @@ std::expected FastFileContext::LoadFastFile(const std: std::expected FastFileContext::UnloadZone(const std::string& zoneName) { - std::unique_ptr removedLoadedZone; + std::unique_ptr removedLoadedZone; { std::lock_guard lock(m_zone_lock); const auto existingZone = std::ranges::find_if(m_loaded_zones, - [&zoneName](const std::unique_ptr& loadedZone) + [&zoneName](const std::unique_ptr& loadedZone) { return loadedZone->GetZone().m_name == zoneName; }); @@ -197,32 +109,18 @@ std::expected FastFileContext::UnloadZone(const std::string& { std::lock_guard lock(m_search_path_lock); for (const auto& searchPathStr : removedLoadedZone->GetSearchPaths()) - { - const auto existingSearchPath = m_context_search_paths.find(searchPathStr); - if (existingSearchPath != m_context_search_paths.end()) - { - assert(existingSearchPath->second->m_ref_count > 0); - const auto newRefCount = --existingSearchPath->second->m_ref_count; - - if (newRefCount == 0) - { - m_search_paths.RemoveSearchPath(existingSearchPath->second->m_search_path.get()); - m_context_search_paths.erase(existingSearchPath); - con::debug("Unloaded search path \"{}\"", searchPathStr); - } - } - } + m_shared_search_paths.UnrefSearchPath(searchPathStr); } return {}; } -ReadAccess>> FastFileContext::GetLoadedZones() +ReadAccess>> FastFileContext::GetLoadedZones() { - return ReadAccess>>(std::shared_lock(m_zone_lock), m_loaded_zones); + return ReadAccess>>(std::shared_lock(m_zone_lock), m_loaded_zones); } ReadAccess FastFileContext::GetSearchPaths() { - return ReadAccess(std::shared_lock(m_search_path_lock), m_search_paths); + return ReadAccess(std::shared_lock(m_search_path_lock), m_shared_search_paths.GetSearchPath()); } diff --git a/src/ModMan/Context/FastFileContext.h b/src/ModMan/Context/FastFileContext.h index 73aaf66c..acbcb496 100644 --- a/src/ModMan/Context/FastFileContext.h +++ b/src/ModMan/Context/FastFileContext.h @@ -1,41 +1,15 @@ #pragma once -#include "SearchPath/SearchPaths.h" +#include "SearchPath/SharedSearchPaths.h" +#include "Zone/LoadedZoneInformation.h" #include "Zone/Zone.h" #include #include #include #include -#include #include -class ContextSearchPath -{ -public: - explicit ContextSearchPath(std::unique_ptr searchPath); - - std::unique_ptr m_search_path; - unsigned m_ref_count; -}; - -class LoadedZone -{ -public: - LoadedZone(std::unique_ptr zone, std::string filePath, std::vector searchPaths); - - [[nodiscard]] Zone& GetZone(); - [[nodiscard]] const Zone& GetZone() const; - - [[nodiscard]] const std::string& GetFilePath() const; - [[nodiscard]] const std::vector& GetSearchPaths() const; - -private: - std::unique_ptr m_zone; - std::string m_file_path; - std::vector m_search_paths; -}; - template class ReadAccess { public: @@ -60,17 +34,16 @@ class FastFileContext public: void Destroy(); - std::expected LoadFastFile(const std::string& path); + std::expected LoadFastFile(const std::string& path); std::expected UnloadZone(const std::string& zoneName); - ReadAccess>> GetLoadedZones(); + ReadAccess>> GetLoadedZones(); ReadAccess GetSearchPaths(); private: - std::vector> m_loaded_zones; + std::vector> m_loaded_zones; std::shared_mutex m_zone_lock; - SearchPaths m_search_paths; - std::unordered_map> m_context_search_paths; + SharedSearchPaths m_shared_search_paths; std::shared_mutex m_search_path_lock; }; diff --git a/src/ModMan/Web/Binds/UnlinkingBinds.cpp b/src/ModMan/Web/Binds/UnlinkingBinds.cpp index 82d14dd7..0df00a7b 100644 --- a/src/ModMan/Web/Binds/UnlinkingBinds.cpp +++ b/src/ModMan/Web/Binds/UnlinkingBinds.cpp @@ -57,7 +57,7 @@ namespace auto& context = ModManContext::Get().m_fast_file; const auto loadedZones = context.GetLoadedZones(); const auto existingZone = std::ranges::find_if(loadedZones.Data(), - [&zoneName](const std::unique_ptr& loadedZone) + [&zoneName](const std::unique_ptr& loadedZone) { return loadedZone->GetZone().m_name == zoneName; }); diff --git a/src/ModMan/Web/Binds/ZoneBinds.cpp b/src/ModMan/Web/Binds/ZoneBinds.cpp index 298727c8..c6a94f3c 100644 --- a/src/ModMan/Web/Binds/ZoneBinds.cpp +++ b/src/ModMan/Web/Binds/ZoneBinds.cpp @@ -61,7 +61,7 @@ namespace NLOHMANN_DEFINE_TYPE_EXTENSION(ZoneUnloadedDto, zoneName); - ZoneDto CreateZoneDto(const LoadedZone& loadedZone) + ZoneDto CreateZoneDto(const LoadedZoneInformation& loadedZone) { return ZoneDto{ .name = loadedZone.GetZone().m_name, @@ -149,7 +149,7 @@ namespace ui Notify(*ModManContext::Get().m_main_window, "zoneLoadProgress", dto); } - void NotifyZoneLoaded(const LoadedZone& loadedZone) + void NotifyZoneLoaded(const LoadedZoneInformation& loadedZone) { const ZoneLoadedDto dto{ .zone = CreateZoneDto(loadedZone), diff --git a/src/ModMan/Web/Binds/ZoneBinds.h b/src/ModMan/Web/Binds/ZoneBinds.h index 3cbcef14..c0b68d13 100644 --- a/src/ModMan/Web/Binds/ZoneBinds.h +++ b/src/ModMan/Web/Binds/ZoneBinds.h @@ -6,7 +6,7 @@ namespace ui { void NotifyZoneLoadProgress(std::string zoneName, double percentage); - void NotifyZoneLoaded(const LoadedZone& loadedZone); + void NotifyZoneLoaded(const LoadedZoneInformation& loadedZone); void NotifyZoneUnloaded(std::string zoneName); void RegisterZoneBinds(webwindowed::commands_builder& commands); diff --git a/src/ObjLoading/SearchPath/IWD.cpp b/src/ObjCommon/SearchPath/IWD.cpp similarity index 99% rename from src/ObjLoading/SearchPath/IWD.cpp rename to src/ObjCommon/SearchPath/IWD.cpp index 3b562b8d..0d04354d 100644 --- a/src/ObjLoading/SearchPath/IWD.cpp +++ b/src/ObjCommon/SearchPath/IWD.cpp @@ -1,6 +1,5 @@ #include "IWD.h" -#include "ObjLoading.h" #include "Utils/FileToZlibWrapper.h" #include "Utils/Logging/Log.h" diff --git a/src/ObjLoading/SearchPath/IWD.h b/src/ObjCommon/SearchPath/IWD.h similarity index 100% rename from src/ObjLoading/SearchPath/IWD.h rename to src/ObjCommon/SearchPath/IWD.h diff --git a/src/ObjCommon/SearchPath/SharedSearchPaths.cpp b/src/ObjCommon/SearchPath/SharedSearchPaths.cpp new file mode 100644 index 00000000..7223ec2b --- /dev/null +++ b/src/ObjCommon/SearchPath/SharedSearchPaths.cpp @@ -0,0 +1,115 @@ +#include "SharedSearchPaths.h" + +#include "SearchPath/IWD.h" +#include "SearchPathFilesystem.h" +#include "Utils/Logging/Log.h" +#include "Utils/StringUtils.h" + +#include +#include + +namespace fs = std::filesystem; + +namespace +{ + std::unique_ptr CreateSearchPath(const std::string& searchPathStr) + { + auto searchPath = std::make_unique(searchPathStr); + con::info("Loaded search path \"{}\"", searchPathStr); + + SearchPaths searchPaths; + bool hasIwds = false; + + std::filesystem::directory_iterator iterator(searchPathStr); + const auto end = fs::end(iterator); + for (auto i = fs::begin(iterator); i != end; ++i) + { + if (!i->is_regular_file()) + continue; + + auto extension = i->path().extension().string(); + utils::MakeStringLowerCase(extension); + if (extension == ".iwd") + { + std::string iwdPath = i->path().string(); + auto iwd = iwd::LoadFromFile(iwdPath); + if (iwd) + { + if (!hasIwds) + { + searchPaths.CommitSearchPath(std::move(searchPath)); + hasIwds = true; + } + + searchPaths.CommitSearchPath(std::move(iwd)); + } + } + } + + if (hasIwds) + return std::make_unique(std::move(searchPaths)); + + return searchPath; + } +} // namespace + +SharedSearchPathEntry::SharedSearchPathEntry(std::unique_ptr searchPath) + : m_search_path(std::move(searchPath)), + m_ref_count(1) +{ +} + +SharedSearchPaths::SharedSearchPaths() = default; + +SharedSearchPaths::~SharedSearchPaths() +{ + Clear(); +} + +void SharedSearchPaths::Clear() +{ + for (auto& entry : m_search_path_entries) + { + entry.second.reset(); + con::info("Unloaded search path \"{}\"", entry.first); + } + m_search_path_entries.clear(); + m_search_paths = SearchPaths(); +} + +ISearchPath& SharedSearchPaths::GetSearchPath() +{ + return m_search_paths; +} + +void SharedSearchPaths::RefSearchPath(const std::string& searchPathStr) +{ + const auto existingSearchPath = m_search_path_entries.find(searchPathStr); + if (existingSearchPath == m_search_path_entries.end()) + { + auto searchPath = CreateSearchPath(searchPathStr); + m_search_paths.IncludeSearchPath(searchPath.get()); + m_search_path_entries.emplace(searchPathStr, std::make_unique(std::move(searchPath))); + } + else + { + existingSearchPath->second->m_ref_count++; + } +} + +void SharedSearchPaths::UnrefSearchPath(const std::string& searchPathStr) +{ + const auto existingSearchPath = m_search_path_entries.find(searchPathStr); + if (existingSearchPath != m_search_path_entries.end()) + { + assert(existingSearchPath->second->m_ref_count > 0); + const auto newRefCount = --existingSearchPath->second->m_ref_count; + + if (newRefCount == 0) + { + m_search_paths.RemoveSearchPath(existingSearchPath->second->m_search_path.get()); + m_search_path_entries.erase(existingSearchPath); + con::info("Unloaded search path \"{}\"", searchPathStr); + } + } +} diff --git a/src/ObjCommon/SearchPath/SharedSearchPaths.h b/src/ObjCommon/SearchPath/SharedSearchPaths.h new file mode 100644 index 00000000..0eab80f4 --- /dev/null +++ b/src/ObjCommon/SearchPath/SharedSearchPaths.h @@ -0,0 +1,39 @@ +#pragma once + +#include "SearchPaths.h" + +#include +#include +#include + +class SharedSearchPathEntry +{ +public: + explicit SharedSearchPathEntry(std::unique_ptr searchPath); + + std::unique_ptr m_search_path; + unsigned m_ref_count; +}; + +class SharedSearchPaths +{ +public: + SharedSearchPaths(); + ~SharedSearchPaths(); + + SharedSearchPaths(const SharedSearchPaths& other) = delete; + SharedSearchPaths(SharedSearchPaths&& other) noexcept = default; + SharedSearchPaths& operator=(const SharedSearchPaths& other) = delete; + SharedSearchPaths& operator=(SharedSearchPaths&& other) noexcept = default; + + void Clear(); + + [[nodiscard]] ISearchPath& GetSearchPath(); + + void RefSearchPath(const std::string& searchPathStr); + void UnrefSearchPath(const std::string& searchPathStr); + +private: + SearchPaths m_search_paths; + std::unordered_map> m_search_path_entries; +}; diff --git a/src/ObjLoading/Game/AutoSearchPaths.cpp b/src/ObjLoading/Game/AutoSearchPaths.cpp index f754a055..dc5dc5c4 100644 --- a/src/ObjLoading/Game/AutoSearchPaths.cpp +++ b/src/ObjLoading/Game/AutoSearchPaths.cpp @@ -2,6 +2,7 @@ #include "IW3/AutoSearchPathsIW3.h" #include "IW4/AutoSearchPathsIW4.h" +#include "IW4/InfoString/InfoStringToStructConverter.h" #include "IW5/AutoSearchPathsIW5.h" #include "T4/AutoSearchPathsT4.h" #include "T5/AutoSearchPathsT5.h" @@ -45,6 +46,8 @@ std::vector AutoSearchPaths::GetSearchPathsForZonePath(const std::s if (!maybeGameRootFolder) return {folderName}; + con::debug("Detected game directory: {}", *maybeGameRootFolder); + std::vector result; const fs::path gameRootFolderPath(*maybeGameRootFolder); diff --git a/src/Unlinking/Unlinker.cpp b/src/Unlinking/Unlinker.cpp index 77781fcf..123f32a1 100644 --- a/src/Unlinking/Unlinker.cpp +++ b/src/Unlinking/Unlinker.cpp @@ -1,26 +1,86 @@ #include "Unlinker.h" #include "ContentLister/ContentPrinter.h" +#include "Game/AutoSearchPaths.h" #include "IObjLoader.h" #include "ObjWriter.h" #include "ObjWriting.h" -#include "SearchPath/IWD.h" #include "SearchPath/OutputPathFilesystem.h" +#include "SearchPath/SharedSearchPaths.h" #include "UnlinkerArgs.h" -#include "UnlinkerPaths.h" #include "Utils/Logging/Log.h" #include "Zone/Definition/ZoneDefWriter.h" +#include "Zone/LoadedZoneInformation.h" #include "ZoneLoading.h" -#include #include #include #include +#include namespace fs = std::filesystem; namespace { + class ReferencedSearchPaths + { + public: + ReferencedSearchPaths() + : m_shared_search_paths(nullptr) + { + } + + ReferencedSearchPaths(SharedSearchPaths& sharedSearchPaths, std::vector searchPaths) + : m_shared_search_paths(&sharedSearchPaths), + m_search_paths(std::move(searchPaths)) + { + } + + ~ReferencedSearchPaths() + { + Clear(); + } + + ReferencedSearchPaths(const ReferencedSearchPaths& other) = delete; + + ReferencedSearchPaths(ReferencedSearchPaths&& other) noexcept + : m_shared_search_paths(other.m_shared_search_paths), + m_search_paths(std::move(other.m_search_paths)) + { + other.m_shared_search_paths = nullptr; + } + + ReferencedSearchPaths& operator=(const ReferencedSearchPaths& other) = delete; + + ReferencedSearchPaths& operator=(ReferencedSearchPaths&& other) noexcept + { + m_shared_search_paths = other.m_shared_search_paths; + other.m_shared_search_paths = nullptr; + m_search_paths = std::move(other.m_search_paths); + + return *this; + } + + void Clear() + { + if (m_shared_search_paths) + { + for (const auto& searchPath : m_search_paths) + m_shared_search_paths->UnrefSearchPath(searchPath); + } + m_shared_search_paths = nullptr; + } + + private: + SharedSearchPaths* m_shared_search_paths; + std::vector m_search_paths; + }; + + [[nodiscard]] std::vector GetSearchPathsForZone(const std::string& zonePath, const GameId gameId) + { + return AutoSearchPaths::GetForGame(gameId)->GetSearchPathsForZonePath(zonePath); + } + class UnlinkerImpl : public Unlinker { public: @@ -31,16 +91,18 @@ namespace bool Start() override { - UnlinkerPaths paths; - if (!paths.LoadUserPaths(m_args)) - return false; + SharedSearchPaths paths; + for (const auto& userPath : m_args.m_user_search_paths) + paths.RefSearchPath(userPath); if (!LoadZones(paths)) return false; const auto result = UnlinkZones(paths); - UnloadZones(); + UnloadZones(paths); + + paths.Clear(); Summarize(result); @@ -203,7 +265,7 @@ namespace return true; } - bool LoadZones(UnlinkerPaths& paths) + bool LoadZones(SharedSearchPaths& paths) { for (const auto& zonePath : m_args.m_zones_to_load) { @@ -215,7 +277,6 @@ namespace auto absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string(); - auto searchPathsForZone = paths.GetSearchPathsForZone(absoluteZoneDirectory); auto maybeZone = ZoneLoading::LoadZone(zonePath, std::nullopt); if (!maybeZone) { @@ -225,44 +286,53 @@ namespace auto zone = std::move(*maybeZone); - con::debug("Loaded zone \"{}\"", zone->m_name); + con::info("Loaded zone \"{}\"", zone->m_name); + + auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory, zone->m_game_id); + for (const auto& searchPath : searchPathsForZone) + paths.RefSearchPath(searchPath); if (ShouldLoadObj()) { const auto* objLoader = IObjLoader::GetObjLoaderForGame(zone->m_game_id); - objLoader->LoadReferencedContainersForZone(*searchPathsForZone, *zone); + objLoader->LoadReferencedContainersForZone(paths.GetSearchPath(), *zone); } - m_loaded_zones.emplace_back(std::move(zone)); + m_loaded_zones.emplace_back( + std::make_unique(std::move(zone), std::move(absoluteZoneDirectory), std::move(searchPathsForZone))); } return true; } - void UnloadZones() + void UnloadZones(SharedSearchPaths& paths) { - for (auto i = m_loaded_zones.rbegin(); i != m_loaded_zones.rend(); ++i) + for (auto& loadedZone : std::ranges::reverse_view(m_loaded_zones)) { - auto& loadedZone = *i; - // Copy zone name since we deallocate before logging - const auto zoneName = loadedZone->m_name; + const auto zoneName = loadedZone->GetZone().m_name; if (ShouldLoadObj()) { - const auto* objLoader = IObjLoader::GetObjLoaderForGame(loadedZone->m_game_id); - objLoader->UnloadContainersOfZone(*loadedZone); + const auto* objLoader = IObjLoader::GetObjLoaderForGame(loadedZone->GetZone().m_game_id); + objLoader->UnloadContainersOfZone(loadedZone->GetZone()); } + for (const auto& searchPath : loadedZone->GetSearchPaths()) + paths.UnrefSearchPath(searchPath); + loadedZone.reset(); - con::debug("Unloaded zone \"{}\"", zoneName); + con::info("Unloaded zone \"{}\"", zoneName); } + m_loaded_zones.clear(); } - bool UnlinkZones(UnlinkerPaths& paths) const + bool UnlinkZones(SharedSearchPaths& paths) const { + ReferencedSearchPaths previousSearchPaths; + for (const auto& zonePath : m_args.m_zones_to_unlink) { if (!fs::is_regular_file(zonePath)) @@ -276,8 +346,6 @@ namespace zoneDirectory = fs::current_path(); auto absoluteZoneDirectory = absolute(zoneDirectory).string(); - auto searchPathsForZone = paths.GetSearchPathsForZone(absoluteZoneDirectory); - auto maybeZone = ZoneLoading::LoadZone(zonePath, std::nullopt); if (!maybeZone) { @@ -287,13 +355,20 @@ namespace auto zone = std::move(*maybeZone); - con::debug("Loaded zone \"{}\"", zone->m_name); + con::info("Loaded zone \"{}\"", zone->m_name); + + auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory, zone->m_game_id); + for (const auto& searchPath : searchPathsForZone) + paths.RefSearchPath(searchPath); + + previousSearchPaths.Clear(); + previousSearchPaths = ReferencedSearchPaths(paths, std::move(searchPathsForZone)); const auto* objLoader = IObjLoader::GetObjLoaderForGame(zone->m_game_id); if (ShouldLoadObj()) - objLoader->LoadReferencedContainersForZone(*searchPathsForZone, *zone); + objLoader->LoadReferencedContainersForZone(paths.GetSearchPath(), *zone); - if (!HandleZone(*searchPathsForZone, *zone)) + if (!HandleZone(paths.GetSearchPath(), *zone)) return false; if (ShouldLoadObj()) @@ -302,9 +377,11 @@ namespace // Copy zone name for using it after freeing the zone std::string zoneName = zone->m_name; zone.reset(); - con::debug("Unloaded zone \"{}\"", zoneName); + con::info("Unloaded zone \"{}\"", zoneName); } + previousSearchPaths.Clear(); + return true; } @@ -315,7 +392,7 @@ namespace } UnlinkerArgs m_args; - std::vector> m_loaded_zones; + std::vector> m_loaded_zones; }; } // namespace diff --git a/src/Unlinking/UnlinkerPaths.cpp b/src/Unlinking/UnlinkerPaths.cpp deleted file mode 100644 index 59aec518..00000000 --- a/src/Unlinking/UnlinkerPaths.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "UnlinkerPaths.h" - -#include "SearchPath/IWD.h" -#include "SearchPath/SearchPathFilesystem.h" -#include "Utils/Logging/Log.h" -#include "Utils/StringUtils.h" - -#include -#include -#include - -namespace fs = std::filesystem; - -bool UnlinkerPaths::LoadUserPaths(const UnlinkerArgs& args) -{ - for (const auto& path : args.m_user_search_paths) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - con::error("Could not find directory of search path: \"{}\"", path); - return false; - } - - auto searchPathName = absolutePath.string(); - m_user_paths.CommitSearchPath(std::make_unique(searchPathName)); - m_specified_user_paths.emplace(std::move(searchPathName)); - - std::filesystem::directory_iterator iterator(absolutePath); - const auto end = fs::end(iterator); - for (auto i = fs::begin(iterator); i != end; ++i) - { - if (!i->is_regular_file()) - continue; - - auto extension = i->path().extension().string(); - utils::MakeStringLowerCase(extension); - if (extension == ".iwd") - { - auto iwd = iwd::LoadFromFile(i->path().string()); - if (iwd) - m_user_paths.CommitSearchPath(std::move(iwd)); - } - } - } - - con::info("{} SearchPaths{}", m_specified_user_paths.size(), !m_specified_user_paths.empty() ? ":" : ""); - for (const auto& absoluteSearchPath : m_specified_user_paths) - con::info(" \"{}\"", absoluteSearchPath); - - if (!m_specified_user_paths.empty()) - con::info(""); - - return true; -} - -std::unique_ptr UnlinkerPaths::GetSearchPathsForZone(const std::string& zonePath) -{ - const auto absoluteZoneDirectory = fs::absolute(std::filesystem::path(zonePath).remove_filename()); - const auto absoluteZoneDirectoryString = absoluteZoneDirectory.string(); - if (m_last_zone_path != absoluteZoneDirectoryString) - { - m_last_zone_path = absoluteZoneDirectoryString; - m_last_zone_search_paths = SearchPaths(); - m_last_zone_search_paths.CommitSearchPath(std::make_unique(absoluteZoneDirectoryString)); - - std::filesystem::directory_iterator iterator(absoluteZoneDirectory); - const auto end = fs::end(iterator); - for (auto i = fs::begin(iterator); i != end; ++i) - { - if (!i->is_regular_file()) - continue; - - auto extension = i->path().extension().string(); - utils::MakeStringLowerCase(extension); - if (extension == ".iwd") - { - auto iwd = iwd::LoadFromFile(i->path().string()); - if (iwd) - m_last_zone_search_paths.CommitSearchPath(std::move(iwd)); - } - } - } - - auto result = std::make_unique(); - result->IncludeSearchPath(&m_last_zone_search_paths); - result->IncludeSearchPath(&m_user_paths); - - return result; -} diff --git a/src/Unlinking/UnlinkerPaths.h b/src/Unlinking/UnlinkerPaths.h deleted file mode 100644 index 7396f523..00000000 --- a/src/Unlinking/UnlinkerPaths.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "SearchPath/SearchPaths.h" -#include "UnlinkerArgs.h" - -#include -#include - -class UnlinkerPaths -{ -public: - bool LoadUserPaths(const UnlinkerArgs& args); - std::unique_ptr GetSearchPathsForZone(const std::string& zonePath); - -private: - std::string m_last_zone_path; - SearchPaths m_last_zone_search_paths; - - std::unordered_set m_specified_user_paths; - SearchPaths m_user_paths; -}; diff --git a/src/ZoneCommon/Zone/LoadedZoneInformation.cpp b/src/ZoneCommon/Zone/LoadedZoneInformation.cpp new file mode 100644 index 00000000..c3a47b8a --- /dev/null +++ b/src/ZoneCommon/Zone/LoadedZoneInformation.cpp @@ -0,0 +1,28 @@ +#include "LoadedZoneInformation.h" + +LoadedZoneInformation::LoadedZoneInformation(std::unique_ptr zone, std::string filePath, std::vector searchPaths) + : m_zone(std::move(zone)), + m_file_path(std::move(filePath)), + m_search_paths(std::move(searchPaths)) +{ +} + +Zone& LoadedZoneInformation::GetZone() +{ + return *m_zone; +} + +const Zone& LoadedZoneInformation::GetZone() const +{ + return *m_zone; +} + +const std::string& LoadedZoneInformation::GetFilePath() const +{ + return m_file_path; +} + +const std::vector& LoadedZoneInformation::GetSearchPaths() const +{ + return m_search_paths; +} diff --git a/src/ZoneCommon/Zone/LoadedZoneInformation.h b/src/ZoneCommon/Zone/LoadedZoneInformation.h new file mode 100644 index 00000000..514775ec --- /dev/null +++ b/src/ZoneCommon/Zone/LoadedZoneInformation.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Zone.h" + +#include +#include +#include + +class LoadedZoneInformation +{ +public: + LoadedZoneInformation(std::unique_ptr zone, std::string filePath, std::vector searchPaths); + + [[nodiscard]] Zone& GetZone(); + [[nodiscard]] const Zone& GetZone() const; + + [[nodiscard]] const std::string& GetFilePath() const; + [[nodiscard]] const std::vector& GetSearchPaths() const; + +private: + std::unique_ptr m_zone; + std::string m_file_path; + std::vector m_search_paths; +};