- Add support for multiple esm contexts in cell store. This will allow to generate references from multiple esX files. Currently, only the first context is used.

- Add many TODOs to mark points where more work is required to fully implement this feature.
actorid
Mark Siewert 12 years ago
parent 64c08eada4
commit 7f77bf76c7

@ -45,23 +45,32 @@ namespace MWWorld
{
assert (cell);
if (cell->mContext.filename.empty())
if (cell->mContextList.size() == 0)
return; // this is a dynamically generated cell -> skipping.
// Reopen the ESM reader and seek to the right position.
cell->restore (esm);
// Load references from all plugins that do something with this cell.
// HACK: only use first entry for now, full support requires some more work
//for (int i = 0; i < cell->mContextList.size(); i++)
for (int i = 0; i < 1; i++)
{
// Reopen the ESM reader and seek to the right position.
// TODO: we will need to intoduce separate "esm"s, one per plugin!
cell->restore (esm);
ESM::CellRef ref;
ESM::CellRef ref;
// Get each reference in turn
while (cell->getNextRef (esm, ref))
{
std::string lowerCase;
// Get each reference in turn
while (cell->getNextRef (esm, ref))
{
std::string lowerCase;
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
mIds.push_back (lowerCase);
// TODO: support deletion / moving references out of the cell. no simple "push_back",
// but see what the plugin wants to do.
mIds.push_back (lowerCase);
}
}
std::sort (mIds.begin(), mIds.end());
@ -71,57 +80,64 @@ namespace MWWorld
{
assert (cell);
if (cell->mContext.filename.empty())
if (cell->mContextList.size() == 0)
return; // this is a dynamically generated cell -> skipping.
// Reopen the ESM reader and seek to the right position.
cell->restore(esm);
ESM::CellRef ref;
// Get each reference in turn
while(cell->getNextRef(esm, ref))
// Load references from all plugins that do something with this cell.
// HACK: only use first entry for now, full support requires some more work
//for (int i = 0; i < cell->mContextList.size(); i++)
for (int i = 0; i < 1; i++)
{
std::string lowerCase;
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
int rec = store.find(ref.mRefID);
// Reopen the ESM reader and seek to the right position.
// TODO: we will need to intoduce separate "esm"s, one per plugin!
cell->restore(esm);
ref.mRefID = lowerCase;
ESM::CellRef ref;
/* We can optimize this further by storing the pointer to the
record itself in store.all, so that we don't need to look it
up again here. However, never optimize. There are infinite
opportunities to do that later.
*/
switch(rec)
// Get each reference in turn
while(cell->getNextRef(esm, ref))
{
case ESM::REC_ACTI: activators.find(ref, store.activators); break;
case ESM::REC_ALCH: potions.find(ref, store.potions); break;
case ESM::REC_APPA: appas.find(ref, store.appas); break;
case ESM::REC_ARMO: armors.find(ref, store.armors); break;
case ESM::REC_BOOK: books.find(ref, store.books); break;
case ESM::REC_CLOT: clothes.find(ref, store.clothes); break;
case ESM::REC_CONT: containers.find(ref, store.containers); break;
case ESM::REC_CREA: creatures.find(ref, store.creatures); break;
case ESM::REC_DOOR: doors.find(ref, store.doors); break;
case ESM::REC_INGR: ingreds.find(ref, store.ingreds); break;
case ESM::REC_LEVC: creatureLists.find(ref, store.creatureLists); break;
case ESM::REC_LEVI: itemLists.find(ref, store.itemLists); break;
case ESM::REC_LIGH: lights.find(ref, store.lights); break;
case ESM::REC_LOCK: lockpicks.find(ref, store.lockpicks); break;
case ESM::REC_MISC: miscItems.find(ref, store.miscItems); break;
case ESM::REC_NPC_: npcs.find(ref, store.npcs); break;
case ESM::REC_PROB: probes.find(ref, store.probes); break;
case ESM::REC_REPA: repairs.find(ref, store.repairs); break;
case ESM::REC_STAT: statics.find(ref, store.statics); break;
case ESM::REC_WEAP: weapons.find(ref, store.weapons); break;
case 0: std::cout << "Cell reference " + ref.mRefID + " not found!\n"; break;
default:
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
std::string lowerCase;
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
int rec = store.find(ref.mRefID);
ref.mRefID = lowerCase;
/* We can optimize this further by storing the pointer to the
record itself in store.all, so that we don't need to look it
up again here. However, never optimize. There are infinite
opportunities to do that later.
*/
switch(rec)
{
case ESM::REC_ACTI: activators.find(ref, store.activators); break;
case ESM::REC_ALCH: potions.find(ref, store.potions); break;
case ESM::REC_APPA: appas.find(ref, store.appas); break;
case ESM::REC_ARMO: armors.find(ref, store.armors); break;
case ESM::REC_BOOK: books.find(ref, store.books); break;
case ESM::REC_CLOT: clothes.find(ref, store.clothes); break;
case ESM::REC_CONT: containers.find(ref, store.containers); break;
case ESM::REC_CREA: creatures.find(ref, store.creatures); break;
case ESM::REC_DOOR: doors.find(ref, store.doors); break;
case ESM::REC_INGR: ingreds.find(ref, store.ingreds); break;
case ESM::REC_LEVC: creatureLists.find(ref, store.creatureLists); break;
case ESM::REC_LEVI: itemLists.find(ref, store.itemLists); break;
case ESM::REC_LIGH: lights.find(ref, store.lights); break;
case ESM::REC_LOCK: lockpicks.find(ref, store.lockpicks); break;
case ESM::REC_MISC: miscItems.find(ref, store.miscItems); break;
case ESM::REC_NPC_: npcs.find(ref, store.npcs); break;
case ESM::REC_PROB: probes.find(ref, store.probes); break;
case ESM::REC_REPA: repairs.find(ref, store.repairs); break;
case ESM::REC_STAT: statics.find(ref, store.statics); break;
case ESM::REC_WEAP: weapons.find(ref, store.weapons); break;
case 0: std::cout << "Cell reference " + ref.mRefID + " not found!\n"; break;
default:
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
}
}
}
}

@ -62,6 +62,10 @@ namespace MWWorld
if(obj == NULL)
throw std::runtime_error("Error resolving cell reference " + ref.mRefID);
// TODO: this line must be modified for multiple plugins and moved references.
// This means: no simple "push back", but search for an existing reference with
// this ID first! If it exists, merge data into this list instead of just adding it.
// I'll probably generate a separate method jist for this.
list.push_back(LiveRef(ref, obj));
}

@ -2,6 +2,7 @@
#include <string>
#include <sstream>
#include <c++/4.6/list>
#include "esmreader.hpp"
#include "esmwriter.hpp"
@ -111,7 +112,7 @@ void Cell::load(ESMReader &esm)
}
// Save position of the cell references and move on
mContext = esm.getContext();
mContextList.push_back(esm.getContext());
esm.skipRecord();
}
@ -148,7 +149,8 @@ void Cell::save(ESMWriter &esm)
void Cell::restore(ESMReader &esm) const
{
esm.restoreContext(mContext);
// TODO: support all contexts in the list!
esm.restoreContext(mContextList[0]);
}
std::string Cell::getDescription() const
@ -167,6 +169,12 @@ std::string Cell::getDescription() const
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
{
// TODO: Add support for moved references. References moved without crossing a cell boundary simply
// overwrite old data. References moved across cell boundaries are using a different set of keywords,
// and I'll have to think more about how this can be done.
// 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;

@ -2,6 +2,7 @@
#define OPENMW_ESM_CELL_H
#include <string>
#include <vector>
#include "esmcommon.hpp"
#include "defs.hpp"
@ -120,7 +121,7 @@ struct Cell
// Optional region name for exterior and quasi-exterior cells.
std::string mRegion;
ESM_Context mContext; // File position
std::vector<ESM_Context> mContextList; // File position; multiple positions for multiple plugin support
DATAstruct mData;
AMBIstruct mAmbi;
float mWater; // Water level

2
extern/shiny vendored

@ -1 +1 @@
Subproject commit f17c4ebab0e7a1f3bbb25fd9b3dbef2bd742536a
Subproject commit 4750676ac46a7aaa86bca53dc68c5a1ba11f3bc1
Loading…
Cancel
Save