void Structs() { foreach (var c in def.structs) { var name = Cleanup.ConvertType(c.Name); if (!Cleanup.ShouldCreate(name)) { continue; } if (name.Contains("::")) { continue; } var partial = ""; if (c.Methods != null) { partial = " partial"; } // // Main struct // WriteLine($"[StructLayout( LayoutKind.Sequential, Pack = Platform.{(c.IsPack4OnWindows?"StructPackSize": "StructPlatformPackSize")} )]"); StartBlock($"{Cleanup.Expose( name )}{partial} struct {name}"); { // // The fields // StructFields(c.Fields); WriteLine(); if (c.Enums != null) { foreach (var e in c.Enums) { WriteEnum(e, e.Name); } } } EndBlock(); WriteLine(); } }
void Structs() { var callbackList = new List <SteamApiDefinition.StructDef>(); foreach (var c in def.structs) { var name = Cleanup.ConvertType(c.Name); if (SkipStructs.Contains(c.Name)) { continue; } if (!Cleanup.ShouldCreate(name)) { continue; } if (name.Contains("::")) { continue; } int defaultPack = c.IsPack4OnWindows ? 4 : 8; var isCallback = !string.IsNullOrEmpty(c.CallbackId); // // Main struct // WriteLine("[StructLayout( LayoutKind.Sequential, Pack = 4 )]"); StartBlock($"{Cleanup.Expose( name )} struct {name}"); { // // The fields // StructFields(c.Fields); WriteLine(); if (isCallback) { WriteLine("#region SteamCallback"); { if (defaultPack == 4) { WriteLine($"internal static readonly int StructSize = System.Runtime.InteropServices.Marshal.SizeOf( typeof({name}) );"); WriteLine($"internal static {name} Fill( IntPtr p ) => (({name})({name}) Marshal.PtrToStructure( p, typeof({name}) ) );"); } else { WriteLine($"internal static readonly int StructSize = System.Runtime.InteropServices.Marshal.SizeOf( Config.PackSmall ? typeof({name}) : typeof(Pack8) );"); WriteLine($"internal static {name} Fill( IntPtr p ) => Config.PackSmall ? (({name})({name}) Marshal.PtrToStructure( p, typeof({name}) )) : (({name})(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));"); } WriteLine(); WriteLine($"static Action<{name}> actionClient;"); WriteLine($"[MonoPInvokeCallback] static void OnClient( IntPtr thisptr, IntPtr pvParam ) => actionClient?.Invoke( Fill( pvParam ) );"); WriteLine($"static Action<{name}> actionServer;"); WriteLine($"[MonoPInvokeCallback] static void OnServer( IntPtr thisptr, IntPtr pvParam ) => actionServer?.Invoke( Fill( pvParam ) );"); StartBlock($"public static void Install( Action<{name}> action, bool server = false )"); { StartBlock("if ( server )"); { WriteLine($"Event.Register( OnServer, StructSize, {c.CallbackId}, true );"); WriteLine($"actionServer = action;"); } Else(); { WriteLine($"Event.Register( OnClient, StructSize, {c.CallbackId}, false );"); WriteLine($"actionClient = action;"); } EndBlock(); } EndBlock(); StartBlock($"public static async Task<{name}?> GetResultAsync( SteamAPICall_t handle )"); { WriteLine($"bool failed = false;"); WriteLine(); StartBlock($"while ( !SteamUtils.IsCallComplete( handle, out failed ) )"); { WriteLine($"await Task.Delay( 1 );"); } EndBlock(); WriteLine($"if ( failed ) return null;"); WriteLine($""); WriteLine($"var ptr = Marshal.AllocHGlobal( StructSize );"); WriteLine($""); WriteLine($"try"); WriteLine($"{{"); WriteLine($" if ( !SteamUtils.Internal.GetAPICallResult( handle, ptr, StructSize, {c.CallbackId}, ref failed ) || failed )"); WriteLine($" return null;"); WriteLine($""); WriteLine($" return Fill( ptr );"); WriteLine($"}}"); WriteLine($"finally"); WriteLine($"{{"); WriteLine($" Marshal.FreeHGlobal( ptr );"); WriteLine($"}}"); } EndBlock(); } WriteLine("#endregion"); } else { WriteLine("#region Marshalling"); { if (defaultPack == 4) { //WriteLine( $"internal static int GetStructSize() => System.Runtime.InteropServices.Marshal.SizeOf( typeof({name}) );" ); WriteLine($"internal static {name} Fill( IntPtr p ) => (({name})({name}) Marshal.PtrToStructure( p, typeof({name}) ) );"); } else { //WriteLine( $"internal static int GetStructSize() => System.Runtime.InteropServices.Marshal.SizeOf( Config.PackSmall ? typeof({name}) : typeof(Pack8) );" ); WriteLine($"internal static {name} Fill( IntPtr p ) => Config.PackSmall ? (({name})({name}) Marshal.PtrToStructure( p, typeof({name}) )) : (({name})(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));"); } } WriteLine("#endregion"); } if (defaultPack != 4) { WriteLine("#region Packed Versions"); { // // Windows Packed version // WriteLine(); WriteLine($"[StructLayout( LayoutKind.Sequential, Pack = {defaultPack} )]"); StartBlock($"public struct Pack8"); { StructFields(c.Fields); // // Implicit convert from PackSmall to regular // WriteLine(); Write($"public static implicit operator {name} ( {name}.Pack8 d ) => "); { Write($"new {name}{{ "); { foreach (var f in c.Fields) { Write($"{CleanMemberName( f.Name )} = d.{CleanMemberName( f.Name )},"); } } WriteLine(" };"); } Write($"public static implicit operator {name}.Pack8 ( {name} d ) => "); { Write($"new {name}.Pack8{{ "); { foreach (var f in c.Fields) { Write($"{CleanMemberName( f.Name )} = d.{CleanMemberName( f.Name )},"); } } WriteLine(" };"); } } EndBlock(); } WriteLine("#endregion"); } if (!string.IsNullOrEmpty(c.CallbackId)) { callbackList.Add(c); } } EndBlock(); WriteLine(); } }
void StructFunctions() { foreach (var c in def.structs.Union(def.callback_structs.Select(x => x as SteamApiDefinition.StructDef)).OrderBy(x => x.Name)) { var name = Cleanup.ConvertType(c.Name); if (name.Contains("::")) { continue; } if (c.Methods == null || c.Methods.Length == 0) { continue; } // // Main struct // StartBlock($"{Cleanup.Expose( name )} partial struct {name}"); { foreach (var func in c.Methods) { if (func.Name.Contains("operator")) { func.Name = func.FlatName.Substring(func.FlatName.LastIndexOf('_') + 1); } var returnType = BaseType.Parse(func.ReturnType, null, func.CallResult); returnType.Func = func.Name; var args = func.Params.Select(x => { var bt = BaseType.Parse(x.ParamType, x.ParamName); bt.Func = func.Name; return(bt); }).ToArray(); for (int i = 0; i < args.Length; i++) { if (args[i] is FetchStringType) { if (args[i + 1] is IntType || args[i + 1] is UIntType || args[i + 1] is UIntPtrType) { if (string.IsNullOrEmpty(args[i + 1].Ref)) { args[i + 1] = new LiteralType(args[i + 1], "(1024 * 32)"); } } else { throw new System.Exception($"String Builder Next Type Is {args[i + 1].GetType()}"); } } } var delegateargstr = string.Join(", ", args.Select(x => x.AsNativeArgument())); if (!string.IsNullOrEmpty(func.Desc)) { WriteLine("/// <summary>"); WriteLine($"/// {func.Desc}"); WriteLine("/// </summary>"); } if (returnType.ReturnAttribute != null) { WriteLine(returnType.ReturnAttribute); } var _unsafe = ""; var firstArg = $"ref {name} self"; // // If this is NetMsg then the ORIGINAL pointer address is important // because we need to pass in the original pointer - not just the data // if (name == "NetMsg") { firstArg = $"{name}* self"; _unsafe = " unsafe"; } WriteLine($"[DllImport( Platform.LibraryName, EntryPoint = \"{func.FlatName}\", CallingConvention = Platform.CC)]"); WriteLine($"internal static{_unsafe} extern {returnType.TypeNameFrom} Internal{func.Name}( {firstArg}, {delegateargstr} );".Replace($"( {firstArg}, )", $"( {firstArg} )")); WriteLine(); } } EndBlock(); WriteLine(); } }
private void WriteEnum(SteamApiDefinition.EnumDef o, string name, string t = "int") { StartBlock($"{Cleanup.Expose( name )} enum {name} : {t}"); { // // If all the enum values start with the same // string, remove it. This converts // "k_EUserHasLicenseResultHasLicense" to "HasLicense" etc // int iFinished = int.MaxValue; for (int i = 0; i < 4096; i++) { var c = o.Values.First().Name[i]; foreach (var entry in o.Values) { if (entry.Name[i] != c) { iFinished = i; break; } } if (iFinished != int.MaxValue) { break; } } foreach (var entry in o.Values) { var ename = entry.Name; if (ename.Contains("Force32Bit")) { continue; } if (iFinished != int.MaxValue) { ename = ename.Substring(iFinished); } // // Names aren't allowed to start with a number // So just stick the enum name on the front // if (char.IsNumber(ename[0])) { var p = name; if (p == "HTTPStatusCode") { p = "Code"; } if (p == "SteamIPType") { p = "Type"; } ename = p + ename; } WriteLine($"{ename.Trim( ' ', '_' )} = {entry.Value},"); } } EndBlock(); WriteLine(); }
private void Enums() { foreach (var o in def.enums) { WriteLine($"//"); WriteLine($"// {o.Name}"); WriteLine($"//"); var name = o.Name; // We're not interested in namespacing if (name.Contains("::")) { name = o.Name.Substring(o.Name.LastIndexOf(":") + 1); } // Skip the E if (name[0] == 'E') { name = name.Substring(1); } name = Cleanup.ConvertType(name); if (!Cleanup.ShouldCreate(name)) { continue; } StartBlock($"{Cleanup.Expose( name )} enum {name} : int"); { // // If all the enum values start with the same // string, remove it. This converts // "k_EUserHasLicenseResultHasLicense" to "HasLicense" etc // int iFinished = int.MaxValue; for (int i = 0; i < 4096; i++) { var c = o.Values.First().Name[i]; foreach (var entry in o.Values) { if (entry.Name[i] != c) { iFinished = i; break; } } if (iFinished != int.MaxValue) { break; } } foreach (var entry in o.Values) { var ename = entry.Name; if (iFinished != int.MaxValue) { ename = ename.Substring(iFinished); } // // Names aren't allowed to start with a number // So just stick the enum name on the front // if (char.IsNumber(ename[0])) { ename = name + ename; } WriteLine($"{ename} = {entry.Value},"); } } EndBlock(); WriteLine(); } }
void Callbacks() { var callbackList = new List <SteamApiDefinition.StructDef>(); foreach (var c in def.callback_structs) { var name = Cleanup.ConvertType(c.Name); if (!Cleanup.ShouldCreate(name)) { continue; } if (name.Contains("::")) { continue; } var partial = ""; if (c.Methods != null) { partial = " partial"; } int defaultPack = c.IsPack4OnWindows ? 4 : 8; var isCallback = true; var iface = ""; if (isCallback) { iface = " : ICallbackData"; } // // Main struct // WriteLine($"[StructLayout( LayoutKind.Sequential, Pack = Platform.{(c.IsPack4OnWindows?"StructPackSize": "StructPlatformPackSize")} )]"); StartBlock($"{Cleanup.Expose( name )}{partial} struct {name}{iface}"); { // // The fields // StructFields(c.Fields); WriteLine(); if (isCallback) { WriteLine("#region SteamCallback"); { WriteLine($"public static int _datasize = System.Runtime.InteropServices.Marshal.SizeOf( typeof({name}) );"); WriteLine($"public int DataSize => _datasize;"); WriteLine($"public CallbackType CallbackType => CallbackType.{name.Replace( "_t", "" )};"); } WriteLine("#endregion"); } if (c.Enums != null) { foreach (var e in c.Enums) { WriteEnum(e, e.Name); } } // if ( c.CallbackId ) ) { callbackList.Add(c); } } EndBlock(); WriteLine(); } }
private void Types() { foreach (var o in def.typedefs.Where(x => !x.Name.Contains("::"))) { if (!Cleanup.ShouldCreate(o.Name)) { continue; } var typeName = Cleanup.ConvertType(o.Name); if (!Cleanup.ShouldCreate(typeName)) { continue; } if (SkipTypes.Contains(o.Name)) { continue; } if (SkipTypesStartingWith.Any(x => o.Name.StartsWith(x))) { continue; } StartBlock($"{Cleanup.Expose( typeName )} struct {typeName} : IEquatable<{typeName}>, IComparable<{typeName}>"); { WriteLine($"// Name: {o.Name}, Type: {o.Type}"); if (o.Type == "char [1024]") { WriteLine($"public fixed char[1024] Value;"); } else { WriteLine($"public {ToManagedType( o.Type )} Value;"); } WriteLine(); WriteLine($"public static implicit operator {typeName}( {ToManagedType( o.Type )} value ) => new {typeName}(){{ Value = value }};"); WriteLine($"public static implicit operator {ToManagedType( o.Type )}( {typeName} value ) => value.Value;"); WriteLine($"public override string ToString() => Value.ToString();"); WriteLine($"public override int GetHashCode() => Value.GetHashCode();"); WriteLine($"public override bool Equals( object p ) => this.Equals( ({typeName}) p );"); WriteLine($"public bool Equals( {typeName} p ) => p.Value == Value;"); WriteLine($"public static bool operator ==( {typeName} a, {typeName} b ) => a.Equals( b );"); WriteLine($"public static bool operator !=( {typeName} a, {typeName} b ) => !a.Equals( b );"); if (ToManagedType(o.Type) == "IntPtr") { WriteLine($"public int CompareTo( {typeName} other ) => Value.ToInt64().CompareTo( other.Value.ToInt64() );"); } else { WriteLine($"public int CompareTo( {typeName} other ) => Value.CompareTo( other.Value );"); } } EndBlock(); WriteLine(); } }