From b103426cf0f1a45efa97ca4d3cf215ee8640dc4f Mon Sep 17 00:00:00 2001 From: Mark Siewert Date: Sun, 25 Nov 2012 19:07:16 +0100 Subject: [PATCH] - Partially reimplement deleting objects defined in a parent esX file. - Try to reimplement multiple esX files dropping references in the same file. NOTE: None of these features works. Maybe the code itself does not build. Anyway, after 12 hours of hacking, I am just tired and want to get a snapshot of the code out. --- apps/openmw/mwworld/cellstore.cpp | 2 ++ apps/openmw/mwworld/esmstore.cpp | 11 ++++++- apps/openmw/mwworld/esmstore.hpp | 3 +- apps/openmw/mwworld/store.hpp | 50 ++++++++++++++++++++++++++----- apps/openmw/mwworld/worldimp.cpp | 2 ++ components/esm/loadcell.cpp | 1 + 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index ba8f5aa61..ff8368dd1 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -83,6 +83,8 @@ namespace MWWorld // Load references from all plugins that do something with this cell. for (size_t i = 0; i < mCell->mContextList.size(); i++) { + if (mCell->mContextList.size() > 1) + std::cout << "number of lists " << mCell->mContextList.size() << std::endl; // Reopen the ESM reader and seek to the right position. int index = mCell->mContextList.at(i).index; mCell->restore (esm[index], i); diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index db444153f..564126797 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -84,6 +84,15 @@ void ESMStore::load(ESM::ESMReader &esm) } else { // Load it std::string id = esm.getHNOString("NAME"); + // ... unless it got deleted! This means that the following record + // has been deleted, and trying to load it using standard assumptions + // on the structure will (probably) fail. + if (esm.isNextSub("DELE")) { + esm.skipRecord(); + all.erase(id); + it->second->remove(id); + continue; + } it->second->load(esm, id); if (n.val==ESM::REC_DIAL) { @@ -113,7 +122,7 @@ void ESMStore::load(ESM::ESMReader &esm) cout << *it << " "; cout << endl; */ - setUp(); + //setUp(); } void ESMStore::setUp() diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 9917254ee..bd8e003f4 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -168,7 +168,8 @@ namespace MWWorld return ptr; } - private: + // This method must be called once, after loading all master/plugin files. This can only be done + // from the outside, so it must be public. void setUp(); }; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 53f4482bb..d4d632eff 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -473,14 +473,48 @@ namespace MWWorld } void load(ESM::ESMReader &esm, const std::string &id) { - ESM::Cell cell; - cell.mName = id; - cell.load(esm); - - if (cell.isExterior()) { - mExt.push_back(cell); - } else { - mInt.push_back(cell); + // 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. + ESM::Cell *cell = new ESM::Cell; + cell->mName = id; + + // The cell itself takes care of all the hairy details + cell->load(esm); + + if(cell->mData.mFlags & ESM::Cell::Interior) + { + // Store interior cell by name, try to merge with existing parent data. + ESM::Cell *oldcell = const_cast(search(id)); + 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.push_back(*cell); + delete cell; + } + else + { + // Store exterior cells by grid position, try to merge with existing parent data. + ESM::Cell *oldcell = const_cast(search(cell->getGridX(), cell->getGridY())); + std::cout << "setup - " << oldcell << " " << cell->getGridX() << " " << cell->getGridY() << std::endl; + 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 + mExt.push_back(*cell); + delete cell; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1fa23700d..6dbba2a45 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -215,6 +215,8 @@ namespace MWWorld mEsm[idx] = lEsm; mStore.load (mEsm[idx]); } + + mStore.setUp(); mPlayer = new MWWorld::Player (mStore.get().find ("player"), *this); mRendering->attachCameraTo(mPlayer->getPlayer()); diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index b7f27b08d..0158af70a 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -201,6 +201,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) ref.mRefnum &= 0x00ffffff; // delete old plugin ID const ESM::ESMReader::MasterList &masters = esm.getMasters(); global = masters[local-1].index + 1; + std::cout << "moved ref: " << local << " " << global << std::endl; ref.mRefnum |= global << 24; // insert global plugin ID } else