forked from teamnwah/openmw-tes3coop
- Add tracking for dependencies between plugins.
- Add reference number mangling required for moving references around.
This commit is contained in:
parent
42eefaf36f
commit
2175f13b67
5 changed files with 53 additions and 4 deletions
|
@ -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…
Reference in a new issue