croizat
croizat
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
Well seems like this may be a solvable problem. The crashing was apparently unrelated but it does throw an error. I can access it multiple times, but only if there's no waiting in between, so e.g. on the same frame where it's not helpful to access it multiple times. If there's a wait, then the properties are all nulled, but only for the imported class. Regular functions work fine after a wait
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
I might give it a try. Not super tied to NLua specifically, it's just what my program used before this rewrite so I'm most familiar with it, though that's not saying much
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
well really not sure how the current service class is unsafe. If I do a simple
class ServiceWrapper
{
public IPlayer Player => Svc.Player;
}
...
var service = new ServiceWrapper();
state["Service"] = service;
class ServiceWrapper
{
public IPlayer Player => Svc.Player;
}
...
var service = new ServiceWrapper();
state["Service"] = service;
// fails by second iteration
local pos = Service.Player.Position
while count < 10 do
pos = Service.Player.Position
Game.LogInfo(pos)
count = count + 1
if count < 10 then
yield("/wait 5")
end
end

// works
Game.LogInfo(Service.Player.Position)
// fails by second iteration
local pos = Service.Player.Position
while count < 10 do
pos = Service.Player.Position
Game.LogInfo(pos)
count = count + 1
if count < 10 then
yield("/wait 5")
end
end

// works
Game.LogInfo(Service.Player.Position)
It results in the same as the last message where it can be accessed once, but multiple lines (like in a loop), it causes a crash. I was thinking maybe it's a speed limitation of the CLR access in nlua but it doesn't matter how fast or slow I access it a second time
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
cannot for the life of me figure out doing it like that import statement. I can however do
lua.DoString(@$"luanet.load_assembly('{typeof(T).Assembly.GetName().Name}')");
lua.DoString(@$"{typeof(T).Name} = luanet.import_type('{typeof(T).FullName}')()");
lua.DoString(@$"luanet.load_assembly('{typeof(T).Assembly.GetName().Name}')");
lua.DoString(@$"{typeof(T).Name} = luanet.import_type('{typeof(T).FullName}')()");
Can't test if it actually accesses it on call though since it seems to crash when called in a loop... Works as a one liner at least
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
I think NLua lets you effectively inject C# objects into your code already...it feels like you might be re-inventing the wheel already.
this very well might be the case and I've wasted hours on this but finding out info about nlua is like pulling teeth
Are they copied by value and don't change every frame, so that's why you're trying to do it via reflection?
as in they're all structs or primitives? Yeah mostly. There are quite a few pointers but I'm mostly not worried about those
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
Yeah that's something I've tried before, but it really just ended up with null values, probably because I'm not fantastic with reflection. This was one iteration for reference
lua.NewTable("Service");

var svcType = typeof(Svc);
var properties = svcType.GetProperties(BindingFlags.Public | BindingFlags.Static);

foreach (var property in properties)
{
if (property.GetValue(null) is not { } service) continue;

lua.NewTable($"Service.{property.Name}");
var serviceTable = lua.GetTable($"Service.{property.Name}");

var serviceType = service.GetType();
var members = serviceType.GetMembers(BindingFlags.Public | BindingFlags.Instance);

foreach (var member in members)
{
if (member is PropertyInfo prop)
{
serviceTable[prop.Name] = new Func<object>(() =>
{
try
{
return prop.GetValue(service);
}
catch (Exception ex)
{
Svc.Log.Error(ex, $"Error getting {prop.Name}");
}
});
}
else if (member is MethodInfo method)
{
serviceTable[method.Name] = new Func<object[], object>(args =>
{
try
{
return method.Invoke(service, args);
}
catch (Exception ex)
{
Svc.Log.Error(ex, $"Error calling {method.Name}");
}
});
}
}
}
lua.NewTable("Service");

var svcType = typeof(Svc);
var properties = svcType.GetProperties(BindingFlags.Public | BindingFlags.Static);

foreach (var property in properties)
{
if (property.GetValue(null) is not { } service) continue;

lua.NewTable($"Service.{property.Name}");
var serviceTable = lua.GetTable($"Service.{property.Name}");

var serviceType = service.GetType();
var members = serviceType.GetMembers(BindingFlags.Public | BindingFlags.Instance);

foreach (var member in members)
{
if (member is PropertyInfo prop)
{
serviceTable[prop.Name] = new Func<object>(() =>
{
try
{
return prop.GetValue(service);
}
catch (Exception ex)
{
Svc.Log.Error(ex, $"Error getting {prop.Name}");
}
});
}
else if (member is MethodInfo method)
{
serviceTable[method.Name] = new Func<object[], object>(args =>
{
try
{
return method.Invoke(service, args);
}
catch (Exception ex)
{
Svc.Log.Error(ex, $"Error calling {method.Name}");
}
});
}
}
}
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
for lua scripting in a game/engine
That would be correct.
is there a particular usecase for you wanting or expecting these properties to return different values each time they are accessed
well yeah, the game is changing every frame after all. Like if you have a lua script where you want to execute something when Servce.Player.ZoneId == 1 you'd just loop checking the value. It wouldn't be helpful if the value is cached on script start or on first access. I do have it setup to be able to trigger scripts on conditions, where you'd really only care about a "snapshot" of the game as you said but it also has the ability to just run scripts alongside the game for an indefinite period of time
24 replies
CC#
Created by croizat on 5/2/2025 in #help
[NLua] How to provide the lua state with a dynamically accessible class
Yes, per-access too to be clear
24 replies