using System; using System.Collections.Generic; using System.Net; using System.Threading.Tasks; namespace Steamworks.Data { /// /// Represents a Steam lobby. /// public struct Lobby { public SteamId Id { get; internal set; } public Result Result { get; internal set; } public Lobby( SteamId id ) { Id = id; Result = Result.OK; } /// /// Try to join this room. Will return on success, /// and anything else is a failure. /// public async Task Join() { if (SteamMatchmaking.Internal is null) { return RoomEnter.Error; } var result = await SteamMatchmaking.Internal.JoinLobby( Id ); if ( !result.HasValue ) return RoomEnter.Error; return (RoomEnter) result.Value.EChatRoomEnterResponse; } /// /// Leave a lobby; this will take effect immediately on the client side /// other users in the lobby will be notified by a LobbyChatUpdate_t callback /// public void Leave() { SteamMatchmaking.Internal?.LeaveLobby( Id ); } /// /// Invite another user to the lobby. /// Will return if the invite is successfully sent, whether or not the target responds /// returns if the local user is not connected to the Steam servers /// public bool InviteFriend( SteamId steamid ) { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.InviteUserToLobby( Id, steamid ); } /// /// Gets the number of users in this lobby. /// public int MemberCount => SteamMatchmaking.Internal?.GetNumLobbyMembers( Id ) ?? 0; /// /// Returns current members in the lobby. The current user must be in the lobby in order to see the users. /// public IEnumerable Members { get { for( int i = 0; i < MemberCount; i++ ) { if (SteamMatchmaking.Internal is null) { break; } yield return new Friend( SteamMatchmaking.Internal.GetLobbyMemberByIndex( Id, i ) ); } } } /// /// Get data associated with this lobby. /// public string? GetData( string key ) { return SteamMatchmaking.Internal?.GetLobbyData( Id, key ); } /// /// Set data associated with this lobby. /// public bool SetData( string key, string value ) { if ( key.Length > 255 ) throw new System.ArgumentException( "Key should be < 255 chars", nameof( key ) ); if ( value.Length > 8192 ) throw new System.ArgumentException( "Value should be < 8192 chars", nameof( key ) ); return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyData( Id, key, value ); } /// /// Removes a metadata key from the lobby. /// public bool DeleteData( string key ) { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.DeleteLobbyData( Id, key ); } /// /// Get all data for this lobby. /// public IEnumerable> Data { get { var cnt = SteamMatchmaking.Internal?.GetLobbyDataCount( Id ) ?? 0; for ( int i =0; i( a, b ); } } } } /// /// Gets per-user metadata for someone in this lobby. /// public string? GetMemberData( Friend member, string key ) { return SteamMatchmaking.Internal?.GetLobbyMemberData( Id, member.Id, key ); } /// /// Sets per-user metadata (for the local user implicitly). /// public void SetMemberData( string key, string value ) { SteamMatchmaking.Internal?.SetLobbyMemberData( Id, key, value ); } /// /// Sends a string to the chat room. /// public bool SendChatString( string message ) { //adding null terminator as it's used in Helpers.MemoryToString var data = System.Text.Encoding.UTF8.GetBytes( message + '\0' ); return SendChatBytes( data ); } /// /// Sends bytes to the chat room. /// public unsafe bool SendChatBytes( byte[] data ) { fixed ( byte* ptr = data ) { return SendChatBytesUnsafe( ptr, data.Length ); } } /// /// Sends bytes to the chat room from an unsafe buffer. /// public unsafe bool SendChatBytesUnsafe( byte* ptr, int length ) { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SendLobbyChatMsg( Id, (IntPtr)ptr, length ); } /// /// Refreshes metadata for a lobby you're not necessarily in right now. /// /// You never do this for lobbies you're a member of, only if your /// this will send down all the metadata associated with a lobby. /// This is an asynchronous call. /// Returns if the local user is not connected to the Steam servers. /// Results will be returned by a LobbyDataUpdate_t callback. /// If the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to . /// /// public bool Refresh() { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.RequestLobbyData( Id ); } /// /// Max members able to join this lobby. Cannot be over 250. /// Can only be set by the owner of the lobby. /// public int MaxMembers { get => SteamMatchmaking.Internal?.GetLobbyMemberLimit( Id ) ?? 0; set => SteamMatchmaking.Internal?.SetLobbyMemberLimit( Id, value ); } /// /// Sets the lobby as public. /// public bool SetPublic() { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Public ); } /// /// Sets the lobby as private. /// public bool SetPrivate() { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Private ); } /// /// Sets the lobby as invisible. /// public bool SetInvisible() { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Invisible ); } /// /// Sets the lobby as friends only. /// public bool SetFriendsOnly() { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.FriendsOnly ); } /// /// Set whether or not the lobby can be joined. /// /// Whether or not the lobby can be joined. public bool SetJoinable( bool b ) { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.SetLobbyJoinable( Id, b ); } /// /// [SteamID variant] /// Allows the owner to set the game server associated with the lobby. Triggers the /// Steammatchmaking.OnLobbyGameCreated event. /// public void SetGameServer( SteamId steamServer ) { if ( !steamServer.IsValid ) throw new ArgumentException( $"SteamId for server is invalid" ); SteamMatchmaking.Internal?.SetLobbyGameServer( Id, 0, 0, steamServer ); } /// /// [IP/Port variant] /// Allows the owner to set the game server associated with the lobby. Triggers the /// Steammatchmaking.OnLobbyGameCreated event. /// public void SetGameServer( string ip, ushort port ) { if ( !IPAddress.TryParse( ip, out IPAddress add ) ) throw new ArgumentException( $"IP address for server is invalid" ); SteamMatchmaking.Internal?.SetLobbyGameServer( Id, add.IpToInt32(), port, new SteamId() ); } /// /// Gets the details of the lobby's game server, if set. Returns true if the lobby is /// valid and has a server set, otherwise returns false. /// public bool GetGameServer( ref uint ip, ref ushort port, ref SteamId serverId ) { return SteamMatchmaking.Internal != null && SteamMatchmaking.Internal.GetLobbyGameServer( Id, ref ip, ref port, ref serverId ); } /// /// Gets or sets the owner of the lobby. You must be the lobby owner to set the owner /// public Friend Owner { get => new Friend( SteamMatchmaking.Internal?.GetLobbyOwner( Id ) ?? 0 ); set => SteamMatchmaking.Internal?.SetLobbyOwner( Id, value.Id ); } /// /// Check if the specified SteamId owns the lobby. /// public bool IsOwnedBy( SteamId k ) => Owner.Id == k; } }