OpenMW
apps/openmw/mwworld/esmstore.hpp
Go to the documentation of this file.
00001 #ifndef OPENMW_MWWORLD_ESMSTORE_H
00002 #define OPENMW_MWWORLD_ESMSTORE_H
00003 
00004 #include <stdexcept>
00005 
00006 #include <components/esm/records.hpp>
00007 #include "store.hpp"
00008 
00009 namespace Loading
00010 {
00011     class Listener;
00012 }
00013 
00014 namespace MWWorld
00015 {
00016     class ESMStore
00017     {
00018         Store<ESM::Activator>       mActivators;
00019         Store<ESM::Potion>          mPotions;
00020         Store<ESM::Apparatus>       mAppas;
00021         Store<ESM::Armor>           mArmors;
00022         Store<ESM::BodyPart>        mBodyParts;
00023         Store<ESM::Book>            mBooks;
00024         Store<ESM::BirthSign>       mBirthSigns;
00025         Store<ESM::Class>           mClasses;
00026         Store<ESM::Clothing>        mClothes;
00027         Store<ESM::LoadCNTC>        mContChange;
00028         Store<ESM::Container>       mContainers;
00029         Store<ESM::Creature>        mCreatures;
00030         Store<ESM::LoadCREC>        mCreaChange;
00031         Store<ESM::Dialogue>        mDialogs;
00032         Store<ESM::Door>            mDoors;
00033         Store<ESM::Enchantment>     mEnchants;
00034         Store<ESM::Faction>         mFactions;
00035         Store<ESM::Global>          mGlobals;
00036         Store<ESM::Ingredient>      mIngreds;
00037         Store<ESM::CreatureLevList> mCreatureLists;
00038         Store<ESM::ItemLevList>     mItemLists;
00039         Store<ESM::Light>           mLights;
00040         Store<ESM::Lockpick>        mLockpicks;
00041         Store<ESM::Miscellaneous>   mMiscItems;
00042         Store<ESM::NPC>             mNpcs;
00043         Store<ESM::LoadNPCC>        mNpcChange;
00044         Store<ESM::Probe>           mProbes;
00045         Store<ESM::Race>            mRaces;
00046         Store<ESM::Region>          mRegions;
00047         Store<ESM::Repair>          mRepairs;
00048         Store<ESM::SoundGenerator>  mSoundGens;
00049         Store<ESM::Sound>           mSounds;
00050         Store<ESM::Spell>           mSpells;
00051         Store<ESM::StartScript>     mStartScripts;
00052         Store<ESM::Static>          mStatics;
00053         Store<ESM::Weapon>          mWeapons;
00054 
00055         Store<ESM::GameSetting>     mGameSettings;
00056         Store<ESM::Script>          mScripts;
00057 
00058         // Lists that need special rules
00059         Store<ESM::Cell>        mCells;
00060         Store<ESM::Land>        mLands;
00061         Store<ESM::LandTexture> mLandTextures;
00062         Store<ESM::Pathgrid>    mPathgrids;
00063 
00064         Store<ESM::MagicEffect> mMagicEffects;
00065         Store<ESM::Skill>       mSkills;
00066 
00067         // Special entry which is hardcoded and not loaded from an ESM
00068         Store<ESM::Attribute>   mAttributes;
00069 
00070         // Lookup of all IDs. Makes looking up references faster. Just
00071         // maps the id name to the record type.
00072         std::map<std::string, int> mIds;
00073         std::map<int, StoreBase *> mStores;
00074 
00075         ESM::NPC mPlayerTemplate;
00076 
00077         unsigned int mDynamicCount;
00078 
00079     public:
00081         typedef std::map<int, StoreBase *>::const_iterator iterator;
00082 
00083         iterator begin() const {
00084             return mStores.begin();
00085         }
00086 
00087         iterator end() const {
00088             return mStores.end();
00089         }
00090 
00091         // Look up the given ID in 'all'. Returns 0 if not found.
00092         int find(const std::string &id) const
00093         {
00094             std::map<std::string, int>::const_iterator it = mIds.find(id);
00095             if (it == mIds.end()) {
00096                 return 0;
00097             }
00098             return it->second;
00099         }
00100 
00101         ESMStore()
00102           : mDynamicCount(0)
00103         {
00104             // Cell store needs access to this for tracking moved references
00105             mCells.mEsmStore = this;
00106             
00107             mStores[ESM::REC_ACTI] = &mActivators;
00108             mStores[ESM::REC_ALCH] = &mPotions;
00109             mStores[ESM::REC_APPA] = &mAppas;
00110             mStores[ESM::REC_ARMO] = &mArmors;
00111             mStores[ESM::REC_BODY] = &mBodyParts;
00112             mStores[ESM::REC_BOOK] = &mBooks;
00113             mStores[ESM::REC_BSGN] = &mBirthSigns;
00114             mStores[ESM::REC_CELL] = &mCells;
00115             mStores[ESM::REC_CLAS] = &mClasses;
00116             mStores[ESM::REC_CLOT] = &mClothes;
00117             mStores[ESM::REC_CNTC] = &mContChange;
00118             mStores[ESM::REC_CONT] = &mContainers;
00119             mStores[ESM::REC_CREA] = &mCreatures;
00120             mStores[ESM::REC_CREC] = &mCreaChange;
00121             mStores[ESM::REC_DIAL] = &mDialogs;
00122             mStores[ESM::REC_DOOR] = &mDoors;
00123             mStores[ESM::REC_ENCH] = &mEnchants;
00124             mStores[ESM::REC_FACT] = &mFactions;
00125             mStores[ESM::REC_GLOB] = &mGlobals;
00126             mStores[ESM::REC_GMST] = &mGameSettings;
00127             mStores[ESM::REC_INGR] = &mIngreds;
00128             mStores[ESM::REC_LAND] = &mLands;
00129             mStores[ESM::REC_LEVC] = &mCreatureLists;
00130             mStores[ESM::REC_LEVI] = &mItemLists;
00131             mStores[ESM::REC_LIGH] = &mLights;
00132             mStores[ESM::REC_LOCK] = &mLockpicks;
00133             mStores[ESM::REC_LTEX] = &mLandTextures;
00134             mStores[ESM::REC_MISC] = &mMiscItems;
00135             mStores[ESM::REC_NPC_] = &mNpcs;
00136             mStores[ESM::REC_NPCC] = &mNpcChange;
00137             mStores[ESM::REC_PGRD] = &mPathgrids;
00138             mStores[ESM::REC_PROB] = &mProbes;
00139             mStores[ESM::REC_RACE] = &mRaces;
00140             mStores[ESM::REC_REGN] = &mRegions;
00141             mStores[ESM::REC_REPA] = &mRepairs;
00142             mStores[ESM::REC_SCPT] = &mScripts;
00143             mStores[ESM::REC_SNDG] = &mSoundGens;
00144             mStores[ESM::REC_SOUN] = &mSounds;
00145             mStores[ESM::REC_SPEL] = &mSpells;
00146             mStores[ESM::REC_SSCR] = &mStartScripts;
00147             mStores[ESM::REC_STAT] = &mStatics;
00148             mStores[ESM::REC_WEAP] = &mWeapons;
00149         }
00150 
00151         void clearDynamic ()
00152         {
00153             for (std::map<int, StoreBase *>::iterator it = mStores.begin(); it != mStores.end(); ++it)
00154                 it->second->clearDynamic();
00155 
00156             mNpcs.insert(mPlayerTemplate);
00157         }
00158 
00159         void movePlayerRecord ()
00160         {
00161             mPlayerTemplate = *mNpcs.find("player");
00162             mNpcs.eraseStatic(mPlayerTemplate.mId);
00163             mNpcs.insert(mPlayerTemplate);
00164         }
00165 
00166         void load(ESM::ESMReader &esm, Loading::Listener* listener);
00167 
00168         template <class T>
00169         const Store<T> &get() const {
00170             throw std::runtime_error("Storage for this type not exist");
00171         }
00172 
00173         template <class T>
00174         const T *insert(const T &x) {
00175             Store<T> &store = const_cast<Store<T> &>(get<T>());
00176             if (store.search(x.mId) != 0) {
00177                 std::ostringstream msg;
00178                 msg << "Try to override existing record '" << x.mId << "'";
00179                 throw std::runtime_error(msg.str());
00180             }
00181             T record = x;
00182 
00183             std::ostringstream id;
00184             id << "$dynamic" << mDynamicCount++;
00185             record.mId = id.str();
00186 
00187             T *ptr = store.insert(record);
00188             for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
00189                 if (it->second == &store) {
00190                     mIds[ptr->mId] = it->first;
00191                 }
00192             }
00193             return ptr;
00194         }
00195 
00196         template <class T>
00197         const T *insertStatic(const T &x) {
00198             Store<T> &store = const_cast<Store<T> &>(get<T>());
00199             if (store.search(x.mId) != 0) {
00200                 std::ostringstream msg;
00201                 msg << "Try to override existing record '" << x.mId << "'";
00202                 throw std::runtime_error(msg.str());
00203             }
00204             T record = x;
00205 
00206             T *ptr = store.insertStatic(record);
00207             for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
00208                 if (it->second == &store) {
00209                     mIds[ptr->mId] = it->first;
00210                 }
00211             }
00212             return ptr;
00213         }
00214 
00215         // This method must be called once, after loading all master/plugin files. This can only be done
00216         //  from the outside, so it must be public.
00217         void setUp();
00218     };
00219 
00220     template <>
00221     inline const ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
00222         return mCells.insert(cell);
00223     }
00224 
00225     template <>
00226     inline const ESM::NPC *ESMStore::insert<ESM::NPC>(const ESM::NPC &npc) {
00227         if (Misc::StringUtils::ciEqual(npc.mId, "player")) {
00228             return mNpcs.insert(npc);
00229         } else if (mNpcs.search(npc.mId) != 0) {
00230             std::ostringstream msg;
00231             msg << "Try to override existing record '" << npc.mId << "'";
00232             throw std::runtime_error(msg.str());
00233         }
00234         ESM::NPC record = npc;
00235 
00236         std::ostringstream id;
00237         id << "$dynamic" << mDynamicCount++;
00238         record.mId = id.str();
00239 
00240         ESM::NPC *ptr = mNpcs.insert(record);
00241         mIds[ptr->mId] = ESM::REC_NPC_;
00242         return ptr;
00243     }
00244 
00245     template <>
00246     inline const Store<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
00247         return mActivators;
00248     }
00249 
00250     template <>
00251     inline const Store<ESM::Potion> &ESMStore::get<ESM::Potion>() const {
00252         return mPotions;
00253     }
00254 
00255     template <>
00256     inline const Store<ESM::Apparatus> &ESMStore::get<ESM::Apparatus>() const {
00257         return mAppas;
00258     }
00259 
00260     template <>
00261     inline const Store<ESM::Armor> &ESMStore::get<ESM::Armor>() const {
00262         return mArmors;
00263     }
00264 
00265     template <>
00266     inline const Store<ESM::BodyPart> &ESMStore::get<ESM::BodyPart>() const {
00267         return mBodyParts;
00268     }
00269 
00270     template <>
00271     inline const Store<ESM::Book> &ESMStore::get<ESM::Book>() const {
00272         return mBooks;
00273     }
00274 
00275     template <>
00276     inline const Store<ESM::BirthSign> &ESMStore::get<ESM::BirthSign>() const {
00277         return mBirthSigns;
00278     }
00279 
00280     template <>
00281     inline const Store<ESM::Class> &ESMStore::get<ESM::Class>() const {
00282         return mClasses;
00283     }
00284 
00285     template <>
00286     inline const Store<ESM::Clothing> &ESMStore::get<ESM::Clothing>() const {
00287         return mClothes;
00288     }
00289 
00290     template <>
00291     inline const Store<ESM::LoadCNTC> &ESMStore::get<ESM::LoadCNTC>() const {
00292         return mContChange;
00293     }
00294 
00295     template <>
00296     inline const Store<ESM::Container> &ESMStore::get<ESM::Container>() const {
00297         return mContainers;
00298     }
00299 
00300     template <>
00301     inline const Store<ESM::Creature> &ESMStore::get<ESM::Creature>() const {
00302         return mCreatures;
00303     }
00304 
00305     template <>
00306     inline const Store<ESM::LoadCREC> &ESMStore::get<ESM::LoadCREC>() const {
00307         return mCreaChange;
00308     }
00309 
00310     template <>
00311     inline const Store<ESM::Dialogue> &ESMStore::get<ESM::Dialogue>() const {
00312         return mDialogs;
00313     }
00314 
00315     template <>
00316     inline const Store<ESM::Door> &ESMStore::get<ESM::Door>() const {
00317         return mDoors;
00318     }
00319 
00320     template <>
00321     inline const Store<ESM::Enchantment> &ESMStore::get<ESM::Enchantment>() const {
00322         return mEnchants;
00323     }
00324 
00325     template <>
00326     inline const Store<ESM::Faction> &ESMStore::get<ESM::Faction>() const {
00327         return mFactions;
00328     }
00329 
00330     template <>
00331     inline const Store<ESM::Global> &ESMStore::get<ESM::Global>() const {
00332         return mGlobals;
00333     }
00334 
00335     template <>
00336     inline const Store<ESM::Ingredient> &ESMStore::get<ESM::Ingredient>() const {
00337         return mIngreds;
00338     }
00339 
00340     template <>
00341     inline const Store<ESM::CreatureLevList> &ESMStore::get<ESM::CreatureLevList>() const {
00342         return mCreatureLists;
00343     }
00344 
00345     template <>
00346     inline const Store<ESM::ItemLevList> &ESMStore::get<ESM::ItemLevList>() const {
00347         return mItemLists;
00348     }
00349 
00350     template <>
00351     inline const Store<ESM::Light> &ESMStore::get<ESM::Light>() const {
00352         return mLights;
00353     }
00354 
00355     template <>
00356     inline const Store<ESM::Lockpick> &ESMStore::get<ESM::Lockpick>() const {
00357         return mLockpicks;
00358     }
00359 
00360     template <>
00361     inline const Store<ESM::Miscellaneous> &ESMStore::get<ESM::Miscellaneous>() const {
00362         return mMiscItems;
00363     }
00364 
00365     template <>
00366     inline const Store<ESM::NPC> &ESMStore::get<ESM::NPC>() const {
00367         return mNpcs;
00368     }
00369 
00370     template <>
00371     inline const Store<ESM::LoadNPCC> &ESMStore::get<ESM::LoadNPCC>() const {
00372         return mNpcChange;
00373     }
00374 
00375     template <>
00376     inline const Store<ESM::Probe> &ESMStore::get<ESM::Probe>() const {
00377         return mProbes;
00378     }
00379 
00380     template <>
00381     inline const Store<ESM::Race> &ESMStore::get<ESM::Race>() const {
00382         return mRaces;
00383     }
00384 
00385     template <>
00386     inline const Store<ESM::Region> &ESMStore::get<ESM::Region>() const {
00387         return mRegions;
00388     }
00389 
00390     template <>
00391     inline const Store<ESM::Repair> &ESMStore::get<ESM::Repair>() const {
00392         return mRepairs;
00393     }
00394 
00395     template <>
00396     inline const Store<ESM::SoundGenerator> &ESMStore::get<ESM::SoundGenerator>() const {
00397         return mSoundGens;
00398     }
00399 
00400     template <>
00401     inline const Store<ESM::Sound> &ESMStore::get<ESM::Sound>() const {
00402         return mSounds;
00403     }
00404 
00405     template <>
00406     inline const Store<ESM::Spell> &ESMStore::get<ESM::Spell>() const {
00407         return mSpells;
00408     }
00409 
00410     template <>
00411     inline const Store<ESM::StartScript> &ESMStore::get<ESM::StartScript>() const {
00412         return mStartScripts;
00413     }
00414 
00415     template <>
00416     inline const Store<ESM::Static> &ESMStore::get<ESM::Static>() const {
00417         return mStatics;
00418     }
00419 
00420     template <>
00421     inline const Store<ESM::Weapon> &ESMStore::get<ESM::Weapon>() const {
00422         return mWeapons;
00423     }
00424 
00425     template <>
00426     inline const Store<ESM::GameSetting> &ESMStore::get<ESM::GameSetting>() const {
00427         return mGameSettings;
00428     }
00429 
00430     template <>
00431     inline const Store<ESM::Script> &ESMStore::get<ESM::Script>() const {
00432         return mScripts;
00433     }
00434 
00435     template <>
00436     inline const Store<ESM::Cell> &ESMStore::get<ESM::Cell>() const {
00437         return mCells;
00438     }
00439 
00440     template <>
00441     inline const Store<ESM::Land> &ESMStore::get<ESM::Land>() const {
00442         return mLands;
00443     }
00444 
00445     template <>
00446     inline const Store<ESM::LandTexture> &ESMStore::get<ESM::LandTexture>() const {
00447         return mLandTextures;
00448     }
00449 
00450     template <>
00451     inline const Store<ESM::Pathgrid> &ESMStore::get<ESM::Pathgrid>() const {
00452         return mPathgrids;
00453     }
00454 
00455     template <>
00456     inline const Store<ESM::MagicEffect> &ESMStore::get<ESM::MagicEffect>() const {
00457         return mMagicEffects;
00458     }
00459 
00460     template <>
00461     inline const Store<ESM::Skill> &ESMStore::get<ESM::Skill>() const {
00462         return mSkills;
00463     }
00464 
00465     template <>
00466     inline const Store<ESM::Attribute> &ESMStore::get<ESM::Attribute>() const {
00467         return mAttributes;
00468     }
00469 }
00470 
00471 #endif