Browse Source

Use custom exceptions to stop control flow in the Quake engine on Error and Quit, and shut down the engine. Doesn't work quite as intended yet (Quit will terminate the entire Unity application for some reason, instead of just Quake) but it's a step in the right direction.

console
Nico de Poel 5 years ago
parent
commit
fa50659490
  1. 9
      Assets/Scripts/SysCalls.cs
  2. 66
      Assets/Scripts/UniQuake.cs
  3. 1
      engine/projects/uniquake/sys_uniquake.c
  4. 5
      engine/projects/uniquake/uniquake.c

9
Assets/Scripts/SysCalls.cs

@ -99,9 +99,8 @@ public class SysCalls: CallbackHandler<SysCalls>
private void Error(string message) private void Error(string message)
{ {
Debug.LogError(message);
// TODO: kill execution of the DLL entirely (Sys_Quit expects immediate exit, which this doesn't do)
Application.Quit(1);
// Use an exception to emulate Quake's behavior of immediately terminating the game's code execution on error
throw new QuakeException(message, 1);
} }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@ -115,8 +114,8 @@ public class SysCalls: CallbackHandler<SysCalls>
private void Quit() private void Quit()
{ {
Debug.Log($"Quitting application normally");
Application.Quit(0);
// This exception will be caught by the UniQuake update loop where the game will be shut down
throw new QuakeException("Quitting application normally");
} }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

66
Assets/Scripts/UniQuake.cs

@ -11,6 +11,8 @@ public class UniQuake: MonoBehaviour
private SysCalls sysCalls; private SysCalls sysCalls;
private ModCalls modCalls; private ModCalls modCalls;
private bool initialized = false;
void Start() void Start()
{ {
string[] arguments = string[] arguments =
@ -33,16 +35,62 @@ public class UniQuake: MonoBehaviour
sysCalls = new SysCalls(this); sysCalls = new SysCalls(this);
modCalls = new ModCalls(this); modCalls = new ModCalls(this);
UniQuake_Init(quakeParms, sysCalls.ToIntPtr, modCalls.ToIntPtr);
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() void Update()
{ {
UniQuake_Update(Time.deltaTime);
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() private void OnDestroy()
{ {
modCalls.Destroy();
sysCalls.Destroy(); sysCalls.Destroy();
if (quakeParms != null) if (quakeParms != null)
@ -57,4 +105,18 @@ public class UniQuake: MonoBehaviour
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void UniQuake_Update(float deltaTime); private static extern void UniQuake_Update(float deltaTime);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void UniQuake_Shutdown();
} }
public class QuakeException: Exception
{
public int ExitCode { get; }
public QuakeException(string message, int exitCode = 0)
: base(message)
{
ExitCode = exitCode;
}
}

1
engine/projects/uniquake/sys_uniquake.c

@ -30,7 +30,6 @@ void Sys_Printf(char *fmt, ...)
void Sys_Quit(void) void Sys_Quit(void)
{ {
Host_Shutdown();
unity_syscalls->SysQuit(unity_syscalls->target); unity_syscalls->SysQuit(unity_syscalls->target);
} }

5
engine/projects/uniquake/uniquake.c

@ -20,3 +20,8 @@ UNIQUAKE_API void UniQuake_Update(float deltaTime)
Host_Frame(deltaTime); Host_Frame(deltaTime);
} }
UNIQUAKE_API void UniQuake_Shutdown()
{
Host_Shutdown();
}
Loading…
Cancel
Save