forked from teamnwah/openmw-tes3coop
- 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:
parent
8ea9f00e6f
commit
896ab44d1e
9 changed files with 102 additions and 66 deletions
|
@ -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
|
||||||
|
|
|
@ -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++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 <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<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 <exl = mStatic[plugin];
|
||||||
}
|
|
||||||
return 0;
|
assert(index < ltexl.size());
|
||||||
|
return <exl.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 <exl = 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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue