- Add tracking for dependencies between plugins.

- Add reference number mangling required for moving references around.
pull/16/head
Mark Siewert 12 years ago
parent 42eefaf36f
commit 2175f13b67

@ -190,8 +190,9 @@ namespace MWWorld
// This parses the ESM file
ESM::ESMReader lEsm;
lEsm.setEncoding(encoding);
lEsm.open (masterPath.string());
lEsm.setIndex(idx);
lEsm.setGlobalReaderList(&mEsm);
lEsm.open (masterPath.string());
mEsm[idx] = lEsm;
mStore.load (mEsm[idx]);
}
@ -205,8 +206,9 @@ namespace MWWorld
// This parses the ESP file
ESM::ESMReader lEsm;
lEsm.setEncoding(encoding);
lEsm.open (pluginPath.string());
lEsm.setIndex(idx);
lEsm.setGlobalReaderList(&mEsm);
lEsm.open (pluginPath.string());
mEsm[idx] = lEsm;
mStore.load (mEsm[idx]);
}

@ -89,6 +89,7 @@ struct MasterData
{
std::string name;
uint64_t size;
int index; // Position of the parent file in the global list of loaded files
};
// Data that is only present in save game files

@ -1,5 +1,6 @@
#include "esmreader.hpp"
#include <stdexcept>
#include <boost/filesystem/v3/operations.hpp>
namespace ESM
{
@ -61,6 +62,7 @@ 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");
@ -78,6 +80,29 @@ 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);
}

@ -83,6 +83,8 @@ public:
int idx;
void setIndex(const int index) {idx = index; mCtx.index = index;}
const int getIndex() {return idx;}
void setGlobalReaderList(std::vector<ESMReader> *list) {mGlobalReaderList = list;}
/*************************************************************************
*
@ -254,6 +256,7 @@ private:
SaveData mSaveData;
MasterList mMasters;
std::vector<ESMReader> *mGlobalReaderList;
ToUTF8::FromType mEncoding;
};
}

@ -170,8 +170,6 @@ std::string Cell::getDescription() const
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
{
// TODO: Add support for multiple plugins. This requires a tricky renaming scheme for "ref.mRefnum".
// I'll probably add something to "ESMReader", we will need one per plugin anyway.
// TODO: Try and document reference numbering, I don't think this has been done anywhere else.
if (!esm.hasMoreSubs())
return false;
@ -194,6 +192,26 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
// This may require some not-so-small behing-the-scenes updates.
esm.getHNT(ref.mRefnum, "FRMR");
ref.mRefID = esm.getHNString("NAME");
// Identify references belonging to a parent file and adapt the ID accordingly.
int local = (ref.mRefnum & 0xff000000) >> 24;
size_t global = esm.getIndex() + 1;
if (local)
{
// If the most significant 8 bits are used, then this reference already exists.
// In this case, do not spawn a new reference, but overwrite the old one.
ref.mRefnum &= 0x00ffffff; // delete old plugin ID
const ESM::ESMReader::MasterList &masters = esm.getMasters();
// TODO: Test how Morrowind does it! Maybe the first entry in the list should be "1"...
global = masters[local-1].index + 1;
ref.mRefnum |= global << 24; // insert global plugin ID
std::cout << "Refnum_old = " << ref.mRefnum << " " << local << " " << global << std::endl;
}
else
{
// This is an addition by the present plugin. Set the corresponding plugin index.
ref.mRefnum |= global << 24; // insert global plugin ID
}
// getHNOT will not change the existing value if the subrecord is
// missing

Loading…
Cancel
Save