1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 03:40:14 +00:00
OpenMW/apps/openmw/mwworld/esmstore.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

333 lines
9.7 KiB
C++
Raw Normal View History

2012-11-05 18:09:14 +04:00
#ifndef OPENMW_MWWORLD_ESMSTORE_H
#define OPENMW_MWWORLD_ESMSTORE_H
2012-10-01 19:17:04 +04:00
#include <memory>
2012-11-05 18:09:14 +04:00
#include <stdexcept>
#include <unordered_map>
2012-10-01 19:17:04 +04:00
#include <components/esm/luascripts.hpp>
2012-11-05 18:09:14 +04:00
#include "store.hpp"
2012-10-01 19:17:04 +04:00
namespace Loading
{
class Listener;
}
namespace MWMechanics
{
class SpellList;
}
namespace ESM
{
class ReadersCache;
}
2012-12-23 23:23:24 +04:00
namespace MWWorld
2012-10-01 19:17:04 +04:00
{
struct ESMStoreImp;
2012-11-05 18:09:14 +04:00
class ESMStore
2012-10-01 19:17:04 +04:00
{
std::unique_ptr<ESMStoreImp> mStoreImp;
2012-11-05 18:09:14 +04:00
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
using IDMap = std::unordered_map<std::string, int, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual>;
IDMap mIds;
2022-04-08 00:54:41 +02:00
std::unordered_map<std::string, int> mStaticIds;
std::unordered_map<std::string, int> mRefCount;
2012-11-05 18:09:14 +04:00
std::map<int, StoreBase *> mStores;
2012-11-06 17:51:38 +04:00
unsigned int mDynamicCount;
mutable std::unordered_map<std::string, std::weak_ptr<MWMechanics::SpellList>, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mSpellListCache;
/// Validate entries in store after setup
void validate();
void countAllCellRefs(ESM::ReadersCache& readers);
2021-07-12 20:51:13 +02:00
template<class T>
void removeMissingObjects(Store<T>& store);
using LuaContent = std::variant<
ESM::LuaScriptsCfg, // data from an omwaddon
std::string>; // path to an omwscripts file
std::vector<LuaContent> mLuaContent;
2012-11-05 18:09:14 +04:00
public:
void addOMWScripts(std::string filePath) { mLuaContent.push_back(std::move(filePath)); }
ESM::LuaScriptsCfg getLuaScriptsCfg() const;
/// \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();
}
2014-05-22 15:29:36 +02:00
/// Look up the given ID in 'all'. Returns 0 if not found.
int find(std::string_view id) const
2012-11-05 18:09:14 +04:00
{
IDMap::const_iterator it = mIds.find(id);
2012-11-05 18:09:14 +04:00
if (it == mIds.end()) {
return 0;
}
return it->second;
}
int findStatic(const std::string &id) const
{
IDMap::const_iterator it = mStaticIds.find(id);
if (it == mStaticIds.end()) {
return 0;
}
return it->second;
}
2012-11-05 18:09:14 +04:00
ESMStore();
~ESMStore();
2012-11-05 18:09:14 +04:00
2013-05-15 17:54:18 +02:00
void clearDynamic ()
{
for (std::map<int, StoreBase *>::iterator it = mStores.begin(); it != mStores.end(); ++it)
it->second->clearDynamic();
2021-03-23 20:43:52 +01:00
movePlayerRecord();
2013-05-15 17:54:18 +02:00
}
void movePlayerRecord();
2013-05-15 17:54:18 +02:00
/// Validate entries in store after loading a save
void validateDynamic();
2022-04-16 16:28:39 +02:00
void load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialogue*& dialogue);
2012-11-05 18:09:14 +04:00
template <class T>
const Store<T> &get() const {
throw std::runtime_error("Storage for this type not exist");
}
2012-11-06 17:51:38 +04:00
/// Insert a custom record (i.e. with a generated ID that will not clash will pre-existing records)
template <class T>
2019-01-07 17:47:39 +04:00
const T *insert(const T &x)
{
const std::string id = "$dynamic" + std::to_string(mDynamicCount++);
2012-11-06 17:51:38 +04:00
Store<T> &store = const_cast<Store<T> &>(get<T>());
2020-11-13 11:39:47 +04:00
if (store.search(id) != nullptr)
2019-01-07 17:47:39 +04:00
{
const std::string msg = "Try to override existing record '" + id + "'";
throw std::runtime_error(msg);
2012-11-08 16:37:57 +04:00
}
2012-11-06 17:51:38 +04:00
T record = x;
2019-01-07 17:47:39 +04:00
record.mId = id;
2012-12-23 23:23:24 +04:00
2012-11-06 17:51:38 +04:00
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;
}
/// Insert a record with set ID, and allow it to override a pre-existing static record.
template <class T>
const T *overrideRecord(const T &x) {
Store<T> &store = const_cast<Store<T> &>(get<T>());
T *ptr = store.insert(x);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) {
mIds[ptr->mId] = it->first;
}
}
return ptr;
}
template <class T>
2019-01-07 17:47:39 +04:00
const T *insertStatic(const T &x)
{
Store<T> &store = const_cast<Store<T> &>(get<T>());
if (store.search(x.mId) != nullptr)
2019-01-07 17:47:39 +04:00
{
const std::string msg = "Try to override existing record '" + x.mId + "'";
2019-01-07 17:47:39 +04:00
throw std::runtime_error(msg);
}
T *ptr = store.insertStatic(x);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) {
mIds[ptr->mId] = it->first;
}
}
return ptr;
}
// This method must be called once, after loading all master/plugin files. This can only be done
// from the outside, so it must be public.
void setUp();
void validateRecords(ESM::ReadersCache& readers);
2013-12-07 13:17:28 +01:00
int countSavedGameRecords() const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
2013-12-07 13:17:28 +01:00
2015-01-22 19:04:59 +01:00
bool readRecord (ESM::ESMReader& reader, uint32_t type);
2013-12-07 13:17:28 +01:00
///< \return Known type?
// To be called when we are done with dynamic record loading
void checkPlayer();
/// @return The number of instances defined in the base files. Excludes changes from the save file.
int getRefCount(std::string_view id) const;
/// Actors with the same ID share spells, abilities, etc.
/// @return The shared spell list to use for this actor and whether or not it has already been initialized.
std::pair<std::shared_ptr<MWMechanics::SpellList>, bool> getSpellList(const std::string& id) const;
2012-11-05 18:09:14 +04:00
};
2012-11-06 17:51:38 +04:00
template <>
const ESM::Cell* ESMStore::insert<ESM::Cell>(const ESM::Cell& cell);
2012-11-06 17:51:38 +04:00
2012-11-08 16:37:57 +04:00
template <>
const ESM::NPC* ESMStore::insert<ESM::NPC>(const ESM::NPC& npc);
2012-11-08 16:37:57 +04:00
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Activator>& ESMStore::get<ESM::Activator>() const;
2012-10-01 19:17:04 +04:00
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Potion>& ESMStore::get<ESM::Potion>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Apparatus>& ESMStore::get<ESM::Apparatus>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Armor>& ESMStore::get<ESM::Armor>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::BodyPart>& ESMStore::get<ESM::BodyPart>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Book>& ESMStore::get<ESM::Book>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::BirthSign>& ESMStore::get<ESM::BirthSign>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Class>& ESMStore::get<ESM::Class>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Clothing>& ESMStore::get<ESM::Clothing>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Container>& ESMStore::get<ESM::Container>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Creature>& ESMStore::get<ESM::Creature>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Dialogue>& ESMStore::get<ESM::Dialogue>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Door>& ESMStore::get<ESM::Door>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Enchantment>& ESMStore::get<ESM::Enchantment>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Faction>& ESMStore::get<ESM::Faction>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Global>& ESMStore::get<ESM::Global>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Ingredient>& ESMStore::get<ESM::Ingredient>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::CreatureLevList>& ESMStore::get<ESM::CreatureLevList>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::ItemLevList>& ESMStore::get<ESM::ItemLevList>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Light>& ESMStore::get<ESM::Light>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Lockpick>& ESMStore::get<ESM::Lockpick>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Miscellaneous>& ESMStore::get<ESM::Miscellaneous>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::NPC>& ESMStore::get<ESM::NPC>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Probe>& ESMStore::get<ESM::Probe>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Race>& ESMStore::get<ESM::Race>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Region>& ESMStore::get<ESM::Region>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Repair>& ESMStore::get<ESM::Repair>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::SoundGenerator>& ESMStore::get<ESM::SoundGenerator>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Sound>& ESMStore::get<ESM::Sound>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Spell>& ESMStore::get<ESM::Spell>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::StartScript>& ESMStore::get<ESM::StartScript>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Static>& ESMStore::get<ESM::Static>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Weapon>& ESMStore::get<ESM::Weapon>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::GameSetting>& ESMStore::get<ESM::GameSetting>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Script>& ESMStore::get<ESM::Script>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Cell>& ESMStore::get<ESM::Cell>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Land>& ESMStore::get<ESM::Land>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::LandTexture>& ESMStore::get<ESM::LandTexture>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Pathgrid>& ESMStore::get<ESM::Pathgrid>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::MagicEffect>& ESMStore::get<ESM::MagicEffect>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Skill>& ESMStore::get<ESM::Skill>() const;
2012-11-05 18:09:14 +04:00
template <>
const Store<ESM::Attribute>& ESMStore::get<ESM::Attribute>() const;
2012-10-01 19:17:04 +04:00
}
#endif