|
|
|
@ -16,8 +16,8 @@
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
// TODO: Switch to C++23 to get a working version of std::unordered_map::erase
|
|
|
|
|
template <class T>
|
|
|
|
|
bool eraseFromMap(T& map, const ESM::RefId& value)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
bool eraseFromMap(T& map, const Id& value)
|
|
|
|
|
{
|
|
|
|
|
auto it = map.find(value);
|
|
|
|
|
if (it != map.end())
|
|
|
|
@ -95,19 +95,19 @@ namespace MWWorld
|
|
|
|
|
template class IndexedStore<ESM::MagicEffect>;
|
|
|
|
|
template class IndexedStore<ESM::Skill>;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
TypedDynamicStore<T>::TypedDynamicStore()
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
TypedDynamicStore<T, Id>::TypedDynamicStore()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
TypedDynamicStore<T>::TypedDynamicStore(const TypedDynamicStore<T>& orig)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
TypedDynamicStore<T, Id>::TypedDynamicStore(const TypedDynamicStore<T, Id>& orig)
|
|
|
|
|
: mStatic(orig.mStatic)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void TypedDynamicStore<T>::clearDynamic()
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
void TypedDynamicStore<T, Id>::clearDynamic()
|
|
|
|
|
{
|
|
|
|
|
// remove the dynamic part of mShared
|
|
|
|
|
assert(mShared.size() >= mStatic.size());
|
|
|
|
@ -115,8 +115,8 @@ namespace MWWorld
|
|
|
|
|
mDynamic.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T* TypedDynamicStore<T>::search(const ESM::RefId& id) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
const T* TypedDynamicStore<T, Id>::search(const Id& id) const
|
|
|
|
|
{
|
|
|
|
|
typename Dynamic::const_iterator dit = mDynamic.find(id);
|
|
|
|
|
if (dit != mDynamic.end())
|
|
|
|
@ -128,8 +128,8 @@ namespace MWWorld
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T* TypedDynamicStore<T>::searchStatic(const ESM::RefId& id) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
const T* TypedDynamicStore<T, Id>::searchStatic(const Id& id) const
|
|
|
|
|
{
|
|
|
|
|
typename Static::const_iterator it = mStatic.find(id);
|
|
|
|
|
if (it != mStatic.end())
|
|
|
|
@ -138,24 +138,29 @@ namespace MWWorld
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool TypedDynamicStore<T>::isDynamic(const ESM::RefId& id) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
bool TypedDynamicStore<T, Id>::isDynamic(const Id& id) const
|
|
|
|
|
{
|
|
|
|
|
typename Dynamic::const_iterator dit = mDynamic.find(id);
|
|
|
|
|
return (dit != mDynamic.end());
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T* TypedDynamicStore<T>::searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
const T* TypedDynamicStore<T, Id>::searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const
|
|
|
|
|
{
|
|
|
|
|
std::vector<const T*> results;
|
|
|
|
|
std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results),
|
|
|
|
|
[prefix](const T* item) { return item->mId.startsWith(prefix); });
|
|
|
|
|
if (!results.empty())
|
|
|
|
|
return results[Misc::Rng::rollDice(results.size(), prng)];
|
|
|
|
|
return nullptr;
|
|
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
|
{
|
|
|
|
|
std::vector<const T*> results;
|
|
|
|
|
std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results),
|
|
|
|
|
[prefix](const T* item) { return item->mId.startsWith(prefix); });
|
|
|
|
|
if (!results.empty())
|
|
|
|
|
return results[Misc::Rng::rollDice(results.size(), prng)];
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw std::runtime_error("Store<T>::searchRandom is supported only if Id is ESM::RefId");
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T* TypedDynamicStore<T>::find(const ESM::RefId& id) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
const T* TypedDynamicStore<T, Id>::find(const Id& id) const
|
|
|
|
|
{
|
|
|
|
|
const T* ptr = search(id);
|
|
|
|
|
if (ptr == nullptr)
|
|
|
|
@ -174,8 +179,8 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
RecordId TypedDynamicStore<T>::load(ESM::ESMReader& esm)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
RecordId TypedDynamicStore<T, Id>::load(ESM::ESMReader& esm)
|
|
|
|
|
{
|
|
|
|
|
T record;
|
|
|
|
|
bool isDeleted = false;
|
|
|
|
@ -188,37 +193,41 @@ namespace MWWorld
|
|
|
|
|
if (inserted.second)
|
|
|
|
|
mShared.push_back(&inserted.first->second);
|
|
|
|
|
|
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
|
else
|
|
|
|
|
return RecordId();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void TypedDynamicStore<T>::setUp()
|
|
|
|
|
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
void TypedDynamicStore<T, Id>::setUp()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
typename TypedDynamicStore<T>::iterator TypedDynamicStore<T>::begin() const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
typename TypedDynamicStore<T, Id>::iterator TypedDynamicStore<T, Id>::begin() const
|
|
|
|
|
{
|
|
|
|
|
return mShared.begin();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
typename TypedDynamicStore<T>::iterator TypedDynamicStore<T>::end() const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
typename TypedDynamicStore<T, Id>::iterator TypedDynamicStore<T, Id>::end() const
|
|
|
|
|
{
|
|
|
|
|
return mShared.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
size_t TypedDynamicStore<T>::getSize() const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
size_t TypedDynamicStore<T, Id>::getSize() const
|
|
|
|
|
{
|
|
|
|
|
return mShared.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
int TypedDynamicStore<T>::getDynamicSize() const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
int TypedDynamicStore<T, Id>::getDynamicSize() const
|
|
|
|
|
{
|
|
|
|
|
return mDynamic.size();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void TypedDynamicStore<T>::listIdentifier(std::vector<ESM::RefId>& list) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
void TypedDynamicStore<T, Id>::listIdentifier(std::vector<Id>& list) const
|
|
|
|
|
{
|
|
|
|
|
list.reserve(list.size() + getSize());
|
|
|
|
|
typename std::vector<T*>::const_iterator it = mShared.begin();
|
|
|
|
@ -227,8 +236,8 @@ namespace MWWorld
|
|
|
|
|
list.push_back((*it)->mId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
T* TypedDynamicStore<T>::insert(const T& item, bool overrideOnly)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
T* TypedDynamicStore<T, Id>::insert(const T& item, bool overrideOnly)
|
|
|
|
|
{
|
|
|
|
|
if (overrideOnly)
|
|
|
|
|
{
|
|
|
|
@ -242,8 +251,8 @@ namespace MWWorld
|
|
|
|
|
mShared.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
T* TypedDynamicStore<T>::insertStatic(const T& item)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
T* TypedDynamicStore<T, Id>::insertStatic(const T& item)
|
|
|
|
|
{
|
|
|
|
|
std::pair<typename Static::iterator, bool> result = mStatic.insert_or_assign(item.mId, item);
|
|
|
|
|
T* ptr = &result.first->second;
|
|
|
|
@ -251,8 +260,8 @@ namespace MWWorld
|
|
|
|
|
mShared.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool TypedDynamicStore<T>::eraseStatic(const ESM::RefId& id)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
bool TypedDynamicStore<T, Id>::eraseStatic(const Id& id)
|
|
|
|
|
{
|
|
|
|
|
typename Static::iterator it = mStatic.find(id);
|
|
|
|
|
|
|
|
|
@ -277,8 +286,8 @@ namespace MWWorld
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool TypedDynamicStore<T>::erase(const ESM::RefId& id)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
bool TypedDynamicStore<T, Id>::erase(const Id& id)
|
|
|
|
|
{
|
|
|
|
|
if (!eraseFromMap(mDynamic, id))
|
|
|
|
|
return false;
|
|
|
|
@ -292,13 +301,13 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool TypedDynamicStore<T>::erase(const T& item)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
bool TypedDynamicStore<T, Id>::erase(const T& item)
|
|
|
|
|
{
|
|
|
|
|
return erase(item.mId);
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void TypedDynamicStore<T>::write(ESM::ESMWriter& writer, Loading::Listener& progress) const
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
void TypedDynamicStore<T, Id>::write(ESM::ESMWriter& writer, Loading::Listener& progress) const
|
|
|
|
|
{
|
|
|
|
|
for (typename Dynamic::const_iterator iter(mDynamic.begin()); iter != mDynamic.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
@ -310,8 +319,8 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
RecordId TypedDynamicStore<T>::read(ESM::ESMReader& reader, bool overrideOnly)
|
|
|
|
|
template <class T, class Id>
|
|
|
|
|
RecordId TypedDynamicStore<T, Id>::read(ESM::ESMReader& reader, bool overrideOnly)
|
|
|
|
|
{
|
|
|
|
|
T record;
|
|
|
|
|
bool isDeleted = false;
|
|
|
|
@ -321,7 +330,10 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
insert(record, overrideOnly);
|
|
|
|
|
|
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
|
else
|
|
|
|
|
return RecordId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LandTexture
|
|
|
|
@ -1232,6 +1244,6 @@ template class MWWorld::TypedDynamicStore<ESM4::Ingredient>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::MiscItem>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Static>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Light>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Reference>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Reference, ESM::FormId>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Cell>;
|
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Weapon>;
|
|
|
|
|