diff --git a/Facepunch.Steamworks.Test/Client/FriendsTest.cs b/Facepunch.Steamworks.Test/Client/FriendsTest.cs index e0548df..8ea5245 100644 --- a/Facepunch.Steamworks.Test/Client/FriendsTest.cs +++ b/Facepunch.Steamworks.Test/Client/FriendsTest.cs @@ -1,6 +1,7 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Linq; +using System.Threading.Tasks; namespace Steamworks { @@ -44,6 +45,70 @@ namespace Steamworks } } + [TestMethod] + public async Task LargeAvatar() + { + ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000)); + + var image = await Friends.GetLargeAvatarAsync( id ); + if ( !image.HasValue ) + return; + + Console.WriteLine( $"image.Width {image.Value.Width}" ); + Console.WriteLine( $"image.Height {image.Value.Height}" ); + + DrawImage( image.Value ); + } + + [TestMethod] + public async Task MediumAvatar() + { + ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000)); + + Console.WriteLine( $"Steam: http://steamcommunity.com/profiles/{id}" ); + + var image = await Friends.GetMediumAvatarAsync( id ); + if ( !image.HasValue ) + return; + + Console.WriteLine( $"image.Width {image.Value.Width}" ); + Console.WriteLine( $"image.Height {image.Value.Height}" ); + + DrawImage( image.Value ); + } + + [TestMethod] + public async Task SmallAvatar() + { + ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000)); + + var image = await Friends.GetSmallAvatarAsync( id ); + if ( !image.HasValue ) + return; + + Console.WriteLine( $"image.Width {image.Value.Width}" ); + Console.WriteLine( $"image.Height {image.Value.Height}" ); + + DrawImage( image.Value ); + } + + [TestMethod] + public async Task GetFriendsAvatars() + { + foreach ( var friend in Friends.GetFriends() ) + { + Console.WriteLine( $"{friend.Id.Value}: {friend.Name}" ); + + var image = await friend.GetSmallAvatarAsync(); + if ( image.HasValue ) + { + DrawImage( image.Value ); + } + + // Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) ); + } + } + /* [TestMethod] public void FriendListWithoutRefresh() @@ -59,40 +124,7 @@ namespace Steamworks } } - [TestMethod] - public void Avatar() - { - using ( var client = new Facepunch.Steamworks.Client( 252490 ) ) - { - Assert.IsTrue( client.IsValid ); - ulong id = (ulong)( 76561197960279927 + (new Random().Next() % 10000)); - bool passed = false; - - client.Friends.GetAvatar( Steamworks.Friends.AvatarSize.Medium, id, ( avatar) => - { - if ( avatar == null ) - { - Console.WriteLine( "No Avatar" ); - } - else - { - Assert.AreEqual( avatar.Width, 64 ); - Assert.AreEqual( avatar.Height, 64 ); - Assert.AreEqual( avatar.Data.Length, avatar.Width * avatar.Height * 4 ); - - DrawImage( avatar ); - } - passed = true; - }); - - while (passed == false ) - { - client.Update(); - System.Threading.Thread.Sleep( 10 ); - } - } - } [TestMethod] public void CachedAvatar() @@ -113,8 +145,8 @@ namespace Steamworks } } } - - public static void DrawImage( Image img ) + */ + public static void DrawImage( Image img ) { var grad = " -:+#"; @@ -136,6 +168,6 @@ namespace Steamworks Console.WriteLine( str ); } } - */ + } } diff --git a/Facepunch.Steamworks/Redux/Friends.cs b/Facepunch.Steamworks/Redux/Friends.cs index 25fa758..5cbed67 100644 --- a/Facepunch.Steamworks/Redux/Friends.cs +++ b/Facepunch.Steamworks/Redux/Friends.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using Facepunch.Steamworks; using SteamNative; namespace Steamworks @@ -113,5 +114,52 @@ namespace Steamworks /// public static void SetPlayedWith( CSteamID steamid ) => Internal.SetPlayedWith( steamid ); + static async Task CacheUserInformationAsync( CSteamID steamid, bool nameonly ) + { + // Got it straight away, skip any waiting. + if ( !Internal.RequestUserInformation( steamid, nameonly ) ) + return; + + await Task.Delay( 100 ); + + while ( Internal.RequestUserInformation( steamid, nameonly ) ) + { + await Task.Delay( 50 ); + } + + // + // And extra wait here seems to solve avatars loading as [?] + // + await Task.Delay( 500 ); + } + + public static async Task GetSmallAvatarAsync( CSteamID steamid ) + { + await CacheUserInformationAsync( steamid, false ); + return Utils.GetImage( Internal.GetSmallFriendAvatar( steamid ) ); + } + + public static async Task GetMediumAvatarAsync( CSteamID steamid ) + { + await CacheUserInformationAsync( steamid, false ); + return Utils.GetImage( Internal.GetMediumFriendAvatar( steamid ) ); + } + + public static async Task GetLargeAvatarAsync( CSteamID steamid ) + { + await CacheUserInformationAsync( steamid, false ); + + var imageid = Internal.GetLargeFriendAvatar( steamid ); + + // Wait for the image to download + while ( imageid == -1 ) + { + await Task.Delay( 50 ); + imageid = Internal.GetLargeFriendAvatar( steamid ); + } + + return Utils.GetImage( imageid ); + } + } } \ No newline at end of file diff --git a/Facepunch.Steamworks/Redux/Structs/Friend.cs b/Facepunch.Steamworks/Redux/Structs/Friend.cs index 874f000..9df1757 100644 --- a/Facepunch.Steamworks/Redux/Structs/Friend.cs +++ b/Facepunch.Steamworks/Redux/Structs/Friend.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; - +using System.Threading.Tasks; namespace Steamworks { @@ -80,6 +80,20 @@ namespace Steamworks } } + public async Task GetSmallAvatarAsync() + { + return await Friends.GetSmallAvatarAsync( Id ); + } + + public async Task GetMediumAvatarAsync() + { + return await Friends.GetMediumAvatarAsync( Id ); + } + + public async Task GetLargeAvatarAsync() + { + return await Friends.GetLargeAvatarAsync( Id ); + } } } \ No newline at end of file diff --git a/Facepunch.Steamworks/Redux/Structs/Image.cs b/Facepunch.Steamworks/Redux/Structs/Image.cs new file mode 100644 index 0000000..90cb913 --- /dev/null +++ b/Facepunch.Steamworks/Redux/Structs/Image.cs @@ -0,0 +1,28 @@ +using Facepunch.Steamworks; + +namespace Steamworks +{ + public struct Image + { + public uint Width; + public uint Height; + public byte[] Data; + + public Color GetPixel( int x, int y ) + { + if ( x < 0 || x >= Width ) throw new System.Exception( "x out of bounds" ); + if ( y < 0 || y >= Height ) throw new System.Exception( "y out of bounds" ); + + Color c = new Color(); + + var i = (y * Width + x) * 4; + + c.r = Data[i + 0]; + c.g = Data[i + 1]; + c.b = Data[i + 2]; + c.a = Data[i + 3]; + + return c; + } + } +} \ No newline at end of file diff --git a/Facepunch.Steamworks/Redux/Utils.cs b/Facepunch.Steamworks/Redux/Utils.cs index 74848c6..b6e60be 100644 --- a/Facepunch.Steamworks/Redux/Utils.cs +++ b/Facepunch.Steamworks/Redux/Utils.cs @@ -92,18 +92,23 @@ namespace Steamworks /// /// returns the image in RGBA format /// - public static byte[] GetImageRGBA( int image ) + public static Image? GetImage( int image ) { - if ( !GetImageSize( image, out var w, out var h ) ) + var i = new Image(); + + if ( !GetImageSize( image, out i.Width, out i.Height ) ) return null; - var size = w * h * 4 * sizeof( char ); - var data = new byte[size]; + var size = i.Width * i.Height * 4; - if ( !Internal.GetImageRGBA( image, data, data.Length ) ) + var buf = Helpers.TakeBuffer( (int) size ); + + if ( !Internal.GetImageRGBA( image, buf, (int)size ) ) return null; - return data; + i.Data = new byte[size]; + Array.Copy( buf, 0, i.Data, 0, size ); + return i; } ///