Exemplo n.º 1
0
        internal GlobalContext(ILua lua)
        {
            this.lua = lua;

            lua.GetField(-10002, "SERVER");
            isServerSide = lua.GetBool(-1);

            module_contexts = new Dictionary <string, Tuple <GmodNetModuleAssemblyLoadContext, List <GCHandle> > >();

            int managed_func_type_id = lua.CreateMetaTable("ManagedFunction");

            unsafe
            {
                lua.PushCFunction(&ManagedFunctionMetaMethods.ManagedDelegateGC);
            }
            lua.SetField(-2, "__gc");
            lua.Pop(1);

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.PushNumber(managed_func_type_id);
            lua.SetField(-2, ManagedFunctionMetaMethods.ManagedFunctionIdField);
            lua.Pop(1);

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.CreateTable();

            lua.PushManagedFunction(LoadModule);
            lua.SetField(-2, "load");

            lua.PushManagedFunction(UnloadModule);
            lua.SetField(-2, "unload");

            lua.SetField(-2, "dotnet");
            lua.Pop(1);
        }
Exemplo n.º 2
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>();

            try
            {
                Random rand = new Random();

                int random_number = rand.Next(1, 500);

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "tonumber");
                lua.PushString(random_number.ToString());
                try
                {
                    lua.MCall(1, 1);
                }
                catch (GmodLuaException)
                {
                    throw new MCallTestException("Exception was thrown by MCall, but it is not expected.");
                }
                int received_number = (int)lua.GetNumber(-1);
                if (received_number != random_number)
                {
                    throw new MCallTestException("Numbers mismatch.");
                }
                lua.Pop(2);

                string random_error_message = Guid.NewGuid().ToString();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "assert");
                lua.PushBool(false);
                lua.PushString(random_error_message);
                try
                {
                    lua.MCall(2, 0);
                }
                catch (GmodLuaException e)
                {
                    if (e.Message != random_error_message)
                    {
                        throw new MCallTestException("Error message is invalid");
                    }

                    taskCompletion.TrySetResult(true);
                }
                catch (Exception)
                {
                    throw new MCallTestException("Wrong exception type was thrown");
                }
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 3
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            try
            {
                Random rand = new Random();

                int random_number = rand.Next(1, 500);

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "tonumber");
                lua.PushString(random_number.ToString());
                if (lua.PCall(1, 1, 0) != 0)
                {
                    throw new PCallTest_NoError_Exception("PCall returned nonzero error code");
                }
                double recieved_num = lua.GetNumber(-1);
                if (recieved_num != (double)random_number)
                {
                    throw new PCallTest_NoError_Exception("Recieved value is invalid");
                }
                lua.Pop(2);

                string random_error_msg = Guid.NewGuid().ToString();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "assert");
                lua.PushBool(false);
                lua.PushString(random_error_msg);
                if (lua.PCall(2, 0, 0) == 0)
                {
                    throw new PCallTest_Exception("assert(false, ...) didn't throw an error");
                }
                string res_err_msg = lua.GetString(-1);
                if (res_err_msg != random_error_msg)
                {
                    throw new PCallTest_Exception("Received error message is invalid");
                }
                lua.Pop(2);

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 4
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            this.lua_extructor = lua_extructor;

            try
            {
                lua.CreateTable();
                lua.CreateTable();
                lua.PushManagedFunction(MetaToStringDelegate);
                lua.SetField(-2, "__tostring");
                lua.SetMetaTable(-2);

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "tostring");
                lua.Push(-3);
                lua.MCall(1, 1);

                string get_val = lua.GetString(-1);

                lua.Pop(2);

                if (get_val != to_str_msg)
                {
                    throw new CreateMetaTableException("Recieved string is incorrect");
                }

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 5
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext assembly_context)
        {
            TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>();

            try
            {
                string random_key1 = Guid.NewGuid().ToString();
                string random_key2 = Guid.NewGuid().ToString();
                string random_key3 = Guid.NewGuid().ToString();

                string random1 = Guid.NewGuid().ToString();
                string random2 = Guid.NewGuid().ToString();
                string random3 = Guid.NewGuid().ToString();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.PushString(random1);
                lua.SetField(-2, random_key1);

                lua.PushString(random2);
                lua.SetField(-2, random_key2);

                lua.PushString(random3);
                lua.SetField(-2, random_key3);

                lua.Pop(lua.Top());

                lua.PushGlobalTable();

                lua.GetField(-1, random_key1);
                if (lua.GetString(-1) != random1)
                {
                    throw new Exception("First random string is invalid");
                }
                lua.Pop(1);

                lua.GetField(-1, random_key2);
                if (lua.GetString(-1) != random2)
                {
                    throw new Exception("Second random string is invalid");
                }
                lua.Pop(1);

                lua.GetField(-1, random_key3);
                if (lua.GetString(-1) != random3)
                {
                    throw new Exception("Third random string is invalid");
                }
                lua.Pop(1);

                lua.Pop(1);

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 6
0
 public static void PushGlobalFunction(ILua lua, string key, Func <ILua, int> value)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "CNode");
     lua.PushManagedFunction(value);
     lua.SetField(-2, key);
     lua.Pop();
 }
Exemplo n.º 7
0
 internal static void PrintToConsole(this ILua lua, string message)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "print");
     lua.PushString(message);
     lua.MCall(1, 0);
     lua.Pop(1);
 }
Exemplo n.º 8
0
 public void Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "print");
     lua.PushString("Hello World!");
     lua.MCall(1, 0);
     lua.Pop();
 }
Exemplo n.º 9
0
 public void Unload(ILua lua)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "print");
     lua.PushString("Goodbye World!");
     lua.MCall(1, 0);
     lua.Pop();
 }
Exemplo n.º 10
0
 public static void PushGlobalVector(ILua lua, string key, Vector3 value)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "CNode");
     lua.PushVector(value);
     lua.SetField(-2, key);
     lua.Pop();
 }
Exemplo n.º 11
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>();

            try
            {
                string table_name = Guid.NewGuid().ToString();
                string field_name = Guid.NewGuid().ToString();

                Random rand     = new Random();
                double rand_num = rand.NextDouble();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.CreateTable();
                lua.PushNumber(rand_num);
                lua.SetField(-2, field_name);
                lua.SetField(-2, table_name);

                lua.Pop(1);

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, table_name);
                if (lua.GetType(-1) != (int)TYPES.TABLE)
                {
                    throw new CreateTableException("Type check failed");
                }
                lua.GetField(-1, field_name);
                double get_num = lua.GetNumber(-1);
                if (get_num != rand_num)
                {
                    throw new CreateTableException("Wrong number recieved");
                }

                lua.Pop(3);

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 12
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            task_completion = new TaskCompletionSource <bool>();

            Random rand = new Random();

            int[] random_numbers = new int[1000];
            for (int i = 0; i < 1000; i++)
            {
                random_numbers[i] = rand.Next(2);
            }

            bool[] random_bools = new bool[1000];
            for (int i = 0; i < 1000; i++)
            {
                if (random_numbers[i] == 0)
                {
                    random_bools[i] = false;
                }
                else
                {
                    random_bools[i] = true;
                }
            }


            try
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                for (int i = 0; i < 1000; i++)
                {
                    lua.PushBool(random_bools[i]);
                    lua.SetField(-2, this.uuid + "Bool" + i.ToString());
                }
                for (int i = 0; i < 1000; i++)
                {
                    lua.GetField(-1, this.uuid + "Bool" + i.ToString());
                    bool tmp = lua.GetBool(-1);
                    lua.Pop(1);

                    if (tmp != random_bools[i])
                    {
                        throw new PushBoolException(i, random_bools[i], tmp);
                    }
                }
                lua.Pop(1);

                task_completion.TrySetResult(true);
            }
            catch (Exception e)
            {
                task_completion.TrySetException(new Exception[] { e });
            }

            return(task_completion.Task);
        }
Exemplo n.º 13
0
 public void Unload(ILua lua)
 {
     lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
     lua.GetField(-1, "hook");
     lua.GetField(-1, "Remove");
     lua.PushString("Tick");
     lua.PushString(this.OnTickIdentifier);
     lua.MCall(2, 0);
     lua.Pop(2);
 }
Exemplo n.º 14
0
        int UnloadModule(ILua lua)
        {
            try
            {
                string module_name = lua.GetString(1);

                if (String.IsNullOrEmpty(module_name))
                {
                    throw new Exception("Module name is empty or null");
                }

                if (!module_contexts.ContainsKey(module_name))
                {
                    throw new Exception($"There is no loaded module with name { module_name }");
                }

                lua.PrintToConsole($"Unloading module { module_name } ...");

                WeakReference <GmodNetModuleAssemblyLoadContext> context_weak_reference = UnloadHelper(module_name);

                for (int i = 0; context_weak_reference.TryGetTarget(out _); i++)
                {
                    lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                    lua.GetField(-1, "collectgarbage");
                    lua.MCall(0, 0);
                    lua.Pop(1);

                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    if (i >= 300)
                    {
                        throw new Exception($"Module {module_name} can't be unloaded: there are remaining references or background threads still executing. " +
                                            $"Module resources can't be freed. Memory leak could occur. Game restart may be required.");
                    }
                }

                lua.PrintToConsole($"Module {module_name} was unloaded.");

                lua.PushBool(true);

                return(1);
            }
            catch (Exception e)
            {
                lua.PrintToConsole("Unable to unload module: exception was thrown");
                lua.PrintToConsole(e.ToString());

                lua.PushBool(false);

                return(1);
            }
        }
Exemplo n.º 15
0
        public void Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
        {
            this.lua                  = lua;
            this.isServerSide         = is_serverside;
            this.current_load_context = assembly_context;
            this.OnTickDelegate       = this.OnTick;
            this.OnTickIdentifier     = Guid.NewGuid().ToString();
            current_test              = null;

            if (isServerSide)
            {
                try
                {
                    lua.Log("Loading test runner");

                    //Register OnTick with Garry's Mod
                    lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                    lua.GetField(-1, "hook");
                    lua.GetField(-1, "Add");
                    lua.PushString("Tick");
                    lua.PushString(this.OnTickIdentifier);
                    lua.PushManagedFunction(this.OnTickDelegate);
                    lua.MCall(3, 0);
                    lua.Pop(2);

                    //Get the list of tests
                    ListOfTests = new List <ITest>();
                    if (typeof(Tests).Assembly.GetTypes().Any(type => typeof(ITest).IsAssignableFrom(type) && type != typeof(ITest)))
                    {
                        foreach (Type t in typeof(Tests).Assembly.GetTypes().Where(type => type != typeof(ITest) && typeof(ITest).IsAssignableFrom(type)))
                        {
                            ListOfTests.Add((ITest)Activator.CreateInstance(t));
                        }
                    }

                    lua.Log("There are " + ListOfTests.Count + " tests to run:");
                    foreach (ITest test in ListOfTests)
                    {
                        lua.Log(test.GetType().ToString());
                    }

                    IsEverythingSuccessful = true;
                    tests_start_time       = DateTime.Now;
                    lua.Log("Test runner was loaded!");
                }
                catch (Exception e)
                {
                    lua.Log("Test runner FAILED to start: " + e.GetType().ToString() + ". Exception message: " + e.Message);
                }
            }
        }
Exemplo n.º 16
0
        public void Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
        {
            // Creating global table
            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.CreateTable();
            lua.SetField(-2, "CNode");
            lua.Pop();

            if (is_serverside)
            {
                PathManager.Load(lua);
                GridManager.Load(lua);
            }
        }
Exemplo n.º 17
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext assembly_context)
        {
            try
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "hook");
                lua.GetField(-1, "Add");
                lua.PushString("Tick");
                lua.PushString(hook_id);
                lua.PushManagedFunction(l =>
                {
                    try
                    {
                        if (counter < 33)
                        {
                            counter++;
                        }
                        else
                        {
                            l.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                            l.GetField(-1, "hook");
                            l.GetField(-1, "Remove");
                            l.PushString("Tick");
                            l.PushString(hook_id);
                            l.MCall(2, 0);
                            l.Pop(2);

                            if (counter == 33)
                            {
                                taskCompletion.TrySetResult(true);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        taskCompletion.TrySetException(new Exception[] { e });
                    }

                    return(0);
                });
                lua.MCall(3, 0);
                lua.Pop(2);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 18
0
        int SpawnFunc(ILua lua)
        {
            try
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "ents");
                lua.GetField(-1, "Create");
                lua.PushString("prop_physics");
                lua.MCall(1, 1);

                if (lua.GetType(-1) != (int)TYPES.ENTITY)
                {
                    throw new SpawnEntityException("ents.Create returned a value which type is not Entity");
                }

                lua.GetField(-1, "SetModel");
                lua.Push(-2);
                lua.PushString("models/props_c17/oildrum001.mdl");
                lua.MCall(2, 0);

                lua.GetField(-1, "SetPos");
                lua.Push(-2);
                lua.PushVector(new System.Numerics.Vector3(0));
                lua.MCall(2, 0);

                lua.GetField(-1, "Spawn");
                lua.Push(-2);
                lua.MCall(1, 0);

                lua.GetField(-1, "IsValid");
                lua.Push(-2);
                lua.MCall(1, 1);
                if (!lua.GetBool(-1))
                {
                    throw new SpawnEntityException("Entity is not valid");
                }

                lua.Pop(lua.Top());

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(0);
        }
        internal static int ManagedDelegateGC(IntPtr lua_state)
        {
            ILua lua = GmodInterop.GetLuaFromState(lua_state);

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.GetField(-1, ManagedFunctionIdField);
            int managed_delegate_type_id = (int)lua.GetNumber(-1);

            lua.Pop(2);

            IntPtr managed_delegate_handle = lua.GetUserType(1, managed_delegate_type_id);

            GCHandle.FromIntPtr(managed_delegate_handle).Free();

            return(0);
        }
Exemplo n.º 20
0
        internal void OnNativeUnload(ILua lua)
        {
            try
            {
                List <string> module_names = new List <string>();

                foreach (var p in module_contexts)
                {
                    module_names.Add(p.Key);
                }

                foreach (string name in module_names)
                {
                    try
                    {
                        WeakReference <GmodNetModuleAssemblyLoadContext> weak_reference = UnloadHelper(name);

                        for (int i = 0; weak_reference.TryGetTarget(out _); i++)
                        {
                            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                            lua.GetField(-1, "collectgarbage");
                            lua.MCall(0, 0);
                            lua.Pop(1);

                            GC.Collect();
                            GC.WaitForPendingFinalizers();

                            if (i >= 300)
                            {
                                throw new Exception($"Module {name} can't be unloaded: there are remaining references or background threads still executing. " +
                                                    $"Module resources can't be freed. Memory leak could occur. Game restart may be required.");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        lua.PrintToConsole($"Exception was thrown while unloading .NET module {name}");
                        lua.PrintToConsole(e.ToString());
                    }
                }
            }
            catch (Exception e)
            {
                lua.PrintToConsole("Critiacal error occured on .NET modules unload");
                lua.PrintToConsole(e.ToString());
            }
        }
Exemplo n.º 21
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            taskSource = new TaskCompletionSource <bool>();

            try
            {
                string LuaNumId = Guid.NewGuid().ToString();

                double[] Random_numbers = new double[10];

                Random rand = new Random();

                for (int i = 0; i < 10; i++)
                {
                    Random_numbers[i] = rand.NextDouble();
                }

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);

                for (int i = 0; i < 10; i++)
                {
                    lua.PushNumber(Random_numbers[i]);
                    lua.SetField(-2, LuaNumId + "Num" + i.ToString());
                }

                for (int i = 0; i < 10; i++)
                {
                    lua.GetField(-1, LuaNumId + "Num" + i.ToString());
                    double tmp = lua.GetNumber(-1);
                    lua.Pop(1);

                    if (tmp != Random_numbers[i])
                    {
                        throw new PushNumberException(i, Random_numbers[i], tmp);
                    }
                }

                taskSource.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskSource.TrySetException(new Exception[] { e });
            }

            return(taskSource.Task);
        }
Exemplo n.º 22
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            taskCompletion = new TaskCompletionSource <bool>();

            string[] TestStrings = new string[5];
            for (int i = 0; i < 5; i++)
            {
                TestStrings[i] = Guid.NewGuid().ToString();
            }

            try
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);

                for (int i = 0; i < 5; i++)
                {
                    lua.PushString(TestStrings[i]);
                    lua.SetField(-2, FieldName + "Str" + i.ToString());
                }

                for (int i = 0; i < 5; i++)
                {
                    lua.GetField(-1, FieldName + "Str" + i.ToString());
                    string tmp = lua.GetString(-1);
                    lua.Pop(1);

                    if (tmp != TestStrings[i])
                    {
                        throw new PushStringException(i, TestStrings[i], tmp);
                    }
                }

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 23
0
        public void Unload(ILua lua)
        {
            // clean our meta-methods
            lua.PushMetaTable(UserType_Id);
            // remove __index method
            lua.PushNil();
            lua.SetField(-2, "__index");
            // remove __eq method
            lua.PushNil();
            lua.SetField(-2, "__eq");
            // remove __gc method
            lua.PushNil();
            lua.SetField(-2, "__gc");
            // remove __tostring method
            lua.PushNil();
            lua.SetField(-2, "__tostring");
            lua.Pop();

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.PushNil();
            lua.SetField(-2, "CreateCSString");
            lua.Pop();
        }
Exemplo n.º 24
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>();

            try
            {
                Random rand = new Random();

                string field_id = Guid.NewGuid().ToString();

                float x = (float)rand.NextDouble() + rand.Next(-100, 101);
                float y = (float)rand.NextDouble() + rand.Next(-100, 101);
                float z = (float)rand.NextDouble() + rand.Next(-100, 101);

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);

                lua.PushVector(new Vector3(x, y, z));
                lua.SetField(-2, field_id);

                lua.GetField(-1, field_id);
                Vector3 recieved_vec = lua.GetVector(-1);
                lua.Pop(2);

                if (recieved_vec != new Vector3(x, y, z))
                {
                    throw new PushVectorException(recieved_vec, new Vector3(x, y, z));
                }

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
        internal static int ManagedDelegateExecutor(IntPtr lua_state)
        {
            ILua lua = GmodInterop.GetLuaFromState(lua_state);

            try
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, ManagedFunctionIdField);
                int managed_delegate_type_id = (int)lua.GetNumber(-1);
                lua.Pop(2);

                IntPtr managed_delegate_handle = lua.GetUserType(GmodInterop.GetUpvalueIndex(1, false), managed_delegate_type_id);

                Func <ILua, int> managed_delegate = (Func <ILua, int>)GCHandle.FromIntPtr(managed_delegate_handle).Target;

                return(Math.Max(0, managed_delegate(lua)));
            }
            catch (Exception e)
            {
                lua.Pop(lua.Top());
                lua.PushString(".NET Exception: " + e.ToString());
                return(-1);
            }
        }
Exemplo n.º 26
0
        void IModule.Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
        {
            if (is_serverside)
            {
                throw new Exception("Must be loaded from client");
            }

            string platformIdentifier = OperatingSystem.IsWindows() ? "win-x64" : "linux-x64";

            assembly_context.SetCustomNativeLibraryResolver((ctx, str) =>
            {
                if (str.Contains("sourcesdkc"))
                {
                    if (sourcesdkc == IntPtr.Zero)
                    {
                        Console.WriteLine("loading sourcesdkc");
                        sourcesdkc = NativeLibrary.Load($"./garrysmod/lua/bin/Modules/GetRenderTargetExample/runtimes/{platformIdentifier}/native/sourcesdkc");
                        Console.WriteLine($"loaded sourcesdkc: {sourcesdkc != IntPtr.Zero}");
                    }
                    return(sourcesdkc);
                }
                return(IntPtr.Zero);
            });

            if (interfaceh.Sys_LoadInterface("vguimatsurface", ISurface.VGUI_SURFACE_INTERFACE_VERSION, out _, out IntPtr isurfacePtr))
            {
                surface = new(isurfacePtr);
            }
            else
            {
                throw new Exception("failed loading vguimatsurface");
            }

            if (interfaceh.Sys_LoadInterface("materialsystem", IMaterialSystem.MATERIAL_SYSTEM_INTERFACE_VERSION, out _, out IntPtr materialSystemPtr))
            {
                materialSystem = new(materialSystemPtr);
            }
            else
            {
                Console.WriteLine("failed loading materialsystem");
            }

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.GetField(-1, "GetRenderTarget");
            lua.PushString("ExampleRTwithAlpha");
            lua.PushNumber(512);
            lua.PushNumber(512);
            lua.MCall(3, 1);
            rt = lua.GetUserType(-1, (int)TYPES.TEXTURE);
            lua.Pop();

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.GetField(-1, "CreateMaterial");
            lua.PushString("ExampleRTwithAlpha_Mat");
            lua.PushString("UnlitGeneric");
            lua.CreateTable();
            {
                lua.PushString("$basetexture");
                lua.PushString("ExampleRTwithAlpha");
                lua.SetTable(-3);

                lua.PushString("$translucent");
                lua.PushString("1");
                lua.SetTable(-3);
            }
            lua.MCall(3, 1);
            mat = lua.GetUserType(-1, (int)TYPES.MATERIAL);
            lua.Pop();

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.GetField(-1, "hook");
            lua.GetField(-1, "Add");
            lua.PushString("HUDPaint");
            lua.PushString("ExampleRTwithAlpha_Render");
            lua.PushManagedFunction(Render);
            lua.MCall(3, 0);
            lua.Pop();
        }
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>();

            try
            {
                this.lua_extructor = lua_extructor;

                this.NewTypeId = lua.CreateMetaTable("TestType1");

                lua.PushManagedFunction(this.ToStringImpl);

                lua.SetField(-2, "__tostring");

                lua.Pop(1);


                //Create new table to test newly created metatable

                lua.CreateTable();

                lua.PushMetaTable(this.NewTypeId);

                lua.SetMetaTable(-2);

                /*
                 * if(!lua.IsType(-1, this.NewTypeId))
                 * {
                 *  throw new Exception("Received type id is invalid");
                 * }
                 *
                 * string received_type_name = lua.GetTypeName(lua.GetType(-1));
                 *
                 * if(received_type_name != "TestType1")
                 * {
                 *  throw new Exception("Received type name is invalid");
                 * }
                 */

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);

                lua.GetField(-1, "tostring");

                lua.Push(-3);

                lua.MCall(1, 1);

                if (lua.GetString(-1) != this.RandomString)
                {
                    throw new Exception("Metatable method __tostring returned incorrect string");
                }

                lua.Pop(3);

                lua.PushMetaTable(NewTypeId);

                lua.PushNil();

                lua.SetField(-2, "__tostring");

                lua.Pop(1);

                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 28
0
        public void Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
        {
            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.GetField(-1, "print");
            lua.PushString("Hello World RPC");
            lua.MCall(1, 0);
            lua.Pop();

            int DiscordRPC_update_callbacks(ILua lua)
            {
                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "print");
                lua.PushString("It Works!");
                lua.MCall(1, 0);
                lua.Pop();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "game");
                lua.GetField(-1, "GetMap");
                lua.MCall(0, 1);
                map = lua.GetString(-1);
                lua.Pop();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "game");
                lua.GetField(-1, "SinglePlayer");
                lua.MCall(0, 1);
                bool IsSinglePlayer = lua.GetBool(-1);

                lua.Pop();

                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                lua.GetField(-1, "engine");
                lua.GetField(-1, "ActiveGamemode");
                lua.MCall(0, 1);
                gamemode = lua.GetString(-1);
                lua.Pop();

                if (IsSinglePlayer)
                {
                    activityDetails = "SinglePlayer";
                }
                else
                {
                    lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                    lua.GetField(-1, "player");
                    lua.GetField(-1, "GetCount");
                    lua.MCall(0, 1);
                    int players = (int)lua.GetNumber(-1);
                    lua.Pop();

                    lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                    lua.GetField(-1, "game");
                    lua.GetField(-1, "MaxPlayers");
                    lua.MCall(0, 1);
                    int maxPlayers = (int)lua.GetNumber(-1);
                    lua.Pop();

                    activityDetails = $"{players}/{maxPlayers}";
                }

                /*if (!is_serverside)
                 * {
                 *  lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                 *  lua.GetField(-1, "LocalPlayer"); //team.GetScore(ply:Team())
                 *  lua.MCall(0, 1);
                 *
                 *  lua.GetField(-1, "Team");
                 *  lua.Push(-2);
                 *  lua.MCall(0, 1);
                 *  double team = lua.GetNumber(-1);
                 *  lua.Pop();
                 *
                 *  lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                 *  lua.GetField(-1, "teams");
                 *  lua.GetField(-1, "GetScore");
                 *  lua.PushNumber(team);
                 *  lua.MCall(1, 1);
                 *  score = (int)lua.GetNumber(-1);
                 *  lua.Pop();
                 * }*/


                UpdateActivity();
                return(0);
            };

            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.PushManagedFunction(DiscordRPC_update_callbacks);
            lua.SetField(-2, "DiscordRPC_update_activity");
            lua.Pop(1);


            discord = new Discord.Discord(client_ID, (UInt64)Discord.CreateFlags.Default);
            discord.SetLogHook(Discord.LogLevel.Debug, (level, message) =>
            {
                Console.WriteLine("Log[{0}] {1}", level, message);
            });

            var applicationManager = discord.GetApplicationManager();

            // Get the current locale. This can be used to determine what text or audio the user wants.
            Console.WriteLine("Current Locale: {0}", applicationManager.GetCurrentLocale());
            // Get the current branch. For example alpha or beta.
            Console.WriteLine("Current Branch: {0}", applicationManager.GetCurrentBranch());
            // If you want to verify information from your game's server then you can
            // grab the access token and send it to your server.
            //
            // This automatically looks for an environment variable passed by the Discord client,
            // if it does not exist the Discord client will focus itself for manual authorization.
            //
            // By-default the SDK grants the identify and rpc scopes.
            // Read more at https://discordapp.com/developers/docs/topics/oauth2
            // applicationManager.GetOAuth2Token((Discord.Result result, ref Discord.OAuth2Token oauth2Token) =>
            // {
            //     Console.WriteLine("Access Token {0}", oauth2Token.AccessToken);
            // });

            var activityManager = discord.GetActivityManager();
            var lobbyManager    = discord.GetLobbyManager();

            // Received when someone accepts a request to join or invite.
            // Use secrets to receive back the information needed to add the user to the group/party/match
            activityManager.OnActivityJoin += secret =>
            {
                Console.WriteLine("OnJoin {0}", secret);
                lobbyManager.ConnectLobbyWithActivitySecret(secret, (Discord.Result result, ref Discord.Lobby lobby) =>
                {
                    Console.WriteLine("Connected to lobby: {0}", lobby.Id);
                    lobbyManager.ConnectNetwork(lobby.Id);
                    lobbyManager.OpenNetworkChannel(lobby.Id, 0, true);
                    foreach (var user in lobbyManager.GetMemberUsers(lobby.Id))
                    {
                        lobbyManager.SendNetworkMessage(lobby.Id, user.Id, 0,
                                                        Encoding.UTF8.GetBytes(String.Format("Hello, {0}!", user.Username)));
                    }
                    UpdateActivity();
                });
            };
            // Received when someone accepts a request to spectate
            activityManager.OnActivitySpectate += secret =>
            {
                Console.WriteLine("OnSpectate {0}", secret);
            };
            // A join request has been received. Render the request on the UI.
            activityManager.OnActivityJoinRequest += (ref Discord.User user) =>
            {
                Console.WriteLine("OnJoinRequest {0} {1}", user.Id, user.Username);
            };
            // An invite has been received. Consider rendering the user / activity on the UI.
            activityManager.OnActivityInvite += (Discord.ActivityActionType Type, ref Discord.User user, ref Discord.Activity activity2) =>
            {
                Console.WriteLine("OnInvite {0} {1} {2}", Type, user.Username, activity2.Name);
                // activityManager.AcceptInvite(user.Id, result =>
                // {
                //     Console.WriteLine("AcceptInvite {0}", result);
                // });
            };
            // This is used to register the game in the registry such that Discord can find it.
            // This is only needed by games acquired from other platforms, like Steam.
            // activityManager.RegisterCommand();

            var imageManager = discord.GetImageManager();

            var userManager = discord.GetUserManager();


            lobbyManager.OnLobbyMessage += (lobbyID, userID, data) =>
            {
                Console.WriteLine("lobby message: {0} {1}", lobbyID, Encoding.UTF8.GetString(data));
            };
            lobbyManager.OnNetworkMessage += (lobbyId, userId, channelId, data) =>
            {
                Console.WriteLine("network message: {0} {1} {2} {3}", lobbyId, userId, channelId, Encoding.UTF8.GetString(data));
            };
            lobbyManager.OnSpeaking += (lobbyID, userID, speaking) =>
            {
                Console.WriteLine("lobby speaking: {0} {1} {2}", lobbyID, userID, speaking);
            };

            UpdateActivity();


            /*
             * var overlayManager = discord.GetOverlayManager();
             * overlayManager.OnOverlayLocked += locked =>
             * {
             *  Console.WriteLine("Overlay Locked: {0}", locked);
             * };
             * overlayManager.SetLocked(false);
             */

            var storageManager = discord.GetStorageManager();
            var contents       = new byte[20000];
            var random         = new Random();

            random.NextBytes(contents);
            Console.WriteLine("storage path: {0}", storageManager.GetPath());
            storageManager.WriteAsync("foo", contents, res =>
            {
                var files = storageManager.Files();
                foreach (var file in files)
                {
                    Console.WriteLine("file: {0} size: {1} last_modified: {2}", file.Filename, file.Size, file.LastModified);
                }
                storageManager.ReadAsyncPartial("foo", 400, 50, (result, data) =>
                {
                    Console.WriteLine("partial contents of foo match {0}", Enumerable.SequenceEqual(data, new ArraySegment <byte>(contents, 400, 50)));
                });
                storageManager.ReadAsync("foo", (result, data) =>
                {
                    Console.WriteLine("length of contents {0} data {1}", contents.Length, data.Length);
                    Console.WriteLine("contents of foo match {0}", Enumerable.SequenceEqual(data, contents));
                    Console.WriteLine("foo exists? {0}", storageManager.Exists("foo"));
                    storageManager.Delete("foo");
                    Console.WriteLine("post-delete foo exists? {0}", storageManager.Exists("foo"));
                });
            });

            var storeManager = discord.GetStoreManager();

            storeManager.OnEntitlementCreate += (ref Discord.Entitlement entitlement) =>
            {
                Console.WriteLine("Entitlement Create1: {0}", entitlement.Id);
            };

            // Start a purchase flow.
            // storeManager.StartPurchase(487507201519255552, result =>
            // {
            //     if (result == Discord.Result.Ok)
            //     {
            //         Console.WriteLine("Purchase Complete");
            //     }
            //     else
            //     {
            //         Console.WriteLine("Purchase Canceled");
            //     }
            // });

            // Get all entitlements.
            storeManager.FetchEntitlements(result =>
            {
                if (result == Discord.Result.Ok)
                {
                    foreach (var entitlement in storeManager.GetEntitlements())
                    {
                        Console.WriteLine("entitlement: {0} - {1} {2}", entitlement.Id, entitlement.Type, entitlement.SkuId);
                    }
                }
            });

            // Get all SKUs.
            storeManager.FetchSkus(result =>
            {
                if (result == Discord.Result.Ok)
                {
                    foreach (var sku in storeManager.GetSkus())
                    {
                        Console.WriteLine("sku: {0} - {1} {2}", sku.Name, sku.Price.Amount, sku.Price.Currency);
                    }
                }
            });
            updater = new Thread(UpdaterThread);
            updater.Start();
        }
Exemplo n.º 29
0
        public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _)
        {
            try
            {
                Random rand = new Random();

                int    curr_type;
                string curr_name;

                lua.PushNumber(rand.NextDouble());
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.NUMBER || curr_name != "number")
                {
                    throw new CheckTypeException("number");
                }
                lua.Pop(1);


                lua.PushString(Guid.NewGuid().ToString());
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.STRING || curr_name != "string")
                {
                    throw new CheckTypeException("string");
                }
                lua.Pop(1);


                lua.PushBool(true);
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.BOOL || curr_name != "bool")
                {
                    throw new CheckTypeException("bool");
                }
                lua.Pop(1);


                lua.PushNil();
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.NIL || curr_name != "nil")
                {
                    throw new CheckTypeException("nil");
                }
                lua.Pop(1);


                lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.TABLE || curr_name != "table")
                {
                    throw new CheckTypeException("table");
                }
                lua.Pop(1);


                lua.PushVector(new Vector3((float)rand.NextDouble()));
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.Vector || curr_name != "vector")
                {
                    throw new CheckTypeException("vector");
                }
                lua.Pop(1);


                lua.PushAngle(new Vector3((float)rand.NextDouble()));
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.ANGLE || curr_name != "angle")
                {
                    throw new CheckTypeException("angle");
                }
                lua.Pop(1);


                lua.PushManagedFunction(this.test_func);
                curr_type = lua.GetType(-1);
                curr_name = lua.GetTypeName(curr_type);
                if (curr_type != (int)TYPES.FUNCTION || curr_name != "function")
                {
                    throw new CheckTypeException("function");
                }
                lua.Pop(1);



                taskCompletion.TrySetResult(true);
            }
            catch (Exception e)
            {
                taskCompletion.TrySetException(new Exception[] { e });
            }

            return(taskCompletion.Task);
        }
Exemplo n.º 30
0
        public void Load(ILua lua, bool is_serverside, ModuleAssemblyLoadContext assembly_context)
        {
            // create usertype identifier
            UserType_Id = lua.CreateMetaTable("Example_UserType");
            // set meta-methods
            // see http://www.tutorialspoint.com/lua/lua_metatables.htm for all meta-methods
            // also checkout https://www.lua.org/pil/13.html for explanation about meta-methods/tables

            // __index method
            // __index is called when you trying to index usertype ex:
            // MyCSString.Length
            // MyCSString:ToCharArray()
            // FindMetaTable("Example_UserType").ToCharArray(MyCSString)
            lua.PushManagedFunction((lua) =>
            {
                IntPtr ptr = lua.GetUserType(1, UserType_Id);
                if (ptr != IntPtr.Zero)
                {
                    string indexingname = lua.GetString(2);
                    switch (indexingname)
                    {
                    // pushing simple number
                    case "Length":
                        GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                        string csString   = (string)gCHandle.Target;
                        lua.PushNumber(csString.Length);
                        break;

                    // pushing function
                    case "ToCharArray":
                        lua.PushManagedFunction((lua) =>
                        {
                            IntPtr ptr        = lua.GetUserType(1, UserType_Id);
                            GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                            string csString   = (string)gCHandle.Target;
                            lua.CreateTable();
                            char[] charArray = csString.ToCharArray();
                            for (int i = 0; i < charArray.Length; i++)
                            {
                                lua.PushNumber(i);
                                lua.PushString(charArray[i].ToString());
                                lua.SetTable(-3);
                            }
                            return(1);
                        });
                        break;

                    case "Clone":
                        lua.PushManagedFunction((lua) =>
                        {
                            IntPtr ptr1        = lua.GetUserType(1, UserType_Id);
                            GCHandle gCHandle1 = GCHandle.FromIntPtr(ptr1);
                            string csString1   = (string)gCHandle1.Target;
                            string csString2   = (string)csString1.Clone();
                            GCHandle gCHandle2 = GCHandle.Alloc(csString2, GCHandleType.Weak);
                            IntPtr ptr2        = GCHandle.ToIntPtr(gCHandle2);
                            lua.PushUserType(ptr2, UserType_Id);
                            return(1);
                        });
                        break;

                    case "IndexOf":
                        lua.PushManagedFunction((lua) =>
                        {
                            IntPtr ptr        = lua.GetUserType(1, UserType_Id);
                            GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                            string csString   = (string)gCHandle.Target;

                            string toFind;
                            if (lua.IsType(2, TYPES.STRING))
                            {
                                toFind = lua.GetString(2);
                            }
                            else if (lua.IsType(2, UserType_Id))
                            {
                                IntPtr ptr2        = lua.GetUserType(2, UserType_Id);
                                GCHandle gCHandle2 = GCHandle.FromIntPtr(ptr2);
                                toFind             = (string)gCHandle2.Target;
                            }
                            else
                            {
                                return(0);
                            }

                            int indexOf = csString.IndexOf(toFind);
                            lua.PushNumber(indexOf);
                            return(1);
                        });
                        break;

                    case "Contains":
                        lua.PushManagedFunction((lua) =>
                        {
                            IntPtr ptr        = lua.GetUserType(1, UserType_Id);
                            GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                            string csString   = (string)gCHandle.Target;

                            string toFind;
                            if (lua.IsType(2, TYPES.STRING))
                            {
                                toFind = lua.GetString(2);
                            }
                            else if (lua.IsType(2, UserType_Id))
                            {
                                IntPtr ptr2        = lua.GetUserType(2, UserType_Id);
                                GCHandle gCHandle2 = GCHandle.FromIntPtr(ptr2);
                                toFind             = (string)gCHandle2.Target;
                            }
                            else
                            {
                                return(0);
                            }

                            bool contains = csString.Contains(toFind);
                            lua.PushBool(contains);
                            return(1);
                        });
                        break;

                    default:
                        lua.PushNil();
                        break;
                    }
                }
                else
                {
                    Console.WriteLine("nil passed to __index");
                    lua.PushNil();
                }
                // function will return 1 result
                return(1);
            });
            lua.SetField(-2, "__index");

            lua.PushManagedFunction((lua) =>
            {
                // 1 - stands for 1st passed to function argument
                IntPtr ptr = lua.GetUserType(1, UserType_Id);
                if (ptr != IntPtr.Zero)
                {
                    GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                    string csString   = (string)gCHandle.Target;
                    lua.PushString(csString);
                }
                else
                {
                    Console.WriteLine("nil passed to __tostring");
                    lua.PushNil();
                }
                return(1);
            });
            lua.SetField(-2, "__tostring");

            // equal (==) method
            lua.PushManagedFunction((lua) =>
            {
                IntPtr ptr1 = lua.GetUserType(1, UserType_Id);
                IntPtr ptr2 = lua.GetUserType(2, UserType_Id);
                // if we have same pointers, then objects are same
                if (ptr1 == ptr2)
                {
                    lua.PushBool(true);
                }
                // check if both pointers not zero
                else if (ptr1 != IntPtr.Zero && ptr2 != IntPtr.Zero)
                {
                    GCHandle gCHandle1 = GCHandle.FromIntPtr(ptr1);
                    GCHandle gCHandle2 = GCHandle.FromIntPtr(ptr2);
                    string csString1   = (string)gCHandle1.Target;
                    string csString2   = (string)gCHandle2.Target;
                    lua.PushBool(csString1 == csString2);
                }
                // some of pointers is Zero, we'll not compare them
                else
                {
                    lua.PushBool(false);
                }
                return(1);
            });
            lua.SetField(-2, "__eq");

            // Dispose() in lua
            lua.PushManagedFunction((lua) =>
            {
                // 1 - stands for 1st passed to function argument
                IntPtr ptr = lua.GetUserType(1, UserType_Id);
                if (ptr != IntPtr.Zero)
                {
                    GCHandle gCHandle = GCHandle.FromIntPtr(ptr);
                    string csString   = (string)gCHandle.Target;
                    Console.WriteLine($"csString ({csString}) is garbage collected");
                    gCHandle.Free();
                }
                else
                {
                    Console.WriteLine("nil passed to __gc");
                }
                return(0);
            });
            lua.SetField(-2, "__gc");
            lua.Pop();

            // now we need to somehow create it
            lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
            lua.PushManagedFunction((lua) =>
            {
                string csString   = lua.GetString(1);
                GCHandle gCHandle = GCHandle.Alloc(csString, GCHandleType.Weak);
                IntPtr ptr        = GCHandle.ToIntPtr(gCHandle);
                lua.PushUserType(ptr, UserType_Id);
                return(1);
            });
            lua.SetField(-2, "CreateCSString");
            lua.Pop();
        }