- Add some updated files missing from last commit.

- Move plugin dependency test from esmreader.cpp to esmstpre.cpp; fixes crash in omwlauncher.
This commit is contained in:
Mark Siewert 2012-11-25 17:19:29 +01:00
parent 8ea9f00e6f
commit 896ab44d1e
9 changed files with 102 additions and 66 deletions

View file

@ -34,7 +34,7 @@ add_openmw_dir (mwgui
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue
dialoguemanagerimp journalimp journalentry quest topic dialoguemanagerimp journalimp journalentry quest topic filter selectwrapper
) )
add_openmw_dir (mwscript add_openmw_dir (mwscript
@ -50,9 +50,10 @@ add_openmw_dir (mwsound
add_openmw_dir (mwworld add_openmw_dir (mwworld
refdata worldimp physicssystem scene globals class action nullaction actionteleport 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 cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
@ -62,7 +63,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells 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 add_openmw_dir (mwbase

View file

@ -221,7 +221,7 @@ namespace MWRender
// //
//If we don't sort the ltex indexes, the splatting order may differ between //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 //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<ESM::LandTexture>().getSize(plugin);
std::set<uint16_t> ltexIndexes; std::set<uint16_t> ltexIndexes;
for ( int y = fromY - 1; y < fromY + size + 1; y++ ) for ( int y = fromY - 1; y < fromY + size + 1; y++ )
{ {

View file

@ -49,10 +49,10 @@ namespace MWWorld
return; // this is a dynamically generated cell -> skipping. return; // this is a dynamically generated cell -> skipping.
// Load references from all plugins that do something with this cell. // 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. // 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); mCell->restore (esm[index], i);
ESM::CellRef ref; ESM::CellRef ref;
@ -81,10 +81,10 @@ namespace MWWorld
return; // this is a dynamically generated cell -> skipping. return; // this is a dynamically generated cell -> skipping.
// Load references from all plugins that do something with this cell. // 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. // 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); mCell->restore (esm[index], i);
ESM::CellRef ref; ESM::CellRef ref;

View file

@ -49,26 +49,32 @@ namespace MWWorld
{ {
typedef LiveCellRef<X> LiveRef; typedef LiveCellRef<X> LiveRef;
typedef std::map<int,LiveRef> List; typedef std::map<int,LiveRef> List;
List list; List mList;
// Search for the given reference in the given reclist from // Search for the given reference in the given reclist from
// ESMStore. Insert the reference into the list if a match is // ESMStore. Insert the reference into the list if a match is
// found. If not, throw an exception. // found. If not, throw an exception.
template <typename Y> /// Searches for reference of appropriate type in given ESMStore.
void find(ESM::CellRef &ref, const Y& recList) /// 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); // for throwing exception on unhandled record type
if(obj == NULL) const MWWorld::Store<X> &store = esmStore.get<X>();
throw std::runtime_error("Error resolving cell reference " + ref.mRefID); const X *ptr = store.find(ref.mRefID);
list[ref.mRefnum] = LiveRef(ref, obj); /// \note redundant because Store<X>::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) LiveRef *find (const std::string& name)
{ {
for (typename std::map<int,LiveRef>::iterator iter (list.begin()); iter!=list.end(); ++iter) for (typename std::map<int,LiveRef>::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; return &iter->second;
} }
@ -76,8 +82,8 @@ namespace MWWorld
} }
LiveRef &insert(const LiveRef &item) { LiveRef &insert(const LiveRef &item) {
list[item.ref.mRefnum] = item; mList[item.mRef.mRefnum] = item;
return list[item.ref.mRefnum]; return mList[item.mRef.mRefnum];
} }
}; };

View file

@ -3,6 +3,8 @@
#include <set> #include <set>
#include <iostream> #include <iostream>
#include <boost/filesystem/v3/operations.hpp>
namespace MWWorld namespace MWWorld
{ {
@ -25,6 +27,33 @@ void ESMStore::load(ESM::ESMReader &esm)
ESM::Dialogue *dialogue = 0; 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<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
for (size_t j = 0; j < masters.size(); j++) {
ESM::MasterData &mast = const_cast<ESM::MasterData&>(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 // Loop through all records
while(esm.hasMoreRecs()) while(esm.hasMoreRecs())
{ {

View file

@ -219,24 +219,31 @@ namespace MWWorld
template <> template <>
class Store<ESM::LandTexture> : public StoreBase class Store<ESM::LandTexture> : public StoreBase
{ {
std::vector<ESM::LandTexture> mStatic; // For multiple ESM/ESP files we need one list per file.
typedef std::vector<ESM::LandTexture> LandTextureList;
std::vector<LandTextureList> mStatic;
public: public:
Store<ESM::LandTexture>() { Store<ESM::LandTexture>() {
mStatic.reserve(128); mStatic.push_back(LandTextureList());
LandTextureList &ltexl = 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<ESM::LandTexture>::const_iterator iterator; typedef std::vector<ESM::LandTexture>::const_iterator iterator;
const ESM::LandTexture *search(size_t index) const { const ESM::LandTexture *search(size_t index, size_t plugin) const {
if (index < mStatic.size()) { assert(plugin < mStatic.size());
return &mStatic.at(index); const LandTextureList &ltexl = mStatic[plugin];
}
return 0; assert(index < ltexl.size());
return &ltexl.at(index);
} }
const ESM::LandTexture *find(size_t index) const { const ESM::LandTexture *find(size_t index, size_t plugin) const {
const ESM::LandTexture *ptr = search(index); const ESM::LandTexture *ptr = search(index, plugin);
if (ptr == 0) { if (ptr == 0) {
std::ostringstream msg; std::ostringstream msg;
msg << "Land texture with index " << index << " not found"; msg << "Land texture with index " << index << " not found";
@ -249,23 +256,40 @@ namespace MWWorld
return mStatic.size(); return mStatic.size();
} }
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;
// Make sure we have room for the structure
if (plugin >= mStatic.size()) {
mStatic.resize(plugin+1);
}
LandTextureList &ltexl = mStatic[plugin];
if(lt.mIndex + 1 > (int)ltexl.size())
ltexl.resize(lt.mIndex+1);
// Store it
ltexl[lt.mIndex] = lt;
}
void load(ESM::ESMReader &esm, const std::string &id) { void load(ESM::ESMReader &esm, const std::string &id) {
ESM::LandTexture ltex; load(esm, id, esm.getIndex());
ltex.load(esm);
if (ltex.mIndex >= (int) mStatic.size()) {
mStatic.resize(ltex.mIndex + 1);
}
mStatic[ltex.mIndex] = ltex;
mStatic[ltex.mIndex].mId = id;
} }
iterator begin() const { iterator begin(size_t plugin) const {
return mStatic.begin(); assert(plugin < mStatic.size());
return mStatic[plugin].begin();
} }
iterator end() const { iterator end(size_t plugin) const {
return mStatic.end(); assert(plugin < mStatic.size());
return mStatic[plugin].end();
} }
}; };

View file

@ -1081,8 +1081,8 @@ namespace MWWorld
std::vector<World::DoorMarker> result; std::vector<World::DoorMarker> result;
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors; MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
std::map< MWWorld::LiveCellRef<ESM::Door> >& refList = doors.mList; CellRefList<ESM::Door>::List& refList = doors.mList;
for (std::map<int, MWWorld::LiveCellRef<ESM::Door> >::iterator it = refList.begin(); it != refList.end(); ++it) for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
{ {
MWWorld::LiveCellRef<ESM::Door>& ref = it->second; MWWorld::LiveCellRef<ESM::Door>& ref = it->second;

View file

@ -1,6 +1,5 @@
#include "esmreader.hpp" #include "esmreader.hpp"
#include <stdexcept> #include <stdexcept>
#include <boost/filesystem/v3/operations.hpp>
namespace ESM 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) void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
{ {
openRaw(_esm, name); openRaw(_esm, name);
std::string fname = boost::filesystem::path(name).filename().string();
if (getRecName() != "TES3") if (getRecName() != "TES3")
fail("Not a valid Morrowind file"); fail("Not a valid Morrowind file");
@ -80,29 +78,6 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
MasterData m; MasterData m;
m.name = getHString(); m.name = getHString();
m.size = getHNLong("DATA"); 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); mMasters.push_back(m);
} }

View file

@ -85,6 +85,7 @@ public:
const int getIndex() {return idx;} const int getIndex() {return idx;}
void setGlobalReaderList(std::vector<ESMReader> *list) {mGlobalReaderList = list;} void setGlobalReaderList(std::vector<ESMReader> *list) {mGlobalReaderList = list;}
std::vector<ESMReader> *getGlobalReaderList() {return mGlobalReaderList;}
/************************************************************************* /*************************************************************************
* *