1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 09:45:36 +00:00

- For pull request: remove all instances of maps used to track refnumbers.

- new file: apps/openmw/mwworld/store.cpp, had to move reference merging method out of the header file to prevent three-way recursion/unresolved forward references in custom compare operators.
This commit is contained in:
Mark Siewert 2013-02-09 13:00:57 +01:00
parent 3e43db5f76
commit eefbdde6de
13 changed files with 233 additions and 225 deletions

View file

@ -213,8 +213,10 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
StringsVector plugin = variables["plugin"].as<StringsVector>();
// Removed check for 255 files, which would be the hard-coded limit in Morrowind.
// I'll keep the following variable in, maybe we can use it for somethng different.
int cnt = master.size() + plugin.size();
// I'll keep the following variable in, maybe we can use it for something different.
// Say, a feedback like "loading file x/cnt".
// Commenting this out for now to silence compiler warning.
//int cnt = master.size() + plugin.size();
// Prepare loading master/plugin files (i.e. send filenames to engine)
for (std::vector<std::string>::size_type i = 0; i < master.size(); i++)

View file

@ -42,30 +42,30 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
cellStore.mContainers.mList.begin());
iter!=cellStore.mContainers.mList.end(); ++iter)
{
Ptr container (&iter->second, &cellStore);
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->second.mBase->mInventory, mStore);
iter->mBase->mInventory, mStore);
}
for (CellRefList<ESM::Creature>::List::iterator iter (
cellStore.mCreatures.mList.begin());
iter!=cellStore.mCreatures.mList.end(); ++iter)
{
Ptr container (&iter->second, &cellStore);
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->second.mBase->mInventory, mStore);
iter->mBase->mInventory, mStore);
}
for (CellRefList<ESM::NPC>::List::iterator iter (
cellStore.mNpcs.mList.begin());
iter!=cellStore.mNpcs.mList.end(); ++iter)
{
Ptr container (&iter->second, &cellStore);
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->second.mBase->mInventory, mStore);
iter->mBase->mInventory, mStore);
}
}

View file

@ -10,6 +10,41 @@
namespace MWWorld
{
template <typename X>
void CellRefList<X>::load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
{
// Get existing reference, in case we need to overwrite it.
typename std::list<LiveRef>::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum);
// Skip this when reference was deleted.
// TODO: Support respawning references, in this case, we need to track it somehow.
if (ref.mDeleted) {
mList.erase(iter);
return;
}
// for throwing exception on unhandled record type
const MWWorld::Store<X> &store = esmStore.get<X>();
const X *ptr = store.search(ref.mRefID);
/// \note no longer redundant - changed to Store<X>::search(), don't throw
/// an exception on miss, try to continue (that's how MW does it, anyway)
if (ptr == NULL) {
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
} else {
if (iter != mList.end())
*iter = LiveRef(ref, ptr);
else
mList.push_back(LiveRef(ref, ptr));
}
}
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum)
{
return (ref.mRef.mRefnum == pRefnum);
}
CellStore::CellStore (const ESM::Cell *cell)
: mCell (cell), mState (State_Unloaded)
{
@ -95,7 +130,8 @@ namespace MWWorld
{
// Don't load reference if it was moved to a different cell.
std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID);
if (mCell->mMovedRefs.find(ref.mRefnum) != mCell->mMovedRefs.end()) {
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
if (iter != mCell->mMovedRefs.end()) {
continue;
}
int rec = store.find(ref.mRefID);
@ -141,8 +177,8 @@ namespace MWWorld
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); it++)
{
// Doesn't seem to work in one line... huh? Too sleepy to check...
//const ESM::CellRef &ref0 = it->second;
ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->second);
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
//ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->second);
std::string lowerCase;

View file

@ -9,11 +9,12 @@
#include "refdata.hpp"
#include "esmstore.hpp"
struct C;
namespace MWWorld
{
class Ptr;
class ESMStore;
/// A reference to one object (of any type) in a cell.
///
/// Constructing this with a CellRef instance in the constructor means that
@ -42,88 +43,25 @@ namespace MWWorld
/// runtime-data
RefData mData;
};
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum);
/// A list of cell references
template <typename X>
struct CellRefList
{
typedef LiveCellRef<X> LiveRef;
typedef std::map<int,LiveRef> List;
typedef std::list<LiveRef> List;
List mList;
// Search for the given reference in the given reclist from
// ESMStore. Insert the reference into the list if a match is
// found. If not, throw an exception.
/// Searches for reference of appropriate type in given ESMStore.
/// If reference exists, loads it into container, throws an exception
/// on miss
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
{
// Skip this when reference was deleted.
// TODO: Support respawning references, in this case, we need to track it somehow.
if (ref.mDeleted) {
mList.erase(ref.mRefnum);
return;
}
// for throwing exception on unhandled record type
const MWWorld::Store<X> &store = esmStore.get<X>();
const X *ptr = store.search(ref.mRefID);
/// \note no longer redundant - changed to Store<X>::search(), don't throw
/// an exception on miss, try to continue (that's how MW does it, anyway)
if (ptr == NULL) {
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
} else
mList[ref.mRefnum] = LiveRef(ref, ptr);
}
LiveRef *find (const std::string& name)
{
for (typename std::map<int,LiveRef>::iterator iter (mList.begin()); iter!=mList.end(); ++iter)
{
if (iter->second.mData.getCount() > 0 && iter->second.mRef.mRefID == name)
return &iter->second;
}
return 0;
}
LiveRef &insert(const LiveRef &item) {
mList[item.mRef.mRefnum] = item;
return mList[item.mRef.mRefnum];
}
};
/// A list of container references. These references do not track their mRefnumber.
/// Otherwise, taking 1 of 20 instances of an object would produce multiple objects
/// with the same reference.
/// Unfortunately, this also means that we need a different STL container.
/// (cells use CellRefList, where refs can be located according to their refnumner,
/// which uses a map; container items do not make use of the refnumber, so we
/// can't use a map with refnumber keys.)
template <typename X>
struct ContainerRefList
{
typedef LiveCellRef<X> LiveRef;
typedef std::list<LiveRef> List;
List mList;
/// Searches for reference of appropriate type in given ESMStore.
/// If reference exists, loads it into container, throws an exception
/// on miss
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
{
// for throwing exception on unhandled record type
const MWWorld::Store<X> &store = esmStore.get<X>();
const X *ptr = store.find(ref.mRefID);
/// \note redundant because Store<X>::find() throws exception on miss
if (ptr == NULL) {
throw std::runtime_error("Error resolving cell reference " + ref.mRefID);
}
mList.push_back(LiveRef(ref, ptr));
}
// Moved to cpp file, as we require a custom compare operator for it,
// and the build will fail with an ugly three-way cyclic header dependence
// so we need to pass the instantiation of the method to the lnker, when
// all methods are known.
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore);
LiveRef *find (const std::string& name)
{
@ -236,7 +174,7 @@ namespace MWWorld
{
for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
++iter)
if (!functor (iter->second.mRef, iter->second.mData))
if (!functor (iter->mRef, iter->mData))
return false;
return true;

View file

@ -21,11 +21,11 @@
namespace
{
template<typename T>
float getTotalWeight (const MWWorld::ContainerRefList<T>& cellRefList)
float getTotalWeight (const MWWorld::CellRefList<T>& cellRefList)
{
float sum = 0;
for (typename MWWorld::ContainerRefList<T>::List::const_iterator iter (
for (typename MWWorld::CellRefList<T>::List::const_iterator iter (
cellRefList.mList.begin());
iter!=cellRefList.mList.end();
++iter)
@ -300,29 +300,29 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor
++*this;
}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Potion>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Potion>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Potion), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mPotion(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Apparatus>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Apparatus), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mApparatus(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Armor>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Armor>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Armor), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mArmor(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Book>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Book>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Book), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mBook(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Clothing>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Clothing>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Clothing), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mClothing(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Ingredient>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Light>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Tool>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Probe>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Probe>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Probe), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mProbe(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Repair>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Repair), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mRepair(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Weapon>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Weapon>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Weapon), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mWeapon(iterator){}
void MWWorld::ContainerStoreIterator::incType()

View file

@ -37,18 +37,18 @@ namespace MWWorld
private:
MWWorld::ContainerRefList<ESM::Potion> potions;
MWWorld::ContainerRefList<ESM::Apparatus> appas;
MWWorld::ContainerRefList<ESM::Armor> armors;
MWWorld::ContainerRefList<ESM::Book> books;
MWWorld::ContainerRefList<ESM::Clothing> clothes;
MWWorld::ContainerRefList<ESM::Ingredient> ingreds;
MWWorld::ContainerRefList<ESM::Light> lights;
MWWorld::ContainerRefList<ESM::Tool> lockpicks;
MWWorld::ContainerRefList<ESM::Miscellaneous> miscItems;
MWWorld::ContainerRefList<ESM::Probe> probes;
MWWorld::ContainerRefList<ESM::Repair> repairs;
MWWorld::ContainerRefList<ESM::Weapon> weapons;
MWWorld::CellRefList<ESM::Potion> potions;
MWWorld::CellRefList<ESM::Apparatus> appas;
MWWorld::CellRefList<ESM::Armor> armors;
MWWorld::CellRefList<ESM::Book> books;
MWWorld::CellRefList<ESM::Clothing> clothes;
MWWorld::CellRefList<ESM::Ingredient> ingreds;
MWWorld::CellRefList<ESM::Light> lights;
MWWorld::CellRefList<ESM::Tool> lockpicks;
MWWorld::CellRefList<ESM::Miscellaneous> miscItems;
MWWorld::CellRefList<ESM::Probe> probes;
MWWorld::CellRefList<ESM::Repair> repairs;
MWWorld::CellRefList<ESM::Weapon> weapons;
int mStateId;
mutable float mCachedWeight;
mutable bool mWeightUpToDate;
@ -120,18 +120,18 @@ namespace MWWorld
ContainerStore *mContainer;
mutable Ptr mPtr;
MWWorld::ContainerRefList<ESM::Potion>::List::iterator mPotion;
MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator mApparatus;
MWWorld::ContainerRefList<ESM::Armor>::List::iterator mArmor;
MWWorld::ContainerRefList<ESM::Book>::List::iterator mBook;
MWWorld::ContainerRefList<ESM::Clothing>::List::iterator mClothing;
MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator mIngredient;
MWWorld::ContainerRefList<ESM::Light>::List::iterator mLight;
MWWorld::ContainerRefList<ESM::Tool>::List::iterator mLockpick;
MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator mMiscellaneous;
MWWorld::ContainerRefList<ESM::Probe>::List::iterator mProbe;
MWWorld::ContainerRefList<ESM::Repair>::List::iterator mRepair;
MWWorld::ContainerRefList<ESM::Weapon>::List::iterator mWeapon;
MWWorld::CellRefList<ESM::Potion>::List::iterator mPotion;
MWWorld::CellRefList<ESM::Apparatus>::List::iterator mApparatus;
MWWorld::CellRefList<ESM::Armor>::List::iterator mArmor;
MWWorld::CellRefList<ESM::Book>::List::iterator mBook;
MWWorld::CellRefList<ESM::Clothing>::List::iterator mClothing;
MWWorld::CellRefList<ESM::Ingredient>::List::iterator mIngredient;
MWWorld::CellRefList<ESM::Light>::List::iterator mLight;
MWWorld::CellRefList<ESM::Tool>::List::iterator mLockpick;
MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator mMiscellaneous;
MWWorld::CellRefList<ESM::Probe>::List::iterator mProbe;
MWWorld::CellRefList<ESM::Repair>::List::iterator mRepair;
MWWorld::CellRefList<ESM::Weapon>::List::iterator mWeapon;
private:
@ -142,18 +142,18 @@ namespace MWWorld
///< Begin-iterator
// construct iterator using a CellRefList iterator
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Potion>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Armor>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Book>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Clothing>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Light>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Tool>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Probe>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Repair>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Weapon>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Potion>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Apparatus>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Armor>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Book>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Clothing>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Ingredient>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Probe>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Weapon>::List::iterator);
void incType();

View file

@ -17,9 +17,9 @@ namespace
cellRefList.mList.begin());
iter!=cellRefList.mList.end(); ++iter)
{
if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount())
if (!iter->mBase->mScript.empty() && iter->mData.getCount())
{
localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell));
localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell));
}
}
}
@ -34,7 +34,7 @@ namespace
iter!=cellRefList.mList.end(); ++iter)
{
MWWorld::Ptr containerPtr (&iter->second, cell);
MWWorld::Ptr containerPtr (&*iter, cell);
MWWorld::ContainerStore& container = MWWorld::Class::get(containerPtr).getContainerStore(containerPtr);
for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3)

View file

@ -23,7 +23,7 @@ namespace
if (!cellRefList.mList.empty())
{
const MWWorld::Class& class_ =
MWWorld::Class::get (MWWorld::Ptr (&cellRefList.mList.begin()->second, &cell));
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell));
int numRefs = cellRefList.mList.size();
int current = 0;
@ -33,9 +33,9 @@ namespace
MWBase::Environment::get().getWindowManager ()->setLoadingProgress ("Loading cells", 1, current, numRefs);
++current;
if (it->second.mData.getCount() || it->second.mData.isEnabled())
if (it->mData.getCount() || it->mData.isEnabled())
{
MWWorld::Ptr ptr (&it->second, &cell);
MWWorld::Ptr ptr (&*it, &cell);
try
{

View file

@ -0,0 +1,65 @@
#include "store.hpp"
namespace MWWorld {
void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
{
// Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
// are not available until both cells have been loaded! So first, proceed as usual.
// All cells have a name record, even nameless exterior cells.
std::string idLower = Misc::StringUtils::lowerCase(id);
ESM::Cell *cell = new ESM::Cell;
cell->mName = id;
// The cell itself takes care of some of the hairy details
cell->load(esm, *mEsmStore);
if(cell->mData.mFlags & ESM::Cell::Interior)
{
// Store interior cell by name, try to merge with existing parent data.
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
if (oldcell) {
// push the new references on the list of references to manage
oldcell->mContextList.push_back(cell->mContextList.at(0));
// copy list into new cell
cell->mContextList = oldcell->mContextList;
// have new cell replace old cell
*oldcell = *cell;
} else
mInt[idLower] = *cell;
}
else
{
// Store exterior cells by grid position, try to merge with existing parent data.
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell->getGridX(), cell->getGridY()));
if (oldcell) {
// push the new references on the list of references to manage
oldcell->mContextList.push_back(cell->mContextList.at(0));
// copy list into new cell
cell->mContextList = oldcell->mContextList;
// merge lists of leased references, use newer data in case of conflict
for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); it++) {
// remove reference from current leased ref tracker and add it to new cell
ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefnum);
if (itold != oldcell->mMovedRefs.end()) {
ESM::MovedCellRef target0 = *itold;
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefnum);
wipecell->mLeasedRefs.erase(it_lease);
*itold = *it;
}
}
cell->mMovedRefs = oldcell->mMovedRefs;
// have new cell replace old cell
*oldcell = *cell;
} else
mExt[std::make_pair(cell->mData.mX, cell->mData.mY)] = *cell;
}
delete cell;
}
}

View file

@ -187,7 +187,7 @@ namespace MWWorld
T item;
item.mId = Misc::StringUtils::lowerCase(id);
typename std::map<std::string, T>::const_iterator it = mStatic.find(item.mId);
typename std::map<std::string, T>::iterator it = mStatic.find(item.mId);
if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->second.mId, id)) {
mStatic.erase(it);
@ -523,62 +523,12 @@ namespace MWWorld
}
}
void load(ESM::ESMReader &esm, const std::string &id) {
// Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
// are not available until both cells have been loaded! So first, proceed as usual.
// All cells have a name record, even nameless exterior cells.
std::string idLower = Misc::StringUtils::lowerCase(id);
ESM::Cell *cell = new ESM::Cell;
cell->mName = id;
// The cell itself takes care of all the hairy details
cell->load(esm, *mEsmStore);
if(cell->mData.mFlags & ESM::Cell::Interior)
{
// Store interior cell by name, try to merge with existing parent data.
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
if (oldcell) {
// push the new references on the list of references to manage
oldcell->mContextList.push_back(cell->mContextList.at(0));
// copy list into new cell
cell->mContextList = oldcell->mContextList;
// have new cell replace old cell
*oldcell = *cell;
} else
mInt[idLower] = *cell;
}
else
{
// Store exterior cells by grid position, try to merge with existing parent data.
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell->getGridX(), cell->getGridY()));
if (oldcell) {
// push the new references on the list of references to manage
oldcell->mContextList.push_back(cell->mContextList.at(0));
// copy list into new cell
cell->mContextList = oldcell->mContextList;
// merge lists of leased references, use newer data in case of conflict
for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); it++) {
// remove reference from current leased ref tracker and add it to new cell
if (oldcell->mMovedRefs.find(it->second.mRefnum) != oldcell->mMovedRefs.end()) {
ESM::MovedCellRef target0 = oldcell->mMovedRefs[it->second.mRefnum];
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
wipecell->mLeasedRefs.erase(it->second.mRefnum);
}
oldcell->mMovedRefs[it->second.mRefnum] = it->second;
}
cell->mMovedRefs = oldcell->mMovedRefs;
// have new cell replace old cell
*oldcell = *cell;
} else
mExt[std::make_pair(cell->mData.mX, cell->mData.mY)] = *cell;
}
delete cell;
}
// HACK: Method implementation had to be moved to a separate cpp file, as we would otherwise get
// errors related to the compare operator used in std::find for ESM::MovedCellRefTracker::find.
// There some nasty three-way cyclic header dependency involved, which I could only fix by moving
// this method.
void load(ESM::ESMReader &esm, const std::string &id);
iterator intBegin() const {
return iterator(mSharedInt.begin());
}

View file

@ -33,13 +33,13 @@ namespace
cellRefList.mList.begin());
iter!=cellRefList.mList.end(); ++iter)
{
if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount())
if (!iter->mBase->mScript.empty() && iter->mData.getCount())
{
if (const ESM::Script *script = store.get<ESM::Script>().find (iter->second.mBase->mScript))
if (const ESM::Script *script = store.get<ESM::Script>().find (iter->mBase->mScript))
{
iter->mData.setLocals (*script);
localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell));
localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell));
}
}
}
@ -53,10 +53,10 @@ namespace
for (iterator iter (refList.mList.begin()); iter!=refList.mList.end(); ++iter)
{
if (iter->second.mData.getCount() > 0 && iter->second.mData.getBaseNode()){
if (iter->second.mData.getHandle()==handle)
if (iter->mData.getCount() > 0 && iter->mData.getBaseNode()){
if (iter->mData.getHandle()==handle)
{
return &iter->second;
return &*iter;
}
}
}
@ -1261,7 +1261,7 @@ namespace MWWorld
CellRefList<ESM::Door>::List& refList = doors.mList;
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
{
MWWorld::LiveCellRef<ESM::Door>& ref = it->second;
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
if (ref.mRef.mTeleport)
{

View file

@ -14,6 +14,17 @@
namespace ESM
{
/// Some overloaded copare operators.
bool operator==(const MovedCellRef& ref, int pRefnum)
{
return (ref.mRefnum == pRefnum);
}
bool operator==(const CellRef& ref, int pRefnum)
{
return (ref.mRefnum == pRefnum);
}
void CellRef::save(ESMWriter &esm)
{
esm.writeHNT("FRMR", mRefnum);
@ -134,13 +145,14 @@ void Cell::load(ESMReader &esm, MWWorld::ESMStore &store)
(int(*)(int)) std::tolower);
// Add data required to make reference appear in the correct cell.
/*
std::cout << "Moving refnumber! First cell: " << mData.mX << " " << mData.mY << std::endl;
std::cout << " New cell: " << cMRef.mTarget[0] << " " << cMRef.mTarget[0] << std::endl;
std::cout << "Refnumber (MVRF): " << cMRef.mRefnum << " (FRMR) " << ref.mRefnum << std::endl;
*/
mMovedRefs[cMRef.mRefnum] = cMRef;
cellAlt->mLeasedRefs[ref.mRefnum] = ref;
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
mMovedRefs.push_back(cMRef);
// But there may be duplicates here!
ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum);
if (iter == cellAlt->mLeasedRefs.end())
cellAlt->mLeasedRefs.push_back(ref);
else
*iter = ref;
}
// Save position of the cell references and move on

View file

@ -6,7 +6,7 @@
#include "esmcommon.hpp"
#include "defs.hpp"
#include <apps/openmw/mwbase/world.hpp>
#include "apps/openmw/mwbase/world.hpp"
/*
namespace MWWorld {
@ -95,24 +95,29 @@ public:
};
/* Moved cell reference tracking object. This mainly stores the target cell
of the reference, so we can easily know where it has been moved when another
plugin tries to move it independently.
*/
of the reference, so we can easily know where it has been moved when another
plugin tries to move it independently.
Unfortunately, we need to implement this here.
*/
class MovedCellRef
{
public:
int mRefnum;
// Target cell (if exterior)
int mTarget[2];
// TODO: Support moving references between exterior and interior cells!
// This may happen in saves, when an NPC follows the player. Tribunal
// introduces a henchman (which no one uses), so we may need this as well.
int mRefnum;
// Target cell (if exterior)
int mTarget[2];
// TODO: Support moving references between exterior and interior cells!
// This may happen in saves, when an NPC follows the player. Tribunal
// introduces a henchman (which no one uses), so we may need this as well.
};
typedef std::map<int, MovedCellRef> MovedCellRefTracker;
typedef std::map<int, CellRef> CellRefTracker;
/// Overloaded copare operator used to search inside a list of cell refs.
bool operator==(const MovedCellRef& ref, int pRefnum);
bool operator==(const CellRef& ref, int pRefnum);
typedef std::list<MovedCellRef> MovedCellRefTracker;
typedef std::list<CellRef> CellRefTracker;
/* Cells hold data about objects, creatures, statics (rocks, walls,
buildings) and landscape (for exterior cells). Cells frequently