using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Facepunch.Steamworks.Data; namespace Facepunch.Steamworks { public struct Friend { public SteamId Id; public Friend( SteamId steamid ) { Id = steamid; } public override string ToString() { return $"{Name} ({Id.ToString()})"; } /// /// Returns true if this is the local user /// public bool IsMe => Id == SteamClient.SteamId; /// /// Return true if this is a friend /// public bool IsFriend => Relationship == Relationship.Friend; /// /// Returns true if you have this user blocked /// public bool IsBlocked => Relationship == Relationship.Blocked; /// /// Return true if this user is playing the game we're running /// public bool IsPlayingThisGame => GameInfo?.GameID == SteamClient.AppId; /// /// Returns true if this friend is online /// public bool IsOnline => State != FriendState.Offline; /// /// Sometimes we don't know the user's name. This will wait until we have /// downloaded the information on this user. /// public async Task RequestInfoAsync() { await SteamFriends.CacheUserInformationAsync( Id, true ); } /// /// Returns true if this friend is marked as away /// public bool IsAway => State == FriendState.Away; /// /// Returns true if this friend is marked as busy /// public bool IsBusy => State == FriendState.Busy; /// /// Returns true if this friend is marked as snoozing /// public bool IsSnoozing => State == FriendState.Snooze; public Relationship Relationship => SteamFriends.Internal.GetFriendRelationship( Id ); public FriendState State => SteamFriends.Internal.GetFriendPersonaState( Id ); public string Name => SteamFriends.Internal.GetFriendPersonaName( Id ); public IEnumerable NameHistory { get { for( int i=0; i<32; i++ ) { var n = SteamFriends.Internal.GetFriendPersonaNameHistory( Id, i ); if ( string.IsNullOrEmpty( n ) ) break; yield return n; } } } public int SteamLevel => SteamFriends.Internal.GetFriendSteamLevel( Id ); public FriendGameInfo? GameInfo { get { FriendGameInfo_t gameInfo = default; if ( !SteamFriends.Internal.GetFriendGamePlayed( Id, ref gameInfo ) ) return null; return FriendGameInfo.From( gameInfo ); } } public bool IsIn( SteamId group_or_room ) { return SteamFriends.Internal.IsUserInSource( Id, group_or_room ); } public struct FriendGameInfo { internal ulong GameID; // m_gameID class CGameID internal uint GameIP; // m_unGameIP uint32 internal ulong SteamIDLobby; // m_steamIDLobby class CSteamID public int ConnectionPort; public int QueryPort; public uint IpAddressRaw => GameIP; public System.Net.IPAddress IpAddress => Utility.Int32ToIp( GameIP ); public Lobby? Lobby { get { if ( SteamIDLobby == 0 ) return null; return new Lobby( SteamIDLobby ); } } internal static FriendGameInfo From( FriendGameInfo_t i ) { return new FriendGameInfo { GameID = i.GameID, GameIP = i.GameIP, ConnectionPort = i.GamePort, QueryPort = i.QueryPort, SteamIDLobby = i.SteamIDLobby, }; } } public async Task GetSmallAvatarAsync() { return await SteamFriends.GetSmallAvatarAsync( Id ); } public async Task GetMediumAvatarAsync() { return await SteamFriends.GetMediumAvatarAsync( Id ); } public async Task GetLargeAvatarAsync() { return await SteamFriends.GetLargeAvatarAsync( Id ); } public string GetRichPresence( string key ) { var val = SteamFriends.Internal.GetFriendRichPresence( Id, key ); if ( string.IsNullOrEmpty( val ) ) return null; return val; } /// /// Invite this friend to the game that we are playing /// public bool InviteToGame( string Text ) { return SteamFriends.Internal.InviteUserToGame( Id, Text ); } /// /// Sends a message to a Steam friend. Returns true if success /// public bool SendMessage( string message ) { return SteamFriends.Internal.ReplyToFriendMessage( Id, message ); } /// /// Tries to get download the latest user stats /// /// True if successful, False if failure public async Task RequestUserStatsAsync() { var result = await SteamUserStats.Internal.RequestUserStats( Id ); return result.HasValue && result.Value.Result == Result.OK; } /// /// Gets a user stat. Must call RequestUserStats first. /// /// The name of the stat you want to get /// Will return this value if not available /// The value, or defult if not available public float GetStatFloat( string statName, float defult = 0 ) { var val = defult; if ( !SteamUserStats.Internal.GetUserStat( Id, statName, ref val ) ) return defult; return val; } /// /// Gets a user stat. Must call RequestUserStats first. /// /// The name of the stat you want to get /// Will return this value if not available /// The value, or defult if not available public int GetStatInt( string statName, int defult = 0 ) { var val = defult; if ( !SteamUserStats.Internal.GetUserStat( Id, statName, ref val ) ) return defult; return val; } /// /// Gets a user achievement state. Must call RequestUserStats first. /// /// The name of the achievement you want to get /// Will return this value if not available /// The value, or defult if not available public bool GetAchievement( string statName, bool defult = false ) { var val = defult; if ( !SteamUserStats.Internal.GetUserAchievement( Id, statName, ref val ) ) return defult; return val; } /// /// Gets a the time this achievement was unlocked. /// /// The name of the achievement you want to get /// The time unlocked. If it wasn't unlocked, or you haven't downloaded the stats yet - will return DateTime.MinValue public DateTime GetAchievementUnlockTime( string statName ) { bool val = false; uint time = 0; if ( !SteamUserStats.Internal.GetUserAchievementAndUnlockTime( Id, statName, ref val, ref time ) || !val ) return DateTime.MinValue; return Epoch.ToDateTime( time ); } } }