Merge remote-tracking branch 'greye/store' into next
Conflicts: apps/openmw/mwclass/light.cpp apps/openmw/mwworld/worldimp.cppactorid
commit
918316168f
@ -0,0 +1,111 @@
|
||||
#include "esmstore.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
static bool isCacheableRecord(int id)
|
||||
{
|
||||
if (id == ESM::REC_ACTI || id == ESM::REC_ALCH || id == ESM::REC_APPA || id == ESM::REC_ARMO ||
|
||||
id == ESM::REC_BOOK || id == ESM::REC_CLOT || id == ESM::REC_CONT || id == ESM::REC_CREA ||
|
||||
id == ESM::REC_DOOR || id == ESM::REC_INGR || id == ESM::REC_LEVC || id == ESM::REC_LEVI ||
|
||||
id == ESM::REC_LIGH || id == ESM::REC_LOCK || id == ESM::REC_MISC || id == ESM::REC_NPC_ ||
|
||||
id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ESMStore::load(ESM::ESMReader &esm)
|
||||
{
|
||||
std::set<std::string> missing;
|
||||
|
||||
ESM::Dialogue *dialogue = 0;
|
||||
|
||||
// Loop through all records
|
||||
while(esm.hasMoreRecs())
|
||||
{
|
||||
ESM::NAME n = esm.getRecName();
|
||||
esm.getRecHeader();
|
||||
|
||||
// Look up the record type.
|
||||
std::map<int, StoreBase *>::iterator it = mStores.find(n.val);
|
||||
|
||||
if (it == mStores.end()) {
|
||||
if (n.val == ESM::REC_INFO) {
|
||||
if (dialogue) {
|
||||
dialogue->mInfo.push_back(ESM::DialInfo());
|
||||
dialogue->mInfo.back().load(esm);
|
||||
} else {
|
||||
std::cerr << "error: info record without dialog" << std::endl;
|
||||
esm.skipRecord();
|
||||
}
|
||||
} else if (n.val == ESM::REC_MGEF) {
|
||||
mMagicEffects.load (esm);
|
||||
} else if (n.val == ESM::REC_SKIL) {
|
||||
mSkills.load (esm);
|
||||
} else {
|
||||
// Not found (this would be an error later)
|
||||
esm.skipRecord();
|
||||
missing.insert(n.toString());
|
||||
}
|
||||
} else {
|
||||
// Load it
|
||||
std::string id = esm.getHNOString("NAME");
|
||||
it->second->load(esm, id);
|
||||
|
||||
if (n.val==ESM::REC_DIAL) {
|
||||
// dirty hack, but it is better than non-const search()
|
||||
// or friends
|
||||
dialogue = &mDialogs.mStatic.back();
|
||||
assert (dialogue->mId == id);
|
||||
} else {
|
||||
dialogue = 0;
|
||||
}
|
||||
// Insert the reference into the global lookup
|
||||
if (!id.empty() && isCacheableRecord(n.val)) {
|
||||
mIds[id] = n.val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This information isn't needed on screen. But keep the code around
|
||||
for debugging purposes later.
|
||||
|
||||
cout << "\n" << mStores.size() << " record types:\n";
|
||||
for(RecListList::iterator it = mStores.begin(); it != mStores.end(); it++)
|
||||
cout << " " << toStr(it->first) << ": " << it->second->getSize() << endl;
|
||||
cout << "\nNot implemented yet: ";
|
||||
for(set<string>::iterator it = missing.begin();
|
||||
it != missing.end(); it++ )
|
||||
cout << *it << " ";
|
||||
cout << endl;
|
||||
*/
|
||||
setUp();
|
||||
}
|
||||
|
||||
void ESMStore::setUp()
|
||||
{
|
||||
std::map<int, StoreBase *>::iterator it = mStores.begin();
|
||||
for (; it != mStores.end(); ++it) {
|
||||
it->second->setUp();
|
||||
}
|
||||
mSkills.setUp();
|
||||
mMagicEffects.setUp();
|
||||
mAttributes.setUp();
|
||||
|
||||
ESM::NPC item;
|
||||
item.mId = "player";
|
||||
|
||||
std::vector<ESM::NPC>::iterator pIt =
|
||||
std::lower_bound(mNpcs.mStatic.begin(), mNpcs.mStatic.end(), item, RecordCmp());
|
||||
assert(pIt != mNpcs.mStatic.end() && pIt->mId == "player");
|
||||
|
||||
mNpcs.insert(*pIt);
|
||||
mNpcs.mStatic.erase(pIt);
|
||||
}
|
||||
|
||||
} // end namespace
|
@ -0,0 +1,401 @@
|
||||
#ifndef OPENMW_MWWORLD_ESMSTORE_H
|
||||
#define OPENMW_MWWORLD_ESMSTORE_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/records.hpp>
|
||||
#include "store.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class ESMStore
|
||||
{
|
||||
Store<ESM::Activator> mActivators;
|
||||
Store<ESM::Potion> mPotions;
|
||||
Store<ESM::Apparatus> mAppas;
|
||||
Store<ESM::Armor> mArmors;
|
||||
Store<ESM::BodyPart> mBodyParts;
|
||||
Store<ESM::Book> mBooks;
|
||||
Store<ESM::BirthSign> mBirthSigns;
|
||||
Store<ESM::Class> mClasses;
|
||||
Store<ESM::Clothing> mClothes;
|
||||
Store<ESM::LoadCNTC> mContChange;
|
||||
Store<ESM::Container> mContainers;
|
||||
Store<ESM::Creature> mCreatures;
|
||||
Store<ESM::LoadCREC> mCreaChange;
|
||||
Store<ESM::Dialogue> mDialogs;
|
||||
Store<ESM::Door> mDoors;
|
||||
Store<ESM::Enchantment> mEnchants;
|
||||
Store<ESM::Faction> mFactions;
|
||||
Store<ESM::Global> mGlobals;
|
||||
Store<ESM::Ingredient> mIngreds;
|
||||
Store<ESM::CreatureLevList> mCreatureLists;
|
||||
Store<ESM::ItemLevList> mItemLists;
|
||||
Store<ESM::Light> mLights;
|
||||
Store<ESM::Tool> mLockpicks;
|
||||
Store<ESM::Miscellaneous> mMiscItems;
|
||||
Store<ESM::NPC> mNpcs;
|
||||
Store<ESM::LoadNPCC> mNpcChange;
|
||||
Store<ESM::Probe> mProbes;
|
||||
Store<ESM::Race> mRaces;
|
||||
Store<ESM::Region> mRegions;
|
||||
Store<ESM::Repair> mRepairs;
|
||||
Store<ESM::SoundGenerator> mSoundGens;
|
||||
Store<ESM::Sound> mSounds;
|
||||
Store<ESM::Spell> mSpells;
|
||||
Store<ESM::StartScript> mStartScripts;
|
||||
Store<ESM::Static> mStatics;
|
||||
Store<ESM::Weapon> mWeapons;
|
||||
|
||||
Store<ESM::GameSetting> mGameSettings;
|
||||
Store<ESM::Script> mScripts;
|
||||
|
||||
// Lists that need special rules
|
||||
Store<ESM::Cell> mCells;
|
||||
Store<ESM::Land> mLands;
|
||||
Store<ESM::LandTexture> mLandTextures;
|
||||
Store<ESM::Pathgrid> mPathgrids;
|
||||
|
||||
Store<ESM::MagicEffect> mMagicEffects;
|
||||
Store<ESM::Skill> mSkills;
|
||||
|
||||
// Special entry which is hardcoded and not loaded from an ESM
|
||||
Store<ESM::Attribute> mAttributes;
|
||||
|
||||
// Lookup of all IDs. Makes looking up references faster. Just
|
||||
// maps the id name to the record type.
|
||||
std::map<std::string, int> mIds;
|
||||
std::map<int, StoreBase *> mStores;
|
||||
|
||||
unsigned int mDynamicCount;
|
||||
|
||||
public:
|
||||
/// \todo replace with SharedIterator<StoreBase>
|
||||
typedef std::map<int, StoreBase *>::const_iterator iterator;
|
||||
|
||||
iterator begin() const {
|
||||
return mStores.begin();
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return mStores.end();
|
||||
}
|
||||
|
||||
// Look up the given ID in 'all'. Returns 0 if not found.
|
||||
int find(const std::string &id) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator it = mIds.find(id);
|
||||
if (it == mIds.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ESMStore()
|
||||
: mDynamicCount(0)
|
||||
{
|
||||
mStores[ESM::REC_ACTI] = &mActivators;
|
||||
mStores[ESM::REC_ALCH] = &mPotions;
|
||||
mStores[ESM::REC_APPA] = &mAppas;
|
||||
mStores[ESM::REC_ARMO] = &mArmors;
|
||||
mStores[ESM::REC_BODY] = &mBodyParts;
|
||||
mStores[ESM::REC_BOOK] = &mBooks;
|
||||
mStores[ESM::REC_BSGN] = &mBirthSigns;
|
||||
mStores[ESM::REC_CELL] = &mCells;
|
||||
mStores[ESM::REC_CLAS] = &mClasses;
|
||||
mStores[ESM::REC_CLOT] = &mClothes;
|
||||
mStores[ESM::REC_CNTC] = &mContChange;
|
||||
mStores[ESM::REC_CONT] = &mContainers;
|
||||
mStores[ESM::REC_CREA] = &mCreatures;
|
||||
mStores[ESM::REC_CREC] = &mCreaChange;
|
||||
mStores[ESM::REC_DIAL] = &mDialogs;
|
||||
mStores[ESM::REC_DOOR] = &mDoors;
|
||||
mStores[ESM::REC_ENCH] = &mEnchants;
|
||||
mStores[ESM::REC_FACT] = &mFactions;
|
||||
mStores[ESM::REC_GLOB] = &mGlobals;
|
||||
mStores[ESM::REC_GMST] = &mGameSettings;
|
||||
mStores[ESM::REC_INGR] = &mIngreds;
|
||||
mStores[ESM::REC_LAND] = &mLands;
|
||||
mStores[ESM::REC_LEVC] = &mCreatureLists;
|
||||
mStores[ESM::REC_LEVI] = &mItemLists;
|
||||
mStores[ESM::REC_LIGH] = &mLights;
|
||||
mStores[ESM::REC_LOCK] = &mLockpicks;
|
||||
mStores[ESM::REC_LTEX] = &mLandTextures;
|
||||
mStores[ESM::REC_MISC] = &mMiscItems;
|
||||
mStores[ESM::REC_NPC_] = &mNpcs;
|
||||
mStores[ESM::REC_NPCC] = &mNpcChange;
|
||||
mStores[ESM::REC_PGRD] = &mPathgrids;
|
||||
mStores[ESM::REC_PROB] = &mProbes;
|
||||
mStores[ESM::REC_RACE] = &mRaces;
|
||||
mStores[ESM::REC_REGN] = &mRegions;
|
||||
mStores[ESM::REC_REPA] = &mRepairs;
|
||||
mStores[ESM::REC_SCPT] = &mScripts;
|
||||
mStores[ESM::REC_SNDG] = &mSoundGens;
|
||||
mStores[ESM::REC_SOUN] = &mSounds;
|
||||
mStores[ESM::REC_SPEL] = &mSpells;
|
||||
mStores[ESM::REC_SSCR] = &mStartScripts;
|
||||
mStores[ESM::REC_STAT] = &mStatics;
|
||||
mStores[ESM::REC_WEAP] = &mWeapons;
|
||||
}
|
||||
|
||||
void load(ESM::ESMReader &esm);
|
||||
|
||||
template <class T>
|
||||
const Store<T> &get() const {
|
||||
throw std::runtime_error("Storage for this type not exist");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *insert(const T &x) {
|
||||
Store<T> &store = const_cast<Store<T> &>(get<T>());
|
||||
T record = x;
|
||||
|
||||
std::ostringstream id;
|
||||
id << "$dynamic" << mDynamicCount++;
|
||||
record.mId = id.str();
|
||||
|
||||
T *ptr = store.insert(record);
|
||||
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
|
||||
if (it->second == &store) {
|
||||
mIds[ptr->mId] = it->first;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void setUp();
|
||||
};
|
||||
|
||||
template <>
|
||||
inline ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
|
||||
return mCells.insert(cell);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
|
||||
return mActivators;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Potion> &ESMStore::get<ESM::Potion>() const {
|
||||
return mPotions;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Apparatus> &ESMStore::get<ESM::Apparatus>() const {
|
||||
return mAppas;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Armor> &ESMStore::get<ESM::Armor>() const {
|
||||
return mArmors;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::BodyPart> &ESMStore::get<ESM::BodyPart>() const {
|
||||
return mBodyParts;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Book> &ESMStore::get<ESM::Book>() const {
|
||||
return mBooks;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::BirthSign> &ESMStore::get<ESM::BirthSign>() const {
|
||||
return mBirthSigns;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Class> &ESMStore::get<ESM::Class>() const {
|
||||
return mClasses;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Clothing> &ESMStore::get<ESM::Clothing>() const {
|
||||
return mClothes;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::LoadCNTC> &ESMStore::get<ESM::LoadCNTC>() const {
|
||||
return mContChange;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Container> &ESMStore::get<ESM::Container>() const {
|
||||
return mContainers;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Creature> &ESMStore::get<ESM::Creature>() const {
|
||||
return mCreatures;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::LoadCREC> &ESMStore::get<ESM::LoadCREC>() const {
|
||||
return mCreaChange;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Dialogue> &ESMStore::get<ESM::Dialogue>() const {
|
||||
return mDialogs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Door> &ESMStore::get<ESM::Door>() const {
|
||||
return mDoors;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Enchantment> &ESMStore::get<ESM::Enchantment>() const {
|
||||
return mEnchants;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Faction> &ESMStore::get<ESM::Faction>() const {
|
||||
return mFactions;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Global> &ESMStore::get<ESM::Global>() const {
|
||||
return mGlobals;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Ingredient> &ESMStore::get<ESM::Ingredient>() const {
|
||||
return mIngreds;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::CreatureLevList> &ESMStore::get<ESM::CreatureLevList>() const {
|
||||
return mCreatureLists;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::ItemLevList> &ESMStore::get<ESM::ItemLevList>() const {
|
||||
return mItemLists;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Light> &ESMStore::get<ESM::Light>() const {
|
||||
return mLights;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Tool> &ESMStore::get<ESM::Tool>() const {
|
||||
return mLockpicks;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Miscellaneous> &ESMStore::get<ESM::Miscellaneous>() const {
|
||||
return mMiscItems;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::NPC> &ESMStore::get<ESM::NPC>() const {
|
||||
return mNpcs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::LoadNPCC> &ESMStore::get<ESM::LoadNPCC>() const {
|
||||
return mNpcChange;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Probe> &ESMStore::get<ESM::Probe>() const {
|
||||
return mProbes;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Race> &ESMStore::get<ESM::Race>() const {
|
||||
return mRaces;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Region> &ESMStore::get<ESM::Region>() const {
|
||||
return mRegions;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Repair> &ESMStore::get<ESM::Repair>() const {
|
||||
return mRepairs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::SoundGenerator> &ESMStore::get<ESM::SoundGenerator>() const {
|
||||
return mSoundGens;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Sound> &ESMStore::get<ESM::Sound>() const {
|
||||
return mSounds;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Spell> &ESMStore::get<ESM::Spell>() const {
|
||||
return mSpells;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::StartScript> &ESMStore::get<ESM::StartScript>() const {
|
||||
return mStartScripts;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Static> &ESMStore::get<ESM::Static>() const {
|
||||
return mStatics;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Weapon> &ESMStore::get<ESM::Weapon>() const {
|
||||
return mWeapons;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::GameSetting> &ESMStore::get<ESM::GameSetting>() const {
|
||||
return mGameSettings;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Script> &ESMStore::get<ESM::Script>() const {
|
||||
return mScripts;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Cell> &ESMStore::get<ESM::Cell>() const {
|
||||
return mCells;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Land> &ESMStore::get<ESM::Land>() const {
|
||||
return mLands;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::LandTexture> &ESMStore::get<ESM::LandTexture>() const {
|
||||
return mLandTextures;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Pathgrid> &ESMStore::get<ESM::Pathgrid>() const {
|
||||
return mPathgrids;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::MagicEffect> &ESMStore::get<ESM::MagicEffect>() const {
|
||||
return mMagicEffects;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Skill> &ESMStore::get<ESM::Skill>() const {
|
||||
return mSkills;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const Store<ESM::Attribute> &ESMStore::get<ESM::Attribute>() const {
|
||||
return mAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue