-
Notifications
You must be signed in to change notification settings - Fork 45
Description
Tl;dr
Assigning the ScriptableDoor as metatable index results in LuaRuntimeException: bad argument #1 to 'index' (ScriptableDoor expected, got Table). This is because the generated class does this in its own metatable indexer context.GetArgument<global::ScriptableDoor>(0):
var csObject = new ScriptableDoor(); // Has [LuaObject] attribute with [LuaMember] members
var table = new LuaTable();
table.Metatable = new LuaTable()
{
[Lua.Runtime.Metamethods.Index] = csObject
};
state.Environment["obj"] = table;Then in lua:
-- Exception
obj:OnOpen(nil);I'm trying to allow users to extend C# objects with Lua code to allow for more object-oriented scripting. For example a scriptable C# object might look like this:
[LuaObject]
public class ScriptableDoor
{
/* Lua state and stuff saved as well */
public ScriptableDoor(LuaTable scriptClass)
{
// Create LuaObject below, set states, metatables, etc.
}
public LuaTable LuaObject { get; }
public bool IsOpen { get; private set; }
[LuaMember]
public void OnCreated()
{
// NOOP
}
[LuaMember]
public void OnOpen(Entity entity)
{
// Open the door
this.IsOpen = true
}
[LuaMember]
public void OnClose(Entity entity)
{
// Close the door
this.IsOpen = false
}
}Then one could create a script for such a door like this:
-- object_trap_door.lua
object_trap_door = object_trap_door or {}
function object_trap_door:OnCreated()
self.damage = 3
end
function object_trap_door:OnOpen(entity)
self.Base:OnOpen(entity)
entity:DealDamage(self.damage)
endThe idea is that it can then be used like this:
local instance = CreateInstance(object_trap_door)
instance:OnOpen(player) -- Uses OnOpen from the script definition
instance:OnClose(player) -- Uses OnClose from the __index (the C# class).CreateInstance would look something like:
var state = LuaState.Create();
await state.DoFileAsync("object_trap_door.lua");
var scriptClass = state.Environment["object_trap_door"].Read<LuaTable>();
var csInstance = new ScriptableDoor(scriptClass);
var luaInstance = csInstance.LuaObject;
luaInstance.Metatable = new LuaTable()
{
[Lua.Runtime.Metamethods.Index] = csInstance,
};
await luaInstance[nameof(ScriptableDoor.OnCreated)].Read<LuaFunction>().InvokeAsync(state, [luaInstance]);
return luaInstance;However this doesn't work. Assigning the ScriptableDoor as metatable index results in LuaRuntimeException: bad argument #1 to 'index' (ScriptableDoor expected, got Table). This is because the generated class does this in its own metatable indexer context.GetArgument<global::ScriptableDoor>(0).
This could be fixed by creating a custom metatable indexer of course, but outside of reflection there is no convenient way to do this.