mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-30 07:21:12 +00:00
Create a custom Lua usertype to expose a record store as a read-only array
This commit is contained in:
parent
11953a421b
commit
85dc0ec481
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Activator>(activator);
|
||||
addRecordFunctionBinding<ESM::Activator>(activator, context);
|
||||
|
||||
sol::usertype<ESM::Activator> record = context.mLua->sol().new_usertype<ESM::Activator>("ESM3_Activator");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -30,7 +30,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Apparatus>(apparatus);
|
||||
addRecordFunctionBinding<ESM::Apparatus>(apparatus, context);
|
||||
|
||||
sol::usertype<ESM::Apparatus> record = context.mLua->sol().new_usertype<ESM::Apparatus>("ESM3_Apparatus");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -37,7 +37,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Armor>(armor);
|
||||
addRecordFunctionBinding<ESM::Armor>(armor, context);
|
||||
|
||||
sol::usertype<ESM::Armor> record = context.mLua->sol().new_usertype<ESM::Armor>("ESM3_Armor");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -32,7 +32,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Book>(book);
|
||||
addRecordFunctionBinding<ESM::Book>(book, context);
|
||||
|
||||
sol::usertype<ESM::Book> record = context.mLua->sol().new_usertype<ESM::Book>("ESM3_Book");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -36,7 +36,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Clothing>(clothing);
|
||||
addRecordFunctionBinding<ESM::Clothing>(clothing, context);
|
||||
|
||||
sol::usertype<ESM::Clothing> record = context.mLua->sol().new_usertype<ESM::Clothing>("ESM3_Clothing");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -48,7 +48,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Container>(container);
|
||||
addRecordFunctionBinding<ESM::Container>(container, context);
|
||||
|
||||
sol::usertype<ESM::Container> record = context.mLua->sol().new_usertype<ESM::Container>("ESM3_Container");
|
||||
record[sol::meta_function::to_string] = [](const ESM::Container& rec) -> std::string {
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Creature>(creature);
|
||||
addRecordFunctionBinding<ESM::Creature>(creature, context);
|
||||
|
||||
sol::usertype<ESM::Creature> record = context.mLua->sol().new_usertype<ESM::Creature>("ESM3_Creature");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -43,7 +43,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Door>(door);
|
||||
addRecordFunctionBinding<ESM::Door>(door, context);
|
||||
|
||||
sol::usertype<ESM::Door> record = context.mLua->sol().new_usertype<ESM::Door>("ESM3_Door");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -24,7 +24,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Ingredient>(ingredient);
|
||||
addRecordFunctionBinding<ESM::Ingredient>(ingredient, context);
|
||||
|
||||
sol::usertype<ESM::Ingredient> record = context.mLua->sol().new_usertype<ESM::Ingredient>(("ESM3_Ingredient"));
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Light>(light);
|
||||
addRecordFunctionBinding<ESM::Light>(light, context);
|
||||
|
||||
sol::usertype<ESM::Light> record = context.mLua->sol().new_usertype<ESM::Light>("ESM3_Light");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Lockpick>(lockpick);
|
||||
addRecordFunctionBinding<ESM::Lockpick>(lockpick, context);
|
||||
|
||||
sol::usertype<ESM::Lockpick> record = context.mLua->sol().new_usertype<ESM::Lockpick>("ESM3_Lockpick");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Miscellaneous>(miscellaneous);
|
||||
addRecordFunctionBinding<ESM::Miscellaneous>(miscellaneous, context);
|
||||
|
||||
sol::usertype<ESM::Miscellaneous> record
|
||||
= context.mLua->sol().new_usertype<ESM::Miscellaneous>("ESM3_Miscellaneous");
|
||||
|
@ -25,7 +25,7 @@ namespace MWLua
|
||||
{
|
||||
addNpcStatsBindings(npc, context);
|
||||
|
||||
addRecordFunctionBinding<ESM::NPC>(npc);
|
||||
addRecordFunctionBinding<ESM::NPC>(npc, context);
|
||||
|
||||
sol::usertype<ESM::NPC> record = context.mLua->sol().new_usertype<ESM::NPC>("ESM3_NPC");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -41,7 +41,7 @@ namespace MWLua
|
||||
{
|
||||
void addPotionBindings(sol::table potion, const Context& context)
|
||||
{
|
||||
addRecordFunctionBinding<ESM::Potion>(potion);
|
||||
addRecordFunctionBinding<ESM::Potion>(potion, context);
|
||||
|
||||
// Creates a new potion struct but does not store it in MWWorld::ESMStore.
|
||||
// Global scripts can use world.createRecord to add the potion to the world.
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Probe>(probe);
|
||||
addRecordFunctionBinding<ESM::Probe>(probe, context);
|
||||
|
||||
sol::usertype<ESM::Probe> record = context.mLua->sol().new_usertype<ESM::Probe>("ESM3_Probe");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Repair>(repair);
|
||||
addRecordFunctionBinding<ESM::Repair>(repair, context);
|
||||
|
||||
sol::usertype<ESM::Repair> record = context.mLua->sol().new_usertype<ESM::Repair>("ESM3_Repair");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -23,7 +23,7 @@ namespace MWLua
|
||||
{
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Static>(stat);
|
||||
addRecordFunctionBinding<ESM::Static>(stat, context);
|
||||
|
||||
sol::usertype<ESM::Static> record = context.mLua->sol().new_usertype<ESM::Static>("ESM3_Static");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
|
||||
#include "apps/openmw/mwbase/environment.hpp"
|
||||
#include "apps/openmw/mwbase/world.hpp"
|
||||
@ -13,6 +14,16 @@
|
||||
#include "../context.hpp"
|
||||
#include "../object.hpp"
|
||||
|
||||
namespace sol
|
||||
{
|
||||
// Ensure sol does not try to create the automatic Container or usertype bindings for Store.
|
||||
// They include write operations and we want the store to be read-only.
|
||||
template <typename T>
|
||||
struct is_automagical<typename MWWorld::Store<T>> : std::false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
// `getLiveCellRefType()` is not exactly what we usually mean by "type" because some refids have special meaning.
|
||||
@ -53,12 +64,33 @@ namespace MWLua
|
||||
void addLightBindings(sol::table light, const Context& context);
|
||||
|
||||
template <class T>
|
||||
void addRecordFunctionBinding(sol::table table)
|
||||
void addRecordFunctionBinding(sol::table table, const Context& context)
|
||||
{
|
||||
const MWWorld::Store<T>& store = MWBase::Environment::get().getWorld()->getStore().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)); });
|
||||
|
||||
// Define a custom user type for the store.
|
||||
// Provide the interface of a read-only array.
|
||||
using StoreT = MWWorld::Store<T>;
|
||||
sol::state_view& lua = context.mLua->sol();
|
||||
sol::usertype<StoreT> storeT = lua.new_usertype<StoreT>(std::string(T::getRecordType()) + "WorldStore");
|
||||
storeT[sol::meta_function::to_string] = [](const StoreT& store) {
|
||||
return "{" + std::to_string(store.getSize()) + " " + std::string(T::getRecordType()) + " records}";
|
||||
};
|
||||
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 store.at(index - 1); // Translate from Lua's 1-based indexing.
|
||||
else
|
||||
throw std::runtime_error("Index out of range");
|
||||
};
|
||||
storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
|
||||
storeT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
|
||||
|
||||
// Provide access to the store.
|
||||
table["records"] = [&store]() { return &store; };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace MWLua
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
||||
addRecordFunctionBinding<ESM::Weapon>(weapon);
|
||||
addRecordFunctionBinding<ESM::Weapon>(weapon, context);
|
||||
|
||||
sol::usertype<ESM::Weapon> record = context.mLua->sol().new_usertype<ESM::Weapon>("ESM3_Weapon");
|
||||
record[sol::meta_function::to_string]
|
||||
|
@ -209,6 +209,11 @@ namespace MWWorld
|
||||
{
|
||||
return mShared.end();
|
||||
}
|
||||
template <typename T>
|
||||
const T& TypedDynamicStore<T>::at(size_t index) const
|
||||
{
|
||||
return *mShared.at(index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t TypedDynamicStore<T>::getSize() const
|
||||
|
@ -209,6 +209,7 @@ namespace MWWorld
|
||||
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
const T& at(size_t index) const;
|
||||
|
||||
size_t getSize() const override;
|
||||
int getDynamicSize() const override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user