mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-01-12 22:58:01 +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 )
|
||||
{
|
||||
this.call = call;
|
||||
Console.WriteLine( $"{this.GetType().ToString()} == {call.Value}" );
|
||||
}
|
||||
|
||||
public void OnCompleted( Action continuation )
|
||||
{
|
||||
var ts = TaskScheduler.Current;
|
||||
var sc = SynchronizationContext.Current;
|
||||
|
||||
while ( !IsCompleted )
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
||||
continuation();
|
||||
Dispatch.OnCallComplete( call, continuation );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//
|
||||
// Dispatch is responsible for pumping the
|
||||
// event loop.
|
||||
//
|
||||
Dispatch.Init();
|
||||
Dispatch.ClientPipe = SteamAPI.GetHSteamPipe();
|
||||
Console.WriteLine( $"Dispatch.ClientPipe = {Dispatch.ClientPipe.Value}" );
|
||||
|
||||
AddInterface<SteamApps>();
|
||||
AddInterface<SteamFriends>();
|
||||
AddInterface<SteamInput>();
|
||||
@ -51,7 +59,11 @@ namespace Steamworks
|
||||
|
||||
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;
|
||||
|
||||
internal static async void RunCallbacksAsync()
|
||||
{
|
||||
while ( IsValid )
|
||||
{
|
||||
await Task.Delay( 16 );
|
||||
|
||||
try
|
||||
{
|
||||
RunCallbacks();
|
||||
}
|
||||
catch ( System.Exception e )
|
||||
{
|
||||
OnCallbackException?.Invoke( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
@ -106,6 +102,8 @@ namespace Steamworks
|
||||
|
||||
internal static void Cleanup()
|
||||
{
|
||||
Dispatch.ClientPipe = 0;
|
||||
|
||||
initialized = false;
|
||||
|
||||
Event.DisposeAllClient();
|
||||
@ -119,9 +117,8 @@ namespace Steamworks
|
||||
|
||||
public static void RunCallbacks()
|
||||
{
|
||||
if ( !IsValid ) return;
|
||||
|
||||
SteamAPI.RunCallbacks();
|
||||
if ( Dispatch.ClientPipe != 0 )
|
||||
Dispatch.Frame( Dispatch.ClientPipe );
|
||||
}
|
||||
|
||||
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}\")" );
|
||||
}
|
||||
|
||||
//
|
||||
// Dispatch is responsible for pumping the
|
||||
// event loop.
|
||||
//
|
||||
Dispatch.Init();
|
||||
Dispatch.ServerPipe = SteamGameServer.GetHSteamPipe();
|
||||
Console.WriteLine( $"Dispatch.ServerPipe = {Dispatch.ServerPipe.Value}" );
|
||||
|
||||
AddInterface<SteamServer>();
|
||||
|
||||
//
|
||||
@ -103,7 +111,11 @@ namespace Steamworks
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
internal static async void RunCallbacksAsync()
|
||||
{
|
||||
while ( IsValid )
|
||||
{
|
||||
try
|
||||
{
|
||||
RunCallbacks();
|
||||
}
|
||||
catch ( System.Exception e )
|
||||
{
|
||||
OnCallbackException?.Invoke( e );
|
||||
}
|
||||
|
||||
await Task.Delay( 16 );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the callbacks. This is also called in Async callbacks.
|
||||
/// </summary>
|
||||
public static void RunCallbacks()
|
||||
{
|
||||
SteamGameServer.RunCallbacks();
|
||||
if ( Dispatch.ServerPipe != 0 )
|
||||
{
|
||||
Dispatch.Frame( Dispatch.ServerPipe );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -49,6 +49,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="CodeWriter\ClassVTable.cs" />
|
||||
<Compile Include="CodeWriter\Constants.cs" />
|
||||
<Compile Include="CodeWriter\CustomEnums.cs" />
|
||||
<Compile Include="CodeWriter\StructCallbacks.cs" />
|
||||
<Compile Include="CodeWriter\Types\BaseType.cs" />
|
||||
<Compile Include="CodeWriter\Writing.cs" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user