diff --git a/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj b/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj index 48932499..d446bec2 100644 --- a/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj +++ b/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj @@ -2,6 +2,8 @@ net6.0 + enable + Nullable MIT GmodNET API GmodNET API library contains all necessary interfaces to write a GmodNET module. diff --git a/gm_dotnet_managed/GmodNET.API/ILua.cs b/gm_dotnet_managed/GmodNET.API/ILua.cs index 4a6a1b15..b34afe40 100644 --- a/gm_dotnet_managed/GmodNET.API/ILua.cs +++ b/gm_dotnet_managed/GmodNET.API/ILua.cs @@ -61,8 +61,8 @@ public interface ILua /// } /// /// - /// - public void GetField(int iStackPos, in string key); + /// + public void GetField(int iStackPos, string key); /// /// Does a table key-value assignment t[k] = v, @@ -102,8 +102,8 @@ public interface ILua /// } /// /// - /// - public void SetField(int iStackPos, in string key); + /// + public void SetField(int iStackPos, string key); /// /// Creates a new table and pushes it to the top of the stack. @@ -375,7 +375,7 @@ public interface ILua /// See lua_pushstring function in the Lua manual: https://www.lua.org/manual/5.1/manual.html /// /// A string to push. - public void PushString(in string str); + public void PushString(string str); /// /// Pushes a given double-precision number to the Lua stack. @@ -593,7 +593,7 @@ public interface ILua /// Creates a new Lua type, pushes its metatable onto the stack, and returns new type’s id. /// /// - /// allows you to extend Lua and Garry’s Mod type system with custom types. + /// allows you to extend Lua and Garry’s Mod type system with custom types. /// Returned type id can be used with . /// /// See section "Metatables" in the Lua manual for more information about types and metatables: https://www.lua.org/manual/5.1/manual.html @@ -601,7 +601,7 @@ public interface ILua /// A name for the new type. /// A type id for newly created type. /// - public int CreateMetaTable(in string name); + public int CreateMetaTable(string name); /// /// Pushes a metatable of the given type onto the stack. @@ -668,7 +668,7 @@ public interface ILua /// and k is an object on top of the stack. /// /// - /// Unlike , allows to get a value from the table when the key in the key-value pair is not a string. + /// Unlike , allows to get a value from the table when the key in the key-value pair is not a string. /// /// Pops a key object from the stack. /// @@ -676,7 +676,7 @@ public interface ILua /// /// A stack position of the table to get a value from. /// - /// The following example shows how can be used to get a value from the table instead of . + /// The following example shows how can be used to get a value from the table instead of . /// /// public static int GetTableExample(ILua lua) /// { @@ -691,7 +691,7 @@ public interface ILua /// } /// /// - /// + /// public void GetTable(int iStackPos); /// @@ -701,7 +701,7 @@ public interface ILua /// and k is a key at stack index -2. /// /// - /// Unlike , allows to add a key-value pair to a table with the key not being a string. + /// Unlike , allows to add a key-value pair to a table with the key not being a string. /// /// Pops both the key and the value from the stack. /// @@ -709,7 +709,7 @@ public interface ILua /// /// A stack position of the table to add a key-value pair to. /// - /// The following example shows how can be used instead of . + /// The following example shows how can be used instead of . /// /// public static int SetTableExample(ILua lua) /// { @@ -723,7 +723,7 @@ public interface ILua /// } /// /// - /// + /// public void SetTable(int iStackPos); /// @@ -882,7 +882,7 @@ public class GmodLuaException : Exception /// /// A Lua exception code. Must be one of the values defined by Lua specification. /// A Lua exception message. - public GmodLuaException(int lua_error_code, string lua_error_message) : base(lua_error_message) + public GmodLuaException(int lua_error_code, string? lua_error_message) : base(lua_error_message) { this.error_code = lua_error_code; } diff --git a/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs b/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs index 17099846..6d4f083a 100644 --- a/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs +++ b/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs @@ -21,7 +21,7 @@ public abstract class ModuleAssemblyLoadContext : AssemblyLoadContext /// /// Get current custom native library resolver delegate. /// - public abstract Func CustomNativeLibraryResolver {get; } + public abstract Func? CustomNativeLibraryResolver { get; } /// /// Initializes a new instance of the class with a value that indicates whether unloading is enabled. diff --git a/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs b/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs index 6eb016e2..47a06a21 100644 --- a/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs +++ b/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs @@ -110,11 +110,11 @@ public GameConsoleWriter(ILua lua) private delegate void MsgFunc(string str); - private static MsgFunc Msg; + private static MsgFunc? Msg; - public override void Write(string value) + public override void Write(string? value) { - if (!String.IsNullOrEmpty(value)) + if (!String.IsNullOrEmpty(value) && Msg is not null) { Msg(value); } @@ -123,7 +123,7 @@ public override void Write(char value) { Write(value.ToString()); } - public override void Write(char[] value) + public override void Write(char[]? value) { Write(new string(value)); } @@ -135,7 +135,7 @@ public override void Write(ReadOnlySpan buffer) { Write(new string(buffer)); } - public override void Write(StringBuilder value) + public override void Write(StringBuilder? value) { if (value != null) { @@ -143,7 +143,7 @@ public override void Write(StringBuilder value) } } // \n begins here - public override void WriteLine(string value) + public override void WriteLine(string? value) { if (!String.IsNullOrEmpty(value)) { @@ -158,7 +158,7 @@ public override void WriteLine(char value) { Write(value.ToString() + NewLine); } - public override void WriteLine(char[] buffer) + public override void WriteLine(char[]? buffer) { Write(new string(buffer) + NewLine); } @@ -170,7 +170,7 @@ public override void WriteLine(ReadOnlySpan buffer) { Write(new string(buffer) + NewLine); } - public override void WriteLine(StringBuilder value) + public override void WriteLine(StringBuilder? value) { if (value != null) { @@ -213,7 +213,7 @@ public override void WriteLine(decimal value) { Write(value.ToString() + NewLine); } - public override void WriteLine(object value) + public override void WriteLine(object? value) { if (value == null) { diff --git a/gm_dotnet_managed/GmodNET/GloabalContext.cs b/gm_dotnet_managed/GmodNET/GloabalContext.cs index 4f01f2cb..b7256910 100644 --- a/gm_dotnet_managed/GmodNET/GloabalContext.cs +++ b/gm_dotnet_managed/GmodNET/GloabalContext.cs @@ -103,9 +103,12 @@ int LoadModule(ILua lua) foreach (Type t in module_types) { - IModule current_module = (IModule)Activator.CreateInstance(t); - modules.Add(current_module); - gc_handles.Add(GCHandle.Alloc(current_module)); + IModule? current_module = Activator.CreateInstance(t) as IModule; + if (current_module is not null) + { + modules.Add(current_module); + gc_handles.Add(GCHandle.Alloc(current_module)); + } } if (modules.Count == 0) @@ -150,7 +153,7 @@ WeakReference UnloadHelper(string module_name) { foreach (GCHandle h in module_contexts[module_name].Item2) { - ((IModule)h.Target).Unload(lua); + (h.Target as IModule)?.Unload(lua); h.Free(); } diff --git a/gm_dotnet_managed/GmodNET/GmodNET.csproj b/gm_dotnet_managed/GmodNET/GmodNET.csproj index 0c7fc51e..0c80f978 100644 --- a/gm_dotnet_managed/GmodNET/GmodNET.csproj +++ b/gm_dotnet_managed/GmodNET/GmodNET.csproj @@ -3,6 +3,8 @@ Exe net7.0 + enable + Nullable GmodNET.BuidReq GmodNET managed module loader. MIT diff --git a/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs b/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs index a929658d..d76d4d3e 100644 --- a/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs +++ b/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs @@ -14,7 +14,7 @@ internal class GmodNetModuleAssemblyLoadContext : ModuleAssemblyLoadContext { private AssemblyDependencyResolver resolver; private string module_name; - private Func customNativeLibraryResolver; + private Func? customNativeLibraryResolver; private List native_libray_handles; public override string ModuleName @@ -25,13 +25,7 @@ public override string ModuleName } } - public override Func CustomNativeLibraryResolver - { - get - { - return customNativeLibraryResolver; - } - } + public override Func? CustomNativeLibraryResolver => customNativeLibraryResolver; public override void SetCustomNativeLibraryResolver(Func resolver) { @@ -65,14 +59,14 @@ internal GmodNetModuleAssemblyLoadContext(string module_name) : base(module_name }; } - protected override System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyName) + protected override System.Reflection.Assembly? Load(System.Reflection.AssemblyName assemblyName) { if(assemblyName.Name == "GmodNET.API") { return null; } - string path = resolver.ResolveAssemblyToPath(assemblyName); + string? path = resolver.ResolveAssemblyToPath(assemblyName); if (string.IsNullOrEmpty(path)) { return null; @@ -98,7 +92,7 @@ protected override IntPtr LoadUnmanagedDll (string unmanagedDllName) } else { - string unmanaged_dep_path = resolver.ResolveUnmanagedDllToPath(unmanagedDllName); + string? unmanaged_dep_path = resolver.ResolveUnmanagedDllToPath(unmanagedDllName); if(String.IsNullOrEmpty(unmanaged_dep_path)) { diff --git a/gm_dotnet_managed/GmodNET/Lua.cs b/gm_dotnet_managed/GmodNET/Lua.cs index 13d7ea68..e6242bf6 100644 --- a/gm_dotnet_managed/GmodNET/Lua.cs +++ b/gm_dotnet_managed/GmodNET/Lua.cs @@ -20,11 +20,21 @@ internal Lua(IntPtr ptr) public int Top() { + if (top is null) + { + throw new LuaInteropDelegateIsNullException(nameof(top)); + } + return top(ptr); } public void Push(int iStackPos) { + if (push is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -34,6 +44,11 @@ public void Push(int iStackPos) public void Pop(int IAmt = 1) { + if (pop is null) + { + throw new LuaInteropDelegateIsNullException(nameof(pop)); + } + if (IAmt < 0) { throw new ArgumentOutOfRangeException("iAmt", "Can't pop negative number of items from the stack"); @@ -46,8 +61,13 @@ public void Pop(int IAmt = 1) pop(ptr, IAmt); } - public void GetField(int iStackPos, in string key) + public void GetField(int iStackPos, string key) { + if (get_field is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_field)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -62,8 +82,13 @@ public void GetField(int iStackPos, in string key) } } - public void SetField(int iStackPos, in string key) + public void SetField(int iStackPos, string key) { + if (set_field is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_field)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -80,11 +105,21 @@ public void SetField(int iStackPos, in string key) public void CreateTable() { + if (create_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(create_table)); + } + create_table(ptr); } public void SetMetaTable(int iStackPos) { + if (set_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_metatable)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -94,6 +129,11 @@ public void SetMetaTable(int iStackPos) public bool GetMetaTable(int iStackPos) { + if (get_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_metatable)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -113,16 +153,31 @@ public bool GetMetaTable(int iStackPos) [Obsolete("Unsafe. Use Lua.PCall instead.", false)] public void Call(int iArgs, int iResults) { + if (call is null) + { + throw new LuaInteropDelegateIsNullException(nameof(call)); + } + call(ptr, iArgs, iResults); } public int PCall(int IArgs, int IResults, int ErrorFunc) { + if (pcall is null) + { + throw new LuaInteropDelegateIsNullException(nameof(pcall)); + } + return pcall(ptr, IArgs, IResults, ErrorFunc); } public bool Equal(int iA, int iB) { + if (equal is null) + { + throw new LuaInteropDelegateIsNullException(nameof(equal)); + } + if(iA == 0 || iB == 0) { throw new ArgumentException("Neither iA or iB can't be 0"); @@ -141,6 +196,11 @@ public bool Equal(int iA, int iB) public bool RawEqual(int iA, int iB) { + if (raw_equal is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_equal)); + } + if(iA == 0 || iB == 0) { throw new ArgumentException("Neither iA or iB can't be 0"); @@ -159,6 +219,11 @@ public bool RawEqual(int iA, int iB) public void Insert(int iStackPos) { + if (insert is null) + { + throw new LuaInteropDelegateIsNullException(nameof(insert)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -168,6 +233,11 @@ public void Insert(int iStackPos) public void Remove(int iStackPos) { + if (remove is null) + { + throw new LuaInteropDelegateIsNullException(nameof(remove)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -177,6 +247,11 @@ public void Remove(int iStackPos) public int Next(int iStackPos) { + if (next is null) + { + throw new LuaInteropDelegateIsNullException(nameof(next)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -187,6 +262,11 @@ public int Next(int iStackPos) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void ThrowError(in string error_message) { + if (throw_error is null) + { + throw new LuaInteropDelegateIsNullException(nameof(throw_error)); + } + byte[] buff = Encoding.UTF8.GetBytes(error_message + "\0"); unsafe { @@ -200,6 +280,11 @@ public void ThrowError(in string error_message) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void CheckType(int iStackPos, int IType) { + if (check_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -210,6 +295,11 @@ public void CheckType(int iStackPos, int IType) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void ArgError(int iArgNum, in string error_message) { + if (arg_error is null) + { + throw new LuaInteropDelegateIsNullException(nameof(arg_error)); + } + byte[] buff = Encoding.UTF8.GetBytes(error_message); unsafe { @@ -222,6 +312,11 @@ public void ArgError(int iArgNum, in string error_message) public string GetString(int iStackPos) { + if (get_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_string)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -241,6 +336,11 @@ public string GetString(int iStackPos) public double GetNumber(int iStackPos) { + if (get_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_number)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -250,6 +350,11 @@ public double GetNumber(int iStackPos) public bool GetBool(int iStackPos) { + if (get_bool is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_bool)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -268,6 +373,11 @@ public bool GetBool(int iStackPos) public IntPtr GetCFunction(int iStackPos) { + if (get_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_c_function)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -277,11 +387,21 @@ public IntPtr GetCFunction(int iStackPos) public void PushNil() { + if (push_nil is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_nil)); + } + push_nil(ptr); } - public void PushString(in string str) + public void PushString(string str) { + if (push_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_string)); + } + byte[] buff = Encoding.UTF8.GetBytes(str); unsafe @@ -295,11 +415,21 @@ public void PushString(in string str) public void PushNumber(double val) { + if (push_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_number)); + } + push_number(ptr, val); } public void PushBool(bool val) { + if (push_bool is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_bool)); + } + int tmp; if(val) @@ -316,6 +446,11 @@ public void PushBool(bool val) public unsafe void PushCFunction(IntPtr native_func_ptr) { + if (push_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_function)); + } + if(native_func_ptr == IntPtr.Zero) { throw new ArgumentNullException("native_func_ptr", "Parameter can't be nullptr."); @@ -326,6 +461,11 @@ public unsafe void PushCFunction(IntPtr native_func_ptr) public unsafe void PushCFunction(delegate* unmanaged[Cdecl] function_pointer) { + if (push_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_function)); + } + IntPtr int_ptr = (IntPtr)function_pointer; if (int_ptr == IntPtr.Zero) @@ -338,31 +478,61 @@ public unsafe void PushCFunction(delegate* unmanaged[Cdecl] functio public void PushCClosure(IntPtr native_func_ptr, int iVars) { + if (push_c_closure is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_closure)); + } + push_c_closure(ptr, native_func_ptr, iVars); } public int ReferenceCreate() { + if (reference_create is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_create)); + } + return reference_create(ptr); } public void ReferenceFree(int reference) { + if (reference_free is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_free)); + } + reference_free(ptr, reference); } public void ReferencePush(int reference) { + if (reference_push is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_push)); + } + reference_push(ptr, reference); } public void PushSpecial(SPECIAL_TABLES table) { + if (push_special is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_special)); + } + push_special(ptr, (int)table); } public bool IsType(int iStackPos, int iType) { + if (is_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(is_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -386,6 +556,11 @@ public bool IsType(int iStackPos, TYPES type) public int GetType(int iStackPos) { + if (get_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -395,6 +570,11 @@ public int GetType(int iStackPos) public string GetTypeName(int iType) { + if (get_type_name is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_type_name)); + } + int len = 0; unsafe @@ -414,6 +594,11 @@ public string GetTypeName(TYPES type) public int ObjLen(int iStackPos) { + if (obj_len is null) + { + throw new LuaInteropDelegateIsNullException(nameof(obj_len)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -423,6 +608,11 @@ public int ObjLen(int iStackPos) public Vector3 GetAngle(int iStackPos) { + if (get_angle is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_angle)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -441,6 +631,11 @@ public Vector3 GetAngle(int iStackPos) public Vector3 GetVector(int iStackPos) { + if (get_vector is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_vector)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -459,21 +654,41 @@ public Vector3 GetVector(int iStackPos) public void PushAngle(Vector3 ang) { + if (push_angle is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_angle)); + } + push_angle(ptr, ang.X, ang.Y, ang.Z); } public void PushVector(Vector3 vec) { + if (push_vector is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_vector)); + } + push_vector(ptr, vec.X, vec.Y, vec.Z); } public void SetState(IntPtr lua_state) { + if (set_state is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_state)); + } + set_state(ptr, lua_state); } - public int CreateMetaTable(in string name) + public int CreateMetaTable(string name) { + if (create_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(create_metatable)); + } + byte[] buff = Encoding.UTF8.GetBytes(name); unsafe @@ -487,6 +702,11 @@ public int CreateMetaTable(in string name) public bool PushMetaTable(int iType) { + if (push_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_metatable)); + } + int tmp = push_metatable(ptr, iType); if(tmp == 0) @@ -506,11 +726,21 @@ public bool PushMetaTable(TYPES type) public void PushUserType(IntPtr data_pointer, int iType) { + if (push_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_user_type)); + } + push_user_type(ptr, data_pointer, iType); } public void SetUserType(int iStackPos, IntPtr data_pointer) { + if (set_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_user_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -519,7 +749,12 @@ public void SetUserType(int iStackPos, IntPtr data_pointer) } public IntPtr GetUserType(int iStackPos, int iType) - { + { + if (get_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_user_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -529,6 +764,11 @@ public IntPtr GetUserType(int iStackPos, int iType) public void GetTable(int iStackPos) { + if (get_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_table)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -538,6 +778,11 @@ public void GetTable(int iStackPos) public void SetTable(int iStackPos) { + if (set_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_table)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -547,6 +792,11 @@ public void SetTable(int iStackPos) public void RawGet(int iStackPos) { + if (raw_get is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_get)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -556,6 +806,11 @@ public void RawGet(int iStackPos) public void RawSet(int iStackPos) { + if (raw_set is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_set)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -565,12 +820,22 @@ public void RawSet(int iStackPos) public void PushUserData(IntPtr data) { + if (push_user_data is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_user_data)); + } + push_user_data(ptr, data); } [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public string CheckString(int iStackPos) { + if (check_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_string)); + } + int str_len = 0; unsafe { @@ -591,6 +856,11 @@ public string CheckString(int iStackPos) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public double CheckNumber(int iStackPos) { + if (check_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_number)); + } + return check_number(ptr, iStackPos); } diff --git a/gm_dotnet_managed/GmodNET/LuaInterop.cs b/gm_dotnet_managed/GmodNET/LuaInterop.cs index b381ab1c..e527034a 100644 --- a/gm_dotnet_managed/GmodNET/LuaInterop.cs +++ b/gm_dotnet_managed/GmodNET/LuaInterop.cs @@ -9,121 +9,134 @@ namespace GmodNET [SuppressUnmanagedCodeSecurity] internal static class LuaInterop { - static internal Func top; + static internal Func? top; - static internal Action push; + static internal Action? push; - static internal Action pop; + static internal Action? pop; - static internal Action get_field; + static internal Action? get_field; - static internal Action set_field; + static internal Action? set_field; - static internal Action create_table; + static internal Action? create_table; - static internal Action set_metatable; + static internal Action? set_metatable; - static internal Func get_metatable; + static internal Func? get_metatable; - static internal Action call; + static internal Action? call; - static internal Func pcall; + static internal Func? pcall; - static internal Func equal; + static internal Func? equal; - static internal Func raw_equal; + static internal Func? raw_equal; - static internal Action insert; + static internal Action? insert; - static internal Action remove; + static internal Action? remove; - static internal Func next; + static internal Func? next; - static internal Action throw_error; + static internal Action? throw_error; - static internal Action check_type; + static internal Action? check_type; - static internal Action arg_error; + static internal Action? arg_error; - static internal Func get_string; + static internal Func? get_string; - static internal Func get_number; + static internal Func? get_number; - static internal Func get_bool; + static internal Func? get_bool; - static internal Func get_c_function; + static internal Func? get_c_function; - static internal Action push_nil; + static internal Action? push_nil; - static internal Action push_string; + static internal Action? push_string; - static internal Action push_number; + static internal Action? push_number; - static internal Action push_bool; + static internal Action? push_bool; - static internal Action push_c_function; + static internal Action? push_c_function; - static internal Action push_c_closure; + static internal Action? push_c_closure; - static internal Func reference_create; + static internal Func? reference_create; - static internal Action reference_free; + static internal Action? reference_free; - static internal Action reference_push; + static internal Action? reference_push; - static internal Action push_special; + static internal Action? push_special; - static internal Func is_type; + static internal Func? is_type; - static internal Func get_type; + static internal Func? get_type; - static internal Func get_type_name; + static internal Func? get_type_name; - static internal Func obj_len; + static internal Func? obj_len; - static internal Action get_angle; + static internal Action? get_angle; - static internal Action get_vector; + static internal Action? get_vector; - static internal Action push_angle; + static internal Action? push_angle; - static internal Action push_vector; + static internal Action? push_vector; - static internal Action set_state; + static internal Action? set_state; - static internal Func create_metatable; + static internal Func? create_metatable; - static internal Func push_metatable; + static internal Func? push_metatable; - static internal Action push_user_type; + static internal Action? push_user_type; - static internal Action set_user_type; + static internal Action? set_user_type; - static internal Func get_user_type; + static internal Func? get_user_type; - static internal Func get_iluabase_from_the_lua_state; + static internal Func? get_iluabase_from_the_lua_state; - static internal Action get_table; + static internal Action? get_table; - static internal Action set_table; + static internal Action? set_table; - static internal Action raw_get; + static internal Action? raw_get; - static internal Action raw_set; + static internal Action? raw_set; - static internal Action push_user_data; + static internal Action? push_user_data; - static internal Func check_string; + static internal Func? check_string; - static internal Func check_number; + static internal Func? check_number; - static internal Action push_c_function_safe; + static internal Action? push_c_function_safe; internal static ILua ExtructLua(IntPtr lua_state) - { + { + if (get_iluabase_from_the_lua_state is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_iluabase_from_the_lua_state)); + } + IntPtr tmp_ptr = LuaInterop.get_iluabase_from_the_lua_state(lua_state); return new Lua(tmp_ptr); } } + + internal class LuaInteropDelegateIsNullException : Exception + { + public LuaInteropDelegateIsNullException(string nameOfDelegate) : base($"Delegate {nameOfDelegate} is null. Critical Gmod.NET runtime error occurred") + { + + } + } } diff --git a/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs b/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs index 2120590c..009d93f9 100644 --- a/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs +++ b/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs @@ -28,7 +28,12 @@ internal static int ManagedDelegateExecutor(IntPtr lua_state) IntPtr managed_delegate_handle = lua.GetUserType(GmodInterop.GetUpvalueIndex(1, false), managed_delegate_type_id); - Func managed_delegate = (Func)GCHandle.FromIntPtr(managed_delegate_handle).Target; + Func? managed_delegate = GCHandle.FromIntPtr(managed_delegate_handle).Target as Func; + + if (managed_delegate is null) + { + throw new Exception("Unable to get managed delegate from GCHandle"); + } return Math.Max(0, managed_delegate(lua)); } diff --git a/gm_dotnet_managed/GmodNET/RuntimeServices.cs b/gm_dotnet_managed/GmodNET/RuntimeServices.cs index 87be015a..ef97f442 100644 --- a/gm_dotnet_managed/GmodNET/RuntimeServices.cs +++ b/gm_dotnet_managed/GmodNET/RuntimeServices.cs @@ -12,7 +12,7 @@ internal static class RuntimeServices { internal static T CreateNativeCaller(IntPtr native_pointer) where T : Delegate { - MethodInfo invoke_info = typeof(T).GetMethod("Invoke"); + MethodInfo invoke_info = typeof(T).GetMethod("Invoke")!; // T is constrained to Delegates only, so Invoke method is always present. var return_type = invoke_info.ReturnType; var parameters_types = invoke_info.GetParameters().Select(param => param.ParameterType).Prepend(typeof(object)).ToArray(); diff --git a/gm_dotnet_managed/GmodNET/Startup.cs b/gm_dotnet_managed/GmodNET/Startup.cs index a971cf2a..03996b2f 100644 --- a/gm_dotnet_managed/GmodNET/Startup.cs +++ b/gm_dotnet_managed/GmodNET/Startup.cs @@ -27,9 +27,20 @@ internal static unsafe IntPtr Main(IntPtr lua_base, IntPtr native_version_string { try { - string full_assembly_version = FileVersionInfo.GetVersionInfo(typeof(Startup).Assembly.Location).ProductVersion; - string friendly_version = full_assembly_version.Split("+")[0]; - string version_codename = full_assembly_version.Split("+")[1].Split(".")[1]; + string full_assembly_version = FileVersionInfo.GetVersionInfo(typeof(Startup).Assembly.Location).ProductVersion ?? string.Empty; + + string friendly_version; + string version_codename; + + try + { + friendly_version = full_assembly_version.Split("+")[0]; + version_codename = full_assembly_version.Split("+")[1].Split(".")[1]; + } + catch + { + throw new Exception("Unable to parse version number according to specification"); + } string native_version = Encoding.UTF8.GetString((byte*)native_version_string.ToPointer(), version_string_length);