diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2023-05-03 20:57:27 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-03 20:57:27 -0500 |
| commit | 634cb8d72c6608512aedba19e5cd669104bc35ea (patch) | |
| tree | f8e76ce9eb43403d29cc0cbcf9a4f51522419dc2 /azalea-inventory/src/slot.rs | |
| parent | 1fb4418f2c9cbd004c64c2f23d2d0352ee12c0e5 (diff) | |
| download | azalea-drasl-634cb8d72c6608512aedba19e5cd669104bc35ea.tar.xz | |
Inventory (#48)
* start adding azalea-inventory
* design more of how inventories are defined
* start working on az-inv-macros
* inventory macro works
* start adding inventory codegen
* update some deps
* add inventory codegen
* manually write inventory menus
* put the inventories in Client
* start on containersetcontent
* inventory menu should hopefully work
* checks in containersetcontent
* format a comment
* move some variant matches
* inventory.rs
* inventory stuff
* more inventory stuff
* inventory/container tracking works
* start adding interact function
* sequence number
* start adding HitResultComponent
* implement traverse_blocks
* start adding clip
* add clip function
* update_hit_result_component
* start trying to fix
* fix
* make some stuff simpler
* clippy
* lever
* chest
* container handle
* fix ambiguity
* fix some doc tests
* move some container stuff from az-client to azalea
* clicking container
* start implementing simulate_click
* keep working on simulate click
* implement more of simulate_click
this is really boring
* inventory fixes
* start implementing shift clicking
* fix panic in azalea-chat i hope
* shift clicking implemented
* more inventory stuff
* fix items not showing in containers sometimes
* fix test
* fix all warnings
* remove a println
---------
Co-authored-by: mat <git@matdoes.dev>
Diffstat (limited to 'azalea-inventory/src/slot.rs')
| -rw-r--r-- | azalea-inventory/src/slot.rs | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/azalea-inventory/src/slot.rs b/azalea-inventory/src/slot.rs new file mode 100644 index 00000000..cef555d7 --- /dev/null +++ b/azalea-inventory/src/slot.rs @@ -0,0 +1,146 @@ +use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable}; +use azalea_nbt::Nbt; +use std::io::{Cursor, Write}; + +/// Either an item in an inventory or nothing. +#[derive(Debug, Clone, Default, PartialEq)] +pub enum ItemSlot { + #[default] + Empty, + Present(ItemSlotData), +} + +impl ItemSlot { + /// Check if the slot is ItemSlot::Empty, if the count is <= 0, or if the + /// item is air. + /// + /// This is the opposite of [`ItemSlot::is_present`]. + pub fn is_empty(&self) -> bool { + match self { + ItemSlot::Empty => true, + ItemSlot::Present(item) => item.is_empty(), + } + } + /// Check if the slot is not ItemSlot::Empty, if the count is > 0, and if + /// the item is not air. + /// + /// This is the opposite of [`ItemSlot::is_empty`]. + pub fn is_present(&self) -> bool { + !self.is_empty() + } + + /// Return the amount of the item in the slot, or 0 if the slot is empty. + /// + /// Note that it's possible for the count to be zero or negative when the + /// slot is present. + pub fn count(&self) -> i8 { + match self { + ItemSlot::Empty => 0, + ItemSlot::Present(i) => i.count, + } + } + + /// Remove `count` items from this slot, returning the removed items. + pub fn split(&mut self, count: u8) -> ItemSlot { + match self { + ItemSlot::Empty => ItemSlot::Empty, + ItemSlot::Present(i) => { + let returning = i.split(count); + if i.is_empty() { + *self = ItemSlot::Empty; + } + ItemSlot::Present(returning) + } + } + } + + /// Get the `kind` of the item in this slot, or + /// [`azalea_registry::Item::Air`] + pub fn kind(&self) -> azalea_registry::Item { + match self { + ItemSlot::Empty => azalea_registry::Item::Air, + ItemSlot::Present(i) => i.kind, + } + } + + /// Update whether this slot is empty, based on the count. + pub fn update_empty(&mut self) { + if let ItemSlot::Present(i) = self { + if i.is_empty() { + *self = ItemSlot::Empty; + } + } + } +} + +/// An item in an inventory, with a count and NBT. Usually you want [`ItemSlot`] +/// or [`azalea_registry::Item`] instead. +#[derive(Debug, Clone, McBuf, PartialEq)] +pub struct ItemSlotData { + pub kind: azalea_registry::Item, + /// The amount of the item in this slot. + /// + /// The count can be zero or negative, but this is rare. + pub count: i8, + pub nbt: Nbt, +} + +impl ItemSlotData { + /// Remove `count` items from this slot, returning the removed items. + pub fn split(&mut self, count: u8) -> ItemSlotData { + let returning_count = i8::min(count as i8, self.count); + let mut returning = self.clone(); + returning.count = returning_count; + self.count -= returning_count; + returning + } + + /// Check if the count of the item is <= 0 or if the item is air. + pub fn is_empty(&self) -> bool { + self.count <= 0 || self.kind == azalea_registry::Item::Air + } + + /// Whether this item is the same as another item, ignoring the count. + /// + /// ``` + /// # use azalea_inventory::ItemSlotData; + /// # use azalea_registry::Item; + /// let mut a = ItemSlotData { + /// kind: Item::Stone, + /// count: 1, + /// nbt: Default::default(), + /// }; + /// let mut b = ItemSlotData { + /// kind: Item::Stone, + /// count: 2, + /// nbt: Default::default(), + /// }; + /// assert!(a.is_same_item_and_nbt(&b)); + /// + /// b.kind = Item::Dirt; + /// assert!(!a.is_same_item_and_nbt(&b)); + /// ``` + pub fn is_same_item_and_nbt(&self, other: &ItemSlotData) -> bool { + self.kind == other.kind && self.nbt == other.nbt + } +} + +impl McBufReadable for ItemSlot { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let slot = Option::<ItemSlotData>::read_from(buf)?; + Ok(slot.map_or(ItemSlot::Empty, ItemSlot::Present)) + } +} + +impl McBufWritable for ItemSlot { + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + match self { + ItemSlot::Empty => false.write_into(buf)?, + ItemSlot::Present(i) => { + true.write_into(buf)?; + i.write_into(buf)?; + } + }; + Ok(()) + } +} |
