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); } }
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); }
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); }
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); }
public Task <bool> Start(ILua lua, GetILuaFromLuaStatePointer lua_extructor, ModuleAssemblyLoadContext _) { TaskCompletionSource <bool> taskCompletion = new TaskCompletionSource <bool>(); try { lua.PushNumber(1); lua.PushString("Dima is the best boy."); lua.PushBool(true); lua.PushNil(); if (!lua.IsType(-4, TYPES.NUMBER)) { throw new Exception("IsType returned false on NUMBER type"); } if (!lua.IsType(-3, TYPES.STRING)) { throw new Exception("IsType returned false on STRING type"); } if (!lua.IsType(-2, TYPES.BOOL)) { throw new Exception("IsType returned false on BOOL type"); } if (!lua.IsType(-1, TYPES.NIL)) { throw new Exception("IsType returned false on NIL type"); } lua.Pop(4); taskCompletion.TrySetResult(true); } catch (Exception e) { taskCompletion.TrySetException(new Exception[] { e }); } return(taskCompletion.Task); }
int LoadModule(ILua lua) { try { string module_name = lua.GetString(1); lua.Pop(lua.Top()); if (String.IsNullOrEmpty(module_name)) { throw new Exception("Module name is null or empty"); } if (module_contexts.ContainsKey(module_name)) { throw new Exception($"Module with name {module_name} is already loaded"); } GmodNetModuleAssemblyLoadContext module_context = new GmodNetModuleAssemblyLoadContext(module_name); Assembly module_assembly = module_context.LoadFromAssemblyPath(Path.GetFullPath("garrysmod/lua/bin/Modules/" + module_name + "/" + module_name + ".dll")); Type[] module_types = module_assembly.GetTypes().Where(t => typeof(IModule).IsAssignableFrom(t)).ToArray(); List <IModule> modules = new List <IModule>(); List <GCHandle> gc_handles = new List <GCHandle>(); foreach (Type t in module_types) { IModule current_module = (IModule)Activator.CreateInstance(t); modules.Add(current_module); gc_handles.Add(GCHandle.Alloc(current_module)); } if (modules.Count == 0) { throw new Exception($"Module {module_name} does not contain any implementations of the IModule interface."); } lua.PrintToConsole("Loading modules from " + module_name + "."); lua.PrintToConsole("Number of the IModule interface implementations: " + modules.Count); foreach (IModule m in modules) { lua.PrintToConsole("Loading class-module " + m.ModuleName + " version " + m.ModuleVersion + "..."); m.Load(lua, isServerSide, module_context); lua.PrintToConsole("Class-module " + m.ModuleName + " was loaded."); } module_contexts.Add(module_name, Tuple.Create(module_context, gc_handles)); lua.PushBool(true); return(1); } catch (Exception e) { lua.PrintToConsole("Unable to load module: exception was thrown"); lua.PrintToConsole(e.ToString()); lua.PushBool(false); return(1); } }
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(); }
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); }