diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index fcdec1e7f0..322b43a00d 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -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); - - 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; + // 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), - (int(*)(int)) std::tolower); + ESM::CellRef ref; - 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()); @@ -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; + // 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), - (int(*)(int)) std::tolower); + ESM::CellRef ref; - 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) + // 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; + std::string lowerCase; - 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::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"; + } } } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 32ab6e07b9..fd739b5651 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -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)); } diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 97ce177753..65c9c23e7a 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -2,6 +2,7 @@ #include #include +#include #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; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index fbd7c04562..9511ae0e74 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -2,6 +2,7 @@ #define OPENMW_ESM_CELL_H #include +#include #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 mContextList; // File position; multiple positions for multiple plugin support DATAstruct mData; AMBIstruct mAmbi; float mWater; // Water level diff --git a/extern/shiny b/extern/shiny index f17c4ebab0..4750676ac4 160000 --- a/extern/shiny +++ b/extern/shiny @@ -1 +1 @@ -Subproject commit f17c4ebab0e7a1f3bbb25fd9b3dbef2bd742536a +Subproject commit 4750676ac46a7aaa86bca53dc68c5a1ba11f3bc1