diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f76590ae8..ce84b8dfe 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -149,16 +149,22 @@ OMW::Engine::~Engine() delete mOgre; } -// Load all BSA files in data directory. +// Load BSA files void OMW::Engine::loadBSA() { - const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa"); - - for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter) + for (std::vector::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive) { - std::cout << "Adding " << iter->second.string() << std::endl; - Bsa::addBSA(iter->second.string()); + if (mFileCollections.doesExist(*archive)) + { + const std::string archivePath = mFileCollections.getPath(*archive).string(); + std::cout << "Adding BSA archive " << archivePath << std::endl; + Bsa::addBSA(archivePath); + } + else + { + std::cout << "Archive " << *archive << " not found" << std::endl; + } } const Files::PathContainer& dataDirs = mFileCollections.getPaths(); @@ -199,6 +205,11 @@ void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs) mFileCollections = Files::Collections (dataDirs, !mFSStrict); } +// Add BSA archive +void OMW::Engine::addArchive (const std::string& archive) { + mArchives.push_back(archive); +} + // Set resource dir void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir) { diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index a4acee523..f80b67a35 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -64,6 +64,7 @@ namespace OMW ToUTF8::FromType mEncoding; ToUTF8::Utf8Encoder* mEncoder; Files::PathContainer mDataDirs; + std::vector mArchives; boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; std::string mCellName; @@ -99,7 +100,7 @@ namespace OMW /// add a .zip resource void addZipResource (const boost::filesystem::path& path); - /// Load all BSA files in data directory. + /// Load BSA files void loadBSA(); void executeLocalScripts(); @@ -126,6 +127,9 @@ namespace OMW /// Set data dirs void setDataDirs(const Files::PathContainer& dataDirs); + /// Add BSA archive + void addArchive(const std::string& archive); + /// Set resource dir void setResourceDir(const boost::filesystem::path& parResDir); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 86978c9b1..1fa461c2f 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -100,6 +100,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("data-local", bpo::value()->default_value(""), "set local data directory (highest priority)") + ("fallback-archive", bpo::value()->default_value(StringsVector(), "fallback-archive") + ->multitoken(), "set fallback BSA archives (later archives have higher priority)") + ("resources", bpo::value()->default_value("resources"), "set resources directory") @@ -201,6 +204,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setDataDirs(dataDirs); + // fallback archives + StringsVector archives = variables["fallback-archive"].as(); + for (StringsVector::const_iterator it = archives.begin(); it != archives.end(); it++) + { + engine.addArchive(*it); + } + engine.setResourceDir(variables["resources"].as()); // master and plugin diff --git a/components/files/collections.cpp b/components/files/collections.cpp index 50340dca4..c6195d88c 100644 --- a/components/files/collections.cpp +++ b/components/files/collections.cpp @@ -31,6 +31,32 @@ namespace Files return iter->second; } + boost::filesystem::path Collections::getPath(const std::string& file) const + { + for (Files::PathContainer::const_iterator iter = mDirectories.begin(); + iter != mDirectories.end(); ++iter) + { + const boost::filesystem::path path = *iter / file; + if (boost::filesystem::exists(path)) + return path.string(); + } + + throw std::runtime_error ("file " + file + " not found"); + } + + bool Collections::doesExist(const std::string& file) const + { + for (Files::PathContainer::const_iterator iter = mDirectories.begin(); + iter != mDirectories.end(); ++iter) + { + const boost::filesystem::path path = *iter / file; + if (boost::filesystem::exists(path)) + return true; + } + + return false; + } + const Files::PathContainer& Collections::getPaths() const { return mDirectories; diff --git a/components/files/collections.hpp b/components/files/collections.hpp index ed4aafa13..def61cf8e 100644 --- a/components/files/collections.hpp +++ b/components/files/collections.hpp @@ -19,6 +19,16 @@ namespace Files /// leading dot and must be all lower-case. const MultiDirCollection& getCollection(const std::string& extension) const; + boost::filesystem::path getPath(const std::string& file) const; + ///< Return full path (including filename) of \a file. + /// + /// If the file does not exist in any of the collection's + /// directories, an exception is thrown. \a file must include the + /// extension. + + bool doesExist(const std::string& file) const; + ///< \return Does a file with the given name exist? + const Files::PathContainer& getPaths() const; private: