mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-04-16 14:22:27 +03:00
New dispatch system
This commit is contained in:
parent
8c603d4880
commit
3f88106c0b
@ -15,19 +15,12 @@ namespace Steamworks
|
|||||||
public CallbackResult( SteamAPICall_t call )
|
public CallbackResult( SteamAPICall_t call )
|
||||||
{
|
{
|
||||||
this.call = call;
|
this.call = call;
|
||||||
|
Console.WriteLine( $"{this.GetType().ToString()} == {call.Value}" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnCompleted( Action continuation )
|
public void OnCompleted( Action continuation )
|
||||||
{
|
{
|
||||||
var ts = TaskScheduler.Current;
|
Dispatch.OnCallComplete( call, continuation );
|
||||||
var sc = SynchronizationContext.Current;
|
|
||||||
|
|
||||||
while ( !IsCompleted )
|
|
||||||
{
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
continuation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T? GetResult()
|
public T? GetResult()
|
||||||
|
146
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
146
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Steamworks.Data;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
internal static class Dispatch
|
||||||
|
{
|
||||||
|
#region interop
|
||||||
|
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||||
|
internal static extern void SteamAPI_ManualDispatch_Init();
|
||||||
|
|
||||||
|
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_RunFrame", CallingConvention = CallingConvention.Cdecl )]
|
||||||
|
internal static extern void SteamAPI_ManualDispatch_RunFrame( HSteamPipe pipe );
|
||||||
|
|
||||||
|
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetNextCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||||
|
[return: MarshalAs( UnmanagedType.I1 )]
|
||||||
|
internal static extern bool SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe pipe, [In, Out] ref CallbackMsg_t msg );
|
||||||
|
|
||||||
|
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_FreeLastCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||||
|
[return: MarshalAs( UnmanagedType.I1 )]
|
||||||
|
internal static extern bool SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe pipe );
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPlatformPackSize )]
|
||||||
|
internal struct CallbackMsg_t
|
||||||
|
{
|
||||||
|
public HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
|
||||||
|
public CallbackType Type; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
|
||||||
|
public IntPtr m_pubParam; // Points to the callback structure
|
||||||
|
public int m_cubParam; // Size of the data pointed to by m_pubParam
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
internal static HSteamPipe ClientPipe { get; set; }
|
||||||
|
internal static HSteamPipe ServerPipe { get; set; }
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
SteamAPI_ManualDispatch_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Frame()
|
||||||
|
{
|
||||||
|
if ( ClientPipe != 0 )
|
||||||
|
Frame( ClientPipe );
|
||||||
|
|
||||||
|
if ( ServerPipe != 0)
|
||||||
|
Frame( ServerPipe );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Frame( HSteamPipe pipe )
|
||||||
|
{
|
||||||
|
SteamAPI_ManualDispatch_RunFrame( pipe );
|
||||||
|
|
||||||
|
CallbackMsg_t msg = default;
|
||||||
|
|
||||||
|
while ( SteamAPI_ManualDispatch_GetNextCallback( pipe, ref msg ) )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessCallback( msg );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SteamAPI_ManualDispatch_FreeLastCallback( pipe );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ProcessCallback( CallbackMsg_t msg )
|
||||||
|
{
|
||||||
|
if ( msg.Type == CallbackType.SteamAPICallCompleted )
|
||||||
|
{
|
||||||
|
ProcessResult( msg );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( $"Callback: {msg.Type}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ProcessResult( CallbackMsg_t msg )
|
||||||
|
{
|
||||||
|
var result = SteamAPICallCompleted_t.Fill( msg.m_pubParam );
|
||||||
|
|
||||||
|
Console.WriteLine( $"Result: {result.AsyncCall} / {result.Callback}" );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do we have an entry added via OnCallComplete
|
||||||
|
//
|
||||||
|
if ( !Callbacks.TryGetValue( result.AsyncCall, out var callbackInfo ) )
|
||||||
|
{
|
||||||
|
// Do we care? Should we throw errors?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Callbacks.Remove( result.AsyncCall );
|
||||||
|
|
||||||
|
// At this point whatever async routine called this
|
||||||
|
// continues running.
|
||||||
|
callbackInfo.continuation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void LoopClientAsync()
|
||||||
|
{
|
||||||
|
while ( ClientPipe != 0 )
|
||||||
|
{
|
||||||
|
Frame( ClientPipe );
|
||||||
|
await Task.Delay( 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( $"Exiting ClientPipe: {ClientPipe}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void LoopServerAsync()
|
||||||
|
{
|
||||||
|
while ( ServerPipe != 0 )
|
||||||
|
{
|
||||||
|
Frame( ServerPipe );
|
||||||
|
await Task.Delay( 32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( $"Exiting ServerPipe: {ServerPipe}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CallbackInfo
|
||||||
|
{
|
||||||
|
public Action continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<ulong, CallbackInfo> Callbacks = new Dictionary<ulong, CallbackInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Watch for a steam api call
|
||||||
|
/// </summary>
|
||||||
|
internal static void OnCallComplete( SteamAPICall_t call, Action continuation )
|
||||||
|
{
|
||||||
|
Callbacks[call.Value] = new CallbackInfo
|
||||||
|
{
|
||||||
|
continuation = continuation
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,14 @@ namespace Steamworks
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dispatch is responsible for pumping the
|
||||||
|
// event loop.
|
||||||
|
//
|
||||||
|
Dispatch.Init();
|
||||||
|
Dispatch.ClientPipe = SteamAPI.GetHSteamPipe();
|
||||||
|
Console.WriteLine( $"Dispatch.ClientPipe = {Dispatch.ClientPipe.Value}" );
|
||||||
|
|
||||||
AddInterface<SteamApps>();
|
AddInterface<SteamApps>();
|
||||||
AddInterface<SteamFriends>();
|
AddInterface<SteamFriends>();
|
||||||
AddInterface<SteamInput>();
|
AddInterface<SteamInput>();
|
||||||
@ -51,7 +59,11 @@ namespace Steamworks
|
|||||||
|
|
||||||
if ( asyncCallbacks )
|
if ( asyncCallbacks )
|
||||||
{
|
{
|
||||||
RunCallbacksAsync();
|
//
|
||||||
|
// This will keep looping in the background every 16 ms
|
||||||
|
// until we shut down.
|
||||||
|
//
|
||||||
|
Dispatch.LoopClientAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,22 +90,6 @@ namespace Steamworks
|
|||||||
|
|
||||||
public static bool IsValid => initialized;
|
public static bool IsValid => initialized;
|
||||||
|
|
||||||
internal static async void RunCallbacksAsync()
|
|
||||||
{
|
|
||||||
while ( IsValid )
|
|
||||||
{
|
|
||||||
await Task.Delay( 16 );
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RunCallbacks();
|
|
||||||
}
|
|
||||||
catch ( System.Exception e )
|
|
||||||
{
|
|
||||||
OnCallbackException?.Invoke( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
@ -106,6 +102,8 @@ namespace Steamworks
|
|||||||
|
|
||||||
internal static void Cleanup()
|
internal static void Cleanup()
|
||||||
{
|
{
|
||||||
|
Dispatch.ClientPipe = 0;
|
||||||
|
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
|
||||||
Event.DisposeAllClient();
|
Event.DisposeAllClient();
|
||||||
@ -119,9 +117,8 @@ namespace Steamworks
|
|||||||
|
|
||||||
public static void RunCallbacks()
|
public static void RunCallbacks()
|
||||||
{
|
{
|
||||||
if ( !IsValid ) return;
|
if ( Dispatch.ClientPipe != 0 )
|
||||||
|
Dispatch.Frame( Dispatch.ClientPipe );
|
||||||
SteamAPI.RunCallbacks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void UnregisterCallback( IntPtr intPtr )
|
internal static void UnregisterCallback( IntPtr intPtr )
|
||||||
|
@ -85,6 +85,14 @@ namespace Steamworks
|
|||||||
throw new System.Exception( $"InitGameServer returned false ({ipaddress},{init.SteamPort},{init.GamePort},{init.QueryPort},{secure},\"{init.VersionString}\")" );
|
throw new System.Exception( $"InitGameServer returned false ({ipaddress},{init.SteamPort},{init.GamePort},{init.QueryPort},{secure},\"{init.VersionString}\")" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dispatch is responsible for pumping the
|
||||||
|
// event loop.
|
||||||
|
//
|
||||||
|
Dispatch.Init();
|
||||||
|
Dispatch.ServerPipe = SteamGameServer.GetHSteamPipe();
|
||||||
|
Console.WriteLine( $"Dispatch.ServerPipe = {Dispatch.ServerPipe.Value}" );
|
||||||
|
|
||||||
AddInterface<SteamServer>();
|
AddInterface<SteamServer>();
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -103,7 +111,11 @@ namespace Steamworks
|
|||||||
|
|
||||||
if ( asyncCallbacks )
|
if ( asyncCallbacks )
|
||||||
{
|
{
|
||||||
RunCallbacksAsync();
|
//
|
||||||
|
// This will keep looping in the background every 16 ms
|
||||||
|
// until we shut down.
|
||||||
|
//
|
||||||
|
Dispatch.LoopServerAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,29 +148,15 @@ namespace Steamworks
|
|||||||
SteamGameServer.Shutdown();
|
SteamGameServer.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async void RunCallbacksAsync()
|
|
||||||
{
|
|
||||||
while ( IsValid )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RunCallbacks();
|
|
||||||
}
|
|
||||||
catch ( System.Exception e )
|
|
||||||
{
|
|
||||||
OnCallbackException?.Invoke( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay( 16 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run the callbacks. This is also called in Async callbacks.
|
/// Run the callbacks. This is also called in Async callbacks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void RunCallbacks()
|
public static void RunCallbacks()
|
||||||
{
|
{
|
||||||
SteamGameServer.RunCallbacks();
|
if ( Dispatch.ServerPipe != 0 )
|
||||||
|
{
|
||||||
|
Dispatch.Frame( Dispatch.ServerPipe );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CodeWriter\ClassVTable.cs" />
|
<Compile Include="CodeWriter\ClassVTable.cs" />
|
||||||
<Compile Include="CodeWriter\Constants.cs" />
|
<Compile Include="CodeWriter\Constants.cs" />
|
||||||
|
<Compile Include="CodeWriter\CustomEnums.cs" />
|
||||||
<Compile Include="CodeWriter\StructCallbacks.cs" />
|
<Compile Include="CodeWriter\StructCallbacks.cs" />
|
||||||
<Compile Include="CodeWriter\Types\BaseType.cs" />
|
<Compile Include="CodeWriter\Types\BaseType.cs" />
|
||||||
<Compile Include="CodeWriter\Writing.cs" />
|
<Compile Include="CodeWriter\Writing.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user