Generated callback registration

This commit is contained in:
Garry Newman 2016-10-30 20:52:42 +00:00
parent 17b84c4f58
commit 04c2118ed8
15 changed files with 7800 additions and 459 deletions

View File

@ -320,7 +320,7 @@ public void DownloadFile()
{ {
Assert.IsTrue( client.IsValid ); Assert.IsTrue( client.IsValid );
var item = client.Workshop.GetItem( 661319648); var item = client.Workshop.GetItem( 787387588 );
if ( !item.Installed ) if ( !item.Installed )
{ {

View File

@ -19,11 +19,11 @@ public class BaseSteamworks : IDisposable
public virtual void Dispose() public virtual void Dispose()
{ {
foreach ( var d in Disposables ) foreach ( var h in CallbackHandles )
{ {
d.Dispose(); h.Remove( this );
} }
Disposables.Clear(); CallbackHandles.Clear();
if ( Workshop != null ) if ( Workshop != null )
{ {
@ -65,8 +65,6 @@ public bool IsValid
internal Interop.NativeInterface native; internal Interop.NativeInterface native;
internal virtual bool IsGameServer { get { return false; } } internal virtual bool IsGameServer { get { return false; } }
private List<IDisposable> Disposables = new List<IDisposable>();
public enum MessageType : int public enum MessageType : int
{ {
Message = 0, Message = 0,
@ -78,18 +76,11 @@ public enum MessageType : int
/// </summary> /// </summary>
public Action<MessageType, string> OnMessage; public Action<MessageType, string> OnMessage;
/// <summary>
/// Global callback type
/// </summary>
internal void AddCallback<T, TSmall>( Action<T, bool> Callback, int id ) where T : new()
{
var callback = new Callback<T, TSmall>( native.api, IsGameServer, id, Callback );
Disposables.Add( callback );
}
internal void AddCallback<T>( Action<T, bool> Callback, int id ) where T : new() private List<SteamNative.Callback.Handle> CallbackHandles = new List<SteamNative.Callback.Handle>();
internal void RegisterCallbackHandle( SteamNative.Callback.Handle handle )
{ {
AddCallback<T, T>( Callback, id ); CallbackHandles.Add( handle );
} }
public Action OnUpdate; public Action OnUpdate;

View File

@ -3,22 +3,6 @@
namespace Facepunch.Steamworks.Callbacks.Workshop namespace Facepunch.Steamworks.Callbacks.Workshop
{ {
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
internal struct ItemInstalled
{
public uint AppId;
public ulong FileId;
public const int CallbackId = SteamNative.CallbackIdentifiers.ClientUGC + 5;
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
internal struct Small
{
public uint AppId;
public ulong FileId;
};
};
internal class QueryCompleted : CallResult<SteamNative.SteamUGCQueryCompleted_t, SteamNative.SteamUGCQueryCompleted_t.PackSmall> internal class QueryCompleted : CallResult<SteamNative.SteamUGCQueryCompleted_t, SteamNative.SteamUGCQueryCompleted_t.PackSmall>
{ {
public override int CallbackId { get { return SteamNative.SteamUGCQueryCompleted_t.CallbackId; } } public override int CallbackId { get { return SteamNative.SteamUGCQueryCompleted_t.CallbackId; } }

View File

@ -137,7 +137,6 @@
<Compile Include="Interfaces\Workshop.Editor.cs" /> <Compile Include="Interfaces\Workshop.Editor.cs" />
<Compile Include="Interfaces\Workshop.Item.cs" /> <Compile Include="Interfaces\Workshop.Item.cs" />
<Compile Include="Interfaces\Workshop.Query.cs" /> <Compile Include="Interfaces\Workshop.Query.cs" />
<Compile Include="Interop\Callback.cs" />
<Compile Include="Interop\CallResult.cs" /> <Compile Include="Interop\CallResult.cs" />
<Compile Include="Interop\Native.cs" /> <Compile Include="Interop\Native.cs" />
<Compile Include="Interop\ServerRules.cs" /> <Compile Include="Interop\ServerRules.cs" />
@ -179,12 +178,10 @@
<Compile Include="SteamNative\SteamNative.SteamUserStats.cs" /> <Compile Include="SteamNative\SteamNative.SteamUserStats.cs" />
<Compile Include="SteamNative\SteamNative.SteamUtils.cs" /> <Compile Include="SteamNative\SteamNative.SteamUtils.cs" />
<Compile Include="SteamNative\SteamNative.SteamVideo.cs" /> <Compile Include="SteamNative\SteamNative.SteamVideo.cs" />
<Compile Include="SteamNative\SteamNative.Callback.cs" />
<Compile Include="SteamNative\SteamNative.Structs.cs" /> <Compile Include="SteamNative\SteamNative.Structs.cs" />
<Compile Include="SteamNative\SteamNative.Types.cs" /> <Compile Include="SteamNative\SteamNative.Types.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="Interop\Callback.This.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent> <PostBuildEvent>

View File

@ -14,12 +14,12 @@ public class Networking : IDisposable
internal SteamNative.SteamNetworking networking; internal SteamNative.SteamNetworking networking;
internal Networking( BaseSteamworks sw, SteamNative.SteamNetworking networking ) internal Networking( BaseSteamworks steamworks, SteamNative.SteamNetworking networking )
{ {
this.networking = networking; this.networking = networking;
sw.AddCallback<SteamNative.P2PSessionRequest_t>( onP2PConnectionRequest, SteamNative.P2PSessionRequest_t.CallbackId ); SteamNative.P2PSessionRequest_t.RegisterCallback( steamworks, onP2PConnectionRequest );
sw.AddCallback<SteamNative.P2PSessionConnectFail_t>( onP2PConnectionFailed, SteamNative.P2PSessionConnectFail_t.CallbackId ); SteamNative.P2PSessionConnectFail_t.RegisterCallback( steamworks, onP2PConnectionFailed );
} }
public void Dispose() public void Dispose()

View File

@ -22,8 +22,10 @@ internal Workshop( BaseSteamworks steamworks, SteamNative.SteamUGC ugc, SteamNat
this.steamworks = steamworks; this.steamworks = steamworks;
this.remoteStorage = remoteStorage; this.remoteStorage = remoteStorage;
steamworks.AddCallback<SteamNative.DownloadItemResult_t, SteamNative.DownloadItemResult_t.PackSmall>( onDownloadResult, SteamNative.DownloadItemResult_t.CallbackId ); SteamNative.DownloadItemResult_t.RegisterCallback( steamworks, onDownloadResult );
steamworks.AddCallback<ItemInstalled, ItemInstalled.Small>( onItemInstalled, ItemInstalled.CallbackId ); SteamNative.ItemInstalled_t.RegisterCallback( steamworks, onItemInstalled );
// steamworks.AddCallback<ItemInstalled, ItemInstalled.Small>( onItemInstalled, ItemInstalled.CallbackId );
} }
public void Dispose() public void Dispose()
@ -37,10 +39,10 @@ public void Dispose()
OnItemInstalled = null; OnItemInstalled = null;
} }
private void onItemInstalled( ItemInstalled obj, bool failed ) private void onItemInstalled( SteamNative.ItemInstalled_t obj, bool failed )
{ {
if ( OnItemInstalled != null ) if ( OnItemInstalled != null )
OnItemInstalled( obj.FileId ); OnItemInstalled( obj.PublishedFileId );
} }
private void onDownloadResult( SteamNative.DownloadItemResult_t obj, bool failed ) private void onDownloadResult( SteamNative.DownloadItemResult_t obj, bool failed )

View File

@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Facepunch.Steamworks.Interop.VTable.This
{
[StructLayout( LayoutKind.Sequential )]
internal struct Callback
{
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void Result( IntPtr thisptr, IntPtr pvParam );
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void ResultBool( IntPtr thisptr, IntPtr pvParam, bool bIOFailure, SteamNative.SteamAPICall_t hSteamAPICall );
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate int GetSize( IntPtr thisptr );
[MarshalAs(UnmanagedType.FunctionPtr)] public ResultBool RunCallResult;
[MarshalAs(UnmanagedType.FunctionPtr)] public Result RunCallback;
[MarshalAs(UnmanagedType.FunctionPtr)] public GetSize GetCallbackSizeBytes;
internal static IntPtr Get( Action<IntPtr, IntPtr, bool> onRunCallback, int size, Interop.Callback cb )
{
var ptr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback ) ) );
Callback.Result da = ( _, p ) => { onRunCallback( _, p, false ); };
Callback.ResultBool db = ( _, p, iofailure, call ) => { onRunCallback( _, p, iofailure ); };
Callback.GetSize dc = ( _ ) => { return size; };
cb.AddHandle( GCHandle.Alloc( da ) );
cb.AddHandle( GCHandle.Alloc( db ) );
cb.AddHandle( GCHandle.Alloc( dc ) );
var table = new Callback()
{
RunCallback = da,
RunCallResult = db,
GetCallbackSizeBytes = dc
};
Marshal.StructureToPtr( table, ptr, false );
return ptr;
}
}
}

View File

@ -1,157 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
//
// THANSK AGAIN TO STEAMWORKS.NET
//
// https://github.com/rlabrecque/Steamworks.NET/blob/97935154cf08f60da92c55e2c73ee60a8f456e03/Plugins/Steamworks.NET/CallbackDispatcher.cs
//
// Calling Conventions:
// Unity x86 Windows - StdCall (No this pointer)
// Unity x86 Linux - Cdecl
// Unity x86 OSX - Cdecl
// Unity x64 Windows - Cdecl
// Unity x64 Linux - Cdecl
// Unity x64 OSX - Cdecl
// Microsoft x86 Windows - ThisCall
// Microsoft x64 Windows - ThisCall
// Mono x86 Linux - Cdecl
// Mono x86 OSX - Cdecl
// Mono x64 Linux - Cdecl
// Mono x64 OSX - Cdecl
// Mono on Windows is probably not supported.
namespace Facepunch.Steamworks.Interop
{
internal partial class Callback : IDisposable
{
List<GCHandle> Handles = new List<GCHandle>();
public virtual void Dispose()
{
foreach ( var handle in Handles )
{
handle.Free();
}
Handles = null;
}
internal void AddHandle( GCHandle gCHandle )
{
Handles.Add( gCHandle );
}
}
internal partial class Callback<T, TSmall> : Callback where T : new()
{
private SteamNative.SteamApi api;
public int CallbackId = 0;
public bool GameServer = false;
public Action<T, bool> Function;
private IntPtr vTablePtr = IntPtr.Zero;
private GCHandle callbackPin;
private readonly int m_size = Marshal.SizeOf(typeof(T));
public Callback( SteamNative.SteamApi api, bool gameserver, int callbackid, Action<T, bool> func )
{
this.api = api;
GameServer = gameserver;
CallbackId = callbackid;
Function = func;
BuildVTable();
this.api.SteamAPI_RegisterCallback( callbackPin.AddrOfPinnedObject(), CallbackId );
}
public override void Dispose()
{
if ( callbackPin.IsAllocated )
{
api.SteamAPI_UnregisterCallback( callbackPin.AddrOfPinnedObject() );
callbackPin.Free();
}
if ( vTablePtr != IntPtr.Zero )
{
Marshal.FreeHGlobal( vTablePtr );
vTablePtr = IntPtr.Zero;
}
base.Dispose();
}
private void OnRunCallback( IntPtr thisObject, IntPtr ptr, bool failure )
{
if ( callbackPin == null ) throw new System.Exception( "Callback wasn't pinned!" );
if ( vTablePtr == IntPtr.Zero ) throw new System.Exception( "vTablePtr wasn't pinned!" );
if ( thisObject != IntPtr.Zero && thisObject != callbackPin.AddrOfPinnedObject() ) throw new System.Exception( "This wasn't valid! ("+ thisObject.ToInt64() + ") ( "+ callbackPin.AddrOfPinnedObject().ToInt64() + " )" );
if ( SteamNative.Platform.PackSmall && typeof(T) != typeof( TSmall ) ) throw new System.Exception( "Callback should use PackSmall" );
if ( failure )
{
Function( new T(), failure );
return;
}
T data = (T) Marshal.PtrToStructure( ptr, typeof(T) );
Function( data, failure );
}
private int GetSize()
{
Console.WriteLine( "GET SIZE CALLED" );
throw new System.NotImplementedException();
}
// Steamworks.NET Specific
private void BuildVTable()
{
InitVTable();
var callbackBase = new CallbackBase()
{
vTablePtr = vTablePtr,
CallbackFlags = GameServer ? (byte) CallbackBase.Flags.GameServer : (byte) 0,
CallbackId = CallbackId
};
callbackPin = GCHandle.Alloc( callbackBase, GCHandleType.Pinned );
}
void InitVTable()
{
if ( Config.UseThisCall )
{
vTablePtr = VTable.This.Callback.Get( OnRunCallback, Marshal.SizeOf( typeof( T ) ), this );
return;
}
throw new System.NotImplementedException();
}
}
[StructLayout( LayoutKind.Sequential )]
internal class CallbackBase
{
internal enum Flags : byte
{
Registered = 0x01,
GameServer = 0x02
}
public IntPtr vTablePtr;
public byte CallbackFlags;
public int CallbackId;
};
}

View File

@ -51,7 +51,7 @@ internal ServerAuth( Server s )
{ {
server = s; server = s;
server.AddCallback<SteamNative.ValidateAuthTicketResponse_t>( OnAuthTicketValidate, SteamNative.ValidateAuthTicketResponse_t.CallbackId ); SteamNative.ValidateAuthTicketResponse_t.RegisterCallback( server, OnAuthTicketValidate );
} }
void OnAuthTicketValidate( SteamNative.ValidateAuthTicketResponse_t data, bool b ) void OnAuthTicketValidate( SteamNative.ValidateAuthTicketResponse_t data, bool b )

View File

@ -0,0 +1,83 @@
using System;
using System.Runtime.InteropServices;
using Facepunch.Steamworks;
namespace SteamNative
{
[StructLayout( LayoutKind.Sequential )]
internal class Callback
{
internal enum Flags : byte
{
Registered = 0x01,
GameServer = 0x02
}
public IntPtr vTablePtr;
public byte CallbackFlags;
public int CallbackId;
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public class VTable
{
public IntPtr ResultA;
public IntPtr ResultB;
public IntPtr GetSize;
}
//
// All possible functions
//
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void Result( IntPtr thisptr, IntPtr pvParam );
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void ResultWithInfo( IntPtr thisptr, IntPtr pvParam, bool bIOFailure, SteamNative.SteamAPICall_t hSteamAPICall );
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate int GetSize( IntPtr thisptr );
//
// Created on registration of a callback
//
public class Handle : IDisposable
{
public GCHandle FuncA;
public GCHandle FuncB;
public GCHandle FuncC;
public IntPtr vTablePtr;
public GCHandle PinnedCallback;
public void Dispose()
{
if ( FuncA.IsAllocated )
FuncA.Free();
if ( FuncB.IsAllocated )
FuncB.Free();
if ( FuncC.IsAllocated )
FuncC.Free();
if ( PinnedCallback.IsAllocated )
PinnedCallback.Free();
if ( vTablePtr != IntPtr.Zero )
{
Marshal.FreeHGlobal( vTablePtr );
vTablePtr = IntPtr.Zero;
}
}
internal void Remove( BaseSteamworks baseSteamworks )
{
if ( PinnedCallback.IsAllocated )
{
baseSteamworks.native.api.SteamAPI_UnregisterCallback( PinnedCallback.AddrOfPinnedObject() );
}
Dispose();
}
}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -16,174 +16,6 @@ public CodeWriter( SteamApiDefinition def )
{ {
this.def = def; this.def = def;
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_Init",
ReturnType = "bool",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_RunCallbacks",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_RunCallbacks",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_RegisterCallback",
ReturnType = "void",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pCallback",
Type = "void *"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "callback",
Type = "int"
},
}
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_UnregisterCallback",
ReturnType = "void",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pCallback",
Type = "void *"
}
}
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamInternal_GameServer_Init",
ReturnType = "bool",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "unIP",
Type = "uint32"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usPort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usGamePort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usQueryPort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "eServerMode",
Type = "int"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pchVersionString",
Type = "const char *"
}
},
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_Shutdown",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_Shutdown",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_GetHSteamUser",
ReturnType = "HSteamUser",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_GetHSteamPipe",
ReturnType = "HSteamPipe",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_GetHSteamUser",
ReturnType = "HSteamUser",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_GetHSteamPipe",
ReturnType = "HSteamPipe",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamInternal_CreateInterface",
ReturnType = "void *",
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "version",
Type = "const char *"
}
},
NeedsSelfPointer = false
} );
WorkoutTypes(); WorkoutTypes();
} }

View File

@ -26,7 +26,8 @@ public class TypeDef
"CSteamAPIContext", "CSteamAPIContext",
"CCallResult", "CCallResult",
"CCallback", "CCallback",
"ValvePackingSentinel_t" "ValvePackingSentinel_t",
"CCallbackBase"
}; };
void Structs() void Structs()
@ -115,6 +116,11 @@ void Structs()
} }
EndBlock(); EndBlock();
if ( !string.IsNullOrEmpty( c.CallbackId ) )
{
Callback( c );
}
} }
EndBlock(); EndBlock();
WriteLine(); WriteLine();
@ -187,5 +193,81 @@ private void StructFields( SteamApiDefinition.StructDef.StructFields[] fields )
WriteLine( $"public {t} {CleanMemberName( m.Name )}; // {m.Name} {m.Type}" ); WriteLine( $"public {t} {CleanMemberName( m.Name )}; // {m.Name} {m.Type}" );
} }
} }
private void Callback( SteamApiDefinition.StructDef c )
{
WriteLine();
StartBlock( $"public static void RegisterCallback( Facepunch.Steamworks.BaseSteamworks steamworks, Action<{c.Name}, bool> CallbackFunction )" );
{
WriteLine( $"var handle = new Callback.Handle();" );
WriteLine( $"" );
WriteLine( "//" );
WriteLine( "// Create the functions we need for the vtable" );
WriteLine( "//" );
WriteLine( $"Callback.Result funcA = ( _, p ) => {{ CallbackFunction( FromPointer( p ), false ); }};" );
WriteLine( $"Callback.ResultWithInfo funcB = ( _, p, iofailure, call ) => {{ CallbackFunction( FromPointer( p ), iofailure ); }};" );
WriteLine( $"Callback.GetSize funcC = ( _ ) => {{ return Marshal.SizeOf( typeof( {c.Name} ) ); }};" );
WriteLine();
WriteLine( "//" );
WriteLine( "// If this platform is PackSmall, use PackSmall versions of everything instead" );
WriteLine( "//" );
StartBlock( "if ( Platform.PackSmall )" );
{
WriteLine( $"funcA = ( _, p ) => {{ CallbackFunction( PackSmall.FromPointer( p ), false ); }};" );
WriteLine( $"funcB = ( _, p, iofailure, call ) => {{ CallbackFunction( PackSmall.FromPointer( p ), iofailure ); }};" );
WriteLine( $"funcC = ( _ ) => {{ return Marshal.SizeOf( typeof( PackSmall ) ); }};" );
}
EndBlock();
WriteLine( "" );
WriteLine( "//" );
WriteLine( "// Allocate a handle to each function, so they don't get disposed" );
WriteLine( "//" );
WriteLine( "handle.FuncA = GCHandle.Alloc( funcA );" );
WriteLine( "handle.FuncB = GCHandle.Alloc( funcB );" );
WriteLine( "handle.FuncC = GCHandle.Alloc( funcC );" );
WriteLine();
WriteLine( "//" );
WriteLine( "// Create the VTable by manually allocating the memory and copying across" );
WriteLine( "//" );
WriteLine( "handle.vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTable ) ) );" );
StartBlock( "var vTable = new Callback.VTable()" );
{
WriteLine( "ResultA = Marshal.GetFunctionPointerForDelegate( funcB ), // The order of these functions is a point of contention" );
WriteLine( "ResultB = Marshal.GetFunctionPointerForDelegate( funcA ), // Doesn't seem to matter win64, but win32 crashes if WithInfo not first" );
WriteLine( "GetSize = Marshal.GetFunctionPointerForDelegate( funcC ), // Which is the opposite of how they are in code, but whatever works" );
}
EndBlock( ";" );
WriteLine( "Marshal.StructureToPtr( vTable, handle.vTablePtr, false );" );
WriteLine( "" );
WriteLine( "//" );
WriteLine( "// Create the callback object" );
WriteLine( "//" );
WriteLine( $"var cb = new Callback();" );
WriteLine( $"cb.vTablePtr = handle.vTablePtr;" );
WriteLine( $"cb.CallbackFlags = steamworks.IsGameServer ? (byte) SteamNative.Callback.Flags.GameServer : (byte) 0;" );
WriteLine( $"cb.CallbackId = CallbackId;" );
WriteLine( "" );
WriteLine( "//" );
WriteLine( "// Pin the callback, so it doesn't get garbage collected and we can pass the pointer to native" );
WriteLine( "//" );
WriteLine( $"handle.PinnedCallback = GCHandle.Alloc( cb, GCHandleType.Pinned );" );
WriteLine( "" );
WriteLine( "//" );
WriteLine( "// Register the callback with Steam" );
WriteLine( "//" );
WriteLine( $"steamworks.native.api.SteamAPI_RegisterCallback( handle.PinnedCallback.AddrOfPinnedObject(), CallbackId );" );
WriteLine();
WriteLine( "steamworks.RegisterCallbackHandle( handle );" );
}
EndBlock();
}
} }
} }

View File

@ -14,6 +14,8 @@ static void Main( string[] args )
var content = System.IO.File.ReadAllText( "steam_api.json" ); var content = System.IO.File.ReadAllText( "steam_api.json" );
var def = Newtonsoft.Json.JsonConvert.DeserializeObject<SteamApiDefinition>( content ); var def = Newtonsoft.Json.JsonConvert.DeserializeObject<SteamApiDefinition>( content );
AddExtras( def );
var parser = new CodeParser( @"D:\Dropbox (Facepunch Studios)\Software\SteamWorks\steamworks_sdk_138a\public\steam" ); var parser = new CodeParser( @"D:\Dropbox (Facepunch Studios)\Software\SteamWorks\steamworks_sdk_138a\public\steam" );
parser.ExtendDefinition( def ); parser.ExtendDefinition( def );
@ -22,6 +24,195 @@ static void Main( string[] args )
generator.ToFolder( "../Facepunch.Steamworks/SteamNative/" ); generator.ToFolder( "../Facepunch.Steamworks/SteamNative/" );
} }
private static void AddExtras( SteamApiDefinition def )
{
def.structs.Add( new SteamApiDefinition.StructDef()
{
Name = "ItemInstalled_t",
Fields = new SteamApiDefinition.StructDef.StructFields[]
{
new SteamApiDefinition.StructDef.StructFields()
{
Name = "m_unAppID",
Type = "AppId_t"
},
new SteamApiDefinition.StructDef.StructFields()
{
Name = "m_nPublishedFileId",
Type = "PublishedFileId_t"
}
}
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_Init",
ReturnType = "bool",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_RunCallbacks",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_RunCallbacks",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_RegisterCallback",
ReturnType = "void",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pCallback",
Type = "void *"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "callback",
Type = "int"
},
}
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_UnregisterCallback",
ReturnType = "void",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pCallback",
Type = "void *"
}
}
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamInternal_GameServer_Init",
ReturnType = "bool",
NeedsSelfPointer = false,
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "unIP",
Type = "uint32"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usPort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usGamePort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "usQueryPort",
Type = "uint16"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "eServerMode",
Type = "int"
},
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "pchVersionString",
Type = "const char *"
}
},
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_Shutdown",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_Shutdown",
ReturnType = "void",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_GetHSteamUser",
ReturnType = "HSteamUser",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamAPI_GetHSteamPipe",
ReturnType = "HSteamPipe",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_GetHSteamUser",
ReturnType = "HSteamUser",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamGameServer_GetHSteamPipe",
ReturnType = "HSteamPipe",
NeedsSelfPointer = false
} );
def.methods.Add( new SteamApiDefinition.MethodDef()
{
ClassName = "SteamApi",
Name = "SteamInternal_CreateInterface",
ReturnType = "void *",
Params = new SteamApiDefinition.MethodDef.ParamType[]
{
new SteamApiDefinition.MethodDef.ParamType()
{
Name = "version",
Type = "const char *"
}
},
NeedsSelfPointer = false
} );
}
} }
} }

View File

@ -55,7 +55,7 @@ public class StructFields
public string CallbackId { get; set; } public string CallbackId { get; set; }
} }
public StructDef[] structs { get; set; } public List<StructDef> structs { get; set; }
public class MethodDef public class MethodDef
{ {