using System; using System.IO; using System.Runtime.InteropServices; using UnityEngine; public partial class UniQuake { #if UNITY_EDITOR private const string DllPath = "Plugins/windows/x86_64/uniquake.dll"; #elif UNITY_STANDALONE_WIN #if UNITY_64 private const string DllPath = "Plugins/x86_64/uniquake.dll"; #else private const string DllPath = "Plugins/x86/uniquake.dll"; #endif #endif private IntPtr libraryHandle; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void UniQuake_InitFunc(IntPtr parms, IntPtr sysCalls, IntPtr glCalls, IntPtr gameCalls); private UniQuake_InitFunc UniQuake_Init; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void UniQuake_UpdateFunc(float deltaTime); private UniQuake_UpdateFunc UniQuake_Update; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void UniQuake_ShutdownFunc(); private UniQuake_ShutdownFunc UniQuake_Shutdown; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void UniQuake_SetFmodSystemFunc(IntPtr fmodSystem, int playerNumber = 0); private UniQuake_SetFmodSystemFunc UniQuake_SetFmodSystem; private void LoadLibrary() { string dllFile = Path.Combine(Application.dataPath, DllPath); // Experimental code to allow running multiple instances of Quake next to each other // string dllName = Path.GetFileNameWithoutExtension(dllFile); // string dllExt = Path.GetExtension(dllFile); // string dllCopy = Path.Combine(Application.persistentDataPath, $"{dllName}{GetInstanceID()}{dllExt}"); // File.Copy(dllFile, dllCopy, true); // dllFile = dllCopy; libraryHandle = SystemLibrary.LoadLibrary(dllFile); if (libraryHandle == IntPtr.Zero) { throw new DllNotFoundException($"Failed to load UniQuake library from path: {dllFile}, last error = {Marshal.GetLastWin32Error()}"); } UniQuake_Init = LoadLibraryFunction("UniQuake_Init"); UniQuake_Update = LoadLibraryFunction("UniQuake_Update"); UniQuake_Shutdown = LoadLibraryFunction("UniQuake_Shutdown"); UniQuake_SetFmodSystem = LoadLibraryFunction("UniQuake_SetFmodSystem"); } private TDelegate LoadLibraryFunction(string functionName) { IntPtr procAddress = SystemLibrary.GetProcAddress(libraryHandle, functionName); if (procAddress == IntPtr.Zero) { throw new DllNotFoundException($"Could not find library function: {functionName}"); } return Marshal.GetDelegateForFunctionPointer(procAddress); } private void FreeLibrary() { if (libraryHandle != IntPtr.Zero) { SystemLibrary.FreeLibrary(libraryHandle); libraryHandle = IntPtr.Zero; } } }