Files
BH3/Assets/Plugins/Assembly-CSharp-firstpass/LuaInterface/LuaMethodWrapper.cs
2025-08-13 09:26:42 +08:00

265 lines
7.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
namespace LuaInterface
{
internal class LuaMethodWrapper
{
private ObjectTranslator _Translator;
private MethodBase _Method;
private MethodCache _LastCalledMethod = default(MethodCache);
private string _MethodName;
private MemberInfo[] _Members;
public IReflect _TargetType;
private ExtractValue _ExtractTarget;
private object _Target;
private BindingFlags _BindingType;
public LuaMethodWrapper(ObjectTranslator translator, object target, IReflect targetType, MethodBase method)
{
_Translator = translator;
_Target = target;
_TargetType = targetType;
if (targetType != null)
{
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
}
_Method = method;
_MethodName = method.Name;
if (method.IsStatic)
{
_BindingType = BindingFlags.Static;
}
else
{
_BindingType = BindingFlags.Instance;
}
}
public LuaMethodWrapper(ObjectTranslator translator, IReflect targetType, string methodName, BindingFlags bindingType)
{
_Translator = translator;
_MethodName = methodName;
_TargetType = targetType;
if (targetType != null)
{
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
}
_BindingType = bindingType;
_Members = targetType.UnderlyingSystemType.GetMember(methodName, MemberTypes.Method, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase);
}
private int SetPendingException(Exception e)
{
return _Translator.interpreter.SetPendingException(e);
}
private static bool IsInteger(double x)
{
return Math.Ceiling(x) == x;
}
public int call(IntPtr luaState)
{
MethodBase method = _Method;
object obj = _Target;
bool flag = true;
int num = 0;
if (!LuaDLL.lua_checkstack(luaState, 5))
{
throw new LuaException("Lua stack overflow");
}
bool flag2 = (_BindingType & BindingFlags.Static) == BindingFlags.Static;
SetPendingException(null);
if (method == null)
{
obj = ((!flag2) ? _ExtractTarget(luaState, 1) : null);
if (_LastCalledMethod.cachedMethod != null)
{
int num2 = ((!flag2) ? 1 : 0);
int num3 = LuaDLL.lua_gettop(luaState) - num2;
MethodBase cachedMethod = _LastCalledMethod.cachedMethod;
if (num3 == _LastCalledMethod.argTypes.Length)
{
if (!LuaDLL.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6))
{
throw new LuaException("Lua stack overflow");
}
object[] args = _LastCalledMethod.args;
try
{
int num4 = 0;
while (true)
{
if (num4 < _LastCalledMethod.argTypes.Length)
{
MethodArgs methodArgs = _LastCalledMethod.argTypes[num4];
object obj2 = methodArgs.extractValue(luaState, num4 + 1 + num2);
if (_LastCalledMethod.argTypes[num4].isParamsArray)
{
args[methodArgs.index] = _Translator.tableToArray(obj2, methodArgs.paramsArrayType);
}
else
{
args[methodArgs.index] = obj2;
}
if (args[methodArgs.index] == null && !LuaDLL.lua_isnil(luaState, num4 + 1 + num2))
{
flag = true;
break;
}
num4++;
continue;
}
if ((_BindingType & BindingFlags.Static) == BindingFlags.Static)
{
_Translator.push(luaState, cachedMethod.Invoke(null, args));
}
else if (_LastCalledMethod.cachedMethod.IsConstructor)
{
_Translator.push(luaState, ((ConstructorInfo)cachedMethod).Invoke(args));
}
else
{
_Translator.push(luaState, cachedMethod.Invoke(obj, args));
}
flag = false;
break;
}
}
catch (TargetInvocationException ex)
{
return SetPendingException(ex.GetBaseException());
}
catch (Exception pendingException)
{
if (_Members.Length == 1)
{
return SetPendingException(pendingException);
}
}
}
}
if (flag)
{
if (!flag2)
{
if (obj == null)
{
_Translator.throwError(luaState, string.Format("instance method '{0}' requires a non null target object", _MethodName));
LuaDLL.lua_pushnil(luaState);
return 1;
}
LuaDLL.lua_remove(luaState, 1);
}
bool flag3 = false;
string text = null;
MemberInfo[] members = _Members;
foreach (MemberInfo memberInfo in members)
{
text = memberInfo.ReflectedType.Name + "." + memberInfo.Name;
MethodBase method2 = (MethodInfo)memberInfo;
if (_Translator.matchParameters(luaState, method2, ref _LastCalledMethod))
{
flag3 = true;
break;
}
}
if (!flag3)
{
string e = ((text != null) ? ("invalid arguments to method: " + text) : "invalid arguments to method call");
_Translator.throwError(luaState, e);
LuaDLL.lua_pushnil(luaState);
return 1;
}
}
}
else if (method.ContainsGenericParameters)
{
_Translator.matchParameters(luaState, method, ref _LastCalledMethod);
if (method.IsGenericMethodDefinition)
{
List<Type> list = new List<Type>();
object[] args2 = _LastCalledMethod.args;
foreach (object obj3 in args2)
{
list.Add(obj3.GetType());
}
MethodInfo methodInfo = (method as MethodInfo).MakeGenericMethod(list.ToArray());
_Translator.push(luaState, methodInfo.Invoke(obj, _LastCalledMethod.args));
flag = false;
}
else if (method.ContainsGenericParameters)
{
_Translator.throwError(luaState, "unable to invoke method on generic class as the current method is an open generic method");
LuaDLL.lua_pushnil(luaState);
return 1;
}
}
else
{
if (!method.IsStatic && !method.IsConstructor && obj == null)
{
obj = _ExtractTarget(luaState, 1);
LuaDLL.lua_remove(luaState, 1);
}
if (!_Translator.matchParameters(luaState, method, ref _LastCalledMethod))
{
_Translator.throwError(luaState, "invalid arguments to method call");
LuaDLL.lua_pushnil(luaState);
return 1;
}
}
if (flag)
{
if (!LuaDLL.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6))
{
throw new LuaException("Lua stack overflow");
}
try
{
if (flag2)
{
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
}
else if (_LastCalledMethod.cachedMethod.IsConstructor)
{
_Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
}
else
{
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(obj, _LastCalledMethod.args));
}
}
catch (TargetInvocationException ex2)
{
return SetPendingException(ex2.GetBaseException());
}
catch (Exception pendingException2)
{
return SetPendingException(pendingException2);
}
}
for (int k = 0; k < _LastCalledMethod.outList.Length; k++)
{
num++;
_Translator.push(luaState, _LastCalledMethod.args[_LastCalledMethod.outList[k]]);
}
if (!_LastCalledMethod.IsReturnVoid && num > 0)
{
num++;
}
return (num < 1) ? 1 : num;
}
}
}