mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-24 04:11:50 -04:00
Merge branch 'intern' into 'master'
Draft: Cache Lua GameObjects to prevent duplicate table keys #8677 Closes #8677 See merge request OpenMW/openmw!4902
This commit is contained in:
commit
302ac70d87
@ -63,7 +63,7 @@ add_openmw_dir (mwlua
|
|||||||
context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings
|
context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings
|
||||||
mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings
|
mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings
|
||||||
postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings
|
postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings
|
||||||
classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings weatherbindings regionbindings
|
classbindings intern itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings weatherbindings regionbindings
|
||||||
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
|
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
|
||||||
types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus
|
types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus
|
||||||
types/potion types/ingredient types/misc types/repair types/armor types/light types/static
|
types/potion types/ingredient types/misc types/repair types/armor types/light types/static
|
||||||
|
84
apps/openmw/mwlua/intern.cpp
Normal file
84
apps/openmw/mwlua/intern.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "object.hpp"
|
||||||
|
|
||||||
|
namespace MWLua
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_gameObject = std::is_same_v<LObject, T> || std::is_same_v<GObject, T>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_cell = std::is_same_v<LCell, T> || std::is_same_v<GCell, T>;
|
||||||
|
|
||||||
|
constexpr std::string_view gameObjects = "LUA_GAMEOBJECTS_REGISTRY";
|
||||||
|
constexpr std::string_view cells = "LUA_CELLS_REGISTRY";
|
||||||
|
|
||||||
|
inline constexpr uint64_t toUInt64(const ObjectId& id)
|
||||||
|
{
|
||||||
|
if (id.hasContentFile())
|
||||||
|
return id.mIndex | (static_cast<uint64_t>(id.mContentFile) << 24);
|
||||||
|
else
|
||||||
|
return id.mIndex | (static_cast<uint64_t>(-id.mContentFile - 1) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sol::table getRegistry(std::string_view key, sol::state_view lua)
|
||||||
|
{
|
||||||
|
if (sol::object reg = lua.registry()[key]; reg.valid()) // LUA_REGISTRYINDEX
|
||||||
|
return reg.as<sol::table>();
|
||||||
|
|
||||||
|
sol::table t(lua, sol::create);
|
||||||
|
t[sol::metatable_key] = lua.create_table_with("__mode", "v"); // weak table
|
||||||
|
|
||||||
|
lua.registry()[key] = t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename userT, typename ArgT>
|
||||||
|
sol::object makeOrGetImpl(ArgT arg, sol::state_view lua)
|
||||||
|
{
|
||||||
|
static_assert(std::is_constructible_v<userT, ArgT>);
|
||||||
|
|
||||||
|
sol::table registry;
|
||||||
|
sol::object key;
|
||||||
|
|
||||||
|
if constexpr (is_gameObject<userT>)
|
||||||
|
{
|
||||||
|
registry = getRegistry(gameObjects, lua);
|
||||||
|
if constexpr (std::is_same_v<ArgT, MWWorld::Ptr>)
|
||||||
|
key = sol::make_object(lua, toUInt64(getId(arg)));
|
||||||
|
else
|
||||||
|
key = sol::make_object(lua, toUInt64(arg));
|
||||||
|
}
|
||||||
|
else if constexpr (is_cell<userT>)
|
||||||
|
{
|
||||||
|
registry = getRegistry(cells, lua);
|
||||||
|
key = sol::make_object(lua, sol::make_light(arg));
|
||||||
|
}
|
||||||
|
// else compile error
|
||||||
|
|
||||||
|
sol::object existing = registry[key];
|
||||||
|
if (existing.valid())
|
||||||
|
return existing;
|
||||||
|
|
||||||
|
sol::object obj = sol::make_object(lua, userT(arg));
|
||||||
|
registry[key] = obj; // stored in weak table so garbage collector should work on this
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
template <typename userT, typename ArgT>
|
||||||
|
sol::object makeOrGet(ArgT arg, sol::state_view lua)
|
||||||
|
{
|
||||||
|
return makeOrGetImpl<userT>(arg, lua);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game Objects
|
||||||
|
template sol::object MWLua::makeOrGet<LObject, MWWorld::Ptr>(MWWorld::Ptr, sol::state_view);
|
||||||
|
template sol::object MWLua::makeOrGet<LObject, ObjectId>(ObjectId, sol::state_view);
|
||||||
|
template sol::object MWLua::makeOrGet<GObject, MWWorld::Ptr>(MWWorld::Ptr, sol::state_view);
|
||||||
|
template sol::object MWLua::makeOrGet<GObject, ObjectId>(ObjectId, sol::state_view);
|
||||||
|
|
||||||
|
// Cells
|
||||||
|
template sol::object MWLua::makeOrGet<LCell, MWWorld::CellStore*>(MWWorld::CellStore*, sol::state_view);
|
||||||
|
template sol::object MWLua::makeOrGet<GCell, MWWorld::CellStore*>(MWWorld::CellStore*, sol::state_view);
|
||||||
|
}
|
@ -58,7 +58,8 @@ namespace MWLua
|
|||||||
= lua.new_usertype<SelfObject>("SelfObject", sol::base_classes, sol::bases<LObject, Object>());
|
= lua.new_usertype<SelfObject>("SelfObject", sol::base_classes, sol::bases<LObject, Object>());
|
||||||
selfAPI[sol::meta_function::to_string]
|
selfAPI[sol::meta_function::to_string]
|
||||||
= [](SelfObject& self) { return "openmw.self[" + self.toString() + "]"; };
|
= [](SelfObject& self) { return "openmw.self[" + self.toString() + "]"; };
|
||||||
selfAPI["object"] = sol::readonly_property([](SelfObject& self) -> LObject { return LObject(self); });
|
selfAPI["object"] = sol::readonly_property(
|
||||||
|
[lua](SelfObject& self) -> sol::object { return makeOrGet<LObject>(self.ptr(), lua); });
|
||||||
selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; });
|
selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; });
|
||||||
selfAPI["isActive"] = [](SelfObject& self) -> bool { return self.mIsActive; };
|
selfAPI["isActive"] = [](SelfObject& self) -> bool { return self.mIsActive; };
|
||||||
selfAPI["enableAI"] = [](SelfObject& self, bool v) { self.mControls.mDisableAI = !v; };
|
selfAPI["enableAI"] = [](SelfObject& self, bool v) { self.mControls.mDisableAI = !v; };
|
||||||
|
@ -791,9 +791,8 @@ namespace MWLua
|
|||||||
{
|
{
|
||||||
sol::object selected = sol::nil;
|
sol::object selected = sol::nil;
|
||||||
if (!selectedPtr.isEmpty())
|
if (!selectedPtr.isEmpty())
|
||||||
mLua.protectedCall([&](LuaUtil::LuaView& view) {
|
mLua.protectedCall(
|
||||||
selected = sol::make_object(view.sol(), LObject(getId(selectedPtr)));
|
[&](LuaUtil::LuaView& view) { selected = makeOrGet<LObject>(selectedPtr, view.sol()); });
|
||||||
});
|
|
||||||
if (playerScripts->consoleCommand(consoleMode, command, selected))
|
if (playerScripts->consoleCommand(consoleMode, command, selected))
|
||||||
processed = true;
|
processed = true;
|
||||||
}
|
}
|
||||||
|
@ -130,18 +130,18 @@ namespace MWLua
|
|||||||
mwscript["isRunning"] = sol::readonly_property([](const MWScriptRef& s) { return s.isRunning(); });
|
mwscript["isRunning"] = sol::readonly_property([](const MWScriptRef& s) { return s.isRunning(); });
|
||||||
mwscript["recordId"] = sol::readonly_property([](const MWScriptRef& s) { return s.mId.serializeText(); });
|
mwscript["recordId"] = sol::readonly_property([](const MWScriptRef& s) { return s.mId.serializeText(); });
|
||||||
mwscript["variables"] = sol::readonly_property([](const MWScriptRef& s) { return MWScriptVariables{ s }; });
|
mwscript["variables"] = sol::readonly_property([](const MWScriptRef& s) { return MWScriptVariables{ s }; });
|
||||||
mwscript["object"] = sol::readonly_property([](const MWScriptRef& s) -> sol::optional<GObject> {
|
mwscript["object"] = sol::readonly_property([lua](const MWScriptRef& s) -> sol::object {
|
||||||
if (s.mObj)
|
if (s.mObj)
|
||||||
return s.mObj;
|
return makeOrGet<GObject>(s.mObj->ptr(), lua);
|
||||||
const MWScript::GlobalScriptDesc* script
|
const MWScript::GlobalScriptDesc* script
|
||||||
= MWBase::Environment::get().getScriptManager()->getGlobalScripts().getScriptIfPresent(s.mId);
|
= MWBase::Environment::get().getScriptManager()->getGlobalScripts().getScriptIfPresent(s.mId);
|
||||||
if (!script)
|
if (!script)
|
||||||
throw std::runtime_error("Invalid MWScriptRef");
|
throw std::runtime_error("Invalid MWScriptRef");
|
||||||
const MWWorld::Ptr* ptr = script->getPtrIfPresent();
|
const MWWorld::Ptr* ptr = script->getPtrIfPresent();
|
||||||
if (ptr && !ptr->isEmpty())
|
if (ptr && !ptr->isEmpty())
|
||||||
return GObject(*ptr);
|
return makeOrGet<GObject>(*ptr, lua);
|
||||||
else
|
else
|
||||||
return sol::nullopt;
|
return sol::nil;
|
||||||
});
|
});
|
||||||
mwscript["player"] = sol::readonly_property(
|
mwscript["player"] = sol::readonly_property(
|
||||||
[](const MWScriptRef&) { return GObject(MWBase::Environment::get().getWorld()->getPlayerPtr()); });
|
[](const MWScriptRef&) { return GObject(MWBase::Environment::get().getWorld()->getPlayerPtr()); });
|
||||||
|
@ -35,6 +35,9 @@ namespace MWLua
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename userT, typename ArgT>
|
||||||
|
sol::object makeOrGet(ArgT arg, sol::state_view lua);
|
||||||
|
|
||||||
// Used only in local scripts
|
// Used only in local scripts
|
||||||
struct LCell
|
struct LCell
|
||||||
{
|
{
|
||||||
|
@ -170,11 +170,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) -> sol::optional<ObjectT> {
|
listT[sol::meta_function::index] = [lua](const ListT& list, size_t index) -> sol::object {
|
||||||
if (index > 0 && index <= list.mIds->size())
|
if (index > 0 && index <= list.mIds->size())
|
||||||
return ObjectT((*list.mIds)[LuaUtil::fromLuaIndex(index)]);
|
return makeOrGet<ObjectT>((*list.mIds)[LuaUtil::fromLuaIndex(index)], lua);
|
||||||
else
|
else
|
||||||
return sol::nullopt;
|
return sol::nil;
|
||||||
};
|
};
|
||||||
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>();
|
||||||
@ -278,6 +278,7 @@ namespace MWLua
|
|||||||
template <class ObjectT>
|
template <class ObjectT>
|
||||||
void addBasicBindings(sol::usertype<ObjectT>& objectT, const Context& context)
|
void addBasicBindings(sol::usertype<ObjectT>& objectT, const Context& context)
|
||||||
{
|
{
|
||||||
|
sol::state_view lua = context.sol();
|
||||||
objectT["id"] = sol::readonly_property([](const ObjectT& o) -> std::string { return o.id().toString(); });
|
objectT["id"] = sol::readonly_property([](const ObjectT& o) -> std::string { return o.id().toString(); });
|
||||||
objectT["contentFile"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<std::string> {
|
objectT["contentFile"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<std::string> {
|
||||||
int contentFileIndex = o.id().mContentFile;
|
int contentFileIndex = o.id().mContentFile;
|
||||||
@ -296,13 +297,13 @@ namespace MWLua
|
|||||||
else
|
else
|
||||||
return ESM::RefId::stringRefId(globalVariable).serializeText();
|
return ESM::RefId::stringRefId(globalVariable).serializeText();
|
||||||
});
|
});
|
||||||
objectT["cell"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<Cell<ObjectT>> {
|
objectT["cell"] = sol::readonly_property([lua](const ObjectT& o) -> sol::object {
|
||||||
const MWWorld::Ptr& ptr = o.ptr();
|
const MWWorld::Ptr& ptr = o.ptr();
|
||||||
MWWorld::WorldModel* wm = MWBase::Environment::get().getWorldModel();
|
MWWorld::WorldModel* wm = MWBase::Environment::get().getWorldModel();
|
||||||
if (ptr.isInCell() && ptr.getCell() != &wm->getDraftCell())
|
if (ptr.isInCell() && ptr.getCell() != &wm->getDraftCell())
|
||||||
return Cell<ObjectT>{ ptr.getCell() };
|
return makeOrGet<Cell<ObjectT>>(ptr.getCell(), lua);
|
||||||
else
|
else
|
||||||
return sol::nullopt;
|
return sol::nil;
|
||||||
});
|
});
|
||||||
objectT["parentContainer"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<ObjectT> {
|
objectT["parentContainer"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<ObjectT> {
|
||||||
const MWWorld::Ptr& ptr = o.ptr();
|
const MWWorld::Ptr& ptr = o.ptr();
|
||||||
@ -555,6 +556,7 @@ namespace MWLua
|
|||||||
void addInventoryBindings(sol::usertype<ObjectT>& objectT, const std::string& prefix, const Context& context)
|
void addInventoryBindings(sol::usertype<ObjectT>& objectT, const std::string& prefix, const Context& context)
|
||||||
{
|
{
|
||||||
using InventoryT = Inventory<ObjectT>;
|
using InventoryT = Inventory<ObjectT>;
|
||||||
|
sol::state_view lua = context.sol();
|
||||||
sol::usertype<InventoryT> inventoryT = context.sol().new_usertype<InventoryT>(prefix + "Inventory");
|
sol::usertype<InventoryT> inventoryT = context.sol().new_usertype<InventoryT>(prefix + "Inventory");
|
||||||
|
|
||||||
inventoryT[sol::meta_function::to_string]
|
inventoryT[sol::meta_function::to_string]
|
||||||
@ -651,7 +653,7 @@ namespace MWLua
|
|||||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||||
return store.isResolved();
|
return store.isResolved();
|
||||||
};
|
};
|
||||||
inventoryT["find"] = [](const InventoryT& inventory, std::string_view recordId) -> sol::optional<ObjectT> {
|
inventoryT["find"] = [lua](const InventoryT& inventory, std::string_view recordId) -> sol::object {
|
||||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||||
auto itemId = ESM::RefId::deserializeText(recordId);
|
auto itemId = ESM::RefId::deserializeText(recordId);
|
||||||
@ -660,10 +662,10 @@ namespace MWLua
|
|||||||
if (item.getCellRef().getRefId() == itemId)
|
if (item.getCellRef().getRefId() == itemId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorldModel()->registerPtr(item);
|
MWBase::Environment::get().getWorldModel()->registerPtr(item);
|
||||||
return ObjectT(getId(item));
|
return makeOrGet<ObjectT>(getId(item), lua);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sol::nullopt;
|
return sol::nil;
|
||||||
};
|
};
|
||||||
inventoryT["findAll"] = [](const InventoryT& inventory, std::string_view recordId) {
|
inventoryT["findAll"] = [](const InventoryT& inventory, std::string_view recordId) {
|
||||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||||
|
@ -96,9 +96,9 @@ namespace MWLua
|
|||||||
return sol::nil;
|
return sol::nil;
|
||||||
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell());
|
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell());
|
||||||
if (dynamic_cast<const GObject*>(&o))
|
if (dynamic_cast<const GObject*>(&o))
|
||||||
return sol::make_object(thisState, GCell{ &cell });
|
return makeOrGet<GCell>(&cell, thisState);
|
||||||
else
|
else
|
||||||
return sol::make_object(thisState, LCell{ &cell });
|
return makeOrGet<LCell>(&cell, thisState);
|
||||||
};
|
};
|
||||||
|
|
||||||
addRecordFunctionBinding<ESM::Door>(door, context);
|
addRecordFunctionBinding<ESM::Door>(door, context);
|
||||||
@ -132,9 +132,9 @@ namespace MWLua
|
|||||||
return sol::nil;
|
return sol::nil;
|
||||||
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell());
|
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell());
|
||||||
if (dynamic_cast<const GObject*>(&o))
|
if (dynamic_cast<const GObject*>(&o))
|
||||||
return sol::make_object(lua, GCell{ &cell });
|
return makeOrGet<GCell>(&cell, lua);
|
||||||
else
|
else
|
||||||
return sol::make_object(lua, LCell{ &cell });
|
return makeOrGet<LCell>(&cell, lua);
|
||||||
};
|
};
|
||||||
|
|
||||||
addRecordFunctionBinding<ESM4::Door>(door, context, "ESM4Door");
|
addRecordFunctionBinding<ESM4::Door>(door, context, "ESM4Door");
|
||||||
|
@ -77,9 +77,9 @@ namespace MWLua
|
|||||||
ObjectId id = loadRefNum(binaryData);
|
ObjectId id = loadRefNum(binaryData);
|
||||||
adjustRefNum(id);
|
adjustRefNum(id);
|
||||||
if (mLocalSerializer)
|
if (mLocalSerializer)
|
||||||
sol::stack::push<LObject>(lua, LObject(id));
|
sol::stack::push(lua, makeOrGet<LObject>(id, lua));
|
||||||
else
|
else
|
||||||
sol::stack::push<GObject>(lua, GObject(id));
|
sol::stack::push(lua, makeOrGet<GObject>(id, lua));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (typeName == sObjListTypeName)
|
if (typeName == sObjListTypeName)
|
||||||
|
@ -81,14 +81,16 @@ namespace MWLua
|
|||||||
|
|
||||||
static void addCellGetters(sol::table& api, const Context& context)
|
static void addCellGetters(sol::table& api, const Context& context)
|
||||||
{
|
{
|
||||||
api["getCellByName"] = [](std::string_view name) {
|
sol::state_view lua = context.sol();
|
||||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(name, /*forceLoad=*/false) };
|
api["getCellByName"] = [lua](std::string_view name) {
|
||||||
|
return makeOrGet<GCell>(
|
||||||
|
&MWBase::Environment::get().getWorldModel()->getCell(name, /*forceLoad=*/false), lua);
|
||||||
};
|
};
|
||||||
api["getCellById"] = [](std::string_view stringId) {
|
api["getCellById"] = [lua](std::string_view stringId) {
|
||||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(
|
ESM::RefId id = ESM::RefId::deserializeText(stringId);
|
||||||
ESM::RefId::deserializeText(stringId), /*forceLoad=*/false) };
|
return makeOrGet<GCell>(&MWBase::Environment::get().getWorldModel()->getCell(id, /*forceLoad=*/false), lua);
|
||||||
};
|
};
|
||||||
api["getExteriorCell"] = [](int x, int y, sol::object cellOrName) {
|
api["getExteriorCell"] = [lua](int x, int y, sol::object cellOrName) {
|
||||||
ESM::RefId worldspace;
|
ESM::RefId worldspace;
|
||||||
if (cellOrName.is<GCell>())
|
if (cellOrName.is<GCell>())
|
||||||
worldspace = cellOrName.as<GCell>().mStore->getCell()->getWorldSpace();
|
worldspace = cellOrName.as<GCell>().mStore->getCell()->getWorldSpace();
|
||||||
@ -100,8 +102,9 @@ namespace MWLua
|
|||||||
->getWorldSpace();
|
->getWorldSpace();
|
||||||
else
|
else
|
||||||
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
||||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getExterior(
|
auto location = ESM::ExteriorCellLocation(x, y, worldspace);
|
||||||
ESM::ExteriorCellLocation(x, y, worldspace), /*forceLoad=*/false) };
|
return makeOrGet<GCell>(
|
||||||
|
&MWBase::Environment::get().getWorldModel()->getExterior(location, /*forceLoad=*/false), lua);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Cell>* cells3Store = &MWBase::Environment::get().getESMStore()->get<ESM::Cell>();
|
const MWWorld::Store<ESM::Cell>* cells3Store = &MWBase::Environment::get().getESMStore()->get<ESM::Cell>();
|
||||||
@ -111,22 +114,22 @@ namespace MWLua
|
|||||||
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]
|
cells[sol::meta_function::index]
|
||||||
= [cells3Store, cells4Store](const CellsStore&, size_t index) -> sol::optional<GCell> {
|
= [cells3Store, cells4Store, lua](const CellsStore&, size_t index) -> sol::object {
|
||||||
if (index > cells3Store->getSize() + cells3Store->getSize() || index == 0)
|
if (index > cells3Store->getSize() + cells3Store->getSize() || index == 0)
|
||||||
return sol::nullopt;
|
return sol::nil;
|
||||||
|
|
||||||
index--; // Translate from Lua's 1-based indexing.
|
index--; // Translate from Lua's 1-based indexing.
|
||||||
if (index < cells3Store->getSize())
|
if (index < cells3Store->getSize())
|
||||||
{
|
{
|
||||||
const ESM::Cell* cellRecord = cells3Store->at(index);
|
const ESM::Cell* cellRecord = cells3Store->at(index);
|
||||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(
|
return makeOrGet<GCell>(
|
||||||
cellRecord->mId, /*forceLoad=*/false) };
|
&MWBase::Environment::get().getWorldModel()->getCell(cellRecord->mId, /*forceLoad=*/false), lua);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ESM4::Cell* cellRecord = cells4Store->at(index - cells3Store->getSize());
|
const ESM4::Cell* cellRecord = cells4Store->at(index - cells3Store->getSize());
|
||||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(
|
return makeOrGet<GCell>(
|
||||||
cellRecord->mId, /*forceLoad=*/false) };
|
&MWBase::Environment::get().getWorldModel()->getCell(cellRecord->mId, /*forceLoad=*/false), lua);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cells[sol::meta_function::pairs] = view["ipairsForArray"].template get<sol::function>();
|
cells[sol::meta_function::pairs] = view["ipairsForArray"].template get<sol::function>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user