Пример #1
0
        public void Add(int details_table, int fn)
        {
            var lua = ModTheGungeon.ModLoader.LuaState;

            lua.EnterArea();

            Type   criteria_type       = null;
            string criteria_methodname = null;

            Type[] criteria_argtypes = null;
            bool   criteria_instance = true;
            bool   criteria_public   = true;
            bool   hook_returns      = false;

            lua.PushLuaReference(details_table);

            lua.GetField("type");
            if (lua.Type() == LuaType.Nil)
            {
                lua.LeaveAreaCleanup();
                throw new LuaException($"type: Expected Type, got null");
            }
            else if (!lua.IsCLRObject())
            {
                lua.LeaveAreaCleanup();
                throw new LuaException($"type: Expected CLR Type object, got non-MicroLua userdata");
            }
            var obj = lua.ToCLR();

            if (!(obj is Type))
            {
                lua.Pop();
                throw new LuaException($"type: Expected CLR Type object, got CLR object of type {obj.GetType()}");
            }
            criteria_type = obj as Type;
            lua.Pop();

            string method = null;

            lua.GetField("method");
            if (lua.Type() == LuaType.String)
            {
                criteria_methodname = lua.ToString();
            }
            lua.Pop();

            lua.GetField("instance");
            if (lua.Type() == LuaType.Boolean)
            {
                criteria_instance = lua.ToBool();
            }
            lua.Pop();

            lua.GetField("public");
            if (lua.Type() == LuaType.Boolean)
            {
                criteria_public = lua.ToBool();
            }
            lua.Pop();

            lua.GetField("returns");
            if (lua.Type() == LuaType.Boolean)
            {
                hook_returns = lua.ToBool();
            }
            lua.Pop();

            lua.GetField("args");
            if (lua.Type() == LuaType.Table)
            {
                var count = 0;
                while (true)
                {
                    lua.PushInt(count + 1);
                    lua.GetField();
                    if (lua.Type() == LuaType.Nil)
                    {
                        lua.Pop();
                        break;
                    }
                    if (!lua.IsCLRObject())
                    {
                        lua.LeaveAreaCleanup();
                        throw new LuaException($"args: Expected entry at index {count + 1} to be a CLR Type object, got non-CLR userdata");
                    }
                    var argobj = lua.ToCLR();
                    if (!(argobj is Type))
                    {
                        lua.LeaveAreaCleanup();
                        throw new LuaException($"args: Expected entry at index {count + 1} to be a CLR Type object, got CLR object of type {argobj.GetType()}");
                    }
                    lua.Pop();
                    count += 1;
                }

                var argtypes = new Type[count];

                for (int i = 1; i <= count; i++)
                {
                    lua.PushInt(i);
                    lua.GetField();
                    argtypes[i - 1] = lua.ToCLR <Type>();
                    lua.Pop();
                }

                criteria_argtypes = argtypes;
            }
            lua.Pop();

            lua.Pop();

            var method_info = _TryFindMethod(
                criteria_type,
                criteria_methodname,
                criteria_argtypes,
                criteria_instance,
                criteria_public
                );

            if (method_info == null)
            {
                throw new LuaException($"Method '{criteria_methodname}' in '{criteria_type.FullName}' not found.");
            }
            _CheckForbidden(method_info);

            RuntimeHooks.InstallDispatchHandler(method_info);

            var token = RuntimeHooks.MethodToken(method_info);

            Hooks[token] = fn;

            if (hook_returns)
            {
                HookReturns[token] = method_info.ReturnType;
            }

            _Logger.Debug($"Added Lua hook for method '{criteria_methodname}' ({token})");

            lua.LeaveArea();
        }
Пример #2
0
        public void Add(LuaTable details, LuaFunction fn)
        {
            Type   criteria_type;
            string criteria_methodname;

            Type[] criteria_argtypes = null;
            bool   criteria_instance;
            bool   criteria_public;
            bool   hook_returns;

            using (var ftype = details["type"]) {
                if (ftype == null)
                {
                    throw new LuaException($"type: Expected Type, got null");
                }
                if (!(ftype is IClrObject))
                {
                    throw new LuaException($"type: Expected CLR Type object, got non-CLR object of type {ftype.GetType()}");
                }
                else if (!(((IClrObject)ftype).ClrObject is Type))
                {
                    throw new LuaException($"type: Expected CLR Type object, got CLR object of type {((IClrObject)ftype).ClrObject.GetType()}");
                }

                criteria_type = ((IClrObject)ftype).ClrObject as Type;
                using (var method = details["method"] as LuaString)
                    using (var instance = details["instance"] as LuaBoolean)
                        using (var @public = details["public"] as LuaBoolean)
                            using (var returns = details["returns"] as LuaBoolean)
                                using (var args = details["args"] as LuaTable) {
                                    if (method == null)
                                    {
                                        throw new LuaException("method: Expected string, got null");
                                    }

                                    if (args != null)
                                    {
                                        var count = 0;
                                        while (true)
                                        {
                                            using (var value = args[count + 1]) {
                                                if (value is LuaNil)
                                                {
                                                    break;
                                                }
                                                if (!(value is IClrObject))
                                                {
                                                    throw new LuaException($"args: Expected entry at index {count} to be a CLR Type object, got non-CLR object of type {value.GetType()}");
                                                }
                                                else if (!(((IClrObject)value).ClrObject is Type))
                                                {
                                                    throw new LuaException($"args: Expected entry at index {count} to be a CLR Type object, got CLR object of type {((IClrObject)value).ClrObject.GetType()}");
                                                }
                                            }
                                            count += 1;
                                        }

                                        var argtypes = new Type[args.Count];

                                        for (int i = 1; i <= count; i++)
                                        {
                                            using (var value = args[i]) {
                                                argtypes[i - 1] = (Type)args[i].CLRMappedObject;
                                            }
                                        }

                                        criteria_argtypes = argtypes;
                                    }

                                    criteria_instance   = instance?.ToBoolean() ?? true;
                                    criteria_public     = @public?.ToBoolean() ?? true;
                                    criteria_methodname = method.ToString();

                                    hook_returns = returns?.ToBoolean() ?? false;
                                }
            }

            var method_info = _TryFindMethod(
                criteria_type,
                criteria_methodname,
                criteria_argtypes,
                criteria_instance,
                criteria_public
                );

            if (method_info == null)
            {
                throw new LuaException($"Method '{criteria_methodname}' in '{criteria_type.FullName}' not found.");
            }
            _CheckForbidden(method_info);

            RuntimeHooks.InstallDispatchHandler(method_info);

            var token = RuntimeHooks.MethodToken(method_info);

            Hooks[token] = fn;
            fn.DisposeAfterManagedCall = false;

            if (hook_returns)
            {
                HookReturns[token] = method_info.ReturnType;
            }

            _Logger.Debug($"Added Lua hook for method '{criteria_methodname}' ({token})");
        }