CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

isteammatchmaking.cs (51767B)


      1 // This file is provided under The MIT License as part of Steamworks.NET.
      2 // Copyright (c) 2013-2019 Riley Labrecque
      3 // Please see the included LICENSE.txt for additional information.
      4 
      5 // This file is automatically generated.
      6 // Changes to this file will be reverted when you update Steamworks.NET
      7 
      8 #if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH
      9 	#define DISABLESTEAMWORKS
     10 #endif
     11 
     12 #if !DISABLESTEAMWORKS
     13 
     14 using System.Runtime.InteropServices;
     15 using IntPtr = System.IntPtr;
     16 
     17 namespace Steamworks {
     18 	public static class SteamMatchmaking {
     19 		/// <summary>
     20 		/// <para> game server favorites storage</para>
     21 		/// <para> saves basic details about a multiplayer game server locally</para>
     22 		/// <para> returns the number of favorites servers the user has stored</para>
     23 		/// </summary>
     24 		public static int GetFavoriteGameCount() {
     25 			InteropHelp.TestIfAvailableClient();
     26 			return NativeMethods.ISteamMatchmaking_GetFavoriteGameCount(CSteamAPIContext.GetSteamMatchmaking());
     27 		}
     28 
     29 		/// <summary>
     30 		/// <para> returns the details of the game server</para>
     31 		/// <para> iGame is of range [0,GetFavoriteGameCount())</para>
     32 		/// <para> *pnIP, *pnConnPort are filled in the with IP:port of the game server</para>
     33 		/// <para> *punFlags specify whether the game server was stored as an explicit favorite or in the history of connections</para>
     34 		/// <para> *pRTime32LastPlayedOnServer is filled in the with the Unix time the favorite was added</para>
     35 		/// </summary>
     36 		public static bool GetFavoriteGame(int iGame, out AppId_t pnAppID, out uint pnIP, out ushort pnConnPort, out ushort pnQueryPort, out uint punFlags, out uint pRTime32LastPlayedOnServer) {
     37 			InteropHelp.TestIfAvailableClient();
     38 			return NativeMethods.ISteamMatchmaking_GetFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), iGame, out pnAppID, out pnIP, out pnConnPort, out pnQueryPort, out punFlags, out pRTime32LastPlayedOnServer);
     39 		}
     40 
     41 		/// <summary>
     42 		/// <para> adds the game server to the local list; updates the time played of the server if it already exists in the list</para>
     43 		/// </summary>
     44 		public static int AddFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags, uint rTime32LastPlayedOnServer) {
     45 			InteropHelp.TestIfAvailableClient();
     46 			return NativeMethods.ISteamMatchmaking_AddFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags, rTime32LastPlayedOnServer);
     47 		}
     48 
     49 		/// <summary>
     50 		/// <para> removes the game server from the local storage; returns true if one was removed</para>
     51 		/// </summary>
     52 		public static bool RemoveFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags) {
     53 			InteropHelp.TestIfAvailableClient();
     54 			return NativeMethods.ISteamMatchmaking_RemoveFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags);
     55 		}
     56 
     57 		/// <summary>
     58 		/// <para>/////</para>
     59 		/// <para> Game lobby functions</para>
     60 		/// <para> Get a list of relevant lobbies</para>
     61 		/// <para> this is an asynchronous request</para>
     62 		/// <para> results will be returned by LobbyMatchList_t callback &amp; call result, with the number of lobbies found</para>
     63 		/// <para> this will never return lobbies that are full</para>
     64 		/// <para> to add more filter, the filter calls below need to be call before each and every RequestLobbyList() call</para>
     65 		/// <para> use the CCallResult&lt;&gt; object in steam_api.h to match the SteamAPICall_t call result to a function in an object, e.g.</para>
     66 		/// <para>		class CMyLobbyListManager</para>
     67 		/// <para>		{</para>
     68 		/// <para>			CCallResult&lt;CMyLobbyListManager, LobbyMatchList_t&gt; m_CallResultLobbyMatchList;</para>
     69 		/// <para>			void FindLobbies()</para>
     70 		/// <para>			{</para>
     71 		/// <para>				// SteamMatchmaking()-&gt;AddRequestLobbyListFilter*() functions would be called here, before RequestLobbyList()</para>
     72 		/// <para>				SteamAPICall_t hSteamAPICall = SteamMatchmaking()-&gt;RequestLobbyList();</para>
     73 		/// <para>				m_CallResultLobbyMatchList.Set( hSteamAPICall, this, &amp;CMyLobbyListManager::OnLobbyMatchList );</para>
     74 		/// <para>			}</para>
     75 		/// <para>			void OnLobbyMatchList( LobbyMatchList_t *pLobbyMatchList, bool bIOFailure )</para>
     76 		/// <para>			{</para>
     77 		/// <para>				// lobby list has be retrieved from Steam back-end, use results</para>
     78 		/// <para>			}</para>
     79 		/// <para>		}</para>
     80 		/// </summary>
     81 		public static SteamAPICall_t RequestLobbyList() {
     82 			InteropHelp.TestIfAvailableClient();
     83 			return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_RequestLobbyList(CSteamAPIContext.GetSteamMatchmaking());
     84 		}
     85 
     86 		/// <summary>
     87 		/// <para> filters for lobbies</para>
     88 		/// <para> this needs to be called before RequestLobbyList() to take effect</para>
     89 		/// <para> these are cleared on each call to RequestLobbyList()</para>
     90 		/// </summary>
     91 		public static void AddRequestLobbyListStringFilter(string pchKeyToMatch, string pchValueToMatch, ELobbyComparison eComparisonType) {
     92 			InteropHelp.TestIfAvailableClient();
     93 			using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch))
     94 			using (var pchValueToMatch2 = new InteropHelp.UTF8StringHandle(pchValueToMatch)) {
     95 				NativeMethods.ISteamMatchmaking_AddRequestLobbyListStringFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, pchValueToMatch2, eComparisonType);
     96 			}
     97 		}
     98 
     99 		/// <summary>
    100 		/// <para> numerical comparison</para>
    101 		/// </summary>
    102 		public static void AddRequestLobbyListNumericalFilter(string pchKeyToMatch, int nValueToMatch, ELobbyComparison eComparisonType) {
    103 			InteropHelp.TestIfAvailableClient();
    104 			using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) {
    105 				NativeMethods.ISteamMatchmaking_AddRequestLobbyListNumericalFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToMatch, eComparisonType);
    106 			}
    107 		}
    108 
    109 		/// <summary>
    110 		/// <para> returns results closest to the specified value. Multiple near filters can be added, with early filters taking precedence</para>
    111 		/// </summary>
    112 		public static void AddRequestLobbyListNearValueFilter(string pchKeyToMatch, int nValueToBeCloseTo) {
    113 			InteropHelp.TestIfAvailableClient();
    114 			using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) {
    115 				NativeMethods.ISteamMatchmaking_AddRequestLobbyListNearValueFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToBeCloseTo);
    116 			}
    117 		}
    118 
    119 		/// <summary>
    120 		/// <para> returns only lobbies with the specified number of slots available</para>
    121 		/// </summary>
    122 		public static void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable) {
    123 			InteropHelp.TestIfAvailableClient();
    124 			NativeMethods.ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable(CSteamAPIContext.GetSteamMatchmaking(), nSlotsAvailable);
    125 		}
    126 
    127 		/// <summary>
    128 		/// <para> sets the distance for which we should search for lobbies (based on users IP address to location map on the Steam backed)</para>
    129 		/// </summary>
    130 		public static void AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter eLobbyDistanceFilter) {
    131 			InteropHelp.TestIfAvailableClient();
    132 			NativeMethods.ISteamMatchmaking_AddRequestLobbyListDistanceFilter(CSteamAPIContext.GetSteamMatchmaking(), eLobbyDistanceFilter);
    133 		}
    134 
    135 		/// <summary>
    136 		/// <para> sets how many results to return, the lower the count the faster it is to download the lobby results &amp; details to the client</para>
    137 		/// </summary>
    138 		public static void AddRequestLobbyListResultCountFilter(int cMaxResults) {
    139 			InteropHelp.TestIfAvailableClient();
    140 			NativeMethods.ISteamMatchmaking_AddRequestLobbyListResultCountFilter(CSteamAPIContext.GetSteamMatchmaking(), cMaxResults);
    141 		}
    142 
    143 		public static void AddRequestLobbyListCompatibleMembersFilter(CSteamID steamIDLobby) {
    144 			InteropHelp.TestIfAvailableClient();
    145 			NativeMethods.ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    146 		}
    147 
    148 		/// <summary>
    149 		/// <para> returns the CSteamID of a lobby, as retrieved by a RequestLobbyList call</para>
    150 		/// <para> should only be called after a LobbyMatchList_t callback is received</para>
    151 		/// <para> iLobby is of the range [0, LobbyMatchList_t::m_nLobbiesMatching)</para>
    152 		/// <para> the returned CSteamID::IsValid() will be false if iLobby is out of range</para>
    153 		/// </summary>
    154 		public static CSteamID GetLobbyByIndex(int iLobby) {
    155 			InteropHelp.TestIfAvailableClient();
    156 			return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyByIndex(CSteamAPIContext.GetSteamMatchmaking(), iLobby);
    157 		}
    158 
    159 		/// <summary>
    160 		/// <para> Create a lobby on the Steam servers.</para>
    161 		/// <para> If private, then the lobby will not be returned by any RequestLobbyList() call; the CSteamID</para>
    162 		/// <para> of the lobby will need to be communicated via game channels or via InviteUserToLobby()</para>
    163 		/// <para> this is an asynchronous request</para>
    164 		/// <para> results will be returned by LobbyCreated_t callback and call result; lobby is joined &amp; ready to use at this point</para>
    165 		/// <para> a LobbyEnter_t callback will also be received (since the local user is joining their own lobby)</para>
    166 		/// </summary>
    167 		public static SteamAPICall_t CreateLobby(ELobbyType eLobbyType, int cMaxMembers) {
    168 			InteropHelp.TestIfAvailableClient();
    169 			return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_CreateLobby(CSteamAPIContext.GetSteamMatchmaking(), eLobbyType, cMaxMembers);
    170 		}
    171 
    172 		/// <summary>
    173 		/// <para> Joins an existing lobby</para>
    174 		/// <para> this is an asynchronous request</para>
    175 		/// <para> results will be returned by LobbyEnter_t callback &amp; call result, check m_EChatRoomEnterResponse to see if was successful</para>
    176 		/// <para> lobby metadata is available to use immediately on this call completing</para>
    177 		/// </summary>
    178 		public static SteamAPICall_t JoinLobby(CSteamID steamIDLobby) {
    179 			InteropHelp.TestIfAvailableClient();
    180 			return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_JoinLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    181 		}
    182 
    183 		/// <summary>
    184 		/// <para> Leave a lobby; this will take effect immediately on the client side</para>
    185 		/// <para> other users in the lobby will be notified by a LobbyChatUpdate_t callback</para>
    186 		/// </summary>
    187 		public static void LeaveLobby(CSteamID steamIDLobby) {
    188 			InteropHelp.TestIfAvailableClient();
    189 			NativeMethods.ISteamMatchmaking_LeaveLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    190 		}
    191 
    192 		/// <summary>
    193 		/// <para> Invite another user to the lobby</para>
    194 		/// <para> the target user will receive a LobbyInvite_t callback</para>
    195 		/// <para> will return true if the invite is successfully sent, whether or not the target responds</para>
    196 		/// <para> returns false if the local user is not connected to the Steam servers</para>
    197 		/// <para> if the other user clicks the join link, a GameLobbyJoinRequested_t will be posted if the user is in-game,</para>
    198 		/// <para> or if the game isn't running yet the game will be launched with the parameter +connect_lobby &lt;64-bit lobby id&gt;</para>
    199 		/// </summary>
    200 		public static bool InviteUserToLobby(CSteamID steamIDLobby, CSteamID steamIDInvitee) {
    201 			InteropHelp.TestIfAvailableClient();
    202 			return NativeMethods.ISteamMatchmaking_InviteUserToLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDInvitee);
    203 		}
    204 
    205 		/// <summary>
    206 		/// <para> Lobby iteration, for viewing details of users in a lobby</para>
    207 		/// <para> only accessible if the lobby user is a member of the specified lobby</para>
    208 		/// <para> persona information for other lobby members (name, avatar, etc.) will be asynchronously received</para>
    209 		/// <para> and accessible via ISteamFriends interface</para>
    210 		/// <para> returns the number of users in the specified lobby</para>
    211 		/// </summary>
    212 		public static int GetNumLobbyMembers(CSteamID steamIDLobby) {
    213 			InteropHelp.TestIfAvailableClient();
    214 			return NativeMethods.ISteamMatchmaking_GetNumLobbyMembers(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    215 		}
    216 
    217 		/// <summary>
    218 		/// <para> returns the CSteamID of a user in the lobby</para>
    219 		/// <para> iMember is of range [0,GetNumLobbyMembers())</para>
    220 		/// <para> note that the current user must be in a lobby to retrieve CSteamIDs of other users in that lobby</para>
    221 		/// </summary>
    222 		public static CSteamID GetLobbyMemberByIndex(CSteamID steamIDLobby, int iMember) {
    223 			InteropHelp.TestIfAvailableClient();
    224 			return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyMemberByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iMember);
    225 		}
    226 
    227 		/// <summary>
    228 		/// <para> Get data associated with this lobby</para>
    229 		/// <para> takes a simple key, and returns the string associated with it</para>
    230 		/// <para> "" will be returned if no value is set, or if steamIDLobby is invalid</para>
    231 		/// </summary>
    232 		public static string GetLobbyData(CSteamID steamIDLobby, string pchKey) {
    233 			InteropHelp.TestIfAvailableClient();
    234 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {
    235 				return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2));
    236 			}
    237 		}
    238 
    239 		/// <summary>
    240 		/// <para> Sets a key/value pair in the lobby metadata</para>
    241 		/// <para> each user in the lobby will be broadcast this new value, and any new users joining will receive any existing data</para>
    242 		/// <para> this can be used to set lobby names, map, etc.</para>
    243 		/// <para> to reset a key, just set it to ""</para>
    244 		/// <para> other users in the lobby will receive notification of the lobby data change via a LobbyDataUpdate_t callback</para>
    245 		/// </summary>
    246 		public static bool SetLobbyData(CSteamID steamIDLobby, string pchKey, string pchValue) {
    247 			InteropHelp.TestIfAvailableClient();
    248 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))
    249 			using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {
    250 				return NativeMethods.ISteamMatchmaking_SetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2);
    251 			}
    252 		}
    253 
    254 		/// <summary>
    255 		/// <para> returns the number of metadata keys set on the specified lobby</para>
    256 		/// </summary>
    257 		public static int GetLobbyDataCount(CSteamID steamIDLobby) {
    258 			InteropHelp.TestIfAvailableClient();
    259 			return NativeMethods.ISteamMatchmaking_GetLobbyDataCount(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    260 		}
    261 
    262 		/// <summary>
    263 		/// <para> returns a lobby metadata key/values pair by index, of range [0, GetLobbyDataCount())</para>
    264 		/// </summary>
    265 		public static bool GetLobbyDataByIndex(CSteamID steamIDLobby, int iLobbyData, out string pchKey, int cchKeyBufferSize, out string pchValue, int cchValueBufferSize) {
    266 			InteropHelp.TestIfAvailableClient();
    267 			IntPtr pchKey2 = Marshal.AllocHGlobal(cchKeyBufferSize);
    268 			IntPtr pchValue2 = Marshal.AllocHGlobal(cchValueBufferSize);
    269 			bool ret = NativeMethods.ISteamMatchmaking_GetLobbyDataByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iLobbyData, pchKey2, cchKeyBufferSize, pchValue2, cchValueBufferSize);
    270 			pchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null;
    271 			Marshal.FreeHGlobal(pchKey2);
    272 			pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;
    273 			Marshal.FreeHGlobal(pchValue2);
    274 			return ret;
    275 		}
    276 
    277 		/// <summary>
    278 		/// <para> removes a metadata key from the lobby</para>
    279 		/// </summary>
    280 		public static bool DeleteLobbyData(CSteamID steamIDLobby, string pchKey) {
    281 			InteropHelp.TestIfAvailableClient();
    282 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {
    283 				return NativeMethods.ISteamMatchmaking_DeleteLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2);
    284 			}
    285 		}
    286 
    287 		/// <summary>
    288 		/// <para> Gets per-user metadata for someone in this lobby</para>
    289 		/// </summary>
    290 		public static string GetLobbyMemberData(CSteamID steamIDLobby, CSteamID steamIDUser, string pchKey) {
    291 			InteropHelp.TestIfAvailableClient();
    292 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {
    293 				return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDUser, pchKey2));
    294 			}
    295 		}
    296 
    297 		/// <summary>
    298 		/// <para> Sets per-user metadata (for the local user implicitly)</para>
    299 		/// </summary>
    300 		public static void SetLobbyMemberData(CSteamID steamIDLobby, string pchKey, string pchValue) {
    301 			InteropHelp.TestIfAvailableClient();
    302 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))
    303 			using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {
    304 				NativeMethods.ISteamMatchmaking_SetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2);
    305 			}
    306 		}
    307 
    308 		/// <summary>
    309 		/// <para> Broadcasts a chat message to the all the users in the lobby</para>
    310 		/// <para> users in the lobby (including the local user) will receive a LobbyChatMsg_t callback</para>
    311 		/// <para> returns true if the message is successfully sent</para>
    312 		/// <para> pvMsgBody can be binary or text data, up to 4k</para>
    313 		/// <para> if pvMsgBody is text, cubMsgBody should be strlen( text ) + 1, to include the null terminator</para>
    314 		/// </summary>
    315 		public static bool SendLobbyChatMsg(CSteamID steamIDLobby, byte[] pvMsgBody, int cubMsgBody) {
    316 			InteropHelp.TestIfAvailableClient();
    317 			return NativeMethods.ISteamMatchmaking_SendLobbyChatMsg(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pvMsgBody, cubMsgBody);
    318 		}
    319 
    320 		/// <summary>
    321 		/// <para> Get a chat message as specified in a LobbyChatMsg_t callback</para>
    322 		/// <para> iChatID is the LobbyChatMsg_t::m_iChatID value in the callback</para>
    323 		/// <para> *pSteamIDUser is filled in with the CSteamID of the member</para>
    324 		/// <para> *pvData is filled in with the message itself</para>
    325 		/// <para> return value is the number of bytes written into the buffer</para>
    326 		/// </summary>
    327 		public static int GetLobbyChatEntry(CSteamID steamIDLobby, int iChatID, out CSteamID pSteamIDUser, byte[] pvData, int cubData, out EChatEntryType peChatEntryType) {
    328 			InteropHelp.TestIfAvailableClient();
    329 			return NativeMethods.ISteamMatchmaking_GetLobbyChatEntry(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iChatID, out pSteamIDUser, pvData, cubData, out peChatEntryType);
    330 		}
    331 
    332 		/// <summary>
    333 		/// <para> Refreshes metadata for a lobby you're not necessarily in right now</para>
    334 		/// <para> you never do this for lobbies you're a member of, only if your</para>
    335 		/// <para> this will send down all the metadata associated with a lobby</para>
    336 		/// <para> this is an asynchronous call</para>
    337 		/// <para> returns false if the local user is not connected to the Steam servers</para>
    338 		/// <para> results will be returned by a LobbyDataUpdate_t callback</para>
    339 		/// <para> if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false</para>
    340 		/// </summary>
    341 		public static bool RequestLobbyData(CSteamID steamIDLobby) {
    342 			InteropHelp.TestIfAvailableClient();
    343 			return NativeMethods.ISteamMatchmaking_RequestLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    344 		}
    345 
    346 		/// <summary>
    347 		/// <para> sets the game server associated with the lobby</para>
    348 		/// <para> usually at this point, the users will join the specified game server</para>
    349 		/// <para> either the IP/Port or the steamID of the game server has to be valid, depending on how you want the clients to be able to connect</para>
    350 		/// </summary>
    351 		public static void SetLobbyGameServer(CSteamID steamIDLobby, uint unGameServerIP, ushort unGameServerPort, CSteamID steamIDGameServer) {
    352 			InteropHelp.TestIfAvailableClient();
    353 			NativeMethods.ISteamMatchmaking_SetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, unGameServerIP, unGameServerPort, steamIDGameServer);
    354 		}
    355 
    356 		/// <summary>
    357 		/// <para> returns the details of a game server set in a lobby - returns false if there is no game server set, or that lobby doesn't exist</para>
    358 		/// </summary>
    359 		public static bool GetLobbyGameServer(CSteamID steamIDLobby, out uint punGameServerIP, out ushort punGameServerPort, out CSteamID psteamIDGameServer) {
    360 			InteropHelp.TestIfAvailableClient();
    361 			return NativeMethods.ISteamMatchmaking_GetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, out punGameServerIP, out punGameServerPort, out psteamIDGameServer);
    362 		}
    363 
    364 		/// <summary>
    365 		/// <para> set the limit on the # of users who can join the lobby</para>
    366 		/// </summary>
    367 		public static bool SetLobbyMemberLimit(CSteamID steamIDLobby, int cMaxMembers) {
    368 			InteropHelp.TestIfAvailableClient();
    369 			return NativeMethods.ISteamMatchmaking_SetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, cMaxMembers);
    370 		}
    371 
    372 		/// <summary>
    373 		/// <para> returns the current limit on the # of users who can join the lobby; returns 0 if no limit is defined</para>
    374 		/// </summary>
    375 		public static int GetLobbyMemberLimit(CSteamID steamIDLobby) {
    376 			InteropHelp.TestIfAvailableClient();
    377 			return NativeMethods.ISteamMatchmaking_GetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    378 		}
    379 
    380 		/// <summary>
    381 		/// <para> updates which type of lobby it is</para>
    382 		/// <para> only lobbies that are k_ELobbyTypePublic or k_ELobbyTypeInvisible, and are set to joinable, will be returned by RequestLobbyList() calls</para>
    383 		/// </summary>
    384 		public static bool SetLobbyType(CSteamID steamIDLobby, ELobbyType eLobbyType) {
    385 			InteropHelp.TestIfAvailableClient();
    386 			return NativeMethods.ISteamMatchmaking_SetLobbyType(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, eLobbyType);
    387 		}
    388 
    389 		/// <summary>
    390 		/// <para> sets whether or not a lobby is joinable - defaults to true for a new lobby</para>
    391 		/// <para> if set to false, no user can join, even if they are a friend or have been invited</para>
    392 		/// </summary>
    393 		public static bool SetLobbyJoinable(CSteamID steamIDLobby, bool bLobbyJoinable) {
    394 			InteropHelp.TestIfAvailableClient();
    395 			return NativeMethods.ISteamMatchmaking_SetLobbyJoinable(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, bLobbyJoinable);
    396 		}
    397 
    398 		/// <summary>
    399 		/// <para> returns the current lobby owner</para>
    400 		/// <para> you must be a member of the lobby to access this</para>
    401 		/// <para> there always one lobby owner - if the current owner leaves, another user will become the owner</para>
    402 		/// <para> it is possible (bur rare) to join a lobby just as the owner is leaving, thus entering a lobby with self as the owner</para>
    403 		/// </summary>
    404 		public static CSteamID GetLobbyOwner(CSteamID steamIDLobby) {
    405 			InteropHelp.TestIfAvailableClient();
    406 			return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);
    407 		}
    408 
    409 		/// <summary>
    410 		/// <para> changes who the lobby owner is</para>
    411 		/// <para> you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby</para>
    412 		/// <para> after completion, the local user will no longer be the owner</para>
    413 		/// </summary>
    414 		public static bool SetLobbyOwner(CSteamID steamIDLobby, CSteamID steamIDNewOwner) {
    415 			InteropHelp.TestIfAvailableClient();
    416 			return NativeMethods.ISteamMatchmaking_SetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDNewOwner);
    417 		}
    418 
    419 		/// <summary>
    420 		/// <para> link two lobbies for the purposes of checking player compatibility</para>
    421 		/// <para> you must be the lobby owner of both lobbies</para>
    422 		/// </summary>
    423 		public static bool SetLinkedLobby(CSteamID steamIDLobby, CSteamID steamIDLobbyDependent) {
    424 			InteropHelp.TestIfAvailableClient();
    425 			return NativeMethods.ISteamMatchmaking_SetLinkedLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDLobbyDependent);
    426 		}
    427 #if _PS3
    428 		/// <summary>
    429 		/// <para> changes who the lobby owner is</para>
    430 		/// <para> you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby</para>
    431 		/// <para> after completion, the local user will no longer be the owner</para>
    432 		/// </summary>
    433 		public static void CheckForPSNGameBootInvite(uint iGameBootAttributes) {
    434 			InteropHelp.TestIfAvailableClient();
    435 			NativeMethods.ISteamMatchmaking_CheckForPSNGameBootInvite(CSteamAPIContext.GetSteamMatchmaking(), iGameBootAttributes);
    436 		}
    437 #endif
    438 	}
    439 	public static class SteamMatchmakingServers {
    440 		/// <summary>
    441 		/// <para> Request a new list of servers of a particular type.  These calls each correspond to one of the EMatchMakingType values.</para>
    442 		/// <para> Each call allocates a new asynchronous request object.</para>
    443 		/// <para> Request object must be released by calling ReleaseRequest( hServerListRequest )</para>
    444 		/// </summary>
    445 		public static HServerListRequest RequestInternetServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    446 			InteropHelp.TestIfAvailableClient();
    447 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestInternetServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);
    448 		}
    449 
    450 		public static HServerListRequest RequestLANServerList(AppId_t iApp, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    451 			InteropHelp.TestIfAvailableClient();
    452 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestLANServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, (IntPtr)pRequestServersResponse);
    453 		}
    454 
    455 		public static HServerListRequest RequestFriendsServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    456 			InteropHelp.TestIfAvailableClient();
    457 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFriendsServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);
    458 		}
    459 
    460 		public static HServerListRequest RequestFavoritesServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    461 			InteropHelp.TestIfAvailableClient();
    462 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFavoritesServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);
    463 		}
    464 
    465 		public static HServerListRequest RequestHistoryServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    466 			InteropHelp.TestIfAvailableClient();
    467 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestHistoryServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);
    468 		}
    469 
    470 		public static HServerListRequest RequestSpectatorServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {
    471 			InteropHelp.TestIfAvailableClient();
    472 			return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestSpectatorServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);
    473 		}
    474 
    475 		/// <summary>
    476 		/// <para> Releases the asynchronous request object and cancels any pending query on it if there's a pending query in progress.</para>
    477 		/// <para> RefreshComplete callback is not posted when request is released.</para>
    478 		/// </summary>
    479 		public static void ReleaseRequest(HServerListRequest hServerListRequest) {
    480 			InteropHelp.TestIfAvailableClient();
    481 			NativeMethods.ISteamMatchmakingServers_ReleaseRequest(CSteamAPIContext.GetSteamMatchmakingServers(), hServerListRequest);
    482 		}
    483 
    484 		/// <summary>
    485 		/// <para> the filter operation codes that go in the key part of MatchMakingKeyValuePair_t should be one of these:</para>
    486 		/// <para>		"map"</para>
    487 		/// <para>			- Server passes the filter if the server is playing the specified map.</para>
    488 		/// <para>		"gamedataand"</para>
    489 		/// <para>			- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains all of the</para>
    490 		/// <para>			specified strings.  The value field is a comma-delimited list of strings to match.</para>
    491 		/// <para>		"gamedataor"</para>
    492 		/// <para>			- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains at least one of the</para>
    493 		/// <para>			specified strings.  The value field is a comma-delimited list of strings to match.</para>
    494 		/// <para>		"gamedatanor"</para>
    495 		/// <para>			- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) does not contain any</para>
    496 		/// <para>			of the specified strings.  The value field is a comma-delimited list of strings to check.</para>
    497 		/// <para>		"gametagsand"</para>
    498 		/// <para>			- Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) contains all</para>
    499 		/// <para>			of the specified strings.  The value field is a comma-delimited list of strings to check.</para>
    500 		/// <para>		"gametagsnor"</para>
    501 		/// <para>			- Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) does not contain any</para>
    502 		/// <para>			of the specified strings.  The value field is a comma-delimited list of strings to check.</para>
    503 		/// <para>		"and" (x1 &amp;&amp; x2 &amp;&amp; ... &amp;&amp; xn)</para>
    504 		/// <para>		"or" (x1 || x2 || ... || xn)</para>
    505 		/// <para>		"nand" !(x1 &amp;&amp; x2 &amp;&amp; ... &amp;&amp; xn)</para>
    506 		/// <para>		"nor" !(x1 || x2 || ... || xn)</para>
    507 		/// <para>			- Performs Boolean operation on the following filters.  The operand to this filter specifies</para>
    508 		/// <para>			the "size" of the Boolean inputs to the operation, in Key/value pairs.  (The keyvalue</para>
    509 		/// <para>			pairs must immediately follow, i.e. this is a prefix logical operator notation.)</para>
    510 		/// <para>			In the simplest case where Boolean expressions are not nested, this is simply</para>
    511 		/// <para>			the number of operands.</para>
    512 		/// <para>			For example, to match servers on a particular map or with a particular tag, would would</para>
    513 		/// <para>			use these filters.</para>
    514 		/// <para>				( server.map == "cp_dustbowl" || server.gametags.contains("payload") )</para>
    515 		/// <para>				"or", "2"</para>
    516 		/// <para>				"map", "cp_dustbowl"</para>
    517 		/// <para>				"gametagsand", "payload"</para>
    518 		/// <para>			If logical inputs are nested, then the operand specifies the size of the entire</para>
    519 		/// <para>			"length" of its operands, not the number of immediate children.</para>
    520 		/// <para>				( server.map == "cp_dustbowl" || ( server.gametags.contains("payload") &amp;&amp; !server.gametags.contains("payloadrace") ) )</para>
    521 		/// <para>				"or", "4"</para>
    522 		/// <para>				"map", "cp_dustbowl"</para>
    523 		/// <para>				"and", "2"</para>
    524 		/// <para>				"gametagsand", "payload"</para>
    525 		/// <para>				"gametagsnor", "payloadrace"</para>
    526 		/// <para>			Unary NOT can be achieved using either "nand" or "nor" with a single operand.</para>
    527 		/// <para>		"addr"</para>
    528 		/// <para>			- Server passes the filter if the server's query address matches the specified IP or IP:port.</para>
    529 		/// <para>		"gameaddr"</para>
    530 		/// <para>			- Server passes the filter if the server's game address matches the specified IP or IP:port.</para>
    531 		/// <para>		The following filter operations ignore the "value" part of MatchMakingKeyValuePair_t</para>
    532 		/// <para>		"dedicated"</para>
    533 		/// <para>			- Server passes the filter if it passed true to SetDedicatedServer.</para>
    534 		/// <para>		"secure"</para>
    535 		/// <para>			- Server passes the filter if the server is VAC-enabled.</para>
    536 		/// <para>		"notfull"</para>
    537 		/// <para>			- Server passes the filter if the player count is less than the reported max player count.</para>
    538 		/// <para>		"hasplayers"</para>
    539 		/// <para>			- Server passes the filter if the player count is greater than zero.</para>
    540 		/// <para>		"noplayers"</para>
    541 		/// <para>			- Server passes the filter if it doesn't have any players.</para>
    542 		/// <para>		"linux"</para>
    543 		/// <para>			- Server passes the filter if it's a linux server</para>
    544 		/// <para> Get details on a given server in the list, you can get the valid range of index</para>
    545 		/// <para> values by calling GetServerCount().  You will also receive index values in</para>
    546 		/// <para> ISteamMatchmakingServerListResponse::ServerResponded() callbacks</para>
    547 		/// </summary>
    548 		public static gameserveritem_t GetServerDetails(HServerListRequest hRequest, int iServer) {
    549 			InteropHelp.TestIfAvailableClient();
    550 			return (gameserveritem_t)Marshal.PtrToStructure(NativeMethods.ISteamMatchmakingServers_GetServerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer), typeof(gameserveritem_t));
    551 		}
    552 
    553 		/// <summary>
    554 		/// <para> Cancel an request which is operation on the given list type.  You should call this to cancel</para>
    555 		/// <para> any in-progress requests before destructing a callback object that may have been passed</para>
    556 		/// <para> to one of the above list request calls.  Not doing so may result in a crash when a callback</para>
    557 		/// <para> occurs on the destructed object.</para>
    558 		/// <para> Canceling a query does not release the allocated request handle.</para>
    559 		/// <para> The request handle must be released using ReleaseRequest( hRequest )</para>
    560 		/// </summary>
    561 		public static void CancelQuery(HServerListRequest hRequest) {
    562 			InteropHelp.TestIfAvailableClient();
    563 			NativeMethods.ISteamMatchmakingServers_CancelQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);
    564 		}
    565 
    566 		/// <summary>
    567 		/// <para> Ping every server in your list again but don't update the list of servers</para>
    568 		/// <para> Query callback installed when the server list was requested will be used</para>
    569 		/// <para> again to post notifications and RefreshComplete, so the callback must remain</para>
    570 		/// <para> valid until another RefreshComplete is called on it or the request</para>
    571 		/// <para> is released with ReleaseRequest( hRequest )</para>
    572 		/// </summary>
    573 		public static void RefreshQuery(HServerListRequest hRequest) {
    574 			InteropHelp.TestIfAvailableClient();
    575 			NativeMethods.ISteamMatchmakingServers_RefreshQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);
    576 		}
    577 
    578 		/// <summary>
    579 		/// <para> Returns true if the list is currently refreshing its server list</para>
    580 		/// </summary>
    581 		public static bool IsRefreshing(HServerListRequest hRequest) {
    582 			InteropHelp.TestIfAvailableClient();
    583 			return NativeMethods.ISteamMatchmakingServers_IsRefreshing(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);
    584 		}
    585 
    586 		/// <summary>
    587 		/// <para> How many servers in the given list, GetServerDetails above takes 0... GetServerCount() - 1</para>
    588 		/// </summary>
    589 		public static int GetServerCount(HServerListRequest hRequest) {
    590 			InteropHelp.TestIfAvailableClient();
    591 			return NativeMethods.ISteamMatchmakingServers_GetServerCount(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);
    592 		}
    593 
    594 		/// <summary>
    595 		/// <para> Refresh a single server inside of a query (rather than all the servers )</para>
    596 		/// </summary>
    597 		public static void RefreshServer(HServerListRequest hRequest, int iServer) {
    598 			InteropHelp.TestIfAvailableClient();
    599 			NativeMethods.ISteamMatchmakingServers_RefreshServer(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer);
    600 		}
    601 
    602 		/// <summary>
    603 		/// <para>-----------------------------------------------------------------------------</para>
    604 		/// <para> Queries to individual servers directly via IP/Port</para>
    605 		/// <para>-----------------------------------------------------------------------------</para>
    606 		/// <para> Request updated ping time and other details from a single server</para>
    607 		/// </summary>
    608 		public static HServerQuery PingServer(uint unIP, ushort usPort, ISteamMatchmakingPingResponse pRequestServersResponse) {
    609 			InteropHelp.TestIfAvailableClient();
    610 			return (HServerQuery)NativeMethods.ISteamMatchmakingServers_PingServer(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);
    611 		}
    612 
    613 		/// <summary>
    614 		/// <para> Request the list of players currently playing on a server</para>
    615 		/// </summary>
    616 		public static HServerQuery PlayerDetails(uint unIP, ushort usPort, ISteamMatchmakingPlayersResponse pRequestServersResponse) {
    617 			InteropHelp.TestIfAvailableClient();
    618 			return (HServerQuery)NativeMethods.ISteamMatchmakingServers_PlayerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);
    619 		}
    620 
    621 		/// <summary>
    622 		/// <para> Request the list of rules that the server is running (See ISteamGameServer::SetKeyValue() to set the rules server side)</para>
    623 		/// </summary>
    624 		public static HServerQuery ServerRules(uint unIP, ushort usPort, ISteamMatchmakingRulesResponse pRequestServersResponse) {
    625 			InteropHelp.TestIfAvailableClient();
    626 			return (HServerQuery)NativeMethods.ISteamMatchmakingServers_ServerRules(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);
    627 		}
    628 
    629 		/// <summary>
    630 		/// <para> Cancel an outstanding Ping/Players/Rules query from above.  You should call this to cancel</para>
    631 		/// <para> any in-progress requests before destructing a callback object that may have been passed</para>
    632 		/// <para> to one of the above calls to avoid crashing when callbacks occur.</para>
    633 		/// </summary>
    634 		public static void CancelServerQuery(HServerQuery hServerQuery) {
    635 			InteropHelp.TestIfAvailableClient();
    636 			NativeMethods.ISteamMatchmakingServers_CancelServerQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hServerQuery);
    637 		}
    638 	}
    639 	public static class SteamGameSearch {
    640 		/// <summary>
    641 		/// <para> =============================================================================================</para>
    642 		/// <para> Game Player APIs</para>
    643 		/// <para> a keyname and a list of comma separated values: one of which is must be found in order for the match to qualify</para>
    644 		/// <para> fails if a search is currently in progress</para>
    645 		/// </summary>
    646 		public static EGameSearchErrorCode_t AddGameSearchParams(string pchKeyToFind, string pchValuesToFind) {
    647 			InteropHelp.TestIfAvailableClient();
    648 			using (var pchKeyToFind2 = new InteropHelp.UTF8StringHandle(pchKeyToFind))
    649 			using (var pchValuesToFind2 = new InteropHelp.UTF8StringHandle(pchValuesToFind)) {
    650 				return NativeMethods.ISteamGameSearch_AddGameSearchParams(CSteamAPIContext.GetSteamGameSearch(), pchKeyToFind2, pchValuesToFind2);
    651 			}
    652 		}
    653 
    654 		/// <summary>
    655 		/// <para> all players in lobby enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress</para>
    656 		/// <para> if not the owner of the lobby or search already in progress this call fails</para>
    657 		/// <para> periodic callbacks will be sent as queue time estimates change</para>
    658 		/// </summary>
    659 		public static EGameSearchErrorCode_t SearchForGameWithLobby(CSteamID steamIDLobby, int nPlayerMin, int nPlayerMax) {
    660 			InteropHelp.TestIfAvailableClient();
    661 			return NativeMethods.ISteamGameSearch_SearchForGameWithLobby(CSteamAPIContext.GetSteamGameSearch(), steamIDLobby, nPlayerMin, nPlayerMax);
    662 		}
    663 
    664 		/// <summary>
    665 		/// <para> user enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress</para>
    666 		/// <para> periodic callbacks will be sent as queue time estimates change</para>
    667 		/// </summary>
    668 		public static EGameSearchErrorCode_t SearchForGameSolo(int nPlayerMin, int nPlayerMax) {
    669 			InteropHelp.TestIfAvailableClient();
    670 			return NativeMethods.ISteamGameSearch_SearchForGameSolo(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax);
    671 		}
    672 
    673 		/// <summary>
    674 		/// <para> after receiving SearchForGameResultCallback_t, accept or decline the game</para>
    675 		/// <para> multiple SearchForGameResultCallback_t will follow as players accept game until the host starts or cancels the game</para>
    676 		/// </summary>
    677 		public static EGameSearchErrorCode_t AcceptGame() {
    678 			InteropHelp.TestIfAvailableClient();
    679 			return NativeMethods.ISteamGameSearch_AcceptGame(CSteamAPIContext.GetSteamGameSearch());
    680 		}
    681 
    682 		public static EGameSearchErrorCode_t DeclineGame() {
    683 			InteropHelp.TestIfAvailableClient();
    684 			return NativeMethods.ISteamGameSearch_DeclineGame(CSteamAPIContext.GetSteamGameSearch());
    685 		}
    686 
    687 		/// <summary>
    688 		/// <para> after receiving GameStartedByHostCallback_t get connection details to server</para>
    689 		/// </summary>
    690 		public static EGameSearchErrorCode_t RetrieveConnectionDetails(CSteamID steamIDHost, out string pchConnectionDetails, int cubConnectionDetails) {
    691 			InteropHelp.TestIfAvailableClient();
    692 			IntPtr pchConnectionDetails2 = Marshal.AllocHGlobal(cubConnectionDetails);
    693 			EGameSearchErrorCode_t ret = NativeMethods.ISteamGameSearch_RetrieveConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), steamIDHost, pchConnectionDetails2, cubConnectionDetails);
    694 			pchConnectionDetails = ret != 0 ? InteropHelp.PtrToStringUTF8(pchConnectionDetails2) : null;
    695 			Marshal.FreeHGlobal(pchConnectionDetails2);
    696 			return ret;
    697 		}
    698 
    699 		/// <summary>
    700 		/// <para> leaves queue if still waiting</para>
    701 		/// </summary>
    702 		public static EGameSearchErrorCode_t EndGameSearch() {
    703 			InteropHelp.TestIfAvailableClient();
    704 			return NativeMethods.ISteamGameSearch_EndGameSearch(CSteamAPIContext.GetSteamGameSearch());
    705 		}
    706 
    707 		/// <summary>
    708 		/// <para> =============================================================================================</para>
    709 		/// <para> Game Host APIs</para>
    710 		/// <para> a keyname and a list of comma separated values: all the values you allow</para>
    711 		/// </summary>
    712 		public static EGameSearchErrorCode_t SetGameHostParams(string pchKey, string pchValue) {
    713 			InteropHelp.TestIfAvailableClient();
    714 			using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))
    715 			using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {
    716 				return NativeMethods.ISteamGameSearch_SetGameHostParams(CSteamAPIContext.GetSteamGameSearch(), pchKey2, pchValue2);
    717 			}
    718 		}
    719 
    720 		/// <summary>
    721 		/// <para> set connection details for players once game is found so they can connect to this server</para>
    722 		/// </summary>
    723 		public static EGameSearchErrorCode_t SetConnectionDetails(string pchConnectionDetails, int cubConnectionDetails) {
    724 			InteropHelp.TestIfAvailableClient();
    725 			using (var pchConnectionDetails2 = new InteropHelp.UTF8StringHandle(pchConnectionDetails)) {
    726 				return NativeMethods.ISteamGameSearch_SetConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), pchConnectionDetails2, cubConnectionDetails);
    727 			}
    728 		}
    729 
    730 		/// <summary>
    731 		/// <para> mark server as available for more players with nPlayerMin,nPlayerMax desired</para>
    732 		/// <para> accept no lobbies with playercount greater than nMaxTeamSize</para>
    733 		/// <para> the set of lobbies returned must be partitionable into teams of no more than nMaxTeamSize</para>
    734 		/// <para> RequestPlayersForGameNotificationCallback_t callback will be sent when the search has started</para>
    735 		/// <para> multple RequestPlayersForGameResultCallback_t callbacks will follow when players are found</para>
    736 		/// </summary>
    737 		public static EGameSearchErrorCode_t RequestPlayersForGame(int nPlayerMin, int nPlayerMax, int nMaxTeamSize) {
    738 			InteropHelp.TestIfAvailableClient();
    739 			return NativeMethods.ISteamGameSearch_RequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax, nMaxTeamSize);
    740 		}
    741 
    742 		/// <summary>
    743 		/// <para> accept the player list and release connection details to players</para>
    744 		/// <para> players will only be given connection details and host steamid when this is called</para>
    745 		/// <para> ( allows host to accept after all players confirm, some confirm, or none confirm. decision is entirely up to the host )</para>
    746 		/// </summary>
    747 		public static EGameSearchErrorCode_t HostConfirmGameStart(ulong ullUniqueGameID) {
    748 			InteropHelp.TestIfAvailableClient();
    749 			return NativeMethods.ISteamGameSearch_HostConfirmGameStart(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID);
    750 		}
    751 
    752 		/// <summary>
    753 		/// <para> cancel request and leave the pool of game hosts looking for players</para>
    754 		/// <para> if a set of players has already been sent to host, all players will receive SearchForGameHostFailedToConfirm_t</para>
    755 		/// </summary>
    756 		public static EGameSearchErrorCode_t CancelRequestPlayersForGame() {
    757 			InteropHelp.TestIfAvailableClient();
    758 			return NativeMethods.ISteamGameSearch_CancelRequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch());
    759 		}
    760 
    761 		/// <summary>
    762 		/// <para> submit a result for one player. does not end the game. ullUniqueGameID continues to describe this game</para>
    763 		/// </summary>
    764 		public static EGameSearchErrorCode_t SubmitPlayerResult(ulong ullUniqueGameID, CSteamID steamIDPlayer, EPlayerResult_t EPlayerResult) {
    765 			InteropHelp.TestIfAvailableClient();
    766 			return NativeMethods.ISteamGameSearch_SubmitPlayerResult(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID, steamIDPlayer, EPlayerResult);
    767 		}
    768 
    769 		/// <summary>
    770 		/// <para> ends the game. no further SubmitPlayerResults for ullUniqueGameID will be accepted</para>
    771 		/// <para> any future requests will provide a new ullUniqueGameID</para>
    772 		/// </summary>
    773 		public static EGameSearchErrorCode_t EndGame(ulong ullUniqueGameID) {
    774 			InteropHelp.TestIfAvailableClient();
    775 			return NativeMethods.ISteamGameSearch_EndGame(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID);
    776 		}
    777 	}
    778 	public static class SteamParties {
    779 		/// <summary>
    780 		/// <para> =============================================================================================</para>
    781 		/// <para> Party Client APIs</para>
    782 		/// <para> Enumerate any active beacons for parties you may wish to join</para>
    783 		/// </summary>
    784 		public static uint GetNumActiveBeacons() {
    785 			InteropHelp.TestIfAvailableClient();
    786 			return NativeMethods.ISteamParties_GetNumActiveBeacons(CSteamAPIContext.GetSteamParties());
    787 		}
    788 
    789 		public static PartyBeaconID_t GetBeaconByIndex(uint unIndex) {
    790 			InteropHelp.TestIfAvailableClient();
    791 			return (PartyBeaconID_t)NativeMethods.ISteamParties_GetBeaconByIndex(CSteamAPIContext.GetSteamParties(), unIndex);
    792 		}
    793 
    794 		public static bool GetBeaconDetails(PartyBeaconID_t ulBeaconID, out CSteamID pSteamIDBeaconOwner, out SteamPartyBeaconLocation_t pLocation, out string pchMetadata, int cchMetadata) {
    795 			InteropHelp.TestIfAvailableClient();
    796 			IntPtr pchMetadata2 = Marshal.AllocHGlobal(cchMetadata);
    797 			bool ret = NativeMethods.ISteamParties_GetBeaconDetails(CSteamAPIContext.GetSteamParties(), ulBeaconID, out pSteamIDBeaconOwner, out pLocation, pchMetadata2, cchMetadata);
    798 			pchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null;
    799 			Marshal.FreeHGlobal(pchMetadata2);
    800 			return ret;
    801 		}
    802 
    803 		/// <summary>
    804 		/// <para> Join an open party. Steam will reserve one beacon slot for your SteamID,</para>
    805 		/// <para> and return the necessary JoinGame string for you to use to connect</para>
    806 		/// </summary>
    807 		public static SteamAPICall_t JoinParty(PartyBeaconID_t ulBeaconID) {
    808 			InteropHelp.TestIfAvailableClient();
    809 			return (SteamAPICall_t)NativeMethods.ISteamParties_JoinParty(CSteamAPIContext.GetSteamParties(), ulBeaconID);
    810 		}
    811 
    812 		/// <summary>
    813 		/// <para> =============================================================================================</para>
    814 		/// <para> Party Host APIs</para>
    815 		/// <para> Get a list of possible beacon locations</para>
    816 		/// </summary>
    817 		public static bool GetNumAvailableBeaconLocations(out uint puNumLocations) {
    818 			InteropHelp.TestIfAvailableClient();
    819 			return NativeMethods.ISteamParties_GetNumAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), out puNumLocations);
    820 		}
    821 
    822 		public static bool GetAvailableBeaconLocations(SteamPartyBeaconLocation_t[] pLocationList, uint uMaxNumLocations) {
    823 			InteropHelp.TestIfAvailableClient();
    824 			return NativeMethods.ISteamParties_GetAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), pLocationList, uMaxNumLocations);
    825 		}
    826 
    827 		/// <summary>
    828 		/// <para> Create a new party beacon and activate it in the selected location.</para>
    829 		/// <para> unOpenSlots is the maximum number of users that Steam will send to you.</para>
    830 		/// <para> When people begin responding to your beacon, Steam will send you</para>
    831 		/// <para> PartyReservationCallback_t callbacks to let you know who is on the way.</para>
    832 		/// </summary>
    833 		public static SteamAPICall_t CreateBeacon(uint unOpenSlots, ref SteamPartyBeaconLocation_t pBeaconLocation, string pchConnectString, string pchMetadata) {
    834 			InteropHelp.TestIfAvailableClient();
    835 			using (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString))
    836 			using (var pchMetadata2 = new InteropHelp.UTF8StringHandle(pchMetadata)) {
    837 				return (SteamAPICall_t)NativeMethods.ISteamParties_CreateBeacon(CSteamAPIContext.GetSteamParties(), unOpenSlots, ref pBeaconLocation, pchConnectString2, pchMetadata2);
    838 			}
    839 		}
    840 
    841 		/// <summary>
    842 		/// <para> Call this function when a user that had a reservation (see callback below)</para>
    843 		/// <para> has successfully joined your party.</para>
    844 		/// <para> Steam will manage the remaining open slots automatically.</para>
    845 		/// </summary>
    846 		public static void OnReservationCompleted(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) {
    847 			InteropHelp.TestIfAvailableClient();
    848 			NativeMethods.ISteamParties_OnReservationCompleted(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser);
    849 		}
    850 
    851 		/// <summary>
    852 		/// <para> To cancel a reservation (due to timeout or user input), call this.</para>
    853 		/// <para> Steam will open a new reservation slot.</para>
    854 		/// <para> Note: The user may already be in-flight to your game, so it's possible they will still connect and try to join your party.</para>
    855 		/// </summary>
    856 		public static void CancelReservation(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) {
    857 			InteropHelp.TestIfAvailableClient();
    858 			NativeMethods.ISteamParties_CancelReservation(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser);
    859 		}
    860 
    861 		/// <summary>
    862 		/// <para> Change the number of open beacon reservation slots.</para>
    863 		/// <para> Call this if, for example, someone without a reservation joins your party (eg a friend, or via your own matchmaking system).</para>
    864 		/// </summary>
    865 		public static SteamAPICall_t ChangeNumOpenSlots(PartyBeaconID_t ulBeacon, uint unOpenSlots) {
    866 			InteropHelp.TestIfAvailableClient();
    867 			return (SteamAPICall_t)NativeMethods.ISteamParties_ChangeNumOpenSlots(CSteamAPIContext.GetSteamParties(), ulBeacon, unOpenSlots);
    868 		}
    869 
    870 		/// <summary>
    871 		/// <para> Turn off the beacon.</para>
    872 		/// </summary>
    873 		public static bool DestroyBeacon(PartyBeaconID_t ulBeacon) {
    874 			InteropHelp.TestIfAvailableClient();
    875 			return NativeMethods.ISteamParties_DestroyBeacon(CSteamAPIContext.GetSteamParties(), ulBeacon);
    876 		}
    877 
    878 		/// <summary>
    879 		/// <para> Utils</para>
    880 		/// </summary>
    881 		public static bool GetBeaconLocationData(SteamPartyBeaconLocation_t BeaconLocation, ESteamPartyBeaconLocationData eData, out string pchDataStringOut, int cchDataStringOut) {
    882 			InteropHelp.TestIfAvailableClient();
    883 			IntPtr pchDataStringOut2 = Marshal.AllocHGlobal(cchDataStringOut);
    884 			bool ret = NativeMethods.ISteamParties_GetBeaconLocationData(CSteamAPIContext.GetSteamParties(), BeaconLocation, eData, pchDataStringOut2, cchDataStringOut);
    885 			pchDataStringOut = ret ? InteropHelp.PtrToStringUTF8(pchDataStringOut2) : null;
    886 			Marshal.FreeHGlobal(pchDataStringOut2);
    887 			return ret;
    888 		}
    889 	}
    890 }
    891 
    892 #endif // !DISABLESTEAMWORKS