Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISteamInventory get_all_items, get_result_items, SteamInventoryResultReady, SteamInventoryFullUpdate #205

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 176 additions & 0 deletions src/inventory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
use super::*;
use std::sync::Arc;
use crate::sys;

/// Represents the result of an inventory operation, ready to be processed.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SteamInventoryResultReady {
pub handle: sys::SteamInventoryResult_t,
pub result: Result<(), SteamError>,
}

unsafe impl Callback for SteamInventoryResultReady {
const ID: i32 = sys::SteamInventoryResultReady_t_k_iCallback as i32;
const SIZE: i32 = std::mem::size_of::<sys::SteamInventoryResultReady_t>() as i32;

unsafe fn from_raw(raw: *mut c_void) -> Self {
let status = &*(raw as *mut sys::SteamInventoryResultReady_t);
Self {
handle: status.m_handle,
result: match status.m_result {
sys::EResult::k_EResultOK => Ok(()),
_ => Err(SteamError::from(status.m_result)),
},
}
}
}

/// Represents a full update event for the Steam inventory.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SteamInventoryFullUpdate {
pub handle: sys::SteamInventoryResult_t,
}

unsafe impl Callback for SteamInventoryFullUpdate {
const ID: i32 = sys::SteamInventoryFullUpdate_t_k_iCallback as i32;
const SIZE: i32 = std::mem::size_of::<sys::SteamInventoryFullUpdate_t>() as i32;

unsafe fn from_raw(raw: *mut c_void) -> Self {
let status = &*(raw as *mut sys::SteamInventoryFullUpdate_t);
Self {
handle: status.m_handle,
}
}
}

/// Provides access to the Steam inventory interface.
pub struct Inventory<Manager> {
pub(crate) inventory: *mut sys::ISteamInventory,
pub(crate) _inner: Arc<Inner<Manager>>,
}

impl<Manager> Inventory<Manager> {
/// Retrieves all items in the user's Steam inventory.
pub fn get_all_items(&self) -> Result<sys::SteamInventoryResult_t, InventoryError> {
let mut result_handle = sys::k_SteamInventoryResultInvalid;
unsafe {
if sys::SteamAPI_ISteamInventory_GetAllItems(self.inventory, &mut result_handle) {
Ok(result_handle)
} else {
Err(InventoryError::OperationFailed)
}
}
}

/// Retrieves the detailed list of items from the inventory given a result handle.
pub fn get_result_items(&self, result_handle: sys::SteamInventoryResult_t) -> Result<Vec<SteamItemDetails>, InventoryError> {
let mut items_count = 0;
unsafe {
if !sys::SteamAPI_ISteamInventory_GetResultItems(
self.inventory,
result_handle,
std::ptr::null_mut(),
&mut items_count,
) {
return Err(InventoryError::GetResultItemsFailed);
}

let mut items_array: Vec<sys::SteamItemDetails_t> = Vec::with_capacity(items_count as usize);
if sys::SteamAPI_ISteamInventory_GetResultItems(
self.inventory,
result_handle,
items_array.as_mut_ptr(),
&mut items_count,
) {
items_array.set_len(items_count as usize);
let items = items_array.into_iter().map(|details| SteamItemDetails {
item_id: SteamItemInstanceID(details.m_itemId),
definition: SteamItemDef(details.m_iDefinition),
quantity: details.m_unQuantity,
flags: details.m_unFlags,
}).collect();
Ok(items)
} else {
Err(InventoryError::GetResultItemsFailed)
}
}
}

/// Destroy a result handle after use.
pub fn destroy_result(&self, result_handle: sys::SteamInventoryResult_t) {
unsafe {
sys::SteamAPI_ISteamInventory_DestroyResult(
self.inventory,
result_handle,
);
}
}
}

/// Represents an individual inventory item with its unique details.
#[derive(Clone, Debug)]
pub struct SteamItemDetails {
pub item_id: SteamItemInstanceID,
pub definition: SteamItemDef,
pub quantity: u16,
pub flags: u16,
}

/// Represents a unique identifier for an inventory item instance.
#[derive(Clone, Debug)]
pub struct SteamItemInstanceID(pub u64);

/// Represents a unique identifier for an item definition.
#[derive(Clone, Debug)]
pub struct SteamItemDef(pub i32);

/// Enumerates possible errors that can occur during inventory operations.
#[derive(Debug, Error)]
pub enum InventoryError {
#[error("The inventory operation failed")]
OperationFailed,
#[error("Failed to retrieve result items")]
GetResultItemsFailed,
#[error("Invalid input")]
InvalidInput,
}

#[cfg(test)]
mod tests {
use super::*;
use std::sync::mpsc;

#[test]
fn test_get_result_items() {
let client = Client::init().unwrap();
let (tx, rx) = mpsc::channel::<sys::SteamInventoryResult_t>();

client.register_callback(move |val: SteamInventoryResultReady| {
assert!(val.result.is_ok(), "SteamInventoryResultReady Failed.");
if let Ok(_) = val.result {
tx.send(val.handle).expect("Failed to send handle");
}
});

client.register_callback(move |val: SteamInventoryFullUpdate| {
println!("SteamInventoryFullUpdate: {:?}", val)
});

let _result = client.inventory().get_all_items();

for _ in 0..50 {
client.run_callbacks();
::std::thread::sleep(::std::time::Duration::from_millis(100));
if let Ok(handle) = rx.try_recv() {
let result_items = client.inventory().get_result_items(handle).unwrap();
assert!(!result_items.is_empty(), "No items received");
println!("Result items: {:?}", result_items);
client.inventory().destroy_result(handle);
return;
}
}
panic!("Timed out waiting for inventory result.");
}
}
14 changes: 14 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub use crate::ugc::*;
pub use crate::user::*;
pub use crate::user_stats::*;
pub use crate::utils::*;
pub use crate::inventory::*;

mod app;
mod callback;
Expand All @@ -61,6 +62,7 @@ mod ugc;
mod user;
mod user_stats;
mod utils;
mod inventory;

pub type SResult<T> = Result<T, SteamError>;

Expand Down Expand Up @@ -441,6 +443,18 @@ where
}
}

/// Returns an accessor to the steam inventory interface
pub fn inventory(&self) -> Inventory<Manager> {
unsafe {
let inventory = sys::SteamAPI_SteamInventory_v003();
debug_assert!(!inventory.is_null());
Inventory {
inventory,
_inner: self.inner.clone(),
}
}
}

pub fn networking_messages(&self) -> networking_messages::NetworkingMessages<Manager> {
unsafe {
let net = sys::SteamAPI_SteamNetworkingMessages_SteamAPI_v002();
Expand Down
Loading