mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-06 00:19:42 +00:00
[Lua] makeStrictReadOnly for enums
This commit is contained in:
parent
be100749f8
commit
7ccbf95503
10 changed files with 43 additions and 20 deletions
|
@ -17,7 +17,7 @@ namespace MWLua
|
|||
MWRender::RenderingManager* renderingManager = MWBase::Environment::get().getWorld()->getRenderingManager();
|
||||
|
||||
sol::table api(context.mLua->sol(), sol::create);
|
||||
api["MODE"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
|
||||
api["MODE"] = LuaUtil::makeStrictReadOnly(context.mLua->sol().create_table_with(
|
||||
"Static", CameraMode::Static,
|
||||
"FirstPerson", CameraMode::FirstPerson,
|
||||
"ThirdPerson", CameraMode::ThirdPerson,
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace MWLua
|
|||
return SDL_GetKeyName(SDL_GetKeyFromScancode(code));
|
||||
};
|
||||
|
||||
api["ACTION"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, MWInput::Actions>({
|
||||
api["ACTION"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, MWInput::Actions>({
|
||||
{"GameMenu", MWInput::A_GameMenu},
|
||||
{"Screenshot", MWInput::A_Screenshot},
|
||||
{"Inventory", MWInput::A_Inventory},
|
||||
|
@ -141,7 +141,7 @@ namespace MWLua
|
|||
{"ZoomOut", MWInput::A_ZoomOut}
|
||||
}));
|
||||
|
||||
api["CONTROL_SWITCH"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, std::string_view>({
|
||||
api["CONTROL_SWITCH"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, std::string_view>({
|
||||
{"Controls", "playercontrols"},
|
||||
{"Fighting", "playerfighting"},
|
||||
{"Jumping", "playerjumping"},
|
||||
|
@ -151,7 +151,7 @@ namespace MWLua
|
|||
{"VanityMode", "vanitymode"}
|
||||
}));
|
||||
|
||||
api["CONTROLLER_BUTTON"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, SDL_GameControllerButton>({
|
||||
api["CONTROLLER_BUTTON"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, SDL_GameControllerButton>({
|
||||
{"A", SDL_CONTROLLER_BUTTON_A},
|
||||
{"B", SDL_CONTROLLER_BUTTON_B},
|
||||
{"X", SDL_CONTROLLER_BUTTON_X},
|
||||
|
@ -169,7 +169,7 @@ namespace MWLua
|
|||
{"DPadRight", SDL_CONTROLLER_BUTTON_DPAD_RIGHT}
|
||||
}));
|
||||
|
||||
api["CONTROLLER_AXIS"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
api["CONTROLLER_AXIS"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
{"LeftX", SDL_CONTROLLER_AXIS_LEFTX},
|
||||
{"LeftY", SDL_CONTROLLER_AXIS_LEFTY},
|
||||
{"RightX", SDL_CONTROLLER_AXIS_RIGHTX},
|
||||
|
@ -183,7 +183,7 @@ namespace MWLua
|
|||
{"MoveLeftRight", SDL_CONTROLLER_AXIS_MAX + static_cast<int>(MWInput::A_MoveLeftRight)}
|
||||
}));
|
||||
|
||||
api["KEY"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, SDL_Scancode>({
|
||||
api["KEY"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, SDL_Scancode>({
|
||||
{"_0", SDL_SCANCODE_0},
|
||||
{"_1", SDL_SCANCODE_1},
|
||||
{"_2", SDL_SCANCODE_2},
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace MWLua
|
|||
return LObject(getId(r.mHitObject), worldView->getObjectRegistry());
|
||||
});
|
||||
|
||||
api["COLLISION_TYPE"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, MWPhysics::CollisionType>({
|
||||
api["COLLISION_TYPE"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, MWPhysics::CollisionType>({
|
||||
{"World", MWPhysics::CollisionType_World},
|
||||
{"Door", MWPhysics::CollisionType_Door},
|
||||
{"Actor", MWPhysics::CollisionType_Actor},
|
||||
|
|
|
@ -113,12 +113,12 @@ namespace MWLua
|
|||
|
||||
void addActorBindings(sol::table actor, const Context& context)
|
||||
{
|
||||
actor["STANCE"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
actor["STANCE"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
{"Nothing", MWMechanics::DrawState_Nothing},
|
||||
{"Weapon", MWMechanics::DrawState_Weapon},
|
||||
{"Spell", MWMechanics::DrawState_Spell},
|
||||
}));
|
||||
actor["EQUIPMENT_SLOT"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
actor["EQUIPMENT_SLOT"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
{"Helmet", MWWorld::InventoryStore::Slot_Helmet},
|
||||
{"Cuirass", MWWorld::InventoryStore::Slot_Cuirass},
|
||||
{"Greaves", MWWorld::InventoryStore::Slot_Greaves},
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace MWLua
|
|||
{
|
||||
void addWeaponBindings(sol::table weapon, const Context& context)
|
||||
{
|
||||
weapon["TYPE"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
weapon["TYPE"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, int>({
|
||||
{"ShortBladeOneHand", ESM::Weapon::ShortBladeOneHand},
|
||||
{"LongBladeOneHand", ESM::Weapon::LongBladeOneHand},
|
||||
{"LongBladeTwoHand", ESM::Weapon::LongBladeTwoHand},
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace MWLua
|
|||
{
|
||||
luaManager->addUIMessage(message);
|
||||
};
|
||||
api["CONSOLE_COLOR"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string, Misc::Color>({
|
||||
api["CONSOLE_COLOR"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string, Misc::Color>({
|
||||
{"Default", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Default.substr(1))},
|
||||
{"Error", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Error.substr(1))},
|
||||
{"Success", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Success.substr(1))},
|
||||
|
@ -298,9 +298,9 @@ namespace MWLua
|
|||
sol::table typeTable = context.mLua->newTable();
|
||||
for (const auto& it : LuaUi::widgetTypeToName())
|
||||
typeTable.set(it.second, it.first);
|
||||
api["TYPE"] = LuaUtil::makeReadOnly(typeTable);
|
||||
api["TYPE"] = LuaUtil::makeStrictReadOnly(typeTable);
|
||||
|
||||
api["ALIGNMENT"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs<std::string_view, LuaUi::Alignment>({
|
||||
api["ALIGNMENT"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, LuaUi::Alignment>({
|
||||
{ "Start", LuaUi::Alignment::Start },
|
||||
{ "Center", LuaUi::Alignment::Center },
|
||||
{ "End", LuaUi::Alignment::End }
|
||||
|
|
|
@ -84,12 +84,22 @@ namespace LuaUtil
|
|||
end
|
||||
printGen = function(name) return function(...) return printToLog(name, ...) end end
|
||||
|
||||
function createStrictIndexFn(tbl)
|
||||
return function(_, key)
|
||||
local res = tbl[key]
|
||||
if res ~= nil then
|
||||
return res
|
||||
else
|
||||
error('Key not found: '..tostring(key), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
function pairsForReadOnly(v)
|
||||
local nextFn, t, firstKey = pairs(getmetatable(v).__index)
|
||||
local nextFn, t, firstKey = pairs(getmetatable(v).t)
|
||||
return function(_, k) return nextFn(t, k) end, v, firstKey
|
||||
end
|
||||
function ipairsForReadOnly(v)
|
||||
local nextFn, t, firstKey = ipairs(getmetatable(v).__index)
|
||||
local nextFn, t, firstKey = ipairs(getmetatable(v).t)
|
||||
return function(_, k) return nextFn(t, k) end, v, firstKey
|
||||
end
|
||||
local function nextForArray(array, index)
|
||||
|
@ -136,7 +146,7 @@ namespace LuaUtil
|
|||
mSandboxEnv = sol::nil;
|
||||
}
|
||||
|
||||
sol::table makeReadOnly(sol::table table)
|
||||
sol::table makeReadOnly(const sol::table& table, bool strictIndex)
|
||||
{
|
||||
if (table == sol::nil)
|
||||
return table;
|
||||
|
@ -146,7 +156,11 @@ namespace LuaUtil
|
|||
lua_State* luaState = table.lua_state();
|
||||
sol::state_view lua(luaState);
|
||||
sol::table meta(lua, sol::create);
|
||||
meta["__index"] = table;
|
||||
meta["t"] = table;
|
||||
if (strictIndex)
|
||||
meta["__index"] = lua["createStrictIndexFn"](table);
|
||||
else
|
||||
meta["__index"] = table;
|
||||
meta["__pairs"] = lua["pairsForReadOnly"];
|
||||
meta["__ipairs"] = lua["ipairsForReadOnly"];
|
||||
|
||||
|
@ -158,7 +172,7 @@ namespace LuaUtil
|
|||
|
||||
sol::table getMutableFromReadOnly(const sol::userdata& ro)
|
||||
{
|
||||
return ro[sol::metatable_key].get<sol::table>()["__index"];
|
||||
return ro[sol::metatable_key].get<sol::table>()["t"];
|
||||
}
|
||||
|
||||
void LuaState::addCommonPackage(std::string packageName, sol::object package)
|
||||
|
|
|
@ -139,7 +139,9 @@ namespace LuaUtil
|
|||
|
||||
// Makes a table read only (when accessed from Lua) by wrapping it with an empty userdata.
|
||||
// Needed to forbid any changes in common resources that can be accessed from different sandboxes.
|
||||
sol::table makeReadOnly(sol::table);
|
||||
// `strictIndex = true` replaces default `__index` with a strict version that throws an error if key is not found.
|
||||
sol::table makeReadOnly(const sol::table&, bool strictIndex = false);
|
||||
inline sol::table makeStrictReadOnly(const sol::table& tbl) { return makeReadOnly(tbl, true); }
|
||||
sol::table getMutableFromReadOnly(const sol::userdata&);
|
||||
|
||||
}
|
||||
|
|
|
@ -214,7 +214,8 @@ namespace LuaUtil
|
|||
util["clamp"] = [](float value, float from, float to) { return std::clamp(value, from, to); };
|
||||
// NOTE: `util["clamp"] = std::clamp<float>` causes error 'AddressSanitizer: stack-use-after-scope'
|
||||
util["normalizeAngle"] = &Misc::normalizeAngle;
|
||||
util["makeReadOnly"] = &makeReadOnly;
|
||||
util["makeReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/false); };
|
||||
util["makeStrictReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/true); };
|
||||
|
||||
if (lua["bit32"] != sol::nil)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
-- @param #table table Any table.
|
||||
-- @return #table The same table wrapped with read only userdata.
|
||||
|
||||
---
|
||||
-- Makes a table read only and overrides `__index` with the strict version that throws an error if the key is not found.
|
||||
-- @function [parent=#util] makeStrictReadOnly
|
||||
-- @param #table table Any table.
|
||||
-- @return #table The same table wrapped with read only userdata.
|
||||
|
||||
---
|
||||
-- Parses Lua code from string and returns as a function.
|
||||
-- @function [parent=#util] loadCode
|
||||
|
|
Loading…
Reference in a new issue