mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 04:26:42 +00:00 
			
		
		
		
	Return nil when we try to use an invalid store index from Lua
This commit is contained in:
		
							parent
							
								
									690a237896
								
							
						
					
					
						commit
						5d211d3c93
					
				
					 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");
 | 
					        sol::usertype<CellsStore> cells = context.mLua->sol().new_usertype<CellsStore>("Cells");
 | 
				
			||||||
        cells[sol::meta_function::length]
 | 
					        cells[sol::meta_function::length]
 | 
				
			||||||
            = [cells3Store, cells4Store](const CellsStore&) { return cells3Store->getSize() + cells4Store->getSize(); };
 | 
					            = [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.
 | 
					            index--; // Translate from Lua's 1-based indexing.
 | 
				
			||||||
            if (index < cells3Store->getSize())
 | 
					            if (index < cells3Store->getSize())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,9 +243,13 @@ namespace MWLua
 | 
				
			||||||
            = [](const SpellStore& store) { return "ESM3_SpellStore{" + std::to_string(store.getSize()) + " spells}"; };
 | 
					            = [](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::length] = [](const SpellStore& store) { return store.getSize(); };
 | 
				
			||||||
        spellStoreT[sol::meta_function::index] = sol::overload(
 | 
					        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* {
 | 
					            [](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::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
				
			||||||
        spellStoreT[sol::meta_function::ipairs] = 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::length] = [](const EnchantmentStore& store) { return store.getSize(); };
 | 
				
			||||||
        enchantmentStoreT[sol::meta_function::index] = sol::overload(
 | 
					        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* {
 | 
					            [](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::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
				
			||||||
        enchantmentStoreT[sol::meta_function::ipairs] = 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}";
 | 
					            return "ESM3_MagicEffectStore{" + std::to_string(store.getSize()) + " effects}";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        magicEffectStoreT[sol::meta_function::index] = sol::overload(
 | 
					        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* {
 | 
					            [](const MagicEffectStore& store, std::string_view id) -> const ESM::MagicEffect* {
 | 
				
			||||||
                int index = ESM::MagicEffect::indexNameToIndex(id);
 | 
					                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*/,
 | 
					        auto magicEffectsIter = [magicEffectStore](sol::this_state lua, const sol::object& /*store*/,
 | 
				
			||||||
                                    sol::optional<int> id) -> std::tuple<sol::object, sol::object> {
 | 
					                                    sol::optional<int> id) -> std::tuple<sol::object, sol::object> {
 | 
				
			||||||
| 
						 | 
					@ -665,20 +673,20 @@ namespace MWLua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // types.Actor.spells(o)[i]
 | 
					        // types.Actor.spells(o)[i]
 | 
				
			||||||
        spellsT[sol::meta_function::index] = sol::overload(
 | 
					        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 (auto* store = spells.getStore())
 | 
				
			||||||
                    if (index <= store->count())
 | 
					                    if (index <= store->count() && index > 0)
 | 
				
			||||||
                        return store->at(index - 1);
 | 
					                        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())
 | 
					                if (auto* store = spells.getStore())
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    const ESM::Spell* spell = spellStore->find(ESM::RefId::deserializeText(spellId));
 | 
					                    const ESM::Spell* spell = spellStore->search(ESM::RefId::deserializeText(spellId));
 | 
				
			||||||
                    if (store->hasSpell(spell))
 | 
					                    if (spell && store->hasSpell(spell))
 | 
				
			||||||
                        return spell;
 | 
					                        return spell;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return sol::nullopt;
 | 
					                return nullptr;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // pairs(types.Actor.spells(o))
 | 
					        // pairs(types.Actor.spells(o))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,11 +136,11 @@ namespace MWLua
 | 
				
			||||||
            listT[sol::meta_function::to_string]
 | 
					            listT[sol::meta_function::to_string]
 | 
				
			||||||
                = [](const ListT& list) { return "{" + std::to_string(list.mIds->size()) + " objects}"; };
 | 
					                = [](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::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())
 | 
					                if (index > 0 && index <= list.mIds->size())
 | 
				
			||||||
                    return ObjectT((*list.mIds)[index - 1]);
 | 
					                    return ObjectT((*list.mIds)[index - 1]);
 | 
				
			||||||
                else
 | 
					                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::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
				
			||||||
            listT[sol::meta_function::ipairs] = 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}"; };
 | 
					            = [](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::length] = [](const SoundStore& store) { return store.getSize(); };
 | 
				
			||||||
        soundStoreT[sol::meta_function::index] = sol::overload(
 | 
					        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* {
 | 
					            [](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::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
				
			||||||
        soundStoreT[sol::meta_function::ipairs] = 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");
 | 
					        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::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);
 | 
					            ESM::RefId quest = ESM::RefId::deserializeText(questId);
 | 
				
			||||||
            const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().find(quest);
 | 
					            const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().search(quest);
 | 
				
			||||||
            if (dial->mType != ESM::Dialogue::Journal)
 | 
					            if (dial == nullptr || dial->mType != ESM::Dialogue::Journal)
 | 
				
			||||||
                throw std::runtime_error("Not a quest:" + std::string(questId));
 | 
					                return sol::nullopt;
 | 
				
			||||||
            return Quest{ .mQuestId = quest, .mMutable = quests.mMutable };
 | 
					            return Quest{ .mQuestId = quest, .mMutable = quests.mMutable };
 | 
				
			||||||
        });
 | 
					        };
 | 
				
			||||||
        quests[sol::meta_function::pairs] = [journal](const Quests& quests) {
 | 
					        quests[sol::meta_function::pairs] = [journal](const Quests& quests) {
 | 
				
			||||||
            std::vector<ESM::RefId> ids;
 | 
					            std::vector<ESM::RefId> ids;
 | 
				
			||||||
            for (auto it = journal->questBegin(); it != journal->questEnd(); ++it)
 | 
					            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>();
 | 
					        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; },
 | 
					        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.
 | 
					        // Define a custom user type for the store.
 | 
				
			||||||
        // Provide the interface of a read-only array.
 | 
					        // 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::length] = [](const StoreT& store) { return store.getSize(); };
 | 
				
			||||||
        storeT[sol::meta_function::index] = [](const StoreT& store, size_t index) -> const T* {
 | 
					        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.
 | 
					            return store.at(index - 1); // Translate from Lua's 1-based indexing.
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
					        storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue