diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 38dd2c4190..00606939a3 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -130,68 +131,6 @@ namespace } -template -struct StoreIndexToRecordType { - - typedef void recordType; -}; - -static int sRecordTypeCounter = 0; - -#define OPENMW_ESM_ADD_STORE_TYPE(__Type, __REC_NAME,__ID_NUM) template<> const int MWWorld::SRecordType<__Type>::sStoreIndex = sRecordTypeCounter ++; \ -template<> struct StoreIndexToRecordType<__ID_NUM > {typedef __Type recordType;}; \ - -OPENMW_ESM_ADD_STORE_TYPE(ESM::Activator,ESM::REC_ACTI,0); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Potion,ESM::REC_ALCH,1); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Apparatus,ESM::REC_APPA,2); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Armor, ESM::REC_ARMO , 3); -OPENMW_ESM_ADD_STORE_TYPE(ESM::BodyPart, ESM::REC_BODY , 4); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Book, ESM::REC_BOOK , 5); -OPENMW_ESM_ADD_STORE_TYPE(ESM::BirthSign, ESM::REC_BSGN , 6); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Class, ESM::REC_CLAS , 7); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Clothing, ESM::REC_CLOT , 8); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Container, ESM::REC_CONT , 9); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Creature, ESM::REC_CREA , 10); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Dialogue, ESM::REC_DIAL , 11); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Door, ESM::REC_DOOR , 12); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Enchantment, ESM::REC_ENCH , 13); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Faction, ESM::REC_FACT , 14); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Global, ESM::REC_GLOB , 15); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Ingredient, ESM::REC_INGR , 16); -OPENMW_ESM_ADD_STORE_TYPE(ESM::CreatureLevList, ESM::REC_LEVC , 17); -OPENMW_ESM_ADD_STORE_TYPE(ESM::ItemLevList, ESM::REC_LEVI , 18); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Light, ESM::REC_LIGH , 19); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Lockpick, ESM::REC_LOCK , 20); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Miscellaneous, ESM::REC_MISC , 21); -OPENMW_ESM_ADD_STORE_TYPE(ESM::NPC, ESM::REC_NPC_ , 22); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Probe, ESM::REC_PROB , 23); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Race, ESM::REC_RACE , 24); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Region, ESM::REC_REGN , 25); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Repair, ESM::REC_REPA , 26); -OPENMW_ESM_ADD_STORE_TYPE(ESM::SoundGenerator, ESM::REC_SNDG , 27); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Sound, ESM::REC_SOUN , 28); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Spell, ESM::REC_SPEL , 29); -OPENMW_ESM_ADD_STORE_TYPE(ESM::StartScript, ESM::REC_SSCR , 30); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Static, ESM::REC_STAT , 31); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Weapon, ESM::REC_WEAP , 32); -OPENMW_ESM_ADD_STORE_TYPE(ESM::GameSetting, ESM::REC_GMST , 33); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Script, ESM::REC_SCPT , 34); - -// Lists that need special rules -OPENMW_ESM_ADD_STORE_TYPE(ESM::Cell, ESM::REC_CELL , 35); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Land, ESM::REC_LAND , 36); -OPENMW_ESM_ADD_STORE_TYPE(ESM::LandTexture, ESM::REC_LTEX , 37); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Pathgrid, ESM::REC_PGRD , 38); - -OPENMW_ESM_ADD_STORE_TYPE(ESM::MagicEffect, ESM::REC_MGEF , 39); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Skill, ESM::REC_SKIL , 40); - -// Special entry which is hardcoded and not loaded from an ESM -OPENMW_ESM_ADD_STORE_TYPE(ESM::Attribute, ESM::REC_INTERNAL_PLAYER , 41); - -static const int sRecordTypeCount = sRecordTypeCounter; -constexpr int sRecordIndexCount = 42; - template constexpr void constexpr_for(F&& f) { @@ -210,10 +149,54 @@ namespace MWWorld struct ESMStoreImp { - //These 3 don't inherit from store base - Store mMagicEffect; - Store mSkills; - Store mAttributes; + std::tuple < + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + + // Lists that need special rules + Store, + Store, + Store, + Store, + + Store, + Store, + + // Special entry which is hardcoded and not loaded from an ESM + Store> mStores; std::map mRecNameToStore; std::unordered_map mStoreToRecName; @@ -284,23 +267,32 @@ namespace MWWorld return ptr; } - ESMStoreImp(ESMStore& store) + template + static int AssignStoreToIndex(ESMStore& stores, Store& store) { - } + const int storeIndex = ESMStore::getTypeIndex(); + assert(ESMStore::getTypeIndex() == storeIndex); + if (stores.mStores.size() <= storeIndex) + stores.mStores.resize(storeIndex + 1); - template - static void createStore(ESMStore& stores) - { + assert(&store == &std::get>(stores.mStoreImp->mStores)); + + stores.mStores[storeIndex] = &store; if constexpr (std::is_convertible*, DynamicStore*>::value) { - int storeIndex = SRecordType::sStoreIndex; - stores.mStores[storeIndex] = std::make_unique>(); + stores.mDynamicStores.push_back(&store); constexpr ESM::RecNameInts recName = T::sRecordId; if constexpr (recName != ESM::REC_INTERNAL_PLAYER) { - stores.mStoreImp->mRecNameToStore[recName] = stores.mStores[storeIndex].get(); + stores.mStoreImp->mRecNameToStore[recName] = &store; } } + return 0; + } + + ESMStoreImp(ESMStore& store) + { + } void SetupAfterStoresCreation(ESMStore& store) @@ -336,15 +328,8 @@ namespace MWWorld ESMStore::ESMStore() { - mStores.resize(sRecordTypeCount); - assert(sRecordTypeCounter == sRecordIndexCount); //Otherwise something wen wrong with assigning index to stores mStoreImp = std::make_unique(*this); - - constexpr_for<0, sRecordIndexCount,1> ([this](auto storeIndex) - { - ESMStoreImp::createStore::recordType>(*this); - }); - + std::apply([this](auto& ...x){std::make_tuple(ESMStoreImp::AssignStoreToIndex(*this, x)...);} , mStoreImp->mStores); mDynamicCount = 0; mStoreImp->SetupAfterStoresCreation(*this); getWritable().setCells(getWritable()); @@ -356,7 +341,7 @@ namespace MWWorld void ESMStore::clearDynamic() { - for (const auto& store : mStores) + for (const auto& store : mDynamicStores) store->clearDynamic(); movePlayerRecord(); @@ -451,6 +436,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo } } +static int sTypeIndexCounter = 0; + +int& ESMStore::getTypeIndexCounter() +{ + return sTypeIndexCounter; +} + ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const { ESM::LuaScriptsCfg cfg; @@ -827,14 +819,4 @@ void ESMStore::removeMissingObjects(Store& store) template<> const ESM::Door* ESMStore::overrideRecord(const ESM::Door &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } template<> const ESM::ItemLevList* ESMStore::overrideRecord(const ESM::ItemLevList &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } template<> const ESM::NPC* ESMStore::overrideRecord(const ESM::NPC &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } - - template <> const Store& ESMStore::get() const { return mStoreImp->mMagicEffect; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mMagicEffect; } - - template <> const Store& ESMStore::get() const { return mStoreImp->mSkills; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mSkills; } - - template <> const Store& ESMStore::get() const { return mStoreImp->mAttributes; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mAttributes; } - } // end namespace diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index a097ac6a7f..b4d6e86386 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -26,26 +26,33 @@ namespace ESM namespace MWWorld { struct ESMStoreImp; - template struct SRecordType - { - static const int sStoreIndex; - }; class ESMStore { friend struct ESMStoreImp; //This allows StoreImp to extend esmstore without beeing included everywhere + + static int& getTypeIndexCounter(); + + template + static int getTypeIndex() + { + static int index = getTypeIndexCounter()++; + return index; + } + std::unique_ptr mStoreImp; std::unordered_map mRefCount; - std::vector> mStores; + std::vector mStores; + std::vector mDynamicStores; unsigned int mDynamicCount; mutable std::unordered_map, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mSpellListCache; template - Store& getWritable() {return static_cast&>(*mStores[SRecordType::sStoreIndex]);} + Store& getWritable() {return static_cast&>(*mStores[getTypeIndex()]);} /// Validate entries in store after setup void validate(); @@ -65,14 +72,14 @@ namespace MWWorld ESM::LuaScriptsCfg getLuaScriptsCfg() const; /// \todo replace with SharedIterator - typedef std::vector>::const_iterator iterator; + typedef std::vector::const_iterator iterator; iterator begin() const { - return mStores.begin(); + return mDynamicStores.begin(); } iterator end() const { - return mStores.end(); + return mDynamicStores.end(); } /// Look up the given ID in 'all'. Returns 0 if not found. @@ -94,7 +101,7 @@ namespace MWWorld void load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); template - const Store& get() const {return static_cast&>(*mStores[SRecordType::sStoreIndex]);} + const Store& get() const {return static_cast&>(*mStores[getTypeIndex()]);} /// Insert a custom record (i.e. with a generated ID that will not clash will pre-existing records) template @@ -129,17 +136,6 @@ namespace MWWorld /// @return The shared spell list to use for this actor and whether or not it has already been initialized. std::pair, bool> getSpellList(const std::string& id) const; }; - - //Special cases these aren't DynamicStore, but IndexedStore - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - } #endif diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 2501881803..7d1defad94 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -45,7 +45,7 @@ namespace MWWorld class StoreBase {}; //Empty interface to be parent of all store types - class DynamicStore : StoreBase + class DynamicStore : public StoreBase { public: virtual ~DynamicStore() {} @@ -69,7 +69,7 @@ namespace MWWorld }; template - class IndexedStore : StoreBase + class IndexedStore : public StoreBase { protected: typedef typename std::map Static;