Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Simple Bootstrap. VM/Interop Optimizations #58

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NWN.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<PackageId>NWN.Core</PackageId>
<Authors>NWN-dotnet</Authors>
<Nullable>enable</Nullable>
Expand Down
43 changes: 25 additions & 18 deletions src/Core/CoreGameManager.cs
Original file line number Diff line number Diff line change
@@ -1,70 +1,76 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using NWN.Core.Native;

namespace NWN.Core
{
/// <summary>
/// Simple GameManager implementation. Used by default if no manager is specified during bootstrap.
/// </summary>
public class CoreGameManager : ICoreFunctionHandler, ICoreEventHandler
public class CoreGameManager : ICoreFunctionHandler
{
// Hook-able Events
public delegate void ServerLoopEvent(ulong frame);

/// <inheritdoc cref="ICoreEventHandler.OnMainLoop"/>
public event ServerLoopEvent? OnServerLoop;
public static event ServerLoopEvent? OnServerLoop;

public delegate void SignalEvent(string signal);

/// <inheritdoc cref="ICoreEventHandler.OnSignal"/>
public event SignalEvent? OnSignal;
public static event SignalEvent? OnSignal;

public delegate void RunScriptEvent(string scriptName, uint objectSelf, out int scriptHandleResult);

/// <inheritdoc cref="ICoreEventHandler.OnRunScript"/>
public event RunScriptEvent? OnRunScript;
public static event RunScriptEvent? OnRunScript;

// Native Management
private readonly Stack<uint> scriptContexts = new Stack<uint>();
private readonly Dictionary<ulong, Action> closures = new Dictionary<ulong, Action>();
private ulong nextEventId;
private static readonly Stack<uint> scriptContexts = new Stack<uint>();
private static readonly Dictionary<ulong, Action> closures = new Dictionary<ulong, Action>();
private static ulong nextEventId;

private const uint ObjectInvalid = 0x7F000000;
private uint objectSelf = ObjectInvalid;
private static uint objectSelf = ObjectInvalid;

// Interface Implementations
uint ICoreFunctionHandler.ObjectSelf => objectSelf;

void ICoreEventHandler.OnMainLoop(ulong frame)
=> OnServerLoop?.Invoke(frame);
[UnmanagedCallersOnly]
internal static void MainLoopHandler(ulong frame) => OnServerLoop?.Invoke(frame);

void ICoreEventHandler.OnSignal(string signal)
=> OnSignal?.Invoke(signal);
[UnmanagedCallersOnly]
internal static unsafe void SignalHandler(IntPtr pSignal) => OnSignal?.Invoke(NwStringMarshaller.ConvertToManaged((byte*)pSignal)!);

public void OnAssertFail(string message, string stackTrace)
[UnmanagedCallersOnly]
internal static void AssertFailHandler(IntPtr pMessage, IntPtr pStackTrace)
{
StackTrace managedStackTrace = new StackTrace(true);
Console.Error.WriteLine(managedStackTrace.ToString());
}

public void CrashHandler(int signal, string stackTrace)
[UnmanagedCallersOnly]
internal static unsafe void CrashHandler(int signal, IntPtr pStackTrace)
{
Console.WriteLine(stackTrace);
Console.Error.WriteLine(NwStringMarshaller.ConvertToManaged((byte*)pStackTrace));

StackTrace managedStackTrace = new StackTrace(true);
Console.Error.WriteLine(managedStackTrace.ToString());
}

int ICoreEventHandler.OnRunScript(string script, uint oidSelf)
[UnmanagedCallersOnly]
internal static unsafe int RunScriptHandler(IntPtr pScript, uint oidSelf)
{
int retVal = -1;
objectSelf = oidSelf;
scriptContexts.Push(oidSelf);
string? script = NwStringMarshaller.ConvertToManaged((byte*)pScript);

try
{
OnRunScript?.Invoke(script, oidSelf, out retVal);
OnRunScript?.Invoke(script!, oidSelf, out retVal);
}
catch (Exception e)
{
Expand All @@ -76,7 +82,8 @@ int ICoreEventHandler.OnRunScript(string script, uint oidSelf)
return retVal;
}

void ICoreEventHandler.OnClosure(ulong eid, uint oidSelf)
[UnmanagedCallersOnly]
internal static void ClosureHandler(ulong eid, uint oidSelf)
{
uint old = objectSelf;
objectSelf = oidSelf;
Expand Down
51 changes: 20 additions & 31 deletions src/Core/NWNCore.Native.Events.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,33 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace NWN.Core
{
public static partial class NWNCore
public static unsafe partial class NWNCore
{
public delegate void MainLoopHandlerDelegate(ulong frame);
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterMainLoopHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterMainLoopHandler(delegate* unmanaged<ulong, void> handler);

public delegate int RunScriptHandlerDelegate(string script, uint oid);
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterRunScriptHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterRunScriptHandler(delegate* unmanaged<IntPtr, uint, int> handler);

public delegate void ClosureHandlerDelegate(ulong eid, uint oid);
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterClosureHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterClosureHandler(delegate* unmanaged<ulong, uint, void> handler);

public delegate void SignalHandlerDelegate(string signal);
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterSignalHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterSignalHandler(delegate* unmanaged<IntPtr, void> handler);

public delegate void AssertHandlerDelegate(string message, string stackTrace);
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterAssertHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterAssertHandler(delegate* unmanaged<IntPtr, IntPtr, void> handler);

public delegate void CrashHandlerDelegate(int signal, string stackTrace);

[StructLayout(LayoutKind.Sequential)]
public struct NativeEventHandles
{
public MainLoopHandlerDelegate MainLoop;
public RunScriptHandlerDelegate RunScript;
public ClosureHandlerDelegate Closure;
public SignalHandlerDelegate Signal;
public AssertHandlerDelegate AssertFail;
public CrashHandlerDelegate CrashHandler;
}

#if !NETCOREAPP3_1
[StructLayout(LayoutKind.Sequential)]
public unsafe struct NativeEventHandlesUnmanaged
{
public delegate* unmanaged<ulong, void> MainLoop;
public delegate* unmanaged<IntPtr, uint, int> RunScript;
public delegate* unmanaged<ulong, uint, void> Closure;
public delegate* unmanaged<IntPtr, void> Signal;
public delegate* unmanaged<IntPtr, IntPtr, void> AssertFail;
public delegate* unmanaged<int, IntPtr, void> CrashHandler;
}
#endif
[LibraryImport("NWNX_DotNET", EntryPoint = "RegisterCrashHandler")]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
public static partial void RegisterCrashHandler(delegate* unmanaged<int, IntPtr, void> handler);
}
}
33 changes: 0 additions & 33 deletions src/Core/NWNCore.Native.Globals.cs

This file was deleted.

Loading
Loading