diff options
| author | Matthew Collins <[email protected]> | 2018-02-27 20:30:40 +0000 |
|---|---|---|
| committer | Matthew Collins <[email protected]> | 2018-02-27 20:30:40 +0000 |
| commit | e99c0e0adc490b94b037838757bfa6647f3c3568 (patch) | |
| tree | 1ab022877d951a111820b5c0a1d35facac3ef6ee /src | |
| parent | Add accessors for `SteamId`'s inner values (diff) | |
| download | steamworks-rs-e99c0e0adc490b94b037838757bfa6647f3c3568.tar.xz steamworks-rs-e99c0e0adc490b94b037838757bfa6647f3c3568.zip | |
Try and make the accessors generic over the client and server
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.rs | 6 | ||||
| -rw-r--r-- | src/friends.rs | 20 | ||||
| -rw-r--r-- | src/lib.rs | 152 | ||||
| -rw-r--r-- | src/matchmaking.rs | 14 | ||||
| -rw-r--r-- | src/user.rs | 6 | ||||
| -rw-r--r-- | src/utils.rs | 6 |
6 files changed, 112 insertions, 92 deletions
@@ -5,12 +5,12 @@ use super::*; pub struct AppId(pub u32); /// Access to the steam apps interface -pub struct Apps { +pub struct Apps<Manager> { pub(crate) apps: *mut sys::ISteamApps, - pub(crate) _client: Arc<ClientInner>, + pub(crate) _inner: Arc<Inner<Manager>>, } -impl Apps { +impl <Manager> Apps<Manager> { /// Returns whether the user currently has the app with the given /// ID currently installed. diff --git a/src/friends.rs b/src/friends.rs index 5885e6f..c57d54d 100644 --- a/src/friends.rs +++ b/src/friends.rs @@ -41,13 +41,15 @@ bitflags! { const STEAM_LEVEL = 0x2000; } } -pub struct Friends { + +/// Access to the steam friends interface +pub struct Friends<Manager> { pub(crate) friends: *mut sys::ISteamFriends, - pub(crate) _client: Arc<ClientInner>, + pub(crate) inner: Arc<Inner<Manager>>, } -impl Friends { - pub fn get_friends(&self, flags: FriendFlags) -> Vec<Friend> { +impl <Manager> Friends<Manager> { + pub fn get_friends(&self, flags: FriendFlags) -> Vec<Friend<Manager>> { unsafe { let count = sys::SteamAPI_ISteamFriends_GetFriendCount(self.friends, flags.bits() as _); let mut friends = Vec::with_capacity(count as usize); @@ -56,7 +58,7 @@ impl Friends { friends.push(Friend { id: friend, friends: self.friends, - _client: self._client.clone(), + _inner: self.inner.clone(), }); } @@ -102,19 +104,19 @@ unsafe impl Callback for PersonaStateChange { } } -pub struct Friend { +pub struct Friend<Manager> { id: SteamId, friends: *mut sys::ISteamFriends, - _client: Arc<ClientInner>, + _inner: Arc<Inner<Manager>>, } -impl Debug for Friend { +impl <Manager> Debug for Friend<Manager> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "Friend({:?})", self.id) } } -impl Friend { +impl <Manager> Friend<Manager> { pub fn id(&self) -> SteamId { self.id } @@ -40,11 +40,12 @@ pub type SResult<T> = Result<T, SteamError>; /// /// This provides access to all of the steamworks api. #[derive(Clone)] -pub struct Client { - inner: Arc<ClientInner>, +pub struct Client<Manager = ClientManager> { + inner: Arc<Inner<Manager>>, } -struct ClientInner { +struct Inner<Manager> { + _manager: Manager, _client: *mut sys::ISteamClient, callbacks: Mutex<ClientCallbacks>, } @@ -54,10 +55,10 @@ struct ClientCallbacks { call_results: HashMap<sys::SteamAPICall, *mut libc::c_void>, } -unsafe impl Send for ClientInner {} -unsafe impl Sync for ClientInner {} +unsafe impl <Manager: Send + Sync> Send for Inner<Manager> {} +unsafe impl <Manager: Send + Sync> Sync for Inner<Manager> {} -impl Client { +impl Client<ClientManager> { /// Attempts to initialize the steamworks api and returns /// a client to access the rest of the api. /// @@ -75,13 +76,14 @@ impl Client { /// * The game isn't running on the same user/level as the steam client /// * The user doesn't own a license for the game. /// * The app ID isn't completely set up. - pub fn init() -> SResult<Client> { + pub fn init() -> SResult<Client<ClientManager>> { unsafe { if sys::SteamAPI_Init() == 0 { return Err(SteamError::InitFailed); } let client = sys::steam_rust_get_client(); - let client = Arc::new(ClientInner { + let client = Arc::new(Inner { + _manager: ClientManager { _priv: () }, _client: client, callbacks: Mutex::new(ClientCallbacks { callbacks: Vec::new(), @@ -93,7 +95,9 @@ impl Client { }) } } +} +impl <Manager> Client<Manager> { /// Runs any currently pending callbacks /// /// This runs all currently pending callbacks on the current @@ -149,118 +153,70 @@ impl Client { } } - pub(crate) unsafe fn register_call_result<C, F>(inner: &Arc<ClientInner>, api_call: sys::SteamAPICall, callback_id: i32, f: F) - where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync - { - use std::mem; - - struct Info<F> { - func: F, - api_call: sys::SteamAPICall, - client: Weak<ClientInner>, - } - - let userdata = Box::into_raw(Box::new(Info { - func: f, - api_call, - client: Arc::downgrade(&inner), - })); - - extern "C" fn run_func<C, F>(userdata: *mut libc::c_void, param: *mut libc::c_void, io_error: bool) - where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync - { - unsafe { - let func: &mut Info<F> = &mut *(userdata as *mut Info<F>); - (func.func)(&*(param as *const _), io_error); - } - } - extern "C" fn dealloc<C, F>(userdata: *mut libc::c_void) - where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync - { - let func: Box<Info<F>> = unsafe { Box::from_raw(userdata as _) }; - if let Some(inner) = func.client.upgrade() { - let mut cbs = inner.callbacks.lock().unwrap(); - cbs.call_results.remove(&func.api_call); - } - drop(func); - } - - let ptr = sys::register_rust_steam_call_result( - mem::size_of::<C>() as _, - userdata as _, - run_func::<C, F>, - dealloc::<C, F>, - api_call, - callback_id as _, - ); - let mut cbs = inner.callbacks.lock().unwrap(); - cbs.call_results.insert(api_call, ptr); - } - /// Returns an accessor to the steam utils interface - pub fn utils(&self) -> Utils { + pub fn utils(&self) -> Utils<Manager> { unsafe { let utils = sys::steam_rust_get_utils(); debug_assert!(!utils.is_null()); Utils { utils: utils, - _client: self.inner.clone(), + _inner: self.inner.clone(), } } } /// Returns an accessor to the steam matchmaking interface - pub fn matchmaking(&self) -> Matchmaking { + pub fn matchmaking(&self) -> Matchmaking<Manager> { unsafe { let mm = sys::steam_rust_get_matchmaking(); debug_assert!(!mm.is_null()); Matchmaking { mm: mm, - client: self.inner.clone(), + inner: self.inner.clone(), } } } /// Returns an accessor to the steam apps interface - pub fn apps(&self) -> Apps { + pub fn apps(&self) -> Apps<Manager> { unsafe { let apps = sys::steam_rust_get_apps(); debug_assert!(!apps.is_null()); Apps { apps: apps, - _client: self.inner.clone(), + _inner: self.inner.clone(), } } } /// Returns an accessor to the steam friends interface - pub fn friends(&self) -> Friends { + pub fn friends(&self) -> Friends<Manager> { unsafe { let friends = sys::steam_rust_get_friends(); debug_assert!(!friends.is_null()); Friends { friends: friends, - _client: self.inner.clone(), + inner: self.inner.clone(), } } } /// Returns an accessor to the steam user interface - pub fn user(&self) -> User { + pub fn user(&self) -> User<Manager> { unsafe { let user = sys::steam_rust_get_user(); debug_assert!(!user.is_null()); User { user, - _client: self.inner.clone(), + _inner: self.inner.clone(), } } } } -impl Drop for ClientInner { +impl <Manager> Drop for Inner<Manager> { fn drop(&mut self) { unsafe { { @@ -272,6 +228,68 @@ impl Drop for ClientInner { sys::unregister_rust_steam_call_result(*cb); } } + } + } +} + + + +pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manager>>, api_call: sys::SteamAPICall, callback_id: i32, f: F) + where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync +{ + use std::mem; + + struct Info<F, Manager> { + func: F, + api_call: sys::SteamAPICall, + inner: Weak<Inner<Manager>>, + } + + let userdata = Box::into_raw(Box::new(Info { + func: f, + api_call, + inner: Arc::downgrade(&inner), + })); + + extern "C" fn run_func<C, F, Manager>(userdata: *mut libc::c_void, param: *mut libc::c_void, io_error: bool) + where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync + { + unsafe { + let func: &mut Info<F, Manager> = &mut *(userdata as *mut Info<F, Manager>); + (func.func)(&*(param as *const _), io_error); + } + } + extern "C" fn dealloc<C, F, Manager>(userdata: *mut libc::c_void) + where F: for <'a> FnMut(&'a C, bool) + 'static + Send + Sync + { + let func: Box<Info<F, Manager>> = unsafe { Box::from_raw(userdata as _) }; + if let Some(inner) = func.inner.upgrade() { + let mut cbs = inner.callbacks.lock().unwrap(); + cbs.call_results.remove(&func.api_call); + } + drop(func); + } + + let ptr = sys::register_rust_steam_call_result( + mem::size_of::<C>() as _, + userdata as _, + run_func::<C, F, Manager>, + dealloc::<C, F, Manager>, + api_call, + callback_id as _, + ); + let mut cbs = inner.callbacks.lock().unwrap(); + cbs.call_results.insert(api_call, ptr); +} + +/// Manages keeping the steam api active for clients +pub struct ClientManager { + _priv: (), +} + +impl Drop for ClientManager { + fn drop(&mut self) { + unsafe { sys::SteamAPI_Shutdown(); } } diff --git a/src/matchmaking.rs b/src/matchmaking.rs index 27cf9e5..9ed8f8f 100644 --- a/src/matchmaking.rs +++ b/src/matchmaking.rs @@ -2,9 +2,9 @@ use super::*; /// Access to the steam matchmaking interface -pub struct Matchmaking { +pub struct Matchmaking<Manager> { pub(crate) mm: *mut sys::ISteamMatchmaking, - pub(crate) client: Arc<ClientInner>, + pub(crate) inner: Arc<Inner<Manager>>, } const CALLBACK_BASE_ID: i32 = 500; @@ -19,15 +19,15 @@ pub enum LobbyType { #[derive(Debug)] pub struct LobbyId(u64); -impl Matchmaking { +impl <Manager> Matchmaking<Manager> { pub fn request_lobby_list<F>(&self, mut cb: F) where F: FnMut(Result<Vec<LobbyId>, SteamError>) + 'static + Send + Sync { unsafe { let api_call = sys::SteamAPI_ISteamMatchmaking_RequestLobbyList(self.mm); - Client::register_call_result::<sys::LobbyMatchList, _>( - &self.client, api_call, CALLBACK_BASE_ID + 10, + register_call_result::<sys::LobbyMatchList, _, _>( + &self.inner, api_call, CALLBACK_BASE_ID + 10, move |v, io_error| { cb(if io_error { Err(SteamError::IOFailure) @@ -53,8 +53,8 @@ impl Matchmaking { LobbyType::Invisible => sys::LobbyType::Invisible, }; let api_call = sys::SteamAPI_ISteamMatchmaking_CreateLobby(self.mm, ty, max_members as _); - Client::register_call_result::<sys::LobbyCreated, _>( - &self.client, api_call, CALLBACK_BASE_ID + 13, + register_call_result::<sys::LobbyCreated, _, _>( + &self.inner, api_call, CALLBACK_BASE_ID + 13, move |v, io_error| { cb(if io_error { Err(SteamError::IOFailure) diff --git a/src/user.rs b/src/user.rs index fcd3e40..f589c2b 100644 --- a/src/user.rs +++ b/src/user.rs @@ -2,12 +2,12 @@ use super::*; /// Access to the steam user interface -pub struct User { +pub struct User<Manager> { pub(crate) user: *mut sys::ISteamUser, - pub(crate) _client: Arc<ClientInner>, + pub(crate) _inner: Arc<Inner<Manager>>, } -impl User { +impl <Manager> User<Manager> { /// Returns the steam id of the current user pub fn steam_id(&self) -> SteamId { unsafe { diff --git a/src/utils.rs b/src/utils.rs index aa19d46..eb10d8b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,9 +2,9 @@ use super::*; /// Access to the steam utils interface -pub struct Utils { +pub struct Utils<Manager> { pub(crate) utils: *mut sys::ISteamUtils, - pub(crate) _client: Arc<ClientInner>, + pub(crate) _inner: Arc<Inner<Manager>>, } pub enum NotificationPosition { @@ -14,7 +14,7 @@ pub enum NotificationPosition { BottomRight, } -impl Utils { +impl <Manager> Utils<Manager> { /// Returns the app ID of the current process pub fn app_id(&self) -> AppId { unsafe { |