mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-20 06:19:05 -04:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
248 lines
7.2 KiB
C#
248 lines
7.2 KiB
C#
using Sandbox;
|
|
using Steamworks.Data;
|
|
|
|
namespace Steamworks;
|
|
|
|
internal struct Friend
|
|
{
|
|
public SteamId Id;
|
|
|
|
public Friend( SteamId steamid )
|
|
{
|
|
Id = steamid;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{Name} ({Id})";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if this is the local user
|
|
/// </summary>
|
|
public bool IsMe => Id == SteamClient.SteamId;
|
|
|
|
/// <summary>
|
|
/// Return true if this is a friend
|
|
/// </summary>
|
|
public bool IsFriend => Relationship == Relationship.Friend;
|
|
|
|
/// <summary>
|
|
/// Returns true if you have this user blocked
|
|
/// </summary>
|
|
public bool IsBlocked => Relationship == Relationship.Blocked;
|
|
|
|
/// <summary>
|
|
/// Return true if this user is playing the game we're running
|
|
/// </summary>
|
|
public bool IsPlayingThisGame => GameInfo?.GameID == SteamClient.AppId;
|
|
|
|
/// <summary>
|
|
/// Return true if this user is playing another game
|
|
/// </summary>
|
|
public bool IsPlaying => GameInfo?.GameID > 0;
|
|
|
|
/// <summary>
|
|
/// Returns true if this friend is online
|
|
/// </summary>
|
|
public bool IsOnline => State != FriendState.Offline;
|
|
|
|
/// <summary>
|
|
/// Sometimes we don't know the user's name. This will wait until we have
|
|
/// downloaded the information on this user.
|
|
/// </summary>
|
|
public async Task RequestInfoAsync()
|
|
{
|
|
await SteamFriends.CacheUserInformationAsync( Id, true );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if this friend is marked as away
|
|
/// </summary>
|
|
public bool IsAway => State == FriendState.Away;
|
|
|
|
/// <summary>
|
|
/// Returns true if this friend is marked as busy
|
|
/// </summary>
|
|
public bool IsBusy => State == FriendState.Busy;
|
|
|
|
/// <summary>
|
|
/// Returns true if this friend is marked as snoozing
|
|
/// </summary>
|
|
public bool IsSnoozing => State == FriendState.Snooze;
|
|
|
|
//
|
|
// These take an annoying amount of time to call, innocently iterating on a friends list of 20 was eating 1-2ms
|
|
// And some people have 500+, this could be done a bit neater but I didn't want to break any APIs and this seemed
|
|
// like the best layer to do it on.
|
|
// We get a PersonaStateChange_t whenever any of these are dirty, and clear the cache(s) depending on flags
|
|
//
|
|
|
|
internal static Dictionary<ulong, string> _nameCache = new();
|
|
internal static Dictionary<ulong, Relationship> _relationshipCache = new();
|
|
internal static Dictionary<ulong, FriendState> _stateCache = new();
|
|
internal static Dictionary<ulong, int> _steamLevelCache = new();
|
|
internal static Dictionary<ulong, FriendGameInfo?> _gameInfoCache = new();
|
|
|
|
public string Name => _nameCache.GetOrCreate( Id.Value, SteamFriends.Internal.GetFriendPersonaName );
|
|
public Relationship Relationship => _relationshipCache.GetOrCreate( Id.Value, SteamFriends.Internal.GetFriendRelationship );
|
|
public FriendState State
|
|
{
|
|
get
|
|
{
|
|
if ( !_stateCache.TryGetValue( Id.Value, out var val ) )
|
|
{
|
|
val = SteamFriends.Internal.GetFriendPersonaState( Id.Value );
|
|
_stateCache[Id.Value] = val;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
}
|
|
public int SteamLevel => _steamLevelCache.GetOrCreate( Id.Value, SteamFriends.Internal.GetFriendSteamLevel );
|
|
|
|
public FriendGameInfo? GameInfo => _gameInfoCache.GetOrCreate( Id, x =>
|
|
{
|
|
FriendGameInfo_t gameInfo = default;
|
|
if ( !SteamFriends.Internal.GetFriendGamePlayed( x, ref gameInfo ) )
|
|
return null;
|
|
|
|
return FriendGameInfo.From( gameInfo );
|
|
} );
|
|
|
|
public IEnumerable<string> 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 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 ulong GameId => GameID;
|
|
public int ConnectionPort;
|
|
public int QueryPort;
|
|
|
|
public uint IpAddressRaw => GameIP;
|
|
public System.Net.IPAddress IpAddress => Utility.Int32ToIp( GameIP );
|
|
|
|
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,
|
|
};
|
|
}
|
|
}
|
|
|
|
internal async Task<Data.Image?> GetSmallAvatarAsync()
|
|
{
|
|
return await SteamFriends.GetSmallAvatarAsync( Id );
|
|
}
|
|
|
|
internal async Task<Data.Image?> GetMediumAvatarAsync()
|
|
{
|
|
return await SteamFriends.GetMediumAvatarAsync( Id );
|
|
}
|
|
|
|
internal async Task<Data.Image?> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invite this friend to the game that we are playing
|
|
/// </summary>
|
|
internal bool InviteToGame( string Text )
|
|
{
|
|
return SteamFriends.Internal.InviteUserToGame( Id, Text );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Activates the Steam Overlay to a specific dialog
|
|
/// </summary>
|
|
/// <param name="type">
|
|
/// "steamid" - Opens the overlay web browser to the specified user or groups profile.
|
|
/// "chat" - Opens a chat window to the specified user, or joins the group chat.
|
|
/// "jointrade" - Opens a window to a Steam Trading session that was started with the ISteamEconomy/StartTrade Web API.
|
|
/// "stats" - Opens the overlay web browser to the specified user's stats.
|
|
/// "achievements" - Opens the overlay web browser to the specified user's achievements.
|
|
/// "friendadd" - Opens the overlay in minimal mode prompting the user to add the target user as a friend.
|
|
/// "friendremove" - Opens the overlay in minimal mode prompting the user to remove the target friend.
|
|
/// "friendrequestaccept" - Opens the overlay in minimal mode prompting the user to accept an incoming friend invite.
|
|
/// "friendrequestignore" - Opens the overlay in minimal mode prompting the user to ignore an incoming friend invite.
|
|
/// </param>
|
|
internal void OpenInOverlay( string type = "steamid" )
|
|
{
|
|
SteamFriends.OpenUserOverlay( Id, type );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends a message to a Steam friend. Returns true if success
|
|
/// </summary>
|
|
internal bool SendMessage( string message )
|
|
{
|
|
return SteamFriends.Internal.ReplyToFriendMessage( Id, message );
|
|
}
|
|
|
|
internal static void SteamFriends_OnPersonaStateChange( SteamId id, PersonaChange changeFlags )
|
|
{
|
|
if ( changeFlags.Contains( PersonaChange.Name ) )
|
|
_nameCache.Remove( id );
|
|
|
|
if ( changeFlags.Contains( PersonaChange.RelationshipChanged ) )
|
|
_relationshipCache.Remove( id );
|
|
|
|
if ( changeFlags.Contains( PersonaChange.Status ) || changeFlags.Contains( PersonaChange.GoneOffline ) || changeFlags.Contains( PersonaChange.ComeOnline ) )
|
|
_stateCache.Remove( id );
|
|
|
|
if ( changeFlags.Contains( PersonaChange.SteamLevel ) )
|
|
_steamLevelCache.Remove( id );
|
|
|
|
if ( changeFlags.Contains( PersonaChange.GamePlayed ) || changeFlags.Contains( PersonaChange.GameServer ) )
|
|
_gameInfoCache.Remove( id );
|
|
}
|
|
}
|
|
|
|
static class DictionaryExtensions
|
|
{
|
|
public static TValue GetOrCreate<TKey, TValue>( this IDictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> createNew )
|
|
{
|
|
if ( !dict.TryGetValue( key, out var val ) )
|
|
{
|
|
val = createNew( key );
|
|
dict.Add( key, val );
|
|
}
|
|
|
|
return val;
|
|
}
|
|
}
|