diff options
| author | Matthew Collins <[email protected]> | 2018-05-07 01:02:44 +0100 |
|---|---|---|
| committer | Matthew Collins <[email protected]> | 2018-05-07 01:02:44 +0100 |
| commit | 63f96e3eb579cd53b4a7bee84ef173add5f888e8 (patch) | |
| tree | 8badd7acdc85a70f141f3750bbf047c586cffd44 | |
| parent | Fix building with older steam sdks (diff) | |
| download | steamworks-rs-63f96e3eb579cd53b4a7bee84ef173add5f888e8.tar.xz steamworks-rs-63f96e3eb579cd53b4a7bee84ef173add5f888e8.zip | |
Steam networking support + other improvements
| -rw-r--r-- | src/callback.rs | 33 | ||||
| -rw-r--r-- | src/friends.rs | 96 | ||||
| -rw-r--r-- | src/lib.rs | 67 | ||||
| -rw-r--r-- | src/matchmaking.rs | 60 | ||||
| -rw-r--r-- | src/networking.rs | 109 | ||||
| -rw-r--r-- | src/server.rs | 8 | ||||
| -rw-r--r-- | src/user.rs | 4 | ||||
| -rw-r--r-- | steamworks-sys/src/lib.cpp | 25 | ||||
| -rw-r--r-- | steamworks-sys/src/lib.rs | 24 |
9 files changed, 412 insertions, 14 deletions
diff --git a/src/callback.rs b/src/callback.rs index 18c1db0..d8e186d 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -5,8 +5,11 @@ use sys; use std::mem; use std::sync::{ Arc, Weak }; +#[cfg(debug_assertions)] use std::panic::*; +#[cfg(debug_assertions)] use std::any::Any; +#[cfg(debug_assertions)] use std::process::abort; pub unsafe trait Callback { @@ -15,6 +18,29 @@ pub unsafe trait Callback { unsafe fn from_raw(raw: *mut c_void) -> Self; } +/// A handled that can be used to remove a callback +/// at a later point. +/// +/// Removes the callback when dropped +pub struct CallbackHandle<Manager = ClientManager> { + handle: *mut c_void, + inner: Weak<Inner<Manager>>, +} +unsafe impl <Manager> Send for CallbackHandle<Manager> {} + +impl <Manager> Drop for CallbackHandle<Manager> { + fn drop(&mut self) { + if let Some(inner) = self.inner.upgrade() { + let mut cb = inner.callbacks.lock().unwrap(); + if let Some(pos) = cb.callbacks.iter().position(|v| *v == self.handle) { + cb.callbacks.swap_remove(pos); + unsafe { sys::delete_rust_callback(self.handle); } + } + } + } +} + +#[cfg(debug_assertions)] fn print_err(err: Box<Any>) { if let Some(err) = err.downcast_ref::<&str>() { println!("Steam callback paniced: {}", err); @@ -25,7 +51,7 @@ fn print_err(err: Box<Any>) { } } -pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager>>, f: F, game_server: bool) +pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager>>, f: F, game_server: bool) -> CallbackHandle<Manager> where C: Callback, F: FnMut(C) + Send + 'static { @@ -70,6 +96,11 @@ pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager> let mut cbs = inner.callbacks.lock().unwrap(); cbs.callbacks.push(ptr); + + CallbackHandle { + handle: ptr, + inner: Arc::downgrade(inner), + } } pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manager>>, api_call: sys::SteamAPICall, callback_id: i32, f: F) diff --git a/src/friends.rs b/src/friends.rs index f0fe66e..68cbe6d 100644 --- a/src/friends.rs +++ b/src/friends.rs @@ -1,5 +1,6 @@ use super::*; +use std::net::Ipv4Addr; const CALLBACK_BASE_ID: i32 = 300; @@ -78,6 +79,14 @@ impl <Manager> Friends<Manager> { } } + pub fn get_friend(&self, friend: SteamId) -> Friend<Manager> { + Friend { + id: friend, + friends: self.friends, + _inner: self.inner.clone(), + } + } + pub fn request_user_information(&self, user: SteamId, name_only: bool) { unsafe { sys::SteamAPI_ISteamFriends_RequestUserInformation(self.friends, user.0, name_only as u8); @@ -91,6 +100,29 @@ impl <Manager> Friends<Manager> { sys::SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage(self.friends, url.as_ptr() as *const _); } } + + /// Opens up an invite dialog for the given lobby + pub fn activate_invite_dialog(&self, lobby: LobbyId) { + unsafe { + sys::SteamAPI_ISteamFriends_ActivateGameOverlayInviteDialog(self.friends, lobby.0); + } + } +} + +/// Information about a friend's current state in a game +#[derive(Debug)] +pub struct FriendGame { + /// The id of the game that the friend is + /// playing + pub game: GameId, + /// The address of the server the player is in + pub game_address: Ipv4Addr, + /// The game port of the server the player is in + pub game_port: u16, + /// The query port of the server the player is in + pub query_port: u16, + /// Optional id of the lobby the player is in + pub lobby: LobbyId, } #[derive(Debug)] @@ -171,6 +203,70 @@ impl <Manager> Friend<Manager> { } } } + + /// Returns information about the game the player is current playing if any + pub fn game_played(&self) -> Option<FriendGame> { + unsafe { + let mut info = sys::create_empty_FriendGameInfo_t(); + if sys::SteamAPI_ISteamFriends_GetFriendGamePlayed(self.friends, self.id.0, &mut info) != 0 { + Some(FriendGame { + game: GameId(info.get_m_gameID()), + game_address: info.get_m_unGameIP().into(), + game_port: info.get_m_usGamePort(), + query_port: info.get_m_usQueryPort(), + lobby: LobbyId(info.get_m_steamIDLobby()), + }) + } else { + None + } + } + } + + /// Returns a small (32x32) avatar for the user + pub fn small_avatar(&self) -> Option<Vec<u8>> { + unsafe { + let utils = sys::steam_rust_get_utils(); + let img = sys::SteamAPI_ISteamFriends_GetSmallFriendAvatar(self.friends, self.id.0); + if img == 0 { + return None; + } + let mut width = 0; + let mut height = 0; + if sys::SteamAPI_ISteamUtils_GetImageSize(utils, img, &mut width, &mut height) == 0 { + return None; + } + assert_eq!(width, 32); + assert_eq!(height, 32); + let mut dest = vec![0; 32 * 32 * 4]; + if sys::SteamAPI_ISteamUtils_GetImageRGBA(utils, img, dest.as_mut_ptr(), 32 * 32 * 4) == 0 { + return None; + } + Some(dest) + } + } + + /// Returns a small (64x64) avatar for the user + pub fn medium_avatar(&self) -> Option<Vec<u8>> { + unsafe { + let utils = sys::steam_rust_get_utils(); + let img = sys::SteamAPI_ISteamFriends_GetMediumFriendAvatar(self.friends, self.id.0); + if img == 0 { + return None; + } + let mut width = 0; + let mut height = 0; + if sys::SteamAPI_ISteamUtils_GetImageSize(utils, img, &mut width, &mut height) == 0 { + return None; + } + assert_eq!(width, 64); + assert_eq!(height, 64); + let mut dest = vec![0; 64 * 64 * 4]; + if sys::SteamAPI_ISteamUtils_GetImageRGBA(utils, img, dest.as_mut_ptr(), 64 * 64 * 4) == 0 { + return None; + } + Some(dest) + } + } } #[derive(Clone, Copy, Debug)] @@ -21,6 +21,8 @@ mod friends; pub use friends::*; mod matchmaking; pub use matchmaking::*; +mod networking; +pub use networking::*; mod user; pub use user::*; @@ -160,12 +162,12 @@ impl <Manager> Client<Manager> { /// /// The callback will be run on the thread that `run_callbacks` /// is called when the event arrives. - pub fn register_callback<C, F>(&self, f: F) + pub fn register_callback<C, F>(&self, f: F) -> CallbackHandle<Manager> where C: Callback, F: FnMut(C) + 'static + Send { unsafe { - register_callback(&self.inner, f, false); + register_callback(&self.inner, f, false) } } @@ -193,6 +195,18 @@ impl <Manager> Client<Manager> { } } + /// Returns an accessor to the steam networking interface + pub fn networking(&self) -> Networking<Manager> { + unsafe { + let net = sys::steam_rust_get_networking(); + debug_assert!(!net.is_null()); + Networking { + net: net, + _inner: self.inner.clone(), + } + } + } + /// Returns an accessor to the steam apps interface pub fn apps(&self) -> Apps<Manager> { unsafe { @@ -273,7 +287,7 @@ impl Drop for ClientManager { } /// A user's steam id -#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct SteamId(pub(crate) u64); impl SteamId { @@ -292,6 +306,51 @@ impl SteamId { pub fn raw(&self) -> u64 { self.0 } + + /// Returns whether this id is valid or not + pub fn is_valid(&self) -> bool { + unsafe { + sys::steam_rust_is_steam_id_valid(self.0) != 0 + } + } +} + +/// A game id +/// +/// Combines `AppId` and other information +#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)] +pub struct GameId(pub(crate) u64); + +impl GameId { + /// Creates a `GameId` from a raw 64 bit value. + /// + /// May be useful for deserializing game ids from + /// a network or save format. + pub fn from_raw(id: u64) -> GameId { + GameId(id) + } + + /// Returns the raw 64 bit value of the game id + /// + /// May be useful for serializing game ids over a + /// network or to a save format. + pub fn raw(&self) -> u64 { + self.0 + } + + /// Returns the app id of this game + pub fn app_id(&self) -> AppId { + unsafe { + AppId(sys::steam_rust_get_game_id_app(self.0)) + } + } + + /// Returns whether this id is valid or not + pub fn is_valid(&self) -> bool { + unsafe { + sys::steam_rust_is_game_id_valid(self.0) != 0 + } + } } #[cfg(test)] @@ -301,7 +360,7 @@ mod tests { fn basic_test() { let (client, single) = Client::init().unwrap(); - client.register_callback(|p: PersonaStateChange| { + let _cb = client.register_callback(|p: PersonaStateChange| { println!("Got callback: {:?}", p); }); diff --git a/src/matchmaking.rs b/src/matchmaking.rs index f219381..0f3c17b 100644 --- a/src/matchmaking.rs +++ b/src/matchmaking.rs @@ -17,8 +17,33 @@ pub enum LobbyType { Invisible, } -#[derive(Debug)] -pub struct LobbyId(pub u64); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LobbyId(pub(crate) u64); + +impl LobbyId { + /// Creates a `LobbyId` from a raw 64 bit value. + /// + /// May be useful for deserializing lobby ids from + /// a network or save format. + pub fn from_raw(id: u64) -> LobbyId { + LobbyId(id) + } + + /// Returns the raw 64 bit value of the lobby id + /// + /// May be useful for serializing lobby ids over a + /// network or to a save format. + pub fn raw(&self) -> u64 { + self.0 + } + + /// Returns whether this id is valid or not + pub fn is_valid(&self) -> bool { + unsafe { + sys::steam_rust_is_steam_id_valid(self.0) != 0 + } + } +} impl <Manager> Matchmaking<Manager> { @@ -105,6 +130,37 @@ impl <Manager> Matchmaking<Manager> { sys::SteamAPI_ISteamMatchmaking_LeaveLobby(self.mm, lobby.0); } } + + /// Returns the steam id of the current owner of the passed lobby + pub fn lobby_owner(&self, lobby: LobbyId) -> SteamId { + unsafe { + SteamId(sys::SteamAPI_ISteamMatchmaking_GetLobbyOwner(self.mm, lobby.0)) + } + } + + /// Returns the number of players in a lobby. + /// + /// Useful if you are not currently in the lobby + pub fn lobby_member_count(&self, lobby: LobbyId) -> usize { + unsafe { + let count = sys::SteamAPI_ISteamMatchmaking_GetNumLobbyMembers(self.mm, lobby.0); + count as usize + } + } + + /// Returns a list of members currently in the lobby + pub fn lobby_members(&self, lobby: LobbyId) -> Vec<SteamId> { + unsafe { + let count = sys::SteamAPI_ISteamMatchmaking_GetNumLobbyMembers(self.mm, lobby.0); + let mut members = Vec::with_capacity(count as usize); + for idx in 0 .. count { + members.push(SteamId( + sys::SteamAPI_ISteamMatchmaking_GetLobbyMemberByIndex(self.mm, lobby.0, idx) + )) + } + members + } + } } #[test] diff --git a/src/networking.rs b/src/networking.rs new file mode 100644 index 0000000..258abda --- /dev/null +++ b/src/networking.rs @@ -0,0 +1,109 @@ +use super::*; + +/// Access to the steam networking interface +pub struct Networking<Manager> { + pub(crate) net: *mut sys::ISteamNetworking, + pub(crate) _inner: Arc<Inner<Manager>>, +} + +/// The method used to send a packet +#[derive(Debug)] +pub enum SendType { + /// Send the packet directly over udp. + /// + /// Can't be larger than 1200 bytes + Unreliable, + /// Like `Unreliable` but doesn't buffer packets + /// sent before the connection has started. + UnreliableNoDelay, + /// Reliable packet sending. + /// + /// Can't be larger than 1 megabyte. + Reliable, + /// Like `Reliable` but applies the nagle + /// algorithm to packets being sent + ReliableWithBuffering, +} + +impl <Manager> Networking<Manager> { + /// Accepts incoming packets from the given user + /// + /// Should only be called in response to a `P2PSessionRequest`. + pub fn accept_p2p_session(&self, user: SteamId) { + unsafe { + sys::SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser(self.net, user.0); + } + } + + /// Closes the p2p connection between the given user + pub fn close_p2p_session(&self, user: SteamId) { + unsafe { + sys::SteamAPI_ISteamNetworking_CloseP2PSessionWithUser(self.net, user.0); + } + } + + /// Sends a packet to the start user starting the + /// connection if it isn't started already + pub fn send_p2p_packet(&self, remote: SteamId, send_type: SendType, data: &[u8]) -> bool { + unsafe { + let send_type = match send_type { + SendType::Unreliable => sys::EP2PSend_k_EP2PSendUnreliable, + SendType::UnreliableNoDelay => sys::EP2PSend_k_EP2PSendUnreliableNoDelay, + SendType::Reliable => sys::EP2PSend_k_EP2PSendReliable, + SendType::ReliableWithBuffering => sys::EP2PSend_k_EP2PSendReliableWithBuffering, + }; + sys::SteamAPI_ISteamNetworking_SendP2PPacket(self.net, remote.0, data.as_ptr() as *const _, data.len() as u32, send_type, 0) != 0 + } + } + + /// Returns whether there is a packet queued that can be read. + /// + /// Returns the size of the queued packet if any. + pub fn is_p2p_packet_available(&self) -> Option<usize> { + unsafe { + let mut size = 0; + if sys::SteamAPI_ISteamNetworking_IsP2PPacketAvailable(self.net, &mut size, 0) != 0 { + Some(size as usize) + } else { + None + } + } + } + + /// Attempts to read a queued packet into the buffer + /// if there are any. + /// + /// Returns the steam id of the sender and the size of the + /// packet. + pub fn read_p2p_packet(&self, buf: &mut [u8]) -> Option<(SteamId, usize)> { + unsafe { + let mut size = 0; + let mut remote = 0; + if sys::SteamAPI_ISteamNetworking_ReadP2PPacket(self.net, buf.as_mut_ptr() as *mut _, buf.len() as _, &mut size, &mut remote, 0) != 0 { + Some((SteamId(remote), size as usize)) + } else { + None + } + } + } +} + +/// Called when a user wants to communicate via p2p +#[derive(Debug)] +pub struct P2PSessionRequest { + /// The steam ID of the user requesting a p2p + /// session + pub remote: SteamId, +} + +unsafe impl Callback for P2PSessionRequest { + const ID: i32 = sys::P2PSessionRequest_t_k_iCallback as i32; + const SIZE: i32 = ::std::mem::size_of::<sys::P2PSessionRequest_t>() as i32; + + unsafe fn from_raw(raw: *mut libc::c_void) -> Self { + let val = &mut *(raw as *mut sys::P2PSessionRequest_t); + P2PSessionRequest { + remote: SteamId(val.get_m_steamIDRemote()), + } + } +} diff --git a/src/server.rs b/src/server.rs index ee67742..6a01b7f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -97,12 +97,12 @@ impl Server { /// /// The callback will be run on the thread that `run_callbacks` /// is called when the event arrives. - pub fn register_callback<C, F>(&self, f: F) + pub fn register_callback<C, F>(&self, f: F) -> CallbackHandle<ServerManager> where C: Callback, F: FnMut(C) + 'static + Send + Sync { unsafe { - register_callback(&self.inner, f, true); + register_callback(&self.inner, f, true) } } @@ -251,8 +251,8 @@ fn test() { println!("{:?}", server.steam_id()); - server.register_callback(|v: AuthSessionTicketResponse| println!("{:?}", v)); - server.register_callback(|v: ValidateAuthTicketResponse| println!("{:?}", v)); + let _cb = server.register_callback(|v: AuthSessionTicketResponse| println!("{:?}", v)); + let _cb = server.register_callback(|v: ValidateAuthTicketResponse| println!("{:?}", v)); let id = server.steam_id(); let (auth, ticket) = server.authentication_session_ticket(); diff --git a/src/user.rs b/src/user.rs index 8298656..3263ba6 100644 --- a/src/user.rs +++ b/src/user.rs @@ -111,8 +111,8 @@ fn test() { let (client, single) = Client::init().unwrap(); let user = client.user(); - client.register_callback(|v: AuthSessionTicketResponse| println!("{:?}", v)); - client.register_callback(|v: ValidateAuthTicketResponse| println!("{:?}", v)); + let _cb = client.register_callback(|v: AuthSessionTicketResponse| println!("{:?}", v)); + let _cb = client.register_callback(|v: ValidateAuthTicketResponse| println!("{:?}", v)); let id = user.steam_id(); let (auth, ticket) = user.authentication_session_ticket(); diff --git a/steamworks-sys/src/lib.cpp b/steamworks-sys/src/lib.cpp index 38701da..655eaf4 100644 --- a/steamworks-sys/src/lib.cpp +++ b/steamworks-sys/src/lib.cpp @@ -52,8 +52,33 @@ extern "C" { return SteamGameServer_Init(ip, steam_port, game_port, query_port, server_mode, version); } + int steam_rust_is_steam_id_valid(uint64_t steam_id) { + CSteamID id = CSteamID(); + id.SetFromUint64(steam_id); + return id.IsValid(); + } + + int steam_rust_is_game_id_valid(uint64_t game_id) { + CGameID id = CGameID(); + id.Set(game_id); + return id.IsValid(); + } + + uint32_t steam_rust_get_game_id_mod(uint64_t game_id) { + CGameID id = CGameID(); + id.Set(game_id); + return id.ModID(); + } + + uint32_t steam_rust_get_game_id_app(uint64_t game_id) { + CGameID id = CGameID(); + id.Set(game_id); + return id.AppID(); + } + ISteamClient* steam_rust_get_client() { return SteamClient(); } ISteamMatchmaking* steam_rust_get_matchmaking() { return SteamMatchmaking(); } + ISteamNetworking* steam_rust_get_networking() { return SteamNetworking(); } ISteamUtils* steam_rust_get_utils() { return SteamUtils(); } ISteamApps* steam_rust_get_apps() { return SteamApps(); } ISteamFriends* steam_rust_get_friends() { return SteamFriends(); } diff --git a/steamworks-sys/src/lib.rs b/steamworks-sys/src/lib.rs index 7d6ebae..a89a14d 100644 --- a/steamworks-sys/src/lib.rs +++ b/steamworks-sys/src/lib.rs @@ -26,6 +26,8 @@ pub struct ISteamMatchmaking(c_void); pub struct ISteamUser(c_void); #[repr(C)] pub struct ISteamGameServer(c_void); +#[repr(C)] +pub struct ISteamNetworking(c_void); pub type HSteamPipe = i32; pub type AppId = u32; @@ -53,8 +55,13 @@ extern "C" { pub fn steam_rust_get_user() -> *mut ISteamUser; pub fn steam_rust_get_server() -> *mut ISteamGameServer; pub fn steam_rust_get_server_apps() -> *mut ISteamApps; + pub fn steam_rust_get_networking() -> *mut ISteamNetworking; pub fn steam_rust_game_server_init(ip: u32, steam_port: u16, game_port: u16, query_port: u16, server_mode: EServerMode, version: *const c_char) -> c_int; + pub fn steam_rust_is_steam_id_valid(id: u64) -> c_int; + pub fn steam_rust_is_game_id_valid(id: u64) -> c_int; + pub fn steam_rust_get_game_id_mod(id: u64) -> u32; + pub fn steam_rust_get_game_id_app(id: u64) -> u32; // @@ -76,8 +83,10 @@ extern "C" { pub fn SteamAPI_ISteamUtils_GetAppID(instance: *mut ISteamUtils) -> u32; pub fn SteamAPI_ISteamUtils_GetSteamUILanguage(instance: *mut ISteamUtils) -> *const c_char; - pub fn SteamAPI_ISteamUtils_IsAPICallCompleted(instance: *mut ISteamUtils, api_call: SteamAPICall, failed: *mut bool) -> bool; + pub fn SteamAPI_ISteamUtils_IsAPICallCompleted(instance: *mut ISteamUtils, api_call: SteamAPICall, failed: *mut bool) -> u8; pub fn SteamAPI_ISteamUtils_SetOverlayNotificationPosition(instance: *mut ISteamUtils, position: ENotificationPosition); + pub fn SteamAPI_ISteamUtils_GetImageSize(instance: *mut ISteamUtils, image: c_int, width: *mut u32, height: *mut u32) -> u8; + pub fn SteamAPI_ISteamUtils_GetImageRGBA(instance: *mut ISteamUtils, image: c_int, dest: *mut u8, dest_size: c_int) -> u8; pub fn SteamAPI_ISteamApps_BIsAppInstalled(instance: *mut ISteamApps, app_id: AppId) -> u8; pub fn SteamAPI_ISteamApps_BIsDlcInstalled(instance: *mut ISteamApps, app_id: AppId) -> u8; @@ -101,12 +110,25 @@ extern "C" { pub fn SteamAPI_ISteamFriends_RequestUserInformation(instance: *mut ISteamFriends, user_id: u64, name_only: u8) -> u8; pub fn SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage(instance: *mut ISteamFriends, url: *const c_char); pub fn SteamAPI_ISteamFriends_GetPersonaName(instance: *mut ISteamFriends) -> *const c_char; + pub fn SteamAPI_ISteamFriends_ActivateGameOverlayInviteDialog(instance: *mut ISteamFriends, lobby: u64); + pub fn SteamAPI_ISteamFriends_GetSmallFriendAvatar(instance: *mut ISteamFriends, friend: u64) -> c_int; + pub fn SteamAPI_ISteamFriends_GetMediumFriendAvatar(instance: *mut ISteamFriends, friend: u64) -> c_int; + pub fn SteamAPI_ISteamFriends_GetFriendGamePlayed(instance: *mut ISteamFriends, friend: u64, game_info: *mut FriendGameInfo_t) -> u8; pub fn SteamAPI_ISteamMatchmaking_CreateLobby(instance: *mut ISteamMatchmaking, lobby_ty: ELobbyType, max_members: c_int) -> SteamAPICall; pub fn SteamAPI_ISteamMatchmaking_RequestLobbyList(instance: *mut ISteamMatchmaking) -> SteamAPICall; pub fn SteamAPI_ISteamMatchmaking_GetLobbyByIndex(instance: *mut ISteamMatchmaking, lobby: c_int) -> u64; pub fn SteamAPI_ISteamMatchmaking_LeaveLobby(instance: *mut ISteamMatchmaking, lobby: u64); pub fn SteamAPI_ISteamMatchmaking_JoinLobby(instance: *mut ISteamMatchmaking, lobby: u64) -> SteamAPICall; + pub fn SteamAPI_ISteamMatchmaking_GetLobbyOwner(instance: *mut ISteamMatchmaking, lobby: u64) -> u64; + pub fn SteamAPI_ISteamMatchmaking_GetNumLobbyMembers(instance: *mut ISteamMatchmaking, lobby: u64) -> c_int; + pub fn SteamAPI_ISteamMatchmaking_GetLobbyMemberByIndex(instance: *mut ISteamMatchmaking, lobby: u64, member: c_int) -> u64; + + pub fn SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser(instance: *mut ISteamNetworking, remote: u64) -> u8; + pub fn SteamAPI_ISteamNetworking_CloseP2PSessionWithUser(instance: *mut ISteamNetworking, remote: u64) -> u8; + pub fn SteamAPI_ISteamNetworking_SendP2PPacket(instance: *mut ISteamNetworking, remote: u64, data: *const c_void, data_len: u32, send_type: EP2PSend, channel: c_int) -> u8; + pub fn SteamAPI_ISteamNetworking_IsP2PPacketAvailable(instance: *mut ISteamNetworking, msg_size: *mut u32, channel: c_int) -> u8; + pub fn SteamAPI_ISteamNetworking_ReadP2PPacket(instance: *mut ISteamNetworking, data: *mut c_void, data_len: u32, msg_size: *mut u32, remote: *mut u64, channel: c_int) -> u8; pub fn SteamAPI_ISteamUser_GetSteamID(instance: *mut ISteamUser) -> u64; pub fn SteamAPI_ISteamUser_GetAuthSessionTicket(instance: *mut ISteamUser, ticket: *mut c_void, max_ticket: c_int, ticket_size: *mut u32) -> HAuthTicket; |