Skip to main content

steel_core/entity/projectile/
throwable_item.rs

1//! Vanilla `ThrowableItemProjectile` — carries a synced rendered item stack.
2//!
3//! Vanilla stores the item in `DATA_ITEM_STACK` (synced entity data). Steel keeps
4//! it in the generated `*EntityData` layer, so this trait has no base struct: the
5//! concrete entity implements [`ThrowableItemProjectile::set_item`] /
6//! [`ThrowableItemProjectile::get_item`] against its synced data.
7
8use simdnbt::ToNbtTag;
9use simdnbt::borrow::NbtCompound as BorrowedNbtCompoundView;
10use simdnbt::owned::NbtCompound;
11use steel_registry::item_stack::ItemStack;
12use steel_registry::items::ItemRef;
13
14use crate::entity::projectile::ThrowableProjectile;
15
16/// Vanilla-shaped behavior shared by entities that extend `ThrowableItemProjectile`.
17pub trait ThrowableItemProjectile: ThrowableProjectile {
18    /// Returns the item stack used when no persisted item can be loaded
19    /// (e.g. a plain ender pearl, snowball, or egg).
20    fn get_default_item(&self) -> ItemRef;
21
22    /// Sets the rendered item stack (vanilla `setItem`, count clamped to 1).
23    ///
24    /// The concrete entity stores this in its synced data layer.
25    fn set_item(&self, item: ItemStack);
26
27    /// Returns the rendered item stack (vanilla `getItem`).
28    fn get_item(&self) -> ItemStack;
29
30    /// Sets the rendered item stack, clamping its count to 1.
31    fn set_item_clamped(&self, item: ItemStack) {
32        self.set_item(item.copy_with_count(1));
33    }
34
35    /// Saves the item stack to NBT, omitting the tag entirely when the stack is empty.
36    fn save_throwable_item(&self, nbt: &mut NbtCompound) {
37        let item = self.get_item();
38        if !item.is_empty() {
39            nbt.insert("Item", item.to_nbt_tag());
40        }
41    }
42
43    /// Loads the item stack, falling back to the default item (vanilla
44    /// `readAdditionalSaveData`).
45    fn load_throwable_item(&self, nbt: BorrowedNbtCompoundView<'_, '_>) {
46        let item = nbt
47            .compound("Item")
48            .and_then(|tag| ItemStack::from_borrowed_compound(&tag))
49            .unwrap_or_else(|| ItemStack::new(self.get_default_item()));
50        self.set_item_clamped(item);
51    }
52}