You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.7 KiB
183 lines
4.7 KiB
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using UnityEngine;
|
|
|
|
public class UniQuake: MonoBehaviour
|
|
{
|
|
#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 const int MemSize = 0x4000000; // 64 MB of heap space
|
|
|
|
private IntPtr libraryHandle;
|
|
|
|
private QuakeParms quakeParms;
|
|
private SysCalls sysCalls;
|
|
private ModCalls modCalls;
|
|
|
|
private bool initialized = false;
|
|
private double startTime;
|
|
|
|
/// <summary>
|
|
/// Time since startup for this particular instance of Quake
|
|
/// </summary>
|
|
public double CurrentTime => Time.timeAsDouble - startTime;
|
|
|
|
void Start()
|
|
{
|
|
sysCalls = new SysCalls(this);
|
|
modCalls = new ModCalls(this);
|
|
|
|
LoadLibrary();
|
|
|
|
string[] arguments =
|
|
{
|
|
"",
|
|
"-window",
|
|
"-width", "1440",
|
|
"-height", "1080",
|
|
"+developer", "1",
|
|
};
|
|
|
|
quakeParms = new QuakeParms
|
|
{
|
|
baseDir = Application.persistentDataPath,
|
|
cacheDir = null,
|
|
};
|
|
quakeParms.SetArguments(arguments);
|
|
quakeParms.AllocateMemory(MemSize);
|
|
|
|
startTime = Time.timeAsDouble;
|
|
|
|
try
|
|
{
|
|
UniQuake_Init(quakeParms, sysCalls.ToIntPtr, modCalls.ToIntPtr);
|
|
initialized = true;
|
|
}
|
|
catch (QuakeException ex)
|
|
{
|
|
if (ex.ExitCode == 0)
|
|
Debug.Log(ex.Message);
|
|
else
|
|
Debug.LogException(ex);
|
|
|
|
Shutdown();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogException(ex);
|
|
Shutdown();
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (!initialized)
|
|
return;
|
|
|
|
try
|
|
{
|
|
UniQuake_Update(Time.deltaTime);
|
|
}
|
|
catch (QuakeException ex)
|
|
{
|
|
if (ex.ExitCode == 0)
|
|
Debug.Log(ex.Message);
|
|
else
|
|
Debug.LogException(ex);
|
|
|
|
Shutdown();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogException(ex);
|
|
Shutdown();
|
|
}
|
|
}
|
|
|
|
private void Shutdown()
|
|
{
|
|
initialized = false;
|
|
UniQuake_Shutdown();
|
|
Destroy(this);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
modCalls.Destroy();
|
|
sysCalls.Destroy();
|
|
|
|
if (quakeParms != null)
|
|
{
|
|
quakeParms.Destroy();
|
|
quakeParms = null;
|
|
}
|
|
|
|
FreeLibrary();
|
|
}
|
|
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
private delegate void UniQuake_InitFunc(QuakeParms parms, IntPtr sysCalls, IntPtr modCalls);
|
|
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;
|
|
|
|
private void LoadLibrary()
|
|
{
|
|
string dllFile = Path.Combine(Application.dataPath, DllPath);
|
|
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_InitFunc>("UniQuake_Init");
|
|
UniQuake_Update = LoadLibraryFunction<UniQuake_UpdateFunc>("UniQuake_Update");
|
|
UniQuake_Shutdown = LoadLibraryFunction<UniQuake_ShutdownFunc>("UniQuake_Shutdown");
|
|
}
|
|
|
|
private TDelegate LoadLibraryFunction<TDelegate>(string name)
|
|
{
|
|
IntPtr procAddress = SystemLibrary.GetProcAddress(libraryHandle, name);
|
|
if (procAddress == IntPtr.Zero)
|
|
{
|
|
throw new DllNotFoundException($"Could not find library function: {name}");
|
|
}
|
|
|
|
return Marshal.GetDelegateForFunctionPointer<TDelegate>(procAddress);
|
|
}
|
|
|
|
private void FreeLibrary()
|
|
{
|
|
if (libraryHandle != IntPtr.Zero)
|
|
{
|
|
SystemLibrary.FreeLibrary(libraryHandle);
|
|
libraryHandle = IntPtr.Zero;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class QuakeException: Exception
|
|
{
|
|
public int ExitCode { get; }
|
|
|
|
public QuakeException(string message, int exitCode = 0)
|
|
: base(message)
|
|
{
|
|
ExitCode = exitCode;
|
|
}
|
|
}
|