using System; using System.Collections.Generic; using System.Net; using System.Threading.Tasks; namespace Facepunch.Steamworks.Data { public struct Lobby { public SteamId Id { get; internal set; } public Lobby( SteamId id ) { Id = id; } /// /// Try to join this room. Will return RoomEnter.Success on success, /// and anything else is a failure /// public async Task Join() { 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 true if the invite is successfully sent, whether or not the target responds /// returns false if the local user is not connected to the Steam servers /// public bool InviteFriend( SteamId steamid ) { return SteamMatchmaking.Internal.InviteUserToLobby( Id, steamid ); } /// /// returns the number of users in the specified lobby /// public int MemberCount => SteamMatchmaking.Internal.GetNumLobbyMembers( Id ); /// /// Returns current members. Need to be in the lobby to see the users. /// public IEnumerable Members { get { for( int i = 0; i < MemberCount; i++ ) { 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 ); } /// /// Get 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.SetLobbyData( Id, key, value ); } /// /// Removes a metadata key from the lobby /// public bool DeleteData( string key ) { return SteamMatchmaking.Internal.DeleteLobbyData( Id, key ); } /// /// Get all data for this lobby /// public IEnumerable> Data { get { var cnt = SteamMatchmaking.Internal.GetLobbyDataCount( Id ); 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 ) { var data = System.Text.Encoding.UTF8.GetBytes( message ); return SendChatBytes( data ); } /// /// Sends bytes the the chat room /// this isn't exposed because there's no way to read raw bytes atm, /// and I figure people can send json if they want something more advanced /// internal unsafe bool SendChatBytes( byte[] data ) { fixed ( byte* ptr = data ) { return SteamMatchmaking.Internal.SendLobbyChatMsg( Id, (IntPtr)ptr, data.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 false 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 false /// public bool Refresh() { return SteamMatchmaking.Internal.RequestLobbyData( Id ); } /// /// Max members able to join this lobby. Cannot be over 250. /// Can only be set by the owner /// public int MaxMembers { get => SteamMatchmaking.Internal.GetLobbyMemberLimit( Id ); set => SteamMatchmaking.Internal.SetLobbyMemberLimit( Id, value ); } public bool SetPublic() { return SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Public ); } public bool SetPrivate() { return SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Private ); } public bool SetInvisible() { return SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.Invisible ); } public bool SetFriendsOnly() { return SteamMatchmaking.Internal.SetLobbyType( Id, LobbyType.FriendsOnly ); } public bool SetJoinable( bool b ) { return 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.GetLobbyGameServer( Id, ref ip, ref port, ref serverId ); } /// /// You must be the lobby owner to set the owner /// public Friend Owner { get => new Friend( SteamMatchmaking.Internal.GetLobbyOwner( Id ) ); set => SteamMatchmaking.Internal.SetLobbyOwner( Id, value.Id ); } /// /// Check if the specified SteamId owns the lobby /// public bool IsOwnedBy( SteamId k ) => Owner.Id == k; } }