1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 21:53:51 +00:00

- Add support for moving existing references by plugin files. No cell changing yet.

- Change CellRefList::list from list<> to map<int,> so we can identify live references by their Refnumber.
- Introduce ContainerRefList, a clone of the original CellRefList. It is now used for containers, which do not track Refnumbers.
- Many small tweaks so that the new CellRefList does not conflict with existing code.
This commit is contained in:
Mark Siewert 2012-11-17 21:50:25 +01:00
parent 2175f13b67
commit 31fb715bd7
10 changed files with 119 additions and 85 deletions

View file

@ -43,30 +43,30 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
cellStore.containers.list.begin());
iter!=cellStore.containers.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Ptr container (&iter->second, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->mInventory, mStore);
iter->second.base->mInventory, mStore);
}
for (CellRefList<ESM::Creature>::List::iterator iter (
cellStore.creatures.list.begin());
iter!=cellStore.creatures.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Ptr container (&iter->second, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->mInventory, mStore);
iter->second.base->mInventory, mStore);
}
for (CellRefList<ESM::NPC>::List::iterator iter (
cellStore.npcs.list.begin());
iter!=cellStore.npcs.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Ptr container (&iter->second, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->mInventory, mStore);
iter->second.base->mInventory, mStore);
}
}

View file

@ -65,8 +65,7 @@ namespace MWWorld
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
// TODO: Fully support deletion / moving references out of the cell. no simple "push_back",
// but make sure that the reference exists only once.
// TODO: Fully support deletion of references.
mIds.push_back (lowerCase);
}
}
@ -98,8 +97,7 @@ namespace MWWorld
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
// TODO: Fully support deletion / moving references out of the cell. No simple loading,
// but make sure that the reference exists only once. Current code clones references.
// TODO: Fully support deletion of references.
int rec = store.find(ref.mRefID);
ref.mRefID = lowerCase;

View file

@ -47,6 +47,47 @@ namespace MWWorld
/// A list of cell references
template <typename X>
struct CellRefList
{
typedef LiveCellRef<X> LiveRef;
typedef std::map<int,LiveRef> List;
List list;
// 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.
template <typename Y>
void find(ESM::CellRef &ref, const Y& recList)
{
const X* obj = recList.find(ref.mRefID);
if(obj == NULL)
throw std::runtime_error("Error resolving cell reference " + ref.mRefID);
list[ref.mRefnum] = LiveRef(ref, obj);
}
LiveRef *find (const std::string& name)
{
for (typename std::map<int,LiveRef>::iterator iter (list.begin()); iter!=list.end(); ++iter)
{
if (iter->second.mData.getCount() > 0 && iter->second.ref.mRefID == name)
return &iter->second;
}
return 0;
}
LiveRef &insert(const LiveRef &item) {
list[item.ref.mRefnum] = item;
return list[item.ref.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.
// TODO: Check how Morrowind does this! Maybe auto-generate references on drop.
template <typename X>
struct ContainerRefList
{
typedef LiveCellRef<X> LiveRef;
typedef std::list<LiveRef> List;
@ -62,10 +103,6 @@ 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));
}
@ -180,7 +217,7 @@ namespace MWWorld
{
for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end();
++iter)
if (!functor (iter->ref, iter->mData))
if (!functor (iter->second.ref, iter->second.mData))
return false;
return true;

View file

@ -19,11 +19,11 @@
namespace
{
template<typename T>
float getTotalWeight (const MWWorld::CellRefList<T>& cellRefList)
float getTotalWeight (const MWWorld::ContainerRefList<T>& cellRefList)
{
float sum = 0;
for (typename MWWorld::CellRefList<T>::List::const_iterator iter (
for (typename MWWorld::ContainerRefList<T>::List::const_iterator iter (
cellRefList.list.begin());
iter!=cellRefList.list.end();
++iter)
@ -270,29 +270,29 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor
++*this;
}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Potion>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Apparatus>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Armor>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Book>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Clothing>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Ingredient>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Light>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Tool>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Miscellaneous>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Probe>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Repair>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::CellRefList<ESM::Weapon>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<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::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;
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;
int mStateId;
mutable float mCachedWeight;
mutable bool mWeightUpToDate;
@ -119,18 +119,18 @@ namespace MWWorld
ContainerStore *mContainer;
mutable Ptr mPtr;
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;
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;
private:
@ -141,18 +141,18 @@ namespace MWWorld
///< Begin-iterator
// construct iterator using a CellRefList 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);
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);
void incType();

View file

@ -15,9 +15,9 @@ namespace
cellRefList.list.begin());
iter!=cellRefList.list.end(); ++iter)
{
if (!iter->base->mScript.empty() && iter->mData.getCount())
if (!iter->second.base->mScript.empty() && iter->second.mData.getCount())
{
localScripts.add (iter->base->mScript, MWWorld::Ptr (&*iter, cell));
localScripts.add (iter->second.base->mScript, MWWorld::Ptr (&iter->second, cell));
}
}
}

View file

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

View file

@ -28,13 +28,13 @@ namespace
cellRefList.list.begin());
iter!=cellRefList.list.end(); ++iter)
{
if (!iter->base->script.empty() && iter->mData.getCount())
if (!iter->second->base->script.empty() && iter->second->mData.getCount())
{
if (const ESM::Script *script = store.scripts.find (iter->base->script))
if (const ESM::Script *script = store.scripts.find (iter->second->base->script))
{
iter->mData.setLocals (*script);
localScripts.add (iter->base->script, MWWorld::Ptr (&*iter, cell));
localScripts.add (iter->base->script, MWWorld::Ptr (&iter->second, cell));
}
}
}
@ -48,10 +48,10 @@ namespace
for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter)
{
if(iter->mData.getCount() > 0 && iter->mData.getBaseNode()){
if (iter->mData.getHandle()==handle)
if (iter->second.mData.getCount() > 0 && iter->second.mData.getBaseNode()){
if (iter->second.mData.getHandle()==handle)
{
return &*iter;
return &iter->second;
}
}
}
@ -1115,10 +1115,10 @@ namespace MWWorld
std::vector<World::DoorMarker> result;
MWWorld::CellRefList<ESM::Door>& doors = cell->doors;
std::list< MWWorld::LiveCellRef<ESM::Door> >& refList = doors.list;
for (std::list< MWWorld::LiveCellRef<ESM::Door> >::iterator it = refList.begin(); it != refList.end(); ++it)
std::map<int, MWWorld::LiveCellRef<ESM::Door> >& refList = doors.list;
for (std::map<int, MWWorld::LiveCellRef<ESM::Door> >::iterator it = refList.begin(); it != refList.end(); ++it)
{
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
MWWorld::LiveCellRef<ESM::Door>& ref = it->second;
if (ref.ref.mTeleport)
{

View file

@ -113,8 +113,6 @@ void Cell::load(ESMReader &esm)
// Save position of the cell references and move on
mContextList.push_back(esm.getContext());
if (mContextList.size() > 1)
std::cout << "found two plugins" << std::endl;
esm.skipRecord();
}
@ -202,10 +200,8 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
// 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
{
@ -256,7 +252,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
esm.getHNOT(ref.mFltv, "FLTV");
esm.getHNT(ref.mPos, "DATA", 24);
// Number of references in the cell? Maximum once in each cell,
// but not always at the beginning, and not always right. In other
// words, completely useless.

View file

@ -523,7 +523,10 @@ namespace ESMS
// Store exterior cells by grid position, try to merge with existing parent data.
ESM::Cell *oldcell = const_cast<ESM::Cell*>(searchExt(cell->getGridX(), cell->getGridY()));
if (oldcell) {
cell->mContextList.push_back(oldcell->mContextList.at(0));
// The load order is important. Push the new source context on the *back* of the existing list,
// and then move the list to the new cell.
oldcell->mContextList.push_back(cell->mContextList.at(0));
cell->mContextList = oldcell->mContextList;
delete oldcell;
}
extCells[std::make_pair (cell->mData.mX, cell->mData.mY)] = cell;