using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Facepunch.Steamworks.Data; namespace Facepunch.Steamworks { /// /// Functions for clients to access matchmaking services, favorites, and to operate on game lobbies /// public class SteamMatchmaking : SteamClientClass { internal static ISteamMatchmaking Internal => Interface as ISteamMatchmaking; internal override void InitializeInterface( bool server ) { SetInterface( server, new ISteamMatchmaking( server ) ); InstallEvents(); } /// /// Maximum number of characters a lobby metadata key can be /// internal static int MaxLobbyKeyLength => 255; internal static void InstallEvents() { Dispatch.Install( x => OnLobbyInvite?.Invoke( new Friend( x.SteamIDUser ), new Lobby( x.SteamIDLobby ) ) ); Dispatch.Install( x => OnLobbyEntered?.Invoke( new Lobby( x.SteamIDLobby ) ) ); Dispatch.Install( x => OnLobbyCreated?.Invoke( x.Result, new Lobby( x.SteamIDLobby ) ) ); Dispatch.Install( x => OnLobbyGameCreated?.Invoke( new Lobby( x.SteamIDLobby ), x.IP, x.Port, x.SteamIDGameServer ) ); Dispatch.Install( x => { if ( x.Success == 0 ) return; if ( x.SteamIDLobby == x.SteamIDMember ) OnLobbyDataChanged?.Invoke( new Lobby( x.SteamIDLobby ) ); else OnLobbyMemberDataChanged?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDMember ) ); } ); Dispatch.Install( x => { if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Entered) != 0 ) OnLobbyMemberJoined?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ) ); if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Left) != 0 ) OnLobbyMemberLeave?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ) ); if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Disconnected) != 0 ) OnLobbyMemberDisconnected?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ) ); if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Kicked) != 0 ) OnLobbyMemberKicked?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ), new Friend( x.SteamIDMakingChange ) ); if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Banned) != 0 ) OnLobbyMemberBanned?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ), new Friend( x.SteamIDMakingChange ) ); } ); Dispatch.Install( OnLobbyChatMessageRecievedAPI ); } static private unsafe void OnLobbyChatMessageRecievedAPI( LobbyChatMsg_t callback ) { SteamId steamid = default; ChatEntryType chatEntryType = default; var buffer = Helpers.TakeMemory(); var readData = Internal.GetLobbyChatEntry( callback.SteamIDLobby, (int)callback.ChatID, ref steamid, buffer, Helpers.MemoryBufferSize, ref chatEntryType ); if ( readData > 0 ) { OnChatMessage?.Invoke( new Lobby( callback.SteamIDLobby ), new Friend( steamid ), Helpers.MemoryToString( buffer ) ); } } /// /// Someone invited you to a lobby /// public static event Action OnLobbyInvite; /// /// You joined a lobby /// public static event Action OnLobbyEntered; /// /// You created a lobby /// public static event Action OnLobbyCreated; /// /// A game server has been associated with the lobby /// public static event Action OnLobbyGameCreated; /// /// The lobby metadata has changed /// public static event Action OnLobbyDataChanged; /// /// The lobby member metadata has changed /// public static event Action OnLobbyMemberDataChanged; /// /// The lobby member joined /// public static event Action OnLobbyMemberJoined; /// /// The lobby member left the room /// public static event Action OnLobbyMemberLeave; /// /// The lobby member left the room /// public static event Action OnLobbyMemberDisconnected; /// /// The lobby member was kicked. The 3rd param is the user that kicked them. /// public static event Action OnLobbyMemberKicked; /// /// The lobby member was banned. The 3rd param is the user that banned them. /// public static event Action OnLobbyMemberBanned; /// /// A chat message was recieved from a member of a lobby /// public static event Action OnChatMessage; public static LobbyQuery LobbyList => new LobbyQuery(); /// /// Creates a new invisible lobby. Call lobby.SetPublic to take it online. /// public static async Task CreateLobbyAsync( int maxMembers = 100 ) { var lobby = await Internal.CreateLobby( LobbyType.Invisible, maxMembers ); if ( !lobby.HasValue || lobby.Value.Result != Result.OK ) return null; return new Lobby { Id = lobby.Value.SteamIDLobby }; } /// /// Attempts to directly join the specified lobby /// public static async Task JoinLobbyAsync( SteamId lobbyId ) { var lobby = await Internal.JoinLobby( lobbyId ); if ( !lobby.HasValue ) return null; return new Lobby { Id = lobby.Value.SteamIDLobby }; } /// /// Get a list of servers that are on your favorites list /// public static IEnumerable GetFavoriteServers() { var count = Internal.GetFavoriteGameCount(); for( int i=0; i /// Get a list of servers that you have added to your play history /// public static IEnumerable GetHistoryServers() { var count = Internal.GetFavoriteGameCount(); for ( int i = 0; i < count; i++ ) { uint timeplayed = 0; uint flags = 0; ushort qport = 0; ushort cport = 0; uint ip = 0; AppId appid = default; if ( Internal.GetFavoriteGame( i, ref appid, ref ip, ref cport, ref qport, ref flags, ref timeplayed ) ) { if ( (flags & ServerInfo.k_unFavoriteFlagHistory) == 0 ) continue; yield return new ServerInfo( ip, cport, qport, timeplayed ); } } } } }