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 /// Vanilla `ThrowableItemProjectile.getDefaultItem`.
19 fn get_default_item(&self) -> ItemRef;
20
21 /// Sets the rendered item stack (vanilla `setItem`, count clamped to 1).
22 ///
23 /// The concrete entity stores this in its synced data layer.
24 fn set_item(&self, item: ItemStack);
25
26 /// Returns the rendered item stack (vanilla `getItem`).
27 fn get_item(&self) -> ItemStack;
28
29 /// Vanilla `ThrowableItemProjectile.setItem` count-clamping helper.
30 fn set_item_clamped(&self, item: ItemStack) {
31 self.set_item(item.copy_with_count(1));
32 }
33
34 /// Saves the item stack (vanilla `addAdditionalSaveData`).
35 fn save_throwable_item(&self, nbt: &mut NbtCompound) {
36 let item = self.get_item();
37 if !item.is_empty() {
38 nbt.insert("Item", item.to_nbt_tag());
39 }
40 }
41
42 /// Loads the item stack, falling back to the default item (vanilla
43 /// `readAdditionalSaveData`).
44 fn load_throwable_item(&self, nbt: BorrowedNbtCompoundView<'_, '_>) {
45 let item = nbt
46 .compound("Item")
47 .and_then(|tag| ItemStack::from_borrowed_compound(&tag))
48 .unwrap_or_else(|| ItemStack::new(self.get_default_item()));
49 self.set_item_clamped(item);
50 }
51}