mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 20:23:51 +00:00
- 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.
This commit is contained in:
parent
64c08eada4
commit
7f77bf76c7
5 changed files with 89 additions and 60 deletions
|
@ -45,23 +45,32 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
assert (cell);
|
assert (cell);
|
||||||
|
|
||||||
if (cell->mContext.filename.empty())
|
if (cell->mContextList.size() == 0)
|
||||||
return; // this is a dynamically generated cell -> skipping.
|
return; // this is a dynamically generated cell -> skipping.
|
||||||
|
|
||||||
// Reopen the ESM reader and seek to the right position.
|
// Load references from all plugins that do something with this cell.
|
||||||
cell->restore (esm);
|
// HACK: only use first entry for now, full support requires some more work
|
||||||
|
//for (int i = 0; i < cell->mContextList.size(); i++)
|
||||||
ESM::CellRef ref;
|
for (int i = 0; i < 1; i++)
|
||||||
|
|
||||||
// Get each reference in turn
|
|
||||||
while (cell->getNextRef (esm, ref))
|
|
||||||
{
|
{
|
||||||
std::string lowerCase;
|
// 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);
|
||||||
|
|
||||||
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
ESM::CellRef ref;
|
||||||
(int(*)(int)) std::tolower);
|
|
||||||
|
|
||||||
mIds.push_back (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);
|
||||||
|
|
||||||
|
// 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());
|
std::sort (mIds.begin(), mIds.end());
|
||||||
|
@ -71,57 +80,64 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
assert (cell);
|
assert (cell);
|
||||||
|
|
||||||
if (cell->mContext.filename.empty())
|
if (cell->mContextList.size() == 0)
|
||||||
return; // this is a dynamically generated cell -> skipping.
|
return; // this is a dynamically generated cell -> skipping.
|
||||||
|
|
||||||
// Reopen the ESM reader and seek to the right position.
|
// Load references from all plugins that do something with this cell.
|
||||||
cell->restore(esm);
|
// HACK: only use first entry for now, full support requires some more work
|
||||||
|
//for (int i = 0; i < cell->mContextList.size(); i++)
|
||||||
ESM::CellRef ref;
|
for (int i = 0; i < 1; i++)
|
||||||
|
|
||||||
// Get each reference in turn
|
|
||||||
while(cell->getNextRef(esm, ref))
|
|
||||||
{
|
{
|
||||||
std::string lowerCase;
|
// 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);
|
||||||
|
|
||||||
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
ESM::CellRef ref;
|
||||||
(int(*)(int)) std::tolower);
|
|
||||||
|
|
||||||
int rec = store.find(ref.mRefID);
|
// Get each reference in turn
|
||||||
|
while(cell->getNextRef(esm, ref))
|
||||||
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;
|
std::string lowerCase;
|
||||||
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;
|
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
||||||
default:
|
(int(*)(int)) std::tolower);
|
||||||
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
|
||||||
|
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)
|
if(obj == NULL)
|
||||||
throw std::runtime_error("Error resolving cell reference " + ref.mRefID);
|
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));
|
list.push_back(LiveRef(ref, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <c++/4.6/list>
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
@ -111,7 +112,7 @@ void Cell::load(ESMReader &esm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save position of the cell references and move on
|
// Save position of the cell references and move on
|
||||||
mContext = esm.getContext();
|
mContextList.push_back(esm.getContext());
|
||||||
esm.skipRecord();
|
esm.skipRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +149,8 @@ void Cell::save(ESMWriter &esm)
|
||||||
|
|
||||||
void Cell::restore(ESMReader &esm) const
|
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
|
std::string Cell::getDescription() const
|
||||||
|
@ -167,6 +169,12 @@ std::string Cell::getDescription() const
|
||||||
|
|
||||||
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
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())
|
if (!esm.hasMoreSubs())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define OPENMW_ESM_CELL_H
|
#define OPENMW_ESM_CELL_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "esmcommon.hpp"
|
#include "esmcommon.hpp"
|
||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
|
@ -120,7 +121,7 @@ struct Cell
|
||||||
// Optional region name for exterior and quasi-exterior cells.
|
// Optional region name for exterior and quasi-exterior cells.
|
||||||
std::string mRegion;
|
std::string mRegion;
|
||||||
|
|
||||||
ESM_Context mContext; // File position
|
std::vector<ESM_Context> mContextList; // File position; multiple positions for multiple plugin support
|
||||||
DATAstruct mData;
|
DATAstruct mData;
|
||||||
AMBIstruct mAmbi;
|
AMBIstruct mAmbi;
|
||||||
float mWater; // Water level
|
float mWater; // Water level
|
||||||
|
|
2
extern/shiny
vendored
2
extern/shiny
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit f17c4ebab0e7a1f3bbb25fd9b3dbef2bd742536a
|
Subproject commit 4750676ac46a7aaa86bca53dc68c5a1ba11f3bc1
|
Loading…
Reference in a new issue