diff options
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/callback.rs | 55 | ||||
| -rw-r--r-- | src/error.rs | 228 | ||||
| -rw-r--r-- | src/friends.rs | 43 | ||||
| -rw-r--r-- | src/matchmaking.rs | 77 | ||||
| -rw-r--r-- | src/server.rs | 19 | ||||
| -rw-r--r-- | src/user.rs | 50 | ||||
| -rw-r--r-- | src/utils.rs | 8 | ||||
| -rw-r--r-- | steamworks-sys/Cargo.toml | 11 | ||||
| -rw-r--r-- | steamworks-sys/build.rs | 209 | ||||
| -rw-r--r-- | steamworks-sys/src/lib.cpp | 4 | ||||
| -rw-r--r-- | steamworks-sys/src/lib.rs | 229 | ||||
| -rw-r--r-- | steamworks-sys/wrapper.hpp | 3 |
13 files changed, 527 insertions, 413 deletions
@@ -1,6 +1,6 @@ [package] name = "steamworks" -version = "0.3.2" +version = "0.4.0" authors = ["Thinkofname"] description = "Provides rust friendly bindings to the steamworks sdk" license = "MIT / Apache-2.0" @@ -20,7 +20,7 @@ members = [ ] [dependencies] -steamworks-sys = {path = "./steamworks-sys", version = "0.2.1"} +steamworks-sys = {path = "./steamworks-sys", version = "0.3.0"} failure = "0.1.1" bitflags = "1.0.1" libc = "0.2.36" diff --git a/src/callback.rs b/src/callback.rs index d249207..6808a45 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -5,6 +5,9 @@ use sys; use std::mem; use std::sync::{ Arc, Weak }; +use std::panic::*; +use std::any::Any; +use std::process::abort; pub unsafe trait Callback { const ID: i32; @@ -12,6 +15,16 @@ pub unsafe trait Callback { unsafe fn from_raw(raw: *mut c_void) -> Self; } +fn print_err(err: Box<Any>) { + if let Some(err) = err.downcast_ref::<&str>() { + println!("Steam callback paniced: {}", err); + } else if let Some(err) = err.downcast_ref::<String>() { + println!("Steam callback paniced: {}", err); + } else { + println!("Steam callback paniced"); + } +} + pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager>>, f: F, game_server: bool) where C: Callback, F: FnMut(C) + Send + Sync + 'static @@ -25,7 +38,7 @@ pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager> func(param); } - unsafe extern "C" fn run_extra<C, F>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, _: bool, _: sys::SteamAPICall) + unsafe extern "C" fn run_extra<C, F>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, _: u8, _: sys::SteamAPICall) where C: Callback, F: FnMut(C) + Send + Sync + 'static { @@ -72,18 +85,46 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag where F: for<'a> FnMut(&'a C, bool) + Send + Sync + 'static { let data: &mut CallData<F, Manager> = &mut *(userdata as *mut CallData<F, Manager>); - (data.func)(&*(param as *const _), false); - + #[cfg(debug_assertions)] + { + let res = catch_unwind(AssertUnwindSafe(|| + (data.func)(&*(param as *const _), false) + )); + if let Err(err) = res { + print_err(err); + abort(); + } + + } + #[cfg(not(debug_assertions))] + { + (data.func)(&*(param as *const _), false); + } + sys::delete_rust_callback(cb); } - unsafe extern "C" fn run_extra<C, F, Manager>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, io_error: bool, api_call: sys::SteamAPICall) + unsafe extern "C" fn run_extra<C, F, Manager>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, io_error: u8, api_call: sys::SteamAPICall) where F: for<'a> FnMut(&'a C, bool) + Send + Sync + 'static { let data: &mut CallData<F, Manager> = &mut *(userdata as *mut CallData<F, Manager>); if api_call == data.api_call { - (data.func)(&*(param as *const _), io_error); + #[cfg(debug_assertions)] + { + let res = catch_unwind(AssertUnwindSafe(|| + (data.func)(&*(param as *const _), io_error != 0) + )); + if let Err(err) = res { + print_err(err); + abort(); + } + + } + #[cfg(not(debug_assertions))] + { + (data.func)(&*(param as *const _), io_error != 0); + } sys::delete_rust_callback(cb); } } @@ -94,8 +135,6 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag let data: Box<CallData<F, Manager>> = Box::from_raw(userdata as _); if let Some(inner) = data.inner.upgrade() { - sys::SteamAPI_UnregisterCallResult(cb, data.api_call); - let mut cbs = inner.callbacks.lock().unwrap(); cbs.call_results.remove(&data.api_call); } @@ -110,7 +149,7 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag }; let data = sys::CallbackData { - param_size: mem::size_of::<C> as _, + param_size: mem::size_of::<C>() as _, userdata: Box::into_raw(Box::new(userdata)) as _, run: run::<C, F, Manager>, run_extra: run_extra::<C, F, Manager>, diff --git a/src/error.rs b/src/error.rs index c641392..683b2c6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -385,121 +385,121 @@ pub enum SteamError { LimitedUserAccount, } -impl From<sys::SResult> for SteamError { - fn from(r: sys::SResult) -> Self { - use sys::SResult; +impl From<sys::EResult> for SteamError { + fn from(r: sys::EResult) -> Self { match r { - SResult::Ok => panic!("SResult::Ok isn't an error"), - SResult::Fail => SteamError::Generic, - SResult::NoConnection => SteamError::NoConnection, - SResult::InvalidPassword => SteamError::InvalidPassword, - SResult::LoggedInElsewhere => SteamError::LoggedInElsewhere, - SResult::InvalidProtocolVer => SteamError::InvalidProtocolVersion, - SResult::InvalidParam => SteamError::InvalidParameter, - SResult::FileNotFound => SteamError::FileNotFound, - SResult::Busy => SteamError::Busy, - SResult::InvalidState => SteamError::InvalidState, - SResult::InvalidName => SteamError::InvalidName, - SResult::InvalidEmail => SteamError::InvalidEmail, - SResult::DuplicateName => SteamError::DuplicateName, - SResult::AccessDenied => SteamError::AccessDenied, - SResult::Timeout => SteamError::Timeout, - SResult::Banned => SteamError::Banned, - SResult::AccountNotFound => SteamError::AccountNotFound, - SResult::InvalidSteamID => SteamError::InvalidSteamID, - SResult::ServiceUnavailable => SteamError::ServiceUnavailable, - SResult::NotLoggedOn => SteamError::NotLoggedOn, - SResult::Pending => SteamError::Pending, - SResult::EncryptionFailure => SteamError::EncryptionFailure, - SResult::InsufficientPrivilege => SteamError::InsufficientPrivilege, - SResult::LimitExceeded => SteamError::LimitExceeded, - SResult::Revoked => SteamError::Revoked, - SResult::Expired => SteamError::Expired, - SResult::AlreadyRedeemed => SteamError::AlreadyRedeemed, - SResult::DuplicateRequest => SteamError::DuplicateRequest, - SResult::AlreadyOwned => SteamError::AlreadyOwned, - SResult::IPNotFound => SteamError::IPNotFound, - SResult::PersistFailed => SteamError::PersistFailed, - SResult::LockingFailed => SteamError::LockingFailed, - SResult::LogonSessionReplaced => SteamError::LogonSessionReplaced, - SResult::ConnectFailed => SteamError::ConnectFailed, - SResult::HandshakeFailed => SteamError::HandshakeFailed, - SResult::IOFailure => SteamError::IOFailure, - SResult::RemoteDisconnect => SteamError::RemoteDisconnect, - SResult::ShoppingCartNotFound => SteamError::ShoppingCartNotFound, - SResult::Blocked => SteamError::Blocked, - SResult::Ignored => SteamError::Ignored, - SResult::NoMatch => SteamError::NoMatch, - SResult::AccountDisabled => SteamError::AccountDisabled, - SResult::ServiceReadOnly => SteamError::ServiceReadOnly, - SResult::AccountNotFeatured => SteamError::AccountNotFeatured, - SResult::AdministratorOK => SteamError::AdministratorOK, - SResult::ContentVersion => SteamError::ContentVersion, - SResult::TryAnotherCM => SteamError::TryAnotherCM, - SResult::PasswordRequiredToKickSession => SteamError::PasswordRequiredToKickSession, - SResult::AlreadyLoggedInElsewhere => SteamError::AlreadyLoggedInElsewhere, - SResult::Suspended => SteamError::Suspended, - SResult::Cancelled => SteamError::Cancelled, - SResult::DataCorruption => SteamError::DataCorruption, - SResult::DiskFull => SteamError::DiskFull, - SResult::RemoteCallFailed => SteamError::RemoteCallFailed, - SResult::PasswordUnset => SteamError::PasswordUnset, - SResult::ExternalAccountUnlinked => SteamError::ExternalAccountUnlinked, - SResult::PSNTicketInvalid => SteamError::PSNTicketInvalid, - SResult::ExternalAccountAlreadyLinked => SteamError::ExternalAccountAlreadyLinked, - SResult::RemoteFileConflict => SteamError::RemoteFileConflict, - SResult::IllegalPassword => SteamError::IllegalPassword, - SResult::SameAsPreviousValue => SteamError::SameAsPreviousValue, - SResult::AccountLogonDenied => SteamError::AccountLogonDenied, - SResult::CannotUseOldPassword => SteamError::CannotUseOldPassword, - SResult::InvalidLoginAuthCode => SteamError::InvalidLoginAuthCode, - SResult::AccountLogonDeniedNoMail => SteamError::AccountLogonDeniedNoMail, - SResult::HardwareNotCapableOfIPT => SteamError::HardwareNotCapableOfIPT, - SResult::IPTInitError => SteamError::IPTInitError, - SResult::ParentalControlRestricted => SteamError::ParentalControlRestricted, - SResult::FacebookQueryError => SteamError::FacebookQueryError, - SResult::ExpiredLoginAuthCode => SteamError::ExpiredLoginAuthCode, - SResult::IPLoginRestrictionFailed => SteamError::IPLoginRestrictionFailed, - SResult::AccountLockedDown => SteamError::AccountLockedDown, - SResult::AccountLogonDeniedVerifiedEmailRequired => SteamError::AccountLogonDeniedVerifiedEmailRequired, - SResult::NoMatchingURL => SteamError::NoMatchingURL, - SResult::BadResponse => SteamError::BadResponse, - SResult::RequirePasswordReEntry => SteamError::RequirePasswordReEntry, - SResult::ValueOutOfRange => SteamError::ValueOutOfRange, - SResult::UnexpectedError => SteamError::UnexpectedError, - SResult::Disabled => SteamError::Disabled, - SResult::InvalidCEGSubmission => SteamError::InvalidCEGSubmission, - SResult::RestrictedDevice => SteamError::RestrictedDevice, - SResult::RegionLocked => SteamError::RegionLocked, - SResult::RateLimitExceeded => SteamError::RateLimitExceeded, - SResult::AccountLoginDeniedNeedTwoFactor => SteamError::AccountLoginDeniedNeedTwoFactor, - SResult::ItemDeleted => SteamError::ItemDeleted, - SResult::AccountLoginDeniedThrottle => SteamError::AccountLoginDeniedThrottle, - SResult::TwoFactorCodeMismatch => SteamError::TwoFactorCodeMismatch, - SResult::TwoFactorActivationCodeMismatch => SteamError::TwoFactorActivationCodeMismatch, - SResult::AccountAssociatedToMultiplePartners => SteamError::AccountAssociatedToMultiplePartners, - SResult::NotModified => SteamError::NotModified, - SResult::NoMobileDevice => SteamError::NoMobileDevice, - SResult::TimeNotSynced => SteamError::TimeNotSynced, - SResult::SmsCodeFailed => SteamError::SmsCodeFailed, - SResult::AccountLimitExceeded => SteamError::AccountLimitExceeded, - SResult::AccountActivityLimitExceeded => SteamError::AccountActivityLimitExceeded, - SResult::PhoneActivityLimitExceeded => SteamError::PhoneActivityLimitExceeded, - SResult::RefundToWallet => SteamError::RefundToWallet, - SResult::EmailSendFailure => SteamError::EmailSendFailure, - SResult::NotSettled => SteamError::NotSettled, - SResult::NeedCaptcha => SteamError::NeedCaptcha, - SResult::GSLTDenied => SteamError::GSLTDenied, - SResult::GSOwnerDenied => SteamError::GSOwnerDenied, - SResult::InvalidItemType => SteamError::InvalidItemType, - SResult::IPBanned => SteamError::IPBanned, - SResult::GSLTExpired => SteamError::GSLTExpired, - SResult::InsufficientFunds => SteamError::InsufficientFunds, - SResult::TooManyPending => SteamError::TooManyPending, - SResult::NoSiteLicensesFound => SteamError::NoSiteLicensesFound, - SResult::WGNetworkSendExceeded => SteamError::WGNetworkSendExceeded, - SResult::AccountNotFriends => SteamError::AccountNotFriends, - SResult::LimitedUserAccount => SteamError::LimitedUserAccount, + sys::EResult_k_EResultOK => panic!("EResult_k_EResultOK isn't an error"), + sys::EResult_k_EResultFail => SteamError::Generic, + sys::EResult_k_EResultNoConnection => SteamError::NoConnection, + sys::EResult_k_EResultInvalidPassword => SteamError::InvalidPassword, + sys::EResult_k_EResultLoggedInElsewhere => SteamError::LoggedInElsewhere, + sys::EResult_k_EResultInvalidProtocolVer => SteamError::InvalidProtocolVersion, + sys::EResult_k_EResultInvalidParam => SteamError::InvalidParameter, + sys::EResult_k_EResultFileNotFound => SteamError::FileNotFound, + sys::EResult_k_EResultBusy => SteamError::Busy, + sys::EResult_k_EResultInvalidState => SteamError::InvalidState, + sys::EResult_k_EResultInvalidName => SteamError::InvalidName, + sys::EResult_k_EResultInvalidEmail => SteamError::InvalidEmail, + sys::EResult_k_EResultDuplicateName => SteamError::DuplicateName, + sys::EResult_k_EResultAccessDenied => SteamError::AccessDenied, + sys::EResult_k_EResultTimeout => SteamError::Timeout, + sys::EResult_k_EResultBanned => SteamError::Banned, + sys::EResult_k_EResultAccountNotFound => SteamError::AccountNotFound, + sys::EResult_k_EResultInvalidSteamID => SteamError::InvalidSteamID, + sys::EResult_k_EResultServiceUnavailable => SteamError::ServiceUnavailable, + sys::EResult_k_EResultNotLoggedOn => SteamError::NotLoggedOn, + sys::EResult_k_EResultPending => SteamError::Pending, + sys::EResult_k_EResultEncryptionFailure => SteamError::EncryptionFailure, + sys::EResult_k_EResultInsufficientPrivilege => SteamError::InsufficientPrivilege, + sys::EResult_k_EResultLimitExceeded => SteamError::LimitExceeded, + sys::EResult_k_EResultRevoked => SteamError::Revoked, + sys::EResult_k_EResultExpired => SteamError::Expired, + sys::EResult_k_EResultAlreadyRedeemed => SteamError::AlreadyRedeemed, + sys::EResult_k_EResultDuplicateRequest => SteamError::DuplicateRequest, + sys::EResult_k_EResultAlreadyOwned => SteamError::AlreadyOwned, + sys::EResult_k_EResultIPNotFound => SteamError::IPNotFound, + sys::EResult_k_EResultPersistFailed => SteamError::PersistFailed, + sys::EResult_k_EResultLockingFailed => SteamError::LockingFailed, + sys::EResult_k_EResultLogonSessionReplaced => SteamError::LogonSessionReplaced, + sys::EResult_k_EResultConnectFailed => SteamError::ConnectFailed, + sys::EResult_k_EResultHandshakeFailed => SteamError::HandshakeFailed, + sys::EResult_k_EResultIOFailure => SteamError::IOFailure, + sys::EResult_k_EResultRemoteDisconnect => SteamError::RemoteDisconnect, + sys::EResult_k_EResultShoppingCartNotFound => SteamError::ShoppingCartNotFound, + sys::EResult_k_EResultBlocked => SteamError::Blocked, + sys::EResult_k_EResultIgnored => SteamError::Ignored, + sys::EResult_k_EResultNoMatch => SteamError::NoMatch, + sys::EResult_k_EResultAccountDisabled => SteamError::AccountDisabled, + sys::EResult_k_EResultServiceReadOnly => SteamError::ServiceReadOnly, + sys::EResult_k_EResultAccountNotFeatured => SteamError::AccountNotFeatured, + sys::EResult_k_EResultAdministratorOK => SteamError::AdministratorOK, + sys::EResult_k_EResultContentVersion => SteamError::ContentVersion, + sys::EResult_k_EResultTryAnotherCM => SteamError::TryAnotherCM, + sys::EResult_k_EResultPasswordRequiredToKickSession => SteamError::PasswordRequiredToKickSession, + sys::EResult_k_EResultAlreadyLoggedInElsewhere => SteamError::AlreadyLoggedInElsewhere, + sys::EResult_k_EResultSuspended => SteamError::Suspended, + sys::EResult_k_EResultCancelled => SteamError::Cancelled, + sys::EResult_k_EResultDataCorruption => SteamError::DataCorruption, + sys::EResult_k_EResultDiskFull => SteamError::DiskFull, + sys::EResult_k_EResultRemoteCallFailed => SteamError::RemoteCallFailed, + sys::EResult_k_EResultPasswordUnset => SteamError::PasswordUnset, + sys::EResult_k_EResultExternalAccountUnlinked => SteamError::ExternalAccountUnlinked, + sys::EResult_k_EResultPSNTicketInvalid => SteamError::PSNTicketInvalid, + sys::EResult_k_EResultExternalAccountAlreadyLinked => SteamError::ExternalAccountAlreadyLinked, + sys::EResult_k_EResultRemoteFileConflict => SteamError::RemoteFileConflict, + sys::EResult_k_EResultIllegalPassword => SteamError::IllegalPassword, + sys::EResult_k_EResultSameAsPreviousValue => SteamError::SameAsPreviousValue, + sys::EResult_k_EResultAccountLogonDenied => SteamError::AccountLogonDenied, + sys::EResult_k_EResultCannotUseOldPassword => SteamError::CannotUseOldPassword, + sys::EResult_k_EResultInvalidLoginAuthCode => SteamError::InvalidLoginAuthCode, + sys::EResult_k_EResultAccountLogonDeniedNoMail => SteamError::AccountLogonDeniedNoMail, + sys::EResult_k_EResultHardwareNotCapableOfIPT => SteamError::HardwareNotCapableOfIPT, + sys::EResult_k_EResultIPTInitError => SteamError::IPTInitError, + sys::EResult_k_EResultParentalControlRestricted => SteamError::ParentalControlRestricted, + sys::EResult_k_EResultFacebookQueryError => SteamError::FacebookQueryError, + sys::EResult_k_EResultExpiredLoginAuthCode => SteamError::ExpiredLoginAuthCode, + sys::EResult_k_EResultIPLoginRestrictionFailed => SteamError::IPLoginRestrictionFailed, + sys::EResult_k_EResultAccountLockedDown => SteamError::AccountLockedDown, + sys::EResult_k_EResultAccountLogonDeniedVerifiedEmailRequired => SteamError::AccountLogonDeniedVerifiedEmailRequired, + sys::EResult_k_EResultNoMatchingURL => SteamError::NoMatchingURL, + sys::EResult_k_EResultBadResponse => SteamError::BadResponse, + sys::EResult_k_EResultRequirePasswordReEntry => SteamError::RequirePasswordReEntry, + sys::EResult_k_EResultValueOutOfRange => SteamError::ValueOutOfRange, + sys::EResult_k_EResultUnexpectedError => SteamError::UnexpectedError, + sys::EResult_k_EResultDisabled => SteamError::Disabled, + sys::EResult_k_EResultInvalidCEGSubmission => SteamError::InvalidCEGSubmission, + sys::EResult_k_EResultRestrictedDevice => SteamError::RestrictedDevice, + sys::EResult_k_EResultRegionLocked => SteamError::RegionLocked, + sys::EResult_k_EResultRateLimitExceeded => SteamError::RateLimitExceeded, + sys::EResult_k_EResultAccountLoginDeniedNeedTwoFactor => SteamError::AccountLoginDeniedNeedTwoFactor, + sys::EResult_k_EResultItemDeleted => SteamError::ItemDeleted, + sys::EResult_k_EResultAccountLoginDeniedThrottle => SteamError::AccountLoginDeniedThrottle, + sys::EResult_k_EResultTwoFactorCodeMismatch => SteamError::TwoFactorCodeMismatch, + sys::EResult_k_EResultTwoFactorActivationCodeMismatch => SteamError::TwoFactorActivationCodeMismatch, + sys::EResult_k_EResultAccountAssociatedToMultiplePartners => SteamError::AccountAssociatedToMultiplePartners, + sys::EResult_k_EResultNotModified => SteamError::NotModified, + sys::EResult_k_EResultNoMobileDevice => SteamError::NoMobileDevice, + sys::EResult_k_EResultTimeNotSynced => SteamError::TimeNotSynced, + sys::EResult_k_EResultSmsCodeFailed => SteamError::SmsCodeFailed, + sys::EResult_k_EResultAccountLimitExceeded => SteamError::AccountLimitExceeded, + sys::EResult_k_EResultAccountActivityLimitExceeded => SteamError::AccountActivityLimitExceeded, + sys::EResult_k_EResultPhoneActivityLimitExceeded => SteamError::PhoneActivityLimitExceeded, + sys::EResult_k_EResultRefundToWallet => SteamError::RefundToWallet, + sys::EResult_k_EResultEmailSendFailure => SteamError::EmailSendFailure, + sys::EResult_k_EResultNotSettled => SteamError::NotSettled, + sys::EResult_k_EResultNeedCaptcha => SteamError::NeedCaptcha, + sys::EResult_k_EResultGSLTDenied => SteamError::GSLTDenied, + sys::EResult_k_EResultGSOwnerDenied => SteamError::GSOwnerDenied, + sys::EResult_k_EResultInvalidItemType => SteamError::InvalidItemType, + sys::EResult_k_EResultIPBanned => SteamError::IPBanned, + sys::EResult_k_EResultGSLTExpired => SteamError::GSLTExpired, + sys::EResult_k_EResultInsufficientFunds => SteamError::InsufficientFunds, + sys::EResult_k_EResultTooManyPending => SteamError::TooManyPending, + sys::EResult_k_EResultNoSiteLicensesFound => SteamError::NoSiteLicensesFound, + sys::EResult_k_EResultWGNetworkSendExceeded => SteamError::WGNetworkSendExceeded, + sys::EResult_k_EResultAccountNotFriends => SteamError::AccountNotFriends, + sys::EResult_k_EResultLimitedUserAccount => SteamError::LimitedUserAccount, + _ => unreachable!(), } } }
\ No newline at end of file diff --git a/src/friends.rs b/src/friends.rs index 1d993ed..f0fe66e 100644 --- a/src/friends.rs +++ b/src/friends.rs @@ -1,6 +1,8 @@ use super::*; +const CALLBACK_BASE_ID: i32 = 300; + bitflags! { #[repr(C)] pub struct FriendFlags: u16 { @@ -98,14 +100,33 @@ pub struct PersonaStateChange { } unsafe impl Callback for PersonaStateChange { - const ID: i32 = 304; + const ID: i32 = CALLBACK_BASE_ID + 4; const SIZE: i32 = ::std::mem::size_of::<sys::PersonaStateChange_t>() as i32; unsafe fn from_raw(raw: *mut libc::c_void) -> Self { let val = &mut *(raw as *mut sys::PersonaStateChange_t); PersonaStateChange { - steam_id: SteamId(val.steam_id), - flags: PersonaChange::from_bits_truncate(val.flags as i32), + steam_id: SteamId(val.get_m_ulSteamID()), + flags: PersonaChange::from_bits_truncate(val.get_m_nChangeFlags() as i32), + } + } +} + +#[derive(Debug)] +pub struct GameLobbyJoinRequested { + pub lobby_steam_id: LobbyId, + pub friend_steam_id: SteamId, +} + +unsafe impl Callback for GameLobbyJoinRequested { + const ID: i32 = CALLBACK_BASE_ID + 33; + const SIZE: i32 = ::std::mem::size_of::<sys::GameLobbyJoinRequested_t>() as i32; + + unsafe fn from_raw(raw: *mut libc::c_void) -> Self { + let val = &mut *(raw as *mut sys::GameLobbyJoinRequested_t); + GameLobbyJoinRequested { + lobby_steam_id: LobbyId(val.get_m_steamIDLobby()), + friend_steam_id: SteamId(val.get_m_steamIDFriend()), } } } @@ -139,14 +160,14 @@ impl <Manager> Friend<Manager> { 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!(), + sys::EPersonaState_k_EPersonaStateOffline => FriendState::Offline, + sys::EPersonaState_k_EPersonaStateOnline => FriendState::Online, + sys::EPersonaState_k_EPersonaStateBusy => FriendState::Busy, + sys::EPersonaState_k_EPersonaStateAway => FriendState::Away, + sys::EPersonaState_k_EPersonaStateSnooze => FriendState::Snooze, + sys::EPersonaState_k_EPersonaStateLookingToPlay => FriendState::LookingToPlay, + sys::EPersonaState_k_EPersonaStateLookingToTrade => FriendState::LookingToTrade, + _ => unreachable!(), } } } diff --git a/src/matchmaking.rs b/src/matchmaking.rs index 9ed8f8f..177cb8e 100644 --- a/src/matchmaking.rs +++ b/src/matchmaking.rs @@ -9,6 +9,7 @@ pub struct Matchmaking<Manager> { const CALLBACK_BASE_ID: i32 = 500; +/// The visibility of a lobby pub enum LobbyType { Private, FriendsOnly, @@ -17,7 +18,7 @@ pub enum LobbyType { } #[derive(Debug)] -pub struct LobbyId(u64); +pub struct LobbyId(pub u64); impl <Manager> Matchmaking<Manager> { @@ -26,46 +27,84 @@ impl <Manager> Matchmaking<Manager> { { unsafe { let api_call = sys::SteamAPI_ISteamMatchmaking_RequestLobbyList(self.mm); - register_call_result::<sys::LobbyMatchList, _, _>( + register_call_result::<sys::LobbyMatchList_t, _, _>( &self.inner, api_call, CALLBACK_BASE_ID + 10, move |v, io_error| { - cb(if io_error { - Err(SteamError::IOFailure) - } else { - let mut out = Vec::with_capacity(v.lobbies_matching as usize); - for idx in 0 .. v.lobbies_matching { - out.push(LobbyId(sys::SteamAPI_ISteamMatchmaking_GetLobbyByIndex(sys::steam_rust_get_matchmaking(), idx as _))); - } - Ok(out) - }) + cb(if io_error { + Err(SteamError::IOFailure) + } else { + let mut out = Vec::with_capacity(v.get_m_nLobbiesMatching() as usize); + for idx in 0 .. v.get_m_nLobbiesMatching() { + out.push(LobbyId(sys::SteamAPI_ISteamMatchmaking_GetLobbyByIndex(sys::steam_rust_get_matchmaking(), idx as _))); + } + Ok(out) + }) }); } } + /// Attempts to create a new matchmaking lobby + /// + /// The lobby with have the visibility of the of the passed + /// `LobbyType` and a limit of `max_members` inside it. + /// The `max_members` may not be higher than 250. + /// + /// # Triggers + /// + /// * `LobbyEnter` + /// * `LobbyCreated` pub fn create_lobby<F>(&self, ty: LobbyType, max_members: u32, mut cb: F) where F: FnMut(Result<LobbyId, SteamError>) + 'static + Send + Sync { + assert!(max_members <= 250); // Steam API limits unsafe { let ty = match ty { - LobbyType::Private => sys::LobbyType::Private, - LobbyType::FriendsOnly => sys::LobbyType::FriendsOnly, - LobbyType::Public => sys::LobbyType::Public, - LobbyType::Invisible => sys::LobbyType::Invisible, + LobbyType::Private => sys::ELobbyType_k_ELobbyTypePrivate, + LobbyType::FriendsOnly => sys::ELobbyType_k_ELobbyTypeFriendsOnly, + LobbyType::Public => sys::ELobbyType_k_ELobbyTypePublic, + LobbyType::Invisible => sys::ELobbyType_k_ELobbyTypeInvisible, }; let api_call = sys::SteamAPI_ISteamMatchmaking_CreateLobby(self.mm, ty, max_members as _); - register_call_result::<sys::LobbyCreated, _, _>( + register_call_result::<sys::LobbyCreated_t, _, _>( &self.inner, api_call, CALLBACK_BASE_ID + 13, move |v, io_error| { cb(if io_error { Err(SteamError::IOFailure) - } else if v.result != sys::SResult::Ok { - Err(v.result.into()) + } else if v.get_m_eResult() != sys::EResult_k_EResultOK { + Err(v.get_m_eResult().into()) + } else { + Ok(LobbyId(v.get_m_ulSteamIDLobby())) + }) + }); + } + } + + /// Tries to join the lobby with the given ID + pub fn join_lobby<F>(&self, lobby: LobbyId, mut cb: F) + where F: FnMut(Result<LobbyId, ()>) + 'static + Send + Sync + { + unsafe { + let api_call = sys::SteamAPI_ISteamMatchmaking_JoinLobby(self.mm, lobby.0); + register_call_result::<sys::LobbyEnter_t, _, _>( + &self.inner, api_call, CALLBACK_BASE_ID + 4, + move |v, io_error| { + cb(if io_error { + Err(()) + } else if v.get_m_EChatRoomEnterResponse() != 1 { + Err(()) } else { - Ok(LobbyId(v.lobby_steam_id)) + Ok(LobbyId(v.get_m_ulSteamIDLobby())) }) }); } } + + /// Exits the passed lobby + pub fn leave_lobby(&self, lobby: LobbyId) { + unsafe { + sys::SteamAPI_ISteamMatchmaking_LeaveLobby(self.mm, lobby.0); + } + } } #[test] diff --git a/src/server.rs b/src/server.rs index ee37cac..fc1f6e8 100644 --- a/src/server.rs +++ b/src/server.rs @@ -62,9 +62,9 @@ impl Server { let version = CString::new(version).unwrap(); let raw_ip: u32 = ip.into(); let server_mode = match server_mode { - ServerMode::NoAuthentication => sys::ServerMode::NoAuthentication, - ServerMode::Authentication => sys::ServerMode::Authentication, - ServerMode::AuthenticationAndSecure => sys::ServerMode::AuthenticationAndSecure, + ServerMode::NoAuthentication => sys::EServerMode_eServerModeNoAuthentication, + ServerMode::Authentication => sys::EServerMode_eServerModeAuthentication, + ServerMode::AuthenticationAndSecure => sys::EServerMode_eServerModeAuthenticationAndSecure, }; if sys::steam_rust_game_server_init( raw_ip, steam_port, @@ -170,12 +170,13 @@ impl Server { user.0 ); Err(match res { - sys::BeginAuthSessionResult::Ok => return Ok(()), - sys::BeginAuthSessionResult::InvalidTicket => AuthSessionError::InvalidTicket, - sys::BeginAuthSessionResult::DuplicateRequest => AuthSessionError::DuplicateRequest, - sys::BeginAuthSessionResult::InvalidVersion => AuthSessionError::InvalidVersion, - sys::BeginAuthSessionResult::GameMismatch => AuthSessionError::GameMismatch, - sys::BeginAuthSessionResult::ExpiredTicket => AuthSessionError::ExpiredTicket, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultOK => return Ok(()), + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultInvalidTicket => AuthSessionError::InvalidTicket, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultDuplicateRequest => AuthSessionError::DuplicateRequest, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultInvalidVersion => AuthSessionError::InvalidVersion, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultGameMismatch => AuthSessionError::GameMismatch, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultExpiredTicket => AuthSessionError::ExpiredTicket, + _ => unreachable!(), }) } } diff --git a/src/user.rs b/src/user.rs index ec2c768..b21ac5f 100644 --- a/src/user.rs +++ b/src/user.rs @@ -63,12 +63,13 @@ impl <Manager> User<Manager> { user.0 ); Err(match res { - sys::BeginAuthSessionResult::Ok => return Ok(()), - sys::BeginAuthSessionResult::InvalidTicket => AuthSessionError::InvalidTicket, - sys::BeginAuthSessionResult::DuplicateRequest => AuthSessionError::DuplicateRequest, - sys::BeginAuthSessionResult::InvalidVersion => AuthSessionError::InvalidVersion, - sys::BeginAuthSessionResult::GameMismatch => AuthSessionError::GameMismatch, - sys::BeginAuthSessionResult::ExpiredTicket => AuthSessionError::ExpiredTicket, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultOK => return Ok(()), + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultInvalidTicket => AuthSessionError::InvalidTicket, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultDuplicateRequest => AuthSessionError::DuplicateRequest, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultInvalidVersion => AuthSessionError::InvalidVersion, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultGameMismatch => AuthSessionError::GameMismatch, + sys::EBeginAuthSessionResult_k_EBeginAuthSessionResultExpiredTicket => AuthSessionError::ExpiredTicket, + _ => unreachable!(), }) } } @@ -154,15 +155,15 @@ pub struct AuthSessionTicketResponse { unsafe impl Callback for AuthSessionTicketResponse { const ID: i32 = 163; const SIZE: i32 = ::std::mem::size_of::<sys::GetAuthSessionTicketResponse_t>() as i32; - + unsafe fn from_raw(raw: *mut libc::c_void) -> Self { let val = &mut *(raw as *mut sys::GetAuthSessionTicketResponse_t); AuthSessionTicketResponse { - ticket: AuthTicket(val.auth_ticket), - result: if val.result == sys::SResult::Ok { + ticket: AuthTicket(val.get_m_hAuthTicket()), + result: if val.get_m_eResult() == sys::EResult_k_EResultOK { Ok(()) } else { - Err(val.result.into()) + Err(val.get_m_eResult().into()) } } } @@ -185,23 +186,24 @@ pub struct ValidateAuthTicketResponse { unsafe impl Callback for ValidateAuthTicketResponse { const ID: i32 = 143; const SIZE: i32 = ::std::mem::size_of::<sys::ValidateAuthTicketResponse_t>() as i32; - + unsafe fn from_raw(raw: *mut libc::c_void) -> Self { let val = &mut *(raw as *mut sys::ValidateAuthTicketResponse_t); ValidateAuthTicketResponse { - steam_id: SteamId(val.steam_id), - owner_steam_id: SteamId(val.owner_steam_id), - response: match val.response { - sys::AuthSessionResponse::Ok => Ok(()), - sys::AuthSessionResponse::UserNotConnectedToSteam => Err(AuthSessionValidateError::UserNotConnectedToSteam), - sys::AuthSessionResponse::NoLicenseOrExpired => Err(AuthSessionValidateError::NoLicenseOrExpired), - sys::AuthSessionResponse::VACBanned => Err(AuthSessionValidateError::VACBanned), - sys::AuthSessionResponse::LoggedInElseWhere => Err(AuthSessionValidateError::LoggedInElseWhere), - sys::AuthSessionResponse::VACCheckTimedOut => Err(AuthSessionValidateError::VACCheckTimedOut), - sys::AuthSessionResponse::AuthTicketCancelled => Err(AuthSessionValidateError::AuthTicketCancelled), - sys::AuthSessionResponse::AuthTicketInvalidAlreadyUsed => Err(AuthSessionValidateError::AuthTicketInvalidAlreadyUsed), - sys::AuthSessionResponse::AuthTicketInvalid => Err(AuthSessionValidateError::AuthTicketInvalid), - sys::AuthSessionResponse::PublisherIssuedBan => Err(AuthSessionValidateError::PublisherIssuedBan), + steam_id: SteamId(val.get_m_SteamID()), + owner_steam_id: SteamId(val.get_m_OwnerSteamID()), + response: match val.get_m_eAuthSessionResponse() { + sys::EAuthSessionResponse_k_EAuthSessionResponseOK => Ok(()), + sys::EAuthSessionResponse_k_EAuthSessionResponseUserNotConnectedToSteam => Err(AuthSessionValidateError::UserNotConnectedToSteam), + sys::EAuthSessionResponse_k_EAuthSessionResponseNoLicenseOrExpired => Err(AuthSessionValidateError::NoLicenseOrExpired), + sys::EAuthSessionResponse_k_EAuthSessionResponseVACBanned => Err(AuthSessionValidateError::VACBanned), + sys::EAuthSessionResponse_k_EAuthSessionResponseLoggedInElseWhere => Err(AuthSessionValidateError::LoggedInElseWhere), + sys::EAuthSessionResponse_k_EAuthSessionResponseVACCheckTimedOut => Err(AuthSessionValidateError::VACCheckTimedOut), + sys::EAuthSessionResponse_k_EAuthSessionResponseAuthTicketCanceled => Err(AuthSessionValidateError::AuthTicketCancelled), + sys::EAuthSessionResponse_k_EAuthSessionResponseAuthTicketInvalidAlreadyUsed => Err(AuthSessionValidateError::AuthTicketInvalidAlreadyUsed), + sys::EAuthSessionResponse_k_EAuthSessionResponseAuthTicketInvalid => Err(AuthSessionValidateError::AuthTicketInvalid), + sys::EAuthSessionResponse_k_EAuthSessionResponsePublisherIssuedBan => Err(AuthSessionValidateError::PublisherIssuedBan), + _ => unreachable!(), } } } diff --git a/src/utils.rs b/src/utils.rs index 5c5ae10..43e167b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,10 +39,10 @@ impl <Manager> Utils<Manager> { pub fn set_overlay_notification_position(&self, position: NotificationPosition) { unsafe { let position = match position { - NotificationPosition::TopLeft => sys::NotificationPosition::TopLeft, - NotificationPosition::TopRight => sys::NotificationPosition::TopRight, - NotificationPosition::BottomLeft => sys::NotificationPosition::BottomLeft, - NotificationPosition::BottomRight => sys::NotificationPosition::BottomRight, + NotificationPosition::TopLeft => sys::ENotificationPosition_k_EPositionTopLeft, + NotificationPosition::TopRight => sys::ENotificationPosition_k_EPositionTopRight, + NotificationPosition::BottomLeft => sys::ENotificationPosition_k_EPositionBottomLeft, + NotificationPosition::BottomRight => sys::ENotificationPosition_k_EPositionBottomRight, }; sys::SteamAPI_ISteamUtils_SetOverlayNotificationPosition(self.utils, position); } diff --git a/steamworks-sys/Cargo.toml b/steamworks-sys/Cargo.toml index 96edbe7..9b4960e 100644 --- a/steamworks-sys/Cargo.toml +++ b/steamworks-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "steamworks-sys" -version = "0.2.3" +version = "0.3.0" authors = ["Thinkofname"] build = "build.rs" description = "Provides raw bindings to the steamworks sdk" @@ -8,6 +8,9 @@ license = "MIT / Apache-2.0" repository = "https://github.com/Thinkofname/steamworks-rs" documentation = "https://docs.rs/steamworks-sys" +[package.metadata.docs.rs] +features = [ "docs-only" ] + [features] default = [] @@ -20,6 +23,8 @@ libc = "0.2.36" [build-dependencies] cc = "1.0.4" +bindgen = "0.36.0" +serde = "1.0.37" +serde_derive = "1.0.37" +serde_json = "1.0.14" -[package.metadata.docs.rs] -features = [ "docs-only" ]
\ No newline at end of file diff --git a/steamworks-sys/build.rs b/steamworks-sys/build.rs index 8dbf861..2aa6c42 100644 --- a/steamworks-sys/build.rs +++ b/steamworks-sys/build.rs @@ -1,6 +1,32 @@ - +extern crate bindgen; extern crate cc; +extern crate serde_json; +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] +struct SteamApi { + structs: Vec<SteamStruct>, + enums: Vec<SteamEnum>, +} + +#[derive(Deserialize)] +struct SteamEnum { + enumname: String, +} + +#[derive(Deserialize)] +struct SteamStruct { + #[serde(rename = "struct")] + struct_: String, + fields: Vec<SteamField>, +} +#[derive(Deserialize)] +struct SteamField { + fieldname: String, + fieldtype: String, +} #[cfg(feature = "docs-only")] fn main() {} @@ -8,8 +34,12 @@ fn main() {} #[cfg(not(feature = "docs-only"))] fn main() { use std::env; - use std::path::Path; + use std::path::{Path, PathBuf}; + use std::io::Write; + use std::fmt::Write as FWrite; + use std::fs::File; + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let sdk_loc = env::var("STEAM_SDK_LOCATION") .expect("STEAM_SDK_LOCATION must be set"); let sdk_loc = Path::new(&sdk_loc); @@ -37,9 +67,184 @@ fn main() { println!("cargo:rustc-link-search={}", path.display()); println!("cargo:rustc-link-lib=dylib={}", lib); + let mut builder = bindgen::builder() + .header("wrapper.hpp") + .clang_arg(format!("-I{}", sdk_loc.join("public/steam").display())) + .ctypes_prefix("libc") + .rustfmt_bindings(false); + + // Steamworks uses packed structs making them hard to work + // with normally + let steam_api: SteamApi = serde_json::from_reader(File::open(sdk_loc.join("public/steam/steam_api.json")).unwrap()) + .unwrap(); + + let mut cpp_wrapper = String::from(r#" +#include <steam_api.h> +#include <steam_gameserver.h> +#include <stdint.h> +extern "C" { + "#); + + fn field_type_fix(fty: &str) -> (&str, String){ + let fty = { + if fty.contains("enum") { + fty.trim_left_matches("enum ") + } else if fty.contains("struct") { + fty.trim_left_matches("struct ") + } else if fty == "_Bool" { + "bool" + } else { + fty + } + }; + let fty_rust = if fty == "const char*" || fty == "*const char" || fty == "const char *" { + "*const libc::c_char".to_owned() + } else if fty == "char*" { + "*mut libc::c_char".to_owned() + } else if fty == "const char **" { + "*mut *const libc::c_char".to_owned() + }else if fty.ends_with("*") { + if fty.starts_with("const") { + let trimmed = fty.trim_left_matches("const ").trim_right_matches("*"); + format!("*const {}", trimmed) + } else { + let trimmed = fty.trim_right_matches("*"); + format!("*mut {}", trimmed) + } + } else if fty.contains("[") { + panic!("Unsupported field type array") + } else if fty == "class CSteamID" { + "u64".to_owned() + } else if fty == "class CGameID" { + "u64".to_owned() + } else if fty == "int" { + "libc::c_int".to_owned() + } else if fty == "float" { + "libc::c_float".to_owned() + } else if fty == "double" { + "libc::c_double".to_owned() + } else { + fty.to_owned() + }; + (fty, fty_rust) + } + + for SteamStruct{struct_: ref ty, ref fields} in &steam_api.structs { + if ty.contains("::") || !ty.ends_with("_t") || fields.iter().any(|v| v.fieldtype.contains('[')) + || ty.chars().next().map_or(true, |v| v.is_lowercase()) + || ty.starts_with("GSStats") + { + continue; + } + builder = builder.whitelist_type(ty); + + // Make a raw constructor + writeln!(cpp_wrapper, r#"{ty} __rust_helper_raw__{ty}() {{ + {ty} created_type = {{}}; + return created_type; + }}"#, ty = ty).unwrap(); + builder = builder.raw_line(format!(r#" + extern "C" {{ + fn __rust_helper_raw__{ty}() -> {ty}; + }} + pub unsafe fn create_empty_{ty}() -> {ty} {{ + __rust_helper_raw__{ty}() + }} + "#, ty = ty)); + + // Make a typed constructor + let mut typed_constr_extern = String::new(); + let mut typed_constr_wrap = String::new(); + write!(cpp_wrapper, r#"{ty} __rust_helper_typed__{ty}("#, ty = ty).unwrap(); + write!(typed_constr_extern, r#"extern "C" {{ + fn __rust_helper_typed__{ty}("#, ty = ty).unwrap(); + write!(typed_constr_wrap, r#"pub unsafe fn create_{ty}("#, ty = ty).unwrap(); + for (idx, SteamField{fieldname: ref fname, fieldtype: ref fty}) in fields.iter().enumerate() { + let (fty, fty_rust) = field_type_fix(fty); + write!(cpp_wrapper, "{} {}", fty, fname).unwrap(); + write!(typed_constr_extern, "{}: {},", fname, fty_rust).unwrap(); + write!(typed_constr_wrap, "{}: {},", fname, fty_rust).unwrap(); + if idx != fields.len() - 1 { + cpp_wrapper.push(','); + } + } + + write!(cpp_wrapper, r#") {{ + {ty} created_type = {{}}; + "#, ty = ty).unwrap(); + write!(typed_constr_extern, r#") -> {ty}; + }}"#, ty = ty).unwrap(); + write!(typed_constr_wrap, r#") -> {ty} {{ + __rust_helper_typed__{ty}("#, ty = ty).unwrap(); + for SteamField{fieldname: ref fname, ..} in fields.iter() { + write!(cpp_wrapper, "created_type.{fname} = {fname};", fname = fname).unwrap(); + write!(typed_constr_wrap, "{},", fname).unwrap(); + } + writeln!(cpp_wrapper, r#" + return created_type; + }}"#).unwrap(); + writeln!(typed_constr_wrap, r#") + }}"#).unwrap(); + + builder = builder.raw_line(typed_constr_extern); + builder = builder.raw_line(typed_constr_wrap); + + + for SteamField{fieldname: ref fname, fieldtype: ref fty} in fields.iter() { + let (fty, fty_rust) = field_type_fix(fty); + builder = builder.whitelist_type(fty); + // Generate getters/setters for fields + + writeln!(cpp_wrapper, r#" + {fty} __rust_helper_getter__{ty}_{fname}(const {ty}* from) {{ + return from->{fname}; + }} + void __rust_helper_setter__{ty}_{fname}({ty}* to, {fty} val) {{ + to->{fname} = val; + }} + "#, ty = ty, fty = fty, fname = fname).unwrap(); + + builder = builder.raw_line(format!(r#" + extern "C" {{ + fn __rust_helper_getter__{ty}_{fname}(from: *const {ty}) -> {fty_rust}; + fn __rust_helper_setter__{ty}_{fname}(from: *mut {ty}, val: {fty_rust}); + }} + impl {ty} {{ + pub unsafe fn get_{fname}(&self) -> {fty_rust} {{ + __rust_helper_getter__{ty}_{fname}(self) + }} + pub unsafe fn set_{fname}(&mut self, val: {fty_rust}) {{ + __rust_helper_setter__{ty}_{fname}(self, val) + }} + }} + "#, ty = ty, fty_rust = fty_rust, fname = fname)) + } + } + for e in steam_api.enums { + builder = builder.whitelist_type(e.enumname); + } + builder = builder.whitelist_type("EServerMode"); + + cpp_wrapper.push_str("}"); + + File::create(out_path.join("steam_gen.cpp")) + .unwrap() + .write_all(cpp_wrapper.as_bytes()) + .unwrap(); + + // panic!("{}", out_path.join("steam_gen.cpp").display()); cc::Build::new() .cpp(true) .include(sdk_loc.join("public/steam")) .file("src/lib.cpp") + .file(out_path.join("steam_gen.cpp")) .compile("steamrust"); + + let bindings = builder + .generate() + .unwrap(); + // panic!("{}", bindings.to_string()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); }
\ No newline at end of file diff --git a/steamworks-sys/src/lib.cpp b/steamworks-sys/src/lib.cpp index 226c31a..38701da 100644 --- a/steamworks-sys/src/lib.cpp +++ b/steamworks-sys/src/lib.cpp @@ -6,7 +6,7 @@ struct CallbackData { int param_size; void* userdata; void (*run)(void*, void*, void*); - void (*run_extra)(void*, void*, void*, bool, SteamAPICall_t); + void (*run_extra)(void*, void*, void*, uint8_t, SteamAPICall_t); void (*dealloc)(void*, void*); }; @@ -26,7 +26,7 @@ public: } void Run(void* pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall) { - data.run_extra(this, data.userdata, pvParam, bIOFailure, hSteamAPICall); + data.run_extra(this, data.userdata, pvParam, bIOFailure ? 1 : 0, hSteamAPICall); } int GetCallbackSizeBytes() { diff --git a/steamworks-sys/src/lib.rs b/steamworks-sys/src/lib.rs index 5fbb565..7d6ebae 100644 --- a/steamworks-sys/src/lib.rs +++ b/steamworks-sys/src/lib.rs @@ -1,7 +1,11 @@ #![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] extern crate libc; +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + use libc::{ c_char, c_void, @@ -24,222 +28,15 @@ pub struct ISteamUser(c_void); pub struct ISteamGameServer(c_void); pub type HSteamPipe = i32; -pub type HSteamUser = i32; -pub type HAuthTicket = u32; pub type AppId = u32; pub type SteamAPICall = u64; #[repr(C)] -pub enum PersonaState { - Offline = 0, - Online = 1, - Busy = 2, - Away = 3, - Snooze = 4, - LookingToTrade = 5, - LookingToPlay = 6, - Max, -} - -#[repr(C)] -pub enum LobbyType { - Private = 0, - FriendsOnly = 1, - Public = 2, - Invisible = 3, -} - -#[repr(C)] -pub struct PersonaStateChange_t { - pub steam_id: u64, - pub flags: c_int, -} - -#[repr(C)] -pub struct GetAuthSessionTicketResponse_t { - pub auth_ticket: HAuthTicket, - pub result: SResult, -} - -#[repr(C)] -pub struct ValidateAuthTicketResponse_t { - pub steam_id: u64, - pub response: AuthSessionResponse, - pub owner_steam_id: u64, -} - -#[repr(C)] -pub struct LobbyCreated { - pub result: SResult, - pub lobby_steam_id: u64, -} -#[repr(C)] -pub struct LobbyMatchList { - pub lobbies_matching: u32, -} - -#[repr(C)] -pub enum NotificationPosition { - TopLeft = 0, - TopRight = 1, - BottomLeft = 2, - BottomRight = 3, -} - -#[repr(C)] -pub enum BeginAuthSessionResult { - Ok = 0, - InvalidTicket = 1, - DuplicateRequest = 2, - InvalidVersion = 3, - GameMismatch = 4, - ExpiredTicket = 5, -} - -#[repr(C)] -pub enum AuthSessionResponse { - Ok = 0, - UserNotConnectedToSteam = 1, - NoLicenseOrExpired = 2, - VACBanned = 3, - LoggedInElseWhere = 4, - VACCheckTimedOut = 5, - AuthTicketCancelled = 6, - AuthTicketInvalidAlreadyUsed = 7, - AuthTicketInvalid = 8, - PublisherIssuedBan = 9, -} - -#[repr(C)] -pub enum ServerMode { - Invalid = 0, - NoAuthentication = 1, - Authentication = 2, - AuthenticationAndSecure = 3, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)] -pub enum SResult { - Ok = 1, - Fail = 2, - NoConnection = 3, - InvalidPassword = 5, - LoggedInElsewhere = 6, - InvalidProtocolVer = 7, - InvalidParam = 8, - FileNotFound = 9, - Busy = 10, - InvalidState = 11, - InvalidName = 12, - InvalidEmail = 13, - DuplicateName = 14, - AccessDenied = 15, - Timeout = 16, - Banned = 17, - AccountNotFound = 18, - InvalidSteamID = 19, - ServiceUnavailable = 20, - NotLoggedOn = 21, - Pending = 22, - EncryptionFailure = 23, - InsufficientPrivilege = 24, - LimitExceeded = 25, - Revoked = 26, - Expired = 27, - AlreadyRedeemed = 28, - DuplicateRequest = 29, - AlreadyOwned = 30, - IPNotFound = 31, - PersistFailed = 32, - LockingFailed = 33, - LogonSessionReplaced = 34, - ConnectFailed = 35, - HandshakeFailed = 36, - IOFailure = 37, - RemoteDisconnect = 38, - ShoppingCartNotFound = 39, - Blocked = 40, - Ignored = 41, - NoMatch = 42, - AccountDisabled = 43, - ServiceReadOnly = 44, - AccountNotFeatured = 45, - AdministratorOK = 46, - ContentVersion = 47, - TryAnotherCM = 48, - PasswordRequiredToKickSession = 49, - AlreadyLoggedInElsewhere = 50, - Suspended = 51, - Cancelled = 52, - DataCorruption = 53, - DiskFull = 54, - RemoteCallFailed = 55, - PasswordUnset = 56, - ExternalAccountUnlinked = 57, - PSNTicketInvalid = 58, - ExternalAccountAlreadyLinked = 59, - RemoteFileConflict = 60, - IllegalPassword = 61, - SameAsPreviousValue = 62, - AccountLogonDenied = 63, - CannotUseOldPassword = 64, - InvalidLoginAuthCode = 65, - AccountLogonDeniedNoMail = 66, - HardwareNotCapableOfIPT = 67, - IPTInitError = 68, - ParentalControlRestricted = 69, - FacebookQueryError = 70, - ExpiredLoginAuthCode = 71, - IPLoginRestrictionFailed = 72, - AccountLockedDown = 73, - AccountLogonDeniedVerifiedEmailRequired = 74, - NoMatchingURL = 75, - BadResponse = 76, - RequirePasswordReEntry = 77, - ValueOutOfRange = 78, - UnexpectedError = 79, - Disabled = 80, - InvalidCEGSubmission = 81, - RestrictedDevice = 82, - RegionLocked = 83, - RateLimitExceeded = 84, - AccountLoginDeniedNeedTwoFactor = 85, - ItemDeleted = 86, - AccountLoginDeniedThrottle = 87, - TwoFactorCodeMismatch = 88, - TwoFactorActivationCodeMismatch = 89, - AccountAssociatedToMultiplePartners = 90, - NotModified = 91, - NoMobileDevice = 92, - TimeNotSynced = 93, - SmsCodeFailed = 94, - AccountLimitExceeded = 95, - AccountActivityLimitExceeded = 96, - PhoneActivityLimitExceeded = 97, - RefundToWallet = 98, - EmailSendFailure = 99, - NotSettled = 100, - NeedCaptcha = 101, - GSLTDenied = 102, - GSOwnerDenied = 103, - InvalidItemType = 104, - IPBanned = 105, - GSLTExpired = 106, - InsufficientFunds = 107, - TooManyPending = 108, - NoSiteLicensesFound = 109, - WGNetworkSendExceeded = 110, - AccountNotFriends = 111, - LimitedUserAccount = 112, -} - -#[repr(C)] pub struct CallbackData { pub param_size: c_int, pub userdata: *mut c_void, pub run: unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void), - pub run_extra: unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void, bool, SteamAPICall), + pub run_extra: unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void, u8, SteamAPICall), pub dealloc: unsafe extern "C" fn(*mut c_void, *mut c_void), } @@ -257,7 +54,7 @@ extern "C" { pub fn steam_rust_get_server() -> *mut ISteamGameServer; pub fn steam_rust_get_server_apps() -> *mut ISteamApps; - pub fn steam_rust_game_server_init(ip: u32, steam_port: u16, game_port: u16, query_port: u16, server_mode: ServerMode, version: *const c_char) -> c_int; + 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; // @@ -280,11 +77,11 @@ 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_SetOverlayNotificationPosition(instance: *mut ISteamUtils, position: NotificationPosition); + pub fn SteamAPI_ISteamUtils_SetOverlayNotificationPosition(instance: *mut ISteamUtils, position: ENotificationPosition); pub fn SteamAPI_ISteamApps_BIsAppInstalled(instance: *mut ISteamApps, app_id: AppId) -> u8; pub fn SteamAPI_ISteamApps_BIsDlcInstalled(instance: *mut ISteamApps, app_id: AppId) -> u8; - pub fn SteamAPI_ISteamApps_BIsSubscribedApp(instace: *mut ISteamApps, app_id: AppId) -> u8; + pub fn SteamAPI_ISteamApps_BIsSubscribedApp(instance: *mut ISteamApps, app_id: AppId) -> u8; pub fn SteamAPI_ISteamApps_BIsSubscribedFromFreeWeekend(instance: *mut ISteamApps) -> u8; pub fn SteamAPI_ISteamApps_BIsVACBanned(instance: *mut ISteamApps) -> u8; pub fn SteamAPI_ISteamApps_BIsCybercafe(instance: *mut ISteamApps) -> u8; @@ -300,18 +97,20 @@ extern "C" { pub fn SteamAPI_ISteamFriends_GetFriendCount(instance: *mut ISteamFriends, flags: c_int) -> c_int; pub fn SteamAPI_ISteamFriends_GetFriendByIndex(instance: *mut ISteamFriends, friend: c_int, flags: c_int) -> u64; pub fn SteamAPI_ISteamFriends_GetFriendPersonaName(instance: *mut ISteamFriends, friend: u64) -> *const c_char; - pub fn SteamAPI_ISteamFriends_GetFriendPersonaState(instance: *mut ISteamFriends, friend: u64) -> PersonaState; + pub fn SteamAPI_ISteamFriends_GetFriendPersonaState(instance: *mut ISteamFriends, friend: u64) -> EPersonaState; 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_ISteamMatchmaking_CreateLobby(instance: *mut ISteamMatchmaking, lobby_ty: LobbyType, max_members: c_int) -> SteamAPICall; + 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_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; - pub fn SteamAPI_ISteamUser_BeginAuthSession(instance: *mut ISteamUser, ticket: *const c_void, ticket_size: *mut u32, steam_id: u64) -> BeginAuthSessionResult; + pub fn SteamAPI_ISteamUser_BeginAuthSession(instance: *mut ISteamUser, ticket: *const c_void, ticket_size: *mut u32, steam_id: u64) -> EBeginAuthSessionResult; pub fn SteamAPI_ISteamUser_EndAuthSession(instance: *mut ISteamUser, steam_id: u64); pub fn SteamAPI_ISteamUser_CancelAuthTicket(instance: *mut ISteamUser, auth_ticket: HAuthTicket); @@ -321,7 +120,7 @@ extern "C" { pub fn SteamAPI_ISteamGameServer_SetDedicatedServer(instance: *mut ISteamGameServer, dedicated: u8); pub fn SteamAPI_ISteamGameServer_GetSteamID(instance: *mut ISteamGameServer) -> u64; pub fn SteamAPI_ISteamGameServer_GetAuthSessionTicket(instance: *mut ISteamGameServer, ticket: *mut c_void, max_ticket: c_int, ticket_size: *mut u32) -> HAuthTicket; - pub fn SteamAPI_ISteamGameServer_BeginAuthSession(instance: *mut ISteamGameServer, ticket: *const c_void, ticket_size: *mut u32, steam_id: u64) -> BeginAuthSessionResult; + pub fn SteamAPI_ISteamGameServer_BeginAuthSession(instance: *mut ISteamGameServer, ticket: *const c_void, ticket_size: *mut u32, steam_id: u64) -> EBeginAuthSessionResult; pub fn SteamAPI_ISteamGameServer_EndAuthSession(instance: *mut ISteamGameServer, steam_id: u64); pub fn SteamAPI_ISteamGameServer_CancelAuthTicket(instance: *mut ISteamGameServer, auth_ticket: HAuthTicket); } diff --git a/steamworks-sys/wrapper.hpp b/steamworks-sys/wrapper.hpp new file mode 100644 index 0000000..27c4619 --- /dev/null +++ b/steamworks-sys/wrapper.hpp @@ -0,0 +1,3 @@ +#include <steam_api.h> +#include <steam_gameserver.h> +#include <stdint.h>
\ No newline at end of file |