using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Steamworks.Data; namespace Steamworks { /// /// Functions for clients to access matchmaking services, favorites, and to operate on game lobbies /// public static class SteamMatchmaking { /// /// Maximum number of characters a lobby metadata key can be /// internal static int MaxLobbyKeyLength => 255; static ISteamMatchmaking _internal; internal static ISteamMatchmaking Internal { get { if ( _internal == null ) { _internal = new ISteamMatchmaking(); _internal.Init(); } return _internal; } } internal static void Shutdown() { _internal = null; } internal static void InstallEvents() { LobbyInvite_t.Install( x => OnLobbyInvite?.Invoke( new Friend( x.SteamIDUser ), new Lobby( x.SteamIDLobby ) ) ); LobbyEnter_t.Install( x => OnLobbyEntered?.Invoke( new Lobby( x.SteamIDLobby ) ) ); LobbyDataUpdate_t.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 ) ); } ); LobbyChatUpdate_t.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 ) ); } ); LobbyChatMsg_t.Install( OnLobbyChatMessageRecievedAPI ); } static private unsafe void OnLobbyChatMessageRecievedAPI( LobbyChatMsg_t callback ) { SteamId steamid = default; ChatEntryType chatEntryType = default; var buffer = Helpers.TakeBuffer( 1024 * 4 ); fixed ( byte* p = buffer ) { var readData = Internal.GetLobbyChatEntry( callback.SteamIDLobby, (int)callback.ChatID, ref steamid, (IntPtr)p, buffer.Length, ref chatEntryType ); if ( readData > 0 ) { OnChatMessage?.Invoke( new Lobby( callback.SteamIDLobby ), new Friend( steamid ), Encoding.UTF8.GetString( buffer, 0, readData ) ); } } } /// /// Someone invited you to a lobby /// public static event Action OnLobbyInvite; /// /// You joined a lobby /// public static event Action OnLobbyEntered; /// /// 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 ); } } } } }