diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index c41fc844f9..01c2294450 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -42,7 +42,10 @@ #include #include #include +#include +#include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/luamanager.hpp" @@ -756,19 +759,46 @@ namespace MWWorld } } - void CellStore::listRefs(const ESM4::Cell& cell) - { - auto& refs = MWBase::Environment::get().getWorld()->getStore().get(); - - for (const auto& ref : refs) + template + static void visitCell4References(const ESM4::Cell& cell, ReferenceInvlocable&& invocable) + { + auto stream = Files::openBinaryInputFileStream(cell.mReaderContext.filename); + ESM4::Reader readerESM4( + std::move(stream), cell.mReaderContext.filename, MWBase::Environment::get().getResourceSystem()->getVFS()); + readerESM4.setEncoder(nullptr); + readerESM4.restoreContext(cell.mReaderContext); + bool continueRead = true; + while (ESM::RefId::formIdRefId(readerESM4.getContext().currCell) == cell.mId && readerESM4.hasMoreRecs() + && continueRead) { - if (ref.mParent == cell.mId) - { - mIds.push_back(ref.mBaseObj); - } + continueRead = ESM4::ReaderUtils::readItem( + readerESM4, + [&](ESM4::Reader& reader) { + auto recordType = static_cast(reader.hdr().record.typeId); + ESM::RecNameInts esm4RecName = static_cast(ESM::esm4Recname(recordType)); + if (esm4RecName == ESM::RecNameInts::REC_REFR4) + { + ESM4::Reference ref; + ref.load(reader); + invocable(ref); + return true; + } + else if (esm4RecName == ESM::RecNameInts::REC_CELL4) + { + ESM4::Cell cellToLoad; + cellToLoad.load(reader); // This is necessary to exit + } + return false; + }, + [&](ESM4::Reader& reader) {}); } } + void CellStore::listRefs(const ESM4::Cell& cell) + { + visitCell4References(cell, [&](ESM4::Reference& ref) { mIds.push_back(ref.mBaseObj); }); + } + void CellStore::listRefs() { ESM::visit([&](auto&& cell) { listRefs(cell); }, mCellVariant); @@ -830,15 +860,7 @@ namespace MWWorld void CellStore::loadRefs(const ESM4::Cell& cell, std::map& refNumToID) { - auto& refs = MWBase::Environment::get().getWorld()->getStore().get(); - - for (const auto& ref : refs) - { - if (ref.mParent == cell.mId) - { - loadRef(ref, false); - } - } + visitCell4References(cell, [&](ESM4::Reference& ref) { loadRef(ref, false); }); } void CellStore::loadRefs() diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 3f153d45c0..ea72f6bd9e 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -29,7 +29,6 @@ namespace ESM4 class Reader; struct Static; struct Cell; - struct Reference; struct Light; } @@ -106,7 +105,7 @@ namespace MWWorld // Special entry which is hardcoded and not loaded from an ESM Store, - Store, Store, Store, Store>; + Store, Store, Store>; private: template diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 1b61b746cf..fc199be6fc 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -240,6 +240,8 @@ void ESM4::Cell::load(ESM4::Reader& reader) throw std::runtime_error("ESM4::CELL::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } } + + mReaderContext = reader.getContext(); } // void ESM4::Cell::save(ESM4::Writer& writer) const diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index da7a3fea63..264746a1c6 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace ESM4 { @@ -96,6 +97,8 @@ namespace ESM4 CellGroup* mCellGroup; + ESM4::ReaderContext mReaderContext; + void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const;