mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-05 02:11:32 +00:00
- 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
|
// This parses the ESM file
|
||||||
ESM::ESMReader lEsm;
|
ESM::ESMReader lEsm;
|
||||||
lEsm.setEncoding(encoding);
|
lEsm.setEncoding(encoding);
|
||||||
lEsm.open (masterPath.string());
|
|
||||||
lEsm.setIndex(idx);
|
lEsm.setIndex(idx);
|
||||||
|
lEsm.setGlobalReaderList(&mEsm);
|
||||||
|
lEsm.open (masterPath.string());
|
||||||
mEsm[idx] = lEsm;
|
mEsm[idx] = lEsm;
|
||||||
mStore.load (mEsm[idx]);
|
mStore.load (mEsm[idx]);
|
||||||
}
|
}
|
||||||
|
@ -205,8 +206,9 @@ namespace MWWorld
|
||||||
// This parses the ESP file
|
// This parses the ESP file
|
||||||
ESM::ESMReader lEsm;
|
ESM::ESMReader lEsm;
|
||||||
lEsm.setEncoding(encoding);
|
lEsm.setEncoding(encoding);
|
||||||
lEsm.open (pluginPath.string());
|
|
||||||
lEsm.setIndex(idx);
|
lEsm.setIndex(idx);
|
||||||
|
lEsm.setGlobalReaderList(&mEsm);
|
||||||
|
lEsm.open (pluginPath.string());
|
||||||
mEsm[idx] = lEsm;
|
mEsm[idx] = lEsm;
|
||||||
mStore.load (mEsm[idx]);
|
mStore.load (mEsm[idx]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct MasterData
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
uint64_t size;
|
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
|
// Data that is only present in save game files
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <boost/filesystem/v3/operations.hpp>
|
||||||
|
|
||||||
namespace ESM
|
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)
|
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");
|
||||||
|
@ -78,6 +80,29 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,8 @@ public:
|
||||||
void setIndex(const int index) {idx = index; mCtx.index = index;}
|
void setIndex(const int index) {idx = index; mCtx.index = index;}
|
||||||
const int getIndex() {return idx;}
|
const int getIndex() {return idx;}
|
||||||
|
|
||||||
|
void setGlobalReaderList(std::vector<ESMReader> *list) {mGlobalReaderList = list;}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
*
|
*
|
||||||
* Medium-level reading shortcuts
|
* Medium-level reading shortcuts
|
||||||
|
@ -254,6 +256,7 @@ private:
|
||||||
|
|
||||||
SaveData mSaveData;
|
SaveData mSaveData;
|
||||||
MasterList mMasters;
|
MasterList mMasters;
|
||||||
|
std::vector<ESMReader> *mGlobalReaderList;
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,8 +170,6 @@ std::string Cell::getDescription() const
|
||||||
|
|
||||||
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
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.
|
// TODO: Try and document reference numbering, I don't think this has been done anywhere else.
|
||||||
if (!esm.hasMoreSubs())
|
if (!esm.hasMoreSubs())
|
||||||
return false;
|
return false;
|
||||||
|
@ -195,6 +193,26 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
||||||
esm.getHNT(ref.mRefnum, "FRMR");
|
esm.getHNT(ref.mRefnum, "FRMR");
|
||||||
ref.mRefID = esm.getHNString("NAME");
|
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
|
// getHNOT will not change the existing value if the subrecord is
|
||||||
// missing
|
// missing
|
||||||
ref.mScale = 1.0;
|
ref.mScale = 1.0;
|
||||||
|
|
Loading…
Reference in a new issue