Skip to content

Commit

Permalink
implement more item functions
Browse files Browse the repository at this point in the history
  • Loading branch information
griffi-gh committed Sep 11, 2024
1 parent a2e5a29 commit 1251d07
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 6 deletions.
2 changes: 1 addition & 1 deletion kubi-server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use shipyard::{IntoWorkload, SystemModificator, Workload, WorkloadModificator, World};
use shipyard::{IntoWorkload, Workload, WorkloadModificator, World};
use std::{thread, time::Duration};
use kubi_shared::fixed_timestamp::{FixedTimestamp, init_fixed_timestamp_storage};

Expand Down
175 changes: 170 additions & 5 deletions kubi-shared/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,194 @@ impl Item {
pub struct ItemCollection(Option<(Item, NonZeroU8)>);

impl ItemCollection {
pub const fn new(item: Item, amount: NonZeroU8) -> Self {
/// Create a new item collection with `amount` of `item`
///
/// If `amount` is 0, the slot will be empty, and the item will be ignored
pub const fn new(item: Item, amount: u8) -> Self {
if amount == 0 {
return Self::new_empty()
}
// SAFETY: `amount` guaranteed to be non-zero
let amount = unsafe { NonZeroU8::new_unchecked(amount) };
Self::new_nonzero(item, amount)
}

/// Create a new item collection with `amount` of `item`
pub const fn new_nonzero(item: Item, amount: NonZeroU8) -> Self {
Self(Some((item, amount)))
}

/// Create a new item collection with a single item
pub const fn new_single(item: Item) -> Self {
Self(Some((item, nz::u8!(1))))
}

/// Create a new empty item collection
pub const fn new_empty() -> Self {
Self(None)
}

pub const fn with_amount(&self, amount: NonZeroU8) -> Self {
/// Set the amount of items in the slot to `amount`\
///
/// If `amount` is 0, the slot will be emptied\
/// If slot is empty, this will do nothing, even if `amount` is non-zero
pub const fn with_amount(&self, amount: u8) -> Self {
if amount == 0 {
return Self::new_empty()
}
// SAFETY: `amount` guaranteed to be non-zero
let amount = unsafe { NonZeroU8::new_unchecked(amount) };
self.with_amount_nonzero(amount)
}

/// Set the amount of items in the slot to `amount`
///
/// If slot is empty, this will do nothing
pub const fn with_amount_nonzero(&self, amount: NonZeroU8) -> Self {
Self(match self.0 {
Some((item, _)) => Some((item, amount)),
None => None,
})
}

/// Check if the slot is empty (contains no items)
pub const fn is_empty(&self) -> bool {
self.0.is_none()
}

/// Check if the slot is full (contains the maximum stack size)
pub const fn is_full(&self) -> bool {
match self.0 {
Some((item, amount)) => {
amount.get() >= item.descriptor().stack_size.get()
},
None => false,
}
}

/// Get the item in the slot
///
/// If the slot is empty, returns None
pub const fn item(&self) -> Option<Item> {
match self.0 {
Some((item, _)) => Some(item),
None => None,
}
}

/// Get the amount of items in the slot
///
/// If the slot is empty, returns 0
pub const fn amount(&self) -> u8 {
match self.0 {
Some((_, amount)) => amount.get(),
None => 0,
}
}

/// Get the amount of items in the slot
///
/// If the slot is empty, returns None
pub const fn amount_nonzero(&self) -> Option<NonZeroU8> {
match self.0 {
Some((_, amount)) => Some(amount),
None => None,
}
}

/// Add items from another slot, copying them\
/// Returns the leftover items
/// Returns the leftover items (items that could not be added)
pub fn add(&mut self, from: &Self) -> Self {
let Some((item, count)) = from.0 else { return Self::new_empty() };
todo!() //TODO finish item slot system
// If there are no items to add, return
let Some((add_item, add_count)) = from.0 else {
return Self::new_empty()
};
let item_stack_size = add_item.descriptor().stack_size;

// Add items to the slot
let (this_slot, leftovers) = match self.0 {
None => (
(
add_item,
add_count.min(item_stack_size)
),
match add_count > item_stack_size {
true => Self::new_nonzero(
add_item,
NonZeroU8::new(
add_count.get() - item_stack_size.get()
).unwrap(),
),
false => Self::new_empty()
}
),
Some((cur_item, cur_count)) if cur_item == add_item => {
let total_count = cur_count.checked_add(add_count.get()).unwrap();
(
(
cur_item,
total_count.min(item_stack_size),
),
match total_count > item_stack_size {
true => Self::new_nonzero(
add_item,
NonZeroU8::new(
total_count.get() - item_stack_size.get()
).unwrap()
),
false => Self::new_empty()
}
)
},
// If items are different, do not add anything, everything is leftovers
_ => return *from,
};

self.0 = Some(this_slot);
leftovers
}

/// Move as much as possible items from another slot, removing them
///
/// This may not be possible if the slot is full or contains a different item
pub fn move_all(&mut self, to: &mut Self) {
let leftovers = to.add(self);
*self = leftovers;
}

/// Move up to `amount` items from another slot, removing them
///
/// If `amount` is 0, nothing will be moved
pub fn move_up_to(&mut self, to: &mut Self, limit: u8) {

if self.is_empty() { return }
// SAFETY: slot is guaranteed to be non-empty
let amount = unsafe { self.amount_nonzero().unwrap_unchecked() } ;

if limit == 0 { return }
// SAFETY: `limit` guaranteed to be non-zero
let limit = unsafe { NonZeroU8::new_unchecked(limit) };

let amount_with_limit = amount.min(limit);
let self_with_limit = self.with_amount_nonzero(amount_with_limit);

let mut leftovers = to.add(&self_with_limit);

// Compensate for the amount of items that were not moved
let amount_difference = amount.get() - amount_with_limit.get();
if amount_difference > 0 {
let correct_item = self.item().unwrap();
let correct_amount = leftovers.amount() + amount_difference;
leftovers = Self::new(correct_item, correct_amount);
}

*self = leftovers;
}

/// Try to move a single item from another slot, removing it
///
/// This may not be possible if the slot is full or contains a different item
pub fn move_single(&mut self, to: &mut Self) {
self.move_up_to(to, 1);
}
}

0 comments on commit 1251d07

Please sign in to comment.