aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Collins <[email protected]>2017-09-06 15:51:08 +0100
committerMatthew Collins <[email protected]>2017-09-06 15:51:08 +0100
commitd1be508a5fbee5535593ca246de389f40f1f7b34 (patch)
tree70c3235f9db852097b6ec50b7d532342e8d30287 /src
downloadarchived-steamworks-rs-d1be508a5fbee5535593ca246de389f40f1f7b34.tar.xz
archived-steamworks-rs-d1be508a5fbee5535593ca246de389f40f1f7b34.zip
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/app.rs112
-rw-r--r--src/error.rs17
-rw-r--r--src/friends.rs100
-rw-r--r--src/lib.rs140
-rw-r--r--src/utils.rs23
5 files changed, 392 insertions, 0 deletions
diff --git a/src/app.rs b/src/app.rs
new file mode 100644
index 0000000..2ba0b44
--- /dev/null
+++ b/src/app.rs
@@ -0,0 +1,112 @@
+use super::*;
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct AppId(pub u32);
+
+pub struct Apps {
+ pub(crate) apps: *mut sys::ISteamApps,
+ pub(crate) _client: Rc<ClientInner>,
+}
+
+impl Apps {
+
+ pub fn is_app_installed(&self, app_id: AppId) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsAppInstalled(self.apps, app_id.0) != 0
+ }
+ }
+
+ pub fn is_dlc_installed(&self, app_id: AppId) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsDlcInstalled(self.apps, app_id.0) != 0
+ }
+ }
+
+ pub fn is_subscribed_app(&self, app_id: AppId) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsSubscribedApp(self.apps, app_id.0) != 0
+ }
+ }
+
+ pub fn is_subscribed_from_free_weekend(&self) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsSubscribedFromFreeWeekend(self.apps) != 0
+ }
+ }
+
+ pub fn is_vac_banned(&self) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsVACBanned(self.apps) != 0
+ }
+ }
+
+ pub fn is_cybercafe(&self) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsCybercafe(self.apps) != 0
+ }
+ }
+
+ pub fn is_low_violence(&self) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsLowViolence(self.apps) != 0
+ }
+ }
+
+ pub fn is_subscribed(&self) -> bool {
+ unsafe {
+ sys::SteamAPI_ISteamApps_BIsSubscribed(self.apps) != 0
+ }
+ }
+
+ pub fn app_build_id(&self) -> i32 {
+ unsafe {
+ sys::SteamAPI_ISteamApps_GetAppBuildId(self.apps) as i32
+ }
+ }
+
+ pub fn app_install_dir(&self, app_id: AppId) -> String {
+ unsafe {
+ let buffer = vec![0; 2048];
+ sys::SteamAPI_ISteamApps_GetAppInstallDir(self.apps, app_id.0, buffer.as_ptr(), buffer.len() as u32);
+ let path = CStr::from_ptr(buffer.as_ptr());
+ path.to_string_lossy().into_owned()
+ }
+ }
+
+ pub fn app_owner(&self) -> SteamId {
+ unsafe {
+ SteamId(sys::SteamAPI_ISteamApps_GetAppOwner(self.apps))
+ }
+ }
+
+ pub fn available_game_languages(&self) -> Vec<String> {
+ unsafe {
+ let langs = sys::SteamAPI_ISteamApps_GetAvailableGameLanguages(self.apps);
+ let langs = CStr::from_ptr(langs);
+ let langs = langs.to_string_lossy();
+ langs.split(',')
+ .map(|v| v.to_owned())
+ .collect()
+ }
+ }
+
+ pub fn current_game_language(&self) -> Cow<str> {
+ unsafe {
+ let lang = sys::SteamAPI_ISteamApps_GetCurrentGameLanguage(self.apps);
+ let lang = CStr::from_ptr(lang);
+ lang.to_string_lossy()
+ }
+ }
+
+ pub fn current_beta_name(&self) -> Option<String> {
+ unsafe {
+ let buffer = vec![0; 256];
+ if sys::SteamAPI_ISteamApps_GetCurrentBetaName(self.apps, buffer.as_ptr(), buffer.len() as _) != 0 {
+ let path = CStr::from_ptr(buffer.as_ptr());
+ Some(path.to_string_lossy().into_owned())
+ } else {
+ None
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..6ac1914
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,17 @@
+
+error_chain! {
+ types {
+ Error, ErrorKind, ResultExt, Result;
+ }
+ links {
+ }
+
+ foreign_links {
+ }
+
+ errors {
+ InitFailed {
+ description("failed to init the steamworks API"),
+ }
+ }
+}
diff --git a/src/friends.rs b/src/friends.rs
new file mode 100644
index 0000000..b2e6bf8
--- /dev/null
+++ b/src/friends.rs
@@ -0,0 +1,100 @@
+
+use super::*;
+
+bitflags! {
+ #[repr(C)]
+ pub struct FriendFlags: u16 {
+ const FRIEND_FLAG_NONE = 0x0000;
+ const FRIEND_FLAG_BLOCKED = 0x0001;
+ const FRIEND_FLAG_FRIENDSHIP_REQUESTED = 0x0002;
+ const FRIEND_FLAG_IMMEDIATE = 0x0004;
+ const FRIEND_FLAG_CLAN_MEMBER = 0x0008;
+ const FRIEND_FLAG_ON_GAME_SERVER = 0x0010;
+ // Unused
+ // Unused
+ const FRIEND_FLAG_REQUESTING_FRIENDSHIP = 0x0080;
+ const FRIEND_FLAG_REQUESTING_INFO = 0x0100;
+ const FRIEND_FLAG_IGNORED = 0x0200;
+ const FRIEND_FLAG_IGNORED_FRIEND = 0x0400;
+ // Unused
+ const FRIEND_FLAG_CHAT_MEMBER = 0x1000;
+ const FRIEND_FLAG_ALL = 0xFFFF;
+ }
+}
+
+pub struct Friends {
+ pub(crate) friends: *mut sys::ISteamFriends,
+ pub(crate) _client: Rc<ClientInner>,
+}
+
+impl Friends {
+ pub fn get_friends(&self, flags: FriendFlags) -> Vec<Friend> {
+ unsafe {
+ let count = sys::SteamAPI_ISteamFriends_GetFriendCount(self.friends, flags.bits() as _);
+ let mut friends = Vec::with_capacity(count as usize);
+ for idx in 0 .. count {
+ let friend = SteamId(sys::SteamAPI_ISteamFriends_GetFriendByIndex(self.friends, idx, flags.bits() as _));
+ friends.push(Friend {
+ id: friend,
+ friends: self.friends,
+ _client: self._client.clone(),
+ });
+ }
+
+ friends
+ }
+ }
+}
+
+pub struct Friend {
+ id: SteamId,
+ friends: *mut sys::ISteamFriends,
+ _client: Rc<ClientInner>,
+}
+
+impl Debug for Friend {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "Friend({:?})", self.id)
+ }
+}
+
+impl Friend {
+ pub fn id(&self) -> SteamId {
+ self.id
+ }
+
+ pub fn name(&self) -> Cow<str> {
+ unsafe {
+ let name = sys::SteamAPI_ISteamFriends_GetFriendPersonaName(self.friends, self.id.0);
+ let name = CStr::from_ptr(name);
+ name.to_string_lossy()
+ }
+ }
+
+ pub fn state(&self) -> FriendState {
+ unsafe {
+ let state = sys::SteamAPI_ISteamFriends_GetFriendPersonaState(self.friends, self.id.0);
+ match state {
+ sys::PersonaState::Offline => FriendState::Offline,
+ sys::PersonaState::Online => FriendState::Online,
+ sys::PersonaState::Busy => FriendState::Busy,
+ sys::PersonaState::Away => FriendState::Away,
+ sys::PersonaState::Snooze => FriendState::Snooze,
+ sys::PersonaState::LookingToPlay => FriendState::LookingToPlay,
+ sys::PersonaState::LookingToTrade => FriendState::LookingToTrade,
+ sys::PersonaState::Max => unreachable!(),
+ }
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum FriendState {
+ Offline,
+ Online,
+ Busy,
+ Away,
+ Snooze,
+ LookingToTrade,
+ LookingToPlay,
+} \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..73b9c61
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,140 @@
+
+extern crate steamworks_sys as sys;
+#[macro_use]
+extern crate error_chain;
+#[macro_use]
+extern crate bitflags;
+
+pub mod error;
+pub use error::Result as SResult;
+use error::ErrorKind;
+
+mod utils;
+pub use utils::*;
+mod app;
+pub use app::*;
+mod friends;
+pub use friends::*;
+
+use std::rc::Rc;
+use std::ffi::CStr;
+use std::borrow::Cow;
+use std::fmt::{
+ Debug, Formatter, self
+};
+
+pub struct Client {
+ inner: Rc<ClientInner>,
+}
+
+struct ClientInner {
+ client: *mut sys::ISteamClient,
+ pipe: sys::HSteamPipe,
+}
+
+impl Client {
+ pub fn init() -> SResult<Client> {
+ unsafe {
+ if sys::SteamAPI_Init() == 0 {
+ bail!(ErrorKind::InitFailed);
+ }
+ let client = sys::SteamInternal_CreateInterface(sys::STEAMCLIENT_INTERFACE_VERSION.as_ptr() as *const _);
+ let client = Rc::new(ClientInner {
+ client: client,
+ pipe: sys::SteamAPI_ISteamClient_CreateSteamPipe(client),
+ });
+ Ok(Client {
+ inner: client,
+ })
+ }
+ }
+
+ pub fn utils(&self) -> Utils {
+ unsafe {
+ let utils = sys::SteamAPI_ISteamClient_GetISteamUtils(
+ self.inner.client, self.inner.pipe,
+ sys::STEAMUTILS_INTERFACE_VERSION.as_ptr() as *const _
+ );
+ assert!(!utils.is_null());
+ Utils {
+ utils: utils,
+ _client: self.inner.clone(),
+ }
+ }
+ }
+
+ pub fn apps(&self) -> Apps {
+ unsafe {
+ let user = sys::SteamAPI_ISteamClient_ConnectToGlobalUser(self.inner.client, self.inner.pipe);
+ let apps = sys::SteamAPI_ISteamClient_GetISteamApps(
+ self.inner.client, user, self.inner.pipe,
+ sys::STEAMAPPS_INTERFACE_VERSION.as_ptr() as *const _
+ );
+ assert!(!apps.is_null());
+ Apps {
+ apps: apps,
+ _client: self.inner.clone(),
+ }
+ }
+ }
+
+ pub fn friends(&self) -> Friends {
+ unsafe {
+ let user = sys::SteamAPI_ISteamClient_ConnectToGlobalUser(self.inner.client, self.inner.pipe);
+ let friends = sys::SteamAPI_ISteamClient_GetISteamFriends(
+ self.inner.client, user, self.inner.pipe,
+ sys::STEAMFRIENDS_INTERFACE_VERSION.as_ptr() as *const _
+ );
+ assert!(!friends.is_null());
+ Friends {
+ friends: friends,
+ _client: self.inner.clone(),
+ }
+ }
+
+ }
+}
+
+impl Drop for ClientInner {
+ fn drop(&mut self) {
+ unsafe {
+ debug_assert!(sys::SteamAPI_ISteamClient_BReleaseSteamPipe(self.client, self.pipe) != 0);
+ sys::SteamAPI_Shutdown();
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct SteamId(pub(crate) u64);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn basic_test() {
+ let client = Client::init().unwrap();
+
+ let utils = client.utils();
+ println!("Utils:");
+ println!("AppId: {:?}", utils.app_id());
+ println!("UI Language: {}", utils.ui_language());
+
+ let apps = client.apps();
+ println!("Apps");
+ println!("IsInstalled(480): {}", apps.is_app_installed(AppId(480)));
+ println!("InstallDir(480): {}", apps.app_install_dir(AppId(480)));
+ println!("BuildId: {}", apps.app_build_id());
+ println!("AppOwner: {:?}", apps.app_owner());
+ println!("Langs: {:?}", apps.available_game_languages());
+ println!("Lang: {}", apps.current_game_language());
+ println!("Beta: {:?}", apps.current_beta_name());
+
+ let friends = client.friends();
+ println!("Friends");
+ let list = friends.get_friends(FRIEND_FLAG_IMMEDIATE);
+ println!("{:?}", list);
+ for f in &list {
+ println!("Friend: {:?} - {}({:?})", f.id(), f.name(), f.state());
+ }
+ }
+}
diff --git a/src/utils.rs b/src/utils.rs
new file mode 100644
index 0000000..416b9ee
--- /dev/null
+++ b/src/utils.rs
@@ -0,0 +1,23 @@
+
+use super::*;
+
+pub struct Utils {
+ pub(crate) utils: *mut sys::ISteamUtils,
+ pub(crate) _client: Rc<ClientInner>,
+}
+
+impl Utils {
+ pub fn app_id(&self) -> AppId {
+ unsafe {
+ AppId(sys::SteamAPI_ISteamUtils_GetAppID(self.utils))
+ }
+ }
+
+ pub fn ui_language(&self) -> Cow<str> {
+ unsafe {
+ let lang = sys::SteamAPI_ISteamUtils_GetSteamUILanguage(self.utils);
+ let lang = CStr::from_ptr(lang);
+ lang.to_string_lossy()
+ }
+ }
+} \ No newline at end of file