From 896ab44d1e919852aae03be9ecb71378f031b6f5 Mon Sep 17 00:00:00 2001 From: Mark Siewert Date: Sun, 25 Nov 2012 17:19:29 +0100 Subject: [PATCH] - Add some updated files missing from last commit. - Move plugin dependency test from esmreader.cpp to esmstpre.cpp; fixes crash in omwlauncher. --- apps/openmw/CMakeLists.txt | 7 ++-- apps/openmw/mwrender/terrain.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 8 ++-- apps/openmw/mwworld/cellstore.hpp | 28 ++++++++------ apps/openmw/mwworld/esmstore.cpp | 29 ++++++++++++++ apps/openmw/mwworld/store.hpp | 64 +++++++++++++++++++++---------- apps/openmw/mwworld/worldimp.cpp | 4 +- components/esm/esmreader.cpp | 25 ------------ components/esm/esmreader.hpp | 1 + 9 files changed, 102 insertions(+), 66 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 538f63dc9..e2a2e7f14 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -34,7 +34,7 @@ add_openmw_dir (mwgui ) add_openmw_dir (mwdialogue - dialoguemanagerimp journalimp journalentry quest topic + dialoguemanagerimp journalimp journalentry quest topic filter selectwrapper ) add_openmw_dir (mwscript @@ -50,9 +50,10 @@ add_openmw_dir (mwsound add_openmw_dir (mwworld refdata worldimp physicssystem scene globals class action nullaction actionteleport - containerstore actiontalk actiontake manualref player cellfunctors + containerstore actiontalk actiontake manualref player cellfunctors failedaction cells localscripts customdata weather inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat + esmstore store recordcmp ) add_openmw_dir (mwclass @@ -62,7 +63,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells - activespells npcstats aipackage aisequence alchemy + activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow aiescort aiactivate ) add_openmw_dir (mwbase diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index d46c2521f..eb5b07af4 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -221,7 +221,7 @@ namespace MWRender // //If we don't sort the ltex indexes, the splatting order may differ between //cells which may lead to inconsistent results when shading between cells - int num = MWBase::Environment::get().getWorld()->getStore().landTexts.getSizePlugin(plugin); + int num = MWBase::Environment::get().getWorld()->getStore().get().getSize(plugin); std::set ltexIndexes; for ( int y = fromY - 1; y < fromY + size + 1; y++ ) { diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 74856c9ed..ba8f5aa61 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -49,10 +49,10 @@ namespace MWWorld return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. - for (size_t i = 0; i < cell->mContextList.size(); i++) + for (size_t i = 0; i < mCell->mContextList.size(); i++) { // Reopen the ESM reader and seek to the right position. - int index = cell->mContextList.at(i).index; + int index = mCell->mContextList.at(i).index; mCell->restore (esm[index], i); ESM::CellRef ref; @@ -81,10 +81,10 @@ namespace MWWorld return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. - for (size_t i = 0; i < cell->mContextList.size(); i++) + for (size_t i = 0; i < mCell->mContextList.size(); i++) { // Reopen the ESM reader and seek to the right position. - int index = cell->mContextList.at(i).index; + int index = mCell->mContextList.at(i).index; mCell->restore (esm[index], i); ESM::CellRef ref; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index b66137cc6..bf7581f6e 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -49,26 +49,32 @@ namespace MWWorld { typedef LiveCellRef LiveRef; typedef std::map List; - List list; + List mList; // Search for the given reference in the given reclist from // ESMStore. Insert the reference into the list if a match is // found. If not, throw an exception. - template - void find(ESM::CellRef &ref, const Y& recList) + /// Searches for reference of appropriate type in given ESMStore. + /// If reference exists, loads it into container, throws an exception + /// on miss + void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore) { - const X* obj = recList.find(ref.mRefID); - if(obj == NULL) - throw std::runtime_error("Error resolving cell reference " + ref.mRefID); + // for throwing exception on unhandled record type + const MWWorld::Store &store = esmStore.get(); + const X *ptr = store.find(ref.mRefID); - list[ref.mRefnum] = LiveRef(ref, obj); + /// \note redundant because Store::find() throws exception on miss + if (ptr == NULL) { + throw std::runtime_error("Error resolving cell reference " + ref.mRefID); + } + mList[ref.mRefnum] = LiveRef(ref, ptr); } LiveRef *find (const std::string& name) { - for (typename std::map::iterator iter (list.begin()); iter!=list.end(); ++iter) + for (typename std::map::iterator iter (mList.begin()); iter!=mList.end(); ++iter) { - if (iter->second.mData.getCount() > 0 && iter->second.ref.mRefID == name) + if (iter->second.mData.getCount() > 0 && iter->second.mRef.mRefID == name) return &iter->second; } @@ -76,8 +82,8 @@ namespace MWWorld } LiveRef &insert(const LiveRef &item) { - list[item.ref.mRefnum] = item; - return list[item.ref.mRefnum]; + mList[item.mRef.mRefnum] = item; + return mList[item.mRef.mRefnum]; } }; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 73f5185c9..db444153f 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -3,6 +3,8 @@ #include #include +#include + namespace MWWorld { @@ -25,6 +27,33 @@ void ESMStore::load(ESM::ESMReader &esm) ESM::Dialogue *dialogue = 0; + // Cache parent esX files by tracking their indices in the global list of + // all files/readers used by the engine. This will greaty help to accelerate + // parsing of reference IDs. + size_t index = ~0; + const ESM::ESMReader::MasterList &masters = esm.getMasters(); + std::vector *allPlugins = esm.getGlobalReaderList(); + for (size_t j = 0; j < masters.size(); j++) { + ESM::MasterData &mast = const_cast(masters[j]); + std::string fname = mast.name; + for (size_t i = 0; i < esm.getIndex(); i++) { + const std::string &candidate = allPlugins->at(i).getContext().filename; + std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); + if (fname == fnamecandidate) { + index = i; + break; + } + } + if (index == (size_t)~0) { + // Tried to load a parent file that has not been loaded yet. This is bad, + // the launcher should have taken care of this. + std::string fstring = "File " + fname + " asks for parent file " + masters[j].name + + ", but it has not been loaded yet. Please check your load order."; + esm.fail(fstring); + } + mast.index = index; + } + // Loop through all records while(esm.hasMoreRecs()) { diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index fd93f39f1..53f4482bb 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -219,24 +219,31 @@ namespace MWWorld template <> class Store : public StoreBase { - std::vector mStatic; + // For multiple ESM/ESP files we need one list per file. + typedef std::vector LandTextureList; + std::vector mStatic; public: Store() { - mStatic.reserve(128); + mStatic.push_back(LandTextureList()); + LandTextureList <exl = mStatic[0]; + // More than enough to hold Morrowind.esm. Extra lists for plugins will we + // added on-the-fly in a different method. + ltexl.reserve(128); } typedef std::vector::const_iterator iterator; - const ESM::LandTexture *search(size_t index) const { - if (index < mStatic.size()) { - return &mStatic.at(index); - } - return 0; + const ESM::LandTexture *search(size_t index, size_t plugin) const { + assert(plugin < mStatic.size()); + const LandTextureList <exl = mStatic[plugin]; + + assert(index < ltexl.size()); + return <exl.at(index); } - const ESM::LandTexture *find(size_t index) const { - const ESM::LandTexture *ptr = search(index); + const ESM::LandTexture *find(size_t index, size_t plugin) const { + const ESM::LandTexture *ptr = search(index, plugin); if (ptr == 0) { std::ostringstream msg; msg << "Land texture with index " << index << " not found"; @@ -249,23 +256,40 @@ namespace MWWorld return mStatic.size(); } - void load(ESM::ESMReader &esm, const std::string &id) { - ESM::LandTexture ltex; - ltex.load(esm); + int getSize(size_t plugin) const { + assert(plugin < mStatic.size()); + return mStatic[plugin].size(); + } + + void load(ESM::ESMReader &esm, const std::string &id, size_t plugin) { + ESM::LandTexture lt; + lt.load(esm); + lt.mId = id; - if (ltex.mIndex >= (int) mStatic.size()) { - mStatic.resize(ltex.mIndex + 1); + // Make sure we have room for the structure + if (plugin >= mStatic.size()) { + mStatic.resize(plugin+1); } - mStatic[ltex.mIndex] = ltex; - mStatic[ltex.mIndex].mId = id; + LandTextureList <exl = mStatic[plugin]; + if(lt.mIndex + 1 > (int)ltexl.size()) + ltexl.resize(lt.mIndex+1); + + // Store it + ltexl[lt.mIndex] = lt; } - iterator begin() const { - return mStatic.begin(); + void load(ESM::ESMReader &esm, const std::string &id) { + load(esm, id, esm.getIndex()); } - iterator end() const { - return mStatic.end(); + iterator begin(size_t plugin) const { + assert(plugin < mStatic.size()); + return mStatic[plugin].begin(); + } + + iterator end(size_t plugin) const { + assert(plugin < mStatic.size()); + return mStatic[plugin].end(); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 9f2d419f1..1fa23700d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1081,8 +1081,8 @@ namespace MWWorld std::vector result; MWWorld::CellRefList& doors = cell->mDoors; - std::map< MWWorld::LiveCellRef >& refList = doors.mList; - for (std::map >::iterator it = refList.begin(); it != refList.end(); ++it) + CellRefList::List& refList = doors.mList; + for (CellRefList::List::iterator it = refList.begin(); it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = it->second; diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index d1703a2ac..2915a1ce7 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -1,6 +1,5 @@ #include "esmreader.hpp" #include -#include namespace ESM { @@ -62,7 +61,6 @@ void ESMReader::openRaw(Ogre::DataStreamPtr _esm, const std::string &name) void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name) { openRaw(_esm, name); - std::string fname = boost::filesystem::path(name).filename().string(); if (getRecName() != "TES3") fail("Not a valid Morrowind file"); @@ -80,29 +78,6 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name) MasterData m; m.name = getHString(); m.size = getHNLong("DATA"); - // Cache parent esX files by tracking their indices in the global list of - // all files/readers used by the engine. This will greaty help to accelerate - // parsing of reference IDs. - size_t index = ~0; - // TODO: check for case mismatch, it might be required on Windows. - size_t i = 0; - // FIXME: This is ugly! Make it nicer! - for (; i < idx; i++) { - const std::string &candidate = mGlobalReaderList->at(i).getContext().filename; - std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); - if (m.name == fnamecandidate) { - index = i; - break; - } - } - if (index == (size_t)~0) { - // Tried to load a parent file that has not been loaded yet. This is bad, - // the launcher should have taken care of this. - std::string fstring = "File " + fname + " asks for parent file " + m.name - + ", but it has not been loaded yet. Please check your load order."; - fail(fstring); - } - m.index = index; mMasters.push_back(m); } diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index b415009d3..732dbe9bc 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -85,6 +85,7 @@ public: const int getIndex() {return idx;} void setGlobalReaderList(std::vector *list) {mGlobalReaderList = list;} + std::vector *getGlobalReaderList() {return mGlobalReaderList;} /************************************************************************* *