mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 21:26:41 +00:00 
			
		
		
		
	Merge branch 'lua_nil' into 'master'
Return nil when we try to use an invalid store index from Lua Closes #7550 See merge request OpenMW/openmw!3410
This commit is contained in:
		
						commit
						45a211c098
					
				
					 6 changed files with 42 additions and 24 deletions
				
			
		|  | @ -231,7 +231,11 @@ namespace MWLua | |||
|         sol::usertype<CellsStore> cells = context.mLua->sol().new_usertype<CellsStore>("Cells"); | ||||
|         cells[sol::meta_function::length] | ||||
|             = [cells3Store, cells4Store](const CellsStore&) { return cells3Store->getSize() + cells4Store->getSize(); }; | ||||
|         cells[sol::meta_function::index] = [cells3Store, cells4Store](const CellsStore&, size_t index) -> GCell { | ||||
|         cells[sol::meta_function::index] | ||||
|             = [cells3Store, cells4Store](const CellsStore&, size_t index) -> sol::optional<GCell> { | ||||
|             if (index > cells3Store->getSize() + cells3Store->getSize() || index == 0) | ||||
|                 return sol::nullopt; | ||||
| 
 | ||||
|             index--; // Translate from Lua's 1-based indexing.
 | ||||
|             if (index < cells3Store->getSize()) | ||||
|             { | ||||
|  |  | |||
|  | @ -243,9 +243,13 @@ namespace MWLua | |||
|             = [](const SpellStore& store) { return "ESM3_SpellStore{" + std::to_string(store.getSize()) + " spells}"; }; | ||||
|         spellStoreT[sol::meta_function::length] = [](const SpellStore& store) { return store.getSize(); }; | ||||
|         spellStoreT[sol::meta_function::index] = sol::overload( | ||||
|             [](const SpellStore& store, size_t index) -> const ESM::Spell* { return store.at(index - 1); }, | ||||
|             [](const SpellStore& store, size_t index) -> const ESM::Spell* { | ||||
|                 if (index == 0 || index > store.getSize()) | ||||
|                     return nullptr; | ||||
|                 return store.at(index - 1); | ||||
|             }, | ||||
|             [](const SpellStore& store, std::string_view spellId) -> const ESM::Spell* { | ||||
|                 return store.find(ESM::RefId::deserializeText(spellId)); | ||||
|                 return store.search(ESM::RefId::deserializeText(spellId)); | ||||
|             }); | ||||
|         spellStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|         spellStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|  | @ -262,9 +266,13 @@ namespace MWLua | |||
|         }; | ||||
|         enchantmentStoreT[sol::meta_function::length] = [](const EnchantmentStore& store) { return store.getSize(); }; | ||||
|         enchantmentStoreT[sol::meta_function::index] = sol::overload( | ||||
|             [](const EnchantmentStore& store, size_t index) -> const ESM::Enchantment* { return store.at(index - 1); }, | ||||
|             [](const EnchantmentStore& store, size_t index) -> const ESM::Enchantment* { | ||||
|                 if (index == 0 || index > store.getSize()) | ||||
|                     return nullptr; | ||||
|                 return store.at(index - 1); | ||||
|             }, | ||||
|             [](const EnchantmentStore& store, std::string_view enchantmentId) -> const ESM::Enchantment* { | ||||
|                 return store.find(ESM::RefId::deserializeText(enchantmentId)); | ||||
|                 return store.search(ESM::RefId::deserializeText(enchantmentId)); | ||||
|             }); | ||||
|         enchantmentStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|         enchantmentStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|  | @ -280,10 +288,10 @@ namespace MWLua | |||
|             return "ESM3_MagicEffectStore{" + std::to_string(store.getSize()) + " effects}"; | ||||
|         }; | ||||
|         magicEffectStoreT[sol::meta_function::index] = sol::overload( | ||||
|             [](const MagicEffectStore& store, int id) -> const ESM::MagicEffect* { return store.find(id); }, | ||||
|             [](const MagicEffectStore& store, int id) -> const ESM::MagicEffect* { return store.search(id); }, | ||||
|             [](const MagicEffectStore& store, std::string_view id) -> const ESM::MagicEffect* { | ||||
|                 int index = ESM::MagicEffect::indexNameToIndex(id); | ||||
|                 return store.find(index); | ||||
|                 return store.search(index); | ||||
|             }); | ||||
|         auto magicEffectsIter = [magicEffectStore](sol::this_state lua, const sol::object& /*store*/, | ||||
|                                     sol::optional<int> id) -> std::tuple<sol::object, sol::object> { | ||||
|  | @ -665,20 +673,20 @@ namespace MWLua | |||
| 
 | ||||
|         // types.Actor.spells(o)[i]
 | ||||
|         spellsT[sol::meta_function::index] = sol::overload( | ||||
|             [](const ActorSpells& spells, size_t index) -> sol::optional<const ESM::Spell*> { | ||||
|             [](const ActorSpells& spells, size_t index) -> const ESM::Spell* { | ||||
|                 if (auto* store = spells.getStore()) | ||||
|                     if (index <= store->count()) | ||||
|                     if (index <= store->count() && index > 0) | ||||
|                         return store->at(index - 1); | ||||
|                 return sol::nullopt; | ||||
|                 return nullptr; | ||||
|             }, | ||||
|             [spellStore](const ActorSpells& spells, std::string_view spellId) -> sol::optional<const ESM::Spell*> { | ||||
|             [spellStore](const ActorSpells& spells, std::string_view spellId) -> const ESM::Spell* { | ||||
|                 if (auto* store = spells.getStore()) | ||||
|                 { | ||||
|                     const ESM::Spell* spell = spellStore->find(ESM::RefId::deserializeText(spellId)); | ||||
|                     if (store->hasSpell(spell)) | ||||
|                     const ESM::Spell* spell = spellStore->search(ESM::RefId::deserializeText(spellId)); | ||||
|                     if (spell && store->hasSpell(spell)) | ||||
|                         return spell; | ||||
|                 } | ||||
|                 return sol::nullopt; | ||||
|                 return nullptr; | ||||
|             }); | ||||
| 
 | ||||
|         // pairs(types.Actor.spells(o))
 | ||||
|  |  | |||
|  | @ -136,11 +136,11 @@ namespace MWLua | |||
|             listT[sol::meta_function::to_string] | ||||
|                 = [](const ListT& list) { return "{" + std::to_string(list.mIds->size()) + " objects}"; }; | ||||
|             listT[sol::meta_function::length] = [](const ListT& list) { return list.mIds->size(); }; | ||||
|             listT[sol::meta_function::index] = [](const ListT& list, size_t index) { | ||||
|             listT[sol::meta_function::index] = [](const ListT& list, size_t index) -> sol::optional<ObjectT> { | ||||
|                 if (index > 0 && index <= list.mIds->size()) | ||||
|                     return ObjectT((*list.mIds)[index - 1]); | ||||
|                 else | ||||
|                     throw std::runtime_error("Index out of range"); | ||||
|                     return sol::nullopt; | ||||
|             }; | ||||
|             listT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|             listT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|  |  | |||
|  | @ -169,9 +169,13 @@ namespace MWLua | |||
|             = [](const SoundStore& store) { return "ESM3_SoundStore{" + std::to_string(store.getSize()) + " sounds}"; }; | ||||
|         soundStoreT[sol::meta_function::length] = [](const SoundStore& store) { return store.getSize(); }; | ||||
|         soundStoreT[sol::meta_function::index] = sol::overload( | ||||
|             [](const SoundStore& store, size_t index) -> const ESM::Sound* { return store.at(index - 1); }, | ||||
|             [](const SoundStore& store, size_t index) -> const ESM::Sound* { | ||||
|                 if (index == 0 || index > store.getSize()) | ||||
|                     return nullptr; | ||||
|                 return store.at(index - 1); | ||||
|             }, | ||||
|             [](const SoundStore& store, std::string_view soundId) -> const ESM::Sound* { | ||||
|                 return store.find(ESM::RefId::deserializeText(soundId)); | ||||
|                 return store.search(ESM::RefId::deserializeText(soundId)); | ||||
|             }); | ||||
|         soundStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|         soundStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|  |  | |||
|  | @ -48,13 +48,13 @@ namespace MWLua | |||
|         }; | ||||
|         sol::usertype<Quests> quests = context.mLua->sol().new_usertype<Quests>("Quests"); | ||||
|         quests[sol::meta_function::to_string] = [](const Quests& quests) { return "Quests"; }; | ||||
|         quests[sol::meta_function::index] = sol::overload([](const Quests& quests, std::string_view questId) -> Quest { | ||||
|         quests[sol::meta_function::index] = [](const Quests& quests, std::string_view questId) -> sol::optional<Quest> { | ||||
|             ESM::RefId quest = ESM::RefId::deserializeText(questId); | ||||
|             const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().find(quest); | ||||
|             if (dial->mType != ESM::Dialogue::Journal) | ||||
|                 throw std::runtime_error("Not a quest:" + std::string(questId)); | ||||
|             const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().search(quest); | ||||
|             if (dial == nullptr || dial->mType != ESM::Dialogue::Journal) | ||||
|                 return sol::nullopt; | ||||
|             return Quest{ .mQuestId = quest, .mMutable = quests.mMutable }; | ||||
|         }); | ||||
|         }; | ||||
|         quests[sol::meta_function::pairs] = [journal](const Quests& quests) { | ||||
|             std::vector<ESM::RefId> ids; | ||||
|             for (auto it = journal->questBegin(); it != journal->questEnd(); ++it) | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ namespace MWLua | |||
|         const MWWorld::Store<T>& store = MWBase::Environment::get().getESMStore()->get<T>(); | ||||
| 
 | ||||
|         table["record"] = sol::overload([](const Object& obj) -> const T* { return obj.ptr().get<T>()->mBase; }, | ||||
|             [&store](std::string_view id) -> const T* { return store.find(ESM::RefId::deserializeText(id)); }); | ||||
|             [&store](std::string_view id) -> const T* { return store.search(ESM::RefId::deserializeText(id)); }); | ||||
| 
 | ||||
|         // Define a custom user type for the store.
 | ||||
|         // Provide the interface of a read-only array.
 | ||||
|  | @ -89,6 +89,8 @@ namespace MWLua | |||
|         }; | ||||
|         storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); }; | ||||
|         storeT[sol::meta_function::index] = [](const StoreT& store, size_t index) -> const T* { | ||||
|             if (index == 0 || index > store.getSize()) | ||||
|                 return nullptr; | ||||
|             return store.at(index - 1); // Translate from Lua's 1-based indexing.
 | ||||
|         }; | ||||
|         storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue