#ifndef GAME_MWWORLD_WORLDMODEL_H #define GAME_MWWORLD_WORLDMODEL_H #include #include #include #include #include "cellstore.hpp" #include "ptr.hpp" namespace ESM { class ESMReader; class ESMWriter; class ReadersCache; struct CellId; struct Cell; struct RefNum; } namespace Loading { class Listener; } namespace MWWorld { class ESMStore; /// \brief Cell container class WorldModel { typedef std::vector> IdCache; const MWWorld::ESMStore& mStore; ESM::ReadersCache& mReaders; mutable std::map mInteriors; mutable std::map, CellStore> mExteriors; IdCache mIdCache; std::size_t mIdCacheIndex; WorldModel(const WorldModel&); WorldModel& operator=(const WorldModel&); const ESM::Cell* getESMCellByName(const ESM::RefId& name); CellStore* getCellStore(const ESM::Cell* cell); Ptr getPtrAndCache(const ESM::RefId& name, CellStore& cellStore); Ptr getPtr(CellStore& cellStore, const ESM::RefId& id, const ESM::RefNum& refNum); void writeCell(ESM::ESMWriter& writer, CellStore& cell) const; std::unordered_map mPtrIndex; size_t mPtrIndexUpdateCounter; ESM::RefNum mLastGeneratedRefnum; public: void clear(); explicit WorldModel(const MWWorld::ESMStore& store, ESM::ReadersCache& reader); CellStore* getExterior(int x, int y); CellStore* getInterior(const ESM::RefId& name); CellStore* getCell(const ESM::RefId& name); // interior or named exterior CellStore* getCell(const ESM::CellId& id); // If cellNameInSameWorldSpace is an interior - returns this interior. // Otherwise returns exterior cell for given position in the same world space. // At the moment multiple world spaces are not supported, so all exteriors are in one world space. CellStore* getCellByPosition(const osg::Vec3f& pos, const ESM::RefId& cellNameInSameWorldSpace); void registerPtr(const MWWorld::Ptr& ptr); void deregisterPtr(const MWWorld::Ptr& ptr); ESM::RefNum getLastGeneratedRefNum() const { return mLastGeneratedRefnum; } void setLastGeneratedRefNum(ESM::RefNum v) { mLastGeneratedRefnum = v; } size_t getPtrIndexUpdateCounter() const { return mPtrIndexUpdateCounter; } const std::unordered_map& getAllPtrs() const { return mPtrIndex; } Ptr getPtr(const ESM::RefNum& refNum) const; Ptr getPtr(const ESM::RefId& name, CellStore& cellStore, bool searchInContainers = false); ///< \param searchInContainers Only affect loaded cells. /// @note name must be lower case /// @note name must be lower case Ptr getPtr(const ESM::RefId& name); Ptr getPtr(const ESM::RefId& id, const ESM::RefNum& refNum); template void forEachLoadedCellStore(Fn&& fn) { for (auto& [_, store] : mInteriors) fn(store); for (auto& [_, store] : mExteriors) fn(store); } /// Get all Ptrs referencing \a name in exterior cells /// @note Due to the current implementation of getPtr this only supports one Ptr per cell. /// @note name must be lower case void getExteriorPtrs(const ESM::RefId& name, std::vector& out); /// Get all Ptrs referencing \a name in interior cells /// @note Due to the current implementation of getPtr this only supports one Ptr per cell. /// @note name must be lower case void getInteriorPtrs(const ESM::RefId& name, std::vector& out); std::vector getAll(const ESM::RefId& id); int countSavedGameRecords() const; void write(ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord(ESM::ESMReader& reader, uint32_t type, const std::map& contentFileMap); }; } #endif