mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-01-27 14:08:06 +03:00
New parser, no code skimming
This commit is contained in:
parent
1436ce71f5
commit
9a36dd58ff
@ -1,153 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Generator
|
||||
{
|
||||
public partial class CodeParser
|
||||
{
|
||||
public string Content;
|
||||
|
||||
public CodeParser( string folder )
|
||||
{
|
||||
foreach ( var file in System.IO.Directory.GetFiles( folder, "*.h", System.IO.SearchOption.AllDirectories ) )
|
||||
{
|
||||
Content += System.IO.File.ReadAllText( file );
|
||||
}
|
||||
|
||||
Content = Content.Replace( "\r\n", "\n" );
|
||||
Content = Content.Replace( "\n\r", "\n" );
|
||||
}
|
||||
|
||||
internal void ExtendDefinition( SteamApiDefinition def )
|
||||
{
|
||||
//
|
||||
// Get a list of CallbackIds
|
||||
//
|
||||
def.CallbackIds = new Dictionary<string, int>();
|
||||
|
||||
//v1
|
||||
{
|
||||
var r = new Regex( @"enum { (k_[i|I](?:.+)) = ([0-9]+) };" );
|
||||
var ma = r.Matches( Content );
|
||||
|
||||
foreach ( Match m in ma )
|
||||
{
|
||||
def.CallbackIds.Add( m.Groups[1].Value.Substring( 3 ).Replace( "Callbacks", "" ), int.Parse( m.Groups[2].Value ) );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Associate callbackIds with structs
|
||||
//
|
||||
foreach ( var t in def.structs )
|
||||
{
|
||||
if ( !string.IsNullOrEmpty( t.CallbackId ) ) continue;
|
||||
|
||||
// Standard style
|
||||
{
|
||||
var r = new Regex( @"struct "+t.Name+@"\n{ ?\n(?:.)+enum { k_iCallback = (?:(.+) \+ ([0-9]+)|(.+)) };", RegexOptions.Multiline | RegexOptions.IgnoreCase );
|
||||
var m = r.Match( Content );
|
||||
if ( m.Success )
|
||||
{
|
||||
var kName = m.Groups[1].Value;
|
||||
var num = m.Groups[2].Value;
|
||||
|
||||
if ( string.IsNullOrEmpty( kName ) )
|
||||
{
|
||||
kName = m.Groups[3].Value;
|
||||
num = "0";
|
||||
}
|
||||
|
||||
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
|
||||
|
||||
t.CallbackId = $"{kName} + {num}";
|
||||
}
|
||||
}
|
||||
|
||||
// New style
|
||||
{
|
||||
var r = new Regex( @"DEFINE_CALLBACK\( "+t.Name+@", (.+) \+ ([0-9]+) \)" );
|
||||
var m = r.Match( Content );
|
||||
if ( m.Success )
|
||||
{
|
||||
var kName = m.Groups[1].Value;
|
||||
var num = m.Groups[2].Value;
|
||||
|
||||
//kName = kName.Replace( "k_i", "CallbackIdentifiers." ).Replace( "Callbacks", "" );
|
||||
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
|
||||
|
||||
t.CallbackId = $"{kName} + {num}";
|
||||
}
|
||||
}
|
||||
|
||||
// Even Newer Style
|
||||
{
|
||||
var r = new Regex( @"STEAM_CALLBACK_BEGIN\( " + t.Name + @", (.+) \+ ([0-9]+) \)" );
|
||||
var m = r.Match( Content );
|
||||
if ( m.Success )
|
||||
{
|
||||
var kName = m.Groups[1].Value;
|
||||
var num = m.Groups[2].Value;
|
||||
|
||||
//kName = kName.Replace( "k_i", "CallbackIdentifiers." ).Replace( "Callbacks", "" );
|
||||
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
|
||||
|
||||
t.CallbackId = $"{kName} + {num}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Find defines
|
||||
//
|
||||
def.Defines = new Dictionary<string, string>();
|
||||
{
|
||||
var r = new Regex( @"#define ([a-zA-Z_]+) ""(.+)""" );
|
||||
var ma = r.Matches( Content );
|
||||
|
||||
foreach ( Match m in ma )
|
||||
{
|
||||
def.Defines.Add( m.Groups[1].Value.Replace( "Callbacks", "" ), m.Groups[2].Value );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Find missing structs
|
||||
//
|
||||
{
|
||||
var r = new Regex( @"struct ([a-zA-Z]+_t)" );
|
||||
var ma = r.Matches( Content );
|
||||
|
||||
foreach ( Match m in ma )
|
||||
{
|
||||
var s = def.structs.SingleOrDefault( x => x.Name == m.Groups[1].Value );
|
||||
if ( s == null )
|
||||
{
|
||||
Console.WriteLine( "Missing Struct: " + m.Groups[1].Value );
|
||||
}
|
||||
}
|
||||
|
||||
//Console.ReadKey();
|
||||
}
|
||||
|
||||
//
|
||||
// Change all struct bool fields to bytes (they're technically bytes anyway, and it helps with marshalling)
|
||||
//
|
||||
{
|
||||
foreach ( var s in def.structs )
|
||||
{
|
||||
foreach ( var f in s.Fields )
|
||||
{
|
||||
if ( f.Type == "bool" )
|
||||
f.Type = "byte";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ namespace Generator
|
||||
{
|
||||
public partial class CodeWriter
|
||||
{
|
||||
public void GenerateVTableClass( string className, string filename )
|
||||
public void GenerateVTableClass( SteamApiDefinition.Interface iface, string folder )
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
|
||||
@ -23,26 +23,24 @@ namespace Generator
|
||||
|
||||
StartBlock( $"namespace Steamworks" );
|
||||
{
|
||||
StartBlock( $"internal class {className} : SteamInterface" );
|
||||
StartBlock( $"internal class {iface.Name} : SteamInterface" );
|
||||
{
|
||||
WriteLine( $"public override IntPtr GetInterfacePointer() => GetApi.{className.Substring( 1 )}();" );
|
||||
WriteLine( $"public override IntPtr GetInterfacePointer() => GetApi.{iface.Name.Substring( 1 )}();" );
|
||||
WriteLine();
|
||||
WriteLine();
|
||||
StartBlock( $"internal {className}()" );
|
||||
StartBlock( $"internal {iface.Name}()" );
|
||||
{
|
||||
WriteLine( $"SetupInterface();" );
|
||||
}
|
||||
EndBlock();
|
||||
WriteLine();
|
||||
|
||||
var functions = def.methods.Where( x => x.ClassName == className );
|
||||
|
||||
foreach ( var func in functions )
|
||||
foreach ( var func in iface.Methods )
|
||||
{
|
||||
if ( Cleanup.IsDeprecated( $"{func.ClassName}.{func.Name}" ) )
|
||||
if ( Cleanup.IsDeprecated( $"{iface.Name}.{func.Name}" ) )
|
||||
continue;
|
||||
|
||||
WriteFunction( func );
|
||||
WriteFunction( iface, func );
|
||||
WriteLine();
|
||||
}
|
||||
|
||||
@ -51,19 +49,19 @@ namespace Generator
|
||||
}
|
||||
EndBlock();
|
||||
|
||||
System.IO.File.WriteAllText( $"{filename}", sb.ToString() );
|
||||
System.IO.File.WriteAllText( $"{folder}{iface.Name}.cs", sb.ToString() );
|
||||
}
|
||||
private void WriteFunction( SteamApiDefinition.MethodDef func )
|
||||
private void WriteFunction( SteamApiDefinition.Interface iface, SteamApiDefinition.Interface.Method func )
|
||||
{
|
||||
var returnType = BaseType.Parse( func.ReturnType, null, func.CallResult );
|
||||
var returnType = BaseType.Parse( func.ReturnType, null );
|
||||
returnType.Func = func.Name;
|
||||
|
||||
if ( func.Params == null )
|
||||
func.Params = new SteamApiDefinition.MethodDef.ParamType[0];
|
||||
func.Params = new SteamApiDefinition.Interface.Method.Param[0];
|
||||
|
||||
var args = func.Params.Select( x =>
|
||||
{
|
||||
var bt = BaseType.Parse( x.Type, x.Name );
|
||||
var bt = BaseType.Parse( x.ParamType, x.ParamName );
|
||||
bt.Func = func.Name;
|
||||
return bt;
|
||||
} ).ToArray();
|
||||
@ -89,16 +87,16 @@ namespace Generator
|
||||
var argstr = string.Join( ", ", args.Where( x => !x.ShouldSkipAsArgument ).Select( x => x.AsArgument() ) ); ;
|
||||
var delegateargstr = string.Join( ", ", args.Select( x => x.AsNativeArgument() ) );
|
||||
|
||||
if ( returnType is SteamApiCallType sap )
|
||||
{
|
||||
sap.CallResult = func.CallResult;
|
||||
//if ( returnType is SteamApiCallType sap )
|
||||
// {
|
||||
// sap.CallResult = func.CallResult;
|
||||
|
||||
argstr = string.Join( ", ", args.Select( x => x.AsArgument().Replace( "ref ", " /* ref */ " ) ) );
|
||||
}
|
||||
// argstr = string.Join( ", ", args.Select( x => x.AsArgument().Replace( "ref ", " /* ref */ " ) ) );
|
||||
// }
|
||||
|
||||
WriteLine( $"#region FunctionMeta" );
|
||||
|
||||
WriteLine( $"[DllImport( Platform.LibraryName, EntryPoint = \"SteamAPI_{func.ClassName}_{func.Name}\")]" );
|
||||
WriteLine( $"[DllImport( Platform.LibraryName, EntryPoint = \"{func.FlatName}\")]" );
|
||||
|
||||
if ( returnType.ReturnAttribute != null )
|
||||
WriteLine( returnType.ReturnAttribute );
|
||||
|
@ -11,12 +11,9 @@ namespace Generator
|
||||
public partial class CodeWriter
|
||||
{
|
||||
private SteamApiDefinition def;
|
||||
public CodeParser Parser;
|
||||
|
||||
public CodeWriter( CodeParser parser, SteamApiDefinition def )
|
||||
public CodeWriter( SteamApiDefinition def )
|
||||
{
|
||||
Parser = parser;
|
||||
|
||||
this.def = def;
|
||||
WorkoutTypes();
|
||||
}
|
||||
@ -56,34 +53,15 @@ namespace Generator
|
||||
}
|
||||
|
||||
{
|
||||
GenerateGlobalFunctions( "SteamAPI", $"{folder}../Generated/SteamAPI.cs" );
|
||||
GenerateGlobalFunctions( "SteamGameServer", $"{folder}../Generated/SteamGameServer.cs" );
|
||||
GenerateGlobalFunctions( "SteamInternal", $"{folder}../Generated/SteamInternal.cs" );
|
||||
// GenerateGlobalFunctions( "SteamAPI", $"{folder}../Generated/SteamAPI.cs" );
|
||||
// GenerateGlobalFunctions( "SteamGameServer", $"{folder}../Generated/SteamGameServer.cs" );
|
||||
// GenerateGlobalFunctions( "SteamInternal", $"{folder}../Generated/SteamInternal.cs" );
|
||||
}
|
||||
|
||||
{
|
||||
GenerateVTableClass( "ISteamApps", $"{folder}../Generated/Interfaces/ISteamApps.cs" );
|
||||
GenerateVTableClass( "ISteamUtils", $"{folder}../Generated/Interfaces/ISteamUtils.cs" );
|
||||
GenerateVTableClass( "ISteamParentalSettings", $"{folder}../Generated/Interfaces/ISteamParentalSettings.cs" );
|
||||
GenerateVTableClass( "ISteamMusic", $"{folder}../Generated/Interfaces/ISteamMusic.cs" );
|
||||
GenerateVTableClass( "ISteamVideo", $"{folder}../Generated/Interfaces/ISteamVideo.cs" );
|
||||
GenerateVTableClass( "ISteamUser", $"{folder}../Generated/Interfaces/ISteamUser.cs" );
|
||||
GenerateVTableClass( "ISteamMatchmakingServers", $"{folder}../Generated/Interfaces/ISteamMatchmakingServers.cs" );
|
||||
GenerateVTableClass( "ISteamFriends", $"{folder}../Generated/Interfaces/ISteamFriends.cs" );
|
||||
GenerateVTableClass( "ISteamGameServer", $"{folder}../Generated/Interfaces/ISteamGameServer.cs" );
|
||||
GenerateVTableClass( "ISteamScreenshots", $"{folder}../Generated/Interfaces/ISteamScreenshots.cs" );
|
||||
GenerateVTableClass( "ISteamUserStats", $"{folder}../Generated/Interfaces/ISteamUserStats.cs" );
|
||||
GenerateVTableClass( "ISteamUGC", $"{folder}../Generated/Interfaces/ISteamUGC.cs" );
|
||||
GenerateVTableClass( "ISteamRemoteStorage", $"{folder}../Generated/Interfaces/ISteamRemoteStorage.cs" );
|
||||
GenerateVTableClass( "ISteamInventory", $"{folder}../Generated/Interfaces/ISteamInventory.cs" );
|
||||
GenerateVTableClass( "ISteamNetworking", $"{folder}../Generated/Interfaces/ISteamNetworking.cs" );
|
||||
GenerateVTableClass( "ISteamMatchmaking", $"{folder}../Generated/Interfaces/ISteamMatchmaking.cs" );
|
||||
GenerateVTableClass( "ISteamParties", $"{folder}../Generated/Interfaces/ISteamParties.cs" );
|
||||
GenerateVTableClass( "ISteamNetworkingUtils", $"{folder}../Generated/Interfaces/ISteamNetworkingUtils.cs" );
|
||||
GenerateVTableClass( "ISteamNetworkingSockets", $"{folder}../Generated/Interfaces/ISteamNetworkingSockets.cs" );
|
||||
GenerateVTableClass( "ISteamGameServerStats", $"{folder}../Generated/Interfaces/ISteamGameServerStats.cs" );
|
||||
GenerateVTableClass( "ISteamInput", $"{folder}../Generated/Interfaces/ISteamInput.cs" );
|
||||
}
|
||||
foreach ( var iface in def.Interfaces )
|
||||
{
|
||||
GenerateVTableClass( iface, $"{folder}../Generated/Interfaces/" );
|
||||
}
|
||||
}
|
||||
|
||||
void WorkoutTypes()
|
||||
|
@ -10,6 +10,7 @@ namespace Generator
|
||||
{
|
||||
private void Constants()
|
||||
{
|
||||
/*
|
||||
StartBlock( "internal static class CallbackIdentifiers" );
|
||||
foreach ( var o in def.CallbackIds )
|
||||
{
|
||||
@ -23,6 +24,7 @@ namespace Generator
|
||||
WriteLine( $"internal const string {o.Key} = \"{o.Value}\";" );
|
||||
}
|
||||
EndBlock();
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Generator
|
||||
{
|
||||
/*
|
||||
public partial class CodeWriter
|
||||
{
|
||||
public void GenerateGlobalFunctions( string startingWith, string filename )
|
||||
@ -124,5 +125,8 @@ namespace Generator
|
||||
WriteLine( $"public static extern {(returnType.IsReturnedWeird ? "void" : returnType.TypeNameFrom)} {func.Name}( {delegateargstr} );" );
|
||||
WriteLine();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace Generator
|
||||
{
|
||||
var callbackList = new List<SteamApiDefinition.StructDef>();
|
||||
|
||||
foreach ( var c in def.structs )
|
||||
foreach ( var c in def.callback_structs )
|
||||
{
|
||||
var name = Cleanup.ConvertType( c.Name );
|
||||
|
||||
@ -55,7 +55,7 @@ namespace Generator
|
||||
|
||||
int defaultPack = c.IsPack4OnWindows ? 4 : 8;
|
||||
|
||||
var isCallback = !string.IsNullOrEmpty( c.CallbackId );
|
||||
var isCallback = true;
|
||||
var iface = "";
|
||||
if ( isCallback )
|
||||
iface = " : ICallbackData";
|
||||
@ -117,7 +117,7 @@ namespace Generator
|
||||
WriteLine( "#endregion" );
|
||||
}
|
||||
|
||||
if ( !string.IsNullOrEmpty( c.CallbackId ) )
|
||||
// if ( c.CallbackId ) )
|
||||
{
|
||||
callbackList.Add( c );
|
||||
}
|
||||
|
@ -47,7 +47,6 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CodeParser\CodeParser.cs" />
|
||||
<Compile Include="CodeWriter\GlobalFunctions.cs" />
|
||||
<Compile Include="CodeWriter\ClassVTable.cs" />
|
||||
<Compile Include="CodeWriter\Constants.cs" />
|
||||
|
@ -13,18 +13,14 @@ namespace Generator
|
||||
|
||||
static void Main( string[] args )
|
||||
{
|
||||
var content = System.IO.File.ReadAllText( "steam_sdk/steam_api.json" );
|
||||
var content = System.IO.File.ReadAllText( "steam_api.json" );
|
||||
var def = Newtonsoft.Json.JsonConvert.DeserializeObject<SteamApiDefinition>( content );
|
||||
|
||||
AddMissing( def );
|
||||
|
||||
var parser = new CodeParser( @"steam_sdk" );
|
||||
|
||||
parser.ExtendDefinition( def );
|
||||
// AddMissing( def );
|
||||
|
||||
Definitions = def;
|
||||
|
||||
var generator = new CodeWriter( parser, def );
|
||||
var generator = new CodeWriter( def );
|
||||
|
||||
generator.ToFolder( "../Facepunch.Steamworks/Generated/" );
|
||||
}
|
||||
@ -35,7 +31,7 @@ namespace Generator
|
||||
var missing = Newtonsoft.Json.JsonConvert.DeserializeObject<SteamApiDefinition>( content );
|
||||
|
||||
output.structs.AddRange( missing.structs );
|
||||
output.methods.AddRange( missing.methods );
|
||||
// output.methods.AddRange( missing.methods );
|
||||
|
||||
foreach ( var s in output.structs )
|
||||
{
|
||||
|
@ -9,15 +9,38 @@ namespace Generator
|
||||
{
|
||||
public class SteamApiDefinition
|
||||
{
|
||||
public class TypeDef
|
||||
public class Interface
|
||||
{
|
||||
[JsonProperty( PropertyName = "typedef" )]
|
||||
[JsonProperty( PropertyName = "classname" )]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty( PropertyName = "type" )]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty( PropertyName = "version_string" )]
|
||||
public string VersionString { get; set; }
|
||||
|
||||
public class Method
|
||||
{
|
||||
public string ReturnType { get; set; }
|
||||
|
||||
public class Param
|
||||
{
|
||||
public string ParamType { get; set; }
|
||||
public string ParamName { get; set; }
|
||||
}
|
||||
|
||||
public Param[] Params { get; set; }
|
||||
[JsonProperty( PropertyName = "methodname" )]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty( PropertyName = "flat_name" )]
|
||||
public string FlatName { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public Method[] Methods { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public List<TypeDef> typedefs { get; set; }
|
||||
public Interface[] Interfaces { get; set; }
|
||||
|
||||
|
||||
public class EnumDef
|
||||
{
|
||||
@ -37,6 +60,17 @@ namespace Generator
|
||||
|
||||
public EnumDef[] enums { get; set; }
|
||||
|
||||
|
||||
public class TypeDef
|
||||
{
|
||||
[JsonProperty( PropertyName = "typedef" )]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty( PropertyName = "type" )]
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
public List<TypeDef> typedefs { get; set; }
|
||||
|
||||
public class StructDef
|
||||
{
|
||||
public class StructFields
|
||||
@ -52,55 +86,30 @@ namespace Generator
|
||||
[JsonProperty( PropertyName = "fields" )]
|
||||
public StructFields[] Fields { get; set; }
|
||||
|
||||
public string CallbackId { get; set; }
|
||||
public bool IsPack4OnWindows
|
||||
{
|
||||
get
|
||||
{
|
||||
// 4/8 packing is irrevant to these classes
|
||||
if ( Name.Contains( "MatchMakingKeyValuePair_t" ) ) return true;
|
||||
|
||||
public bool IsPack4OnWindows
|
||||
{
|
||||
get
|
||||
{
|
||||
// 4/8 packing is irrevant to these classes
|
||||
if ( Name.Contains( "MatchMakingKeyValuePair_t" ) ) return true;
|
||||
if ( Fields.Any( x => x.Type.Contains( "CSteamID" ) ) )
|
||||
return true;
|
||||
|
||||
if ( Fields.Any( x => x.Type.Contains( "CSteamID" ) ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<StructDef> structs { get; set; }
|
||||
|
||||
public class MethodDef
|
||||
public class CallbackStructDef : StructDef
|
||||
{
|
||||
public class ParamType
|
||||
{
|
||||
[JsonProperty( PropertyName = "paramname" )]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty( PropertyName = "paramtype" )]
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
[JsonProperty( PropertyName = "classname" )]
|
||||
public string ClassName { get; set; }
|
||||
[JsonProperty( PropertyName = "methodname" )]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty( PropertyName = "returntype" )]
|
||||
public string ReturnType { get; set; }
|
||||
[JsonProperty( PropertyName = "params" )]
|
||||
public ParamType[] Params { get; set; }
|
||||
|
||||
[JsonProperty( PropertyName = "callresult" )]
|
||||
public string CallResult { get; set; }
|
||||
|
||||
public bool NeedsSelfPointer = true;
|
||||
[JsonProperty( PropertyName = "callback_id" )]
|
||||
public int CallbackId { get; set; }
|
||||
}
|
||||
|
||||
public List<MethodDef> methods { get; set; }
|
||||
|
||||
|
||||
public Dictionary<string, int> CallbackIds { get; internal set; }
|
||||
public Dictionary<string, string> Defines { get; internal set; }
|
||||
public List<CallbackStructDef> callback_structs { get; set; }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user