Skip to main content

steel_core/behavior/items/
throwable_potion.rs

1//! Splash/lingering potion item behaviors (`SplashPotionItem`, `LingeringPotionItem`).
2
3use std::borrow::Cow;
4use std::sync::Arc;
5
6use steel_macros::item_behavior;
7use steel_protocol::packets::game::SoundSource;
8use steel_registry::item_stack::ItemStack;
9use steel_registry::items::ItemRef;
10use steel_registry::{sound_events, vanilla_entities};
11use text_components::TextComponent;
12
13use super::dynamic_name::potion_name;
14use super::potion::{potion_default_instance, potion_use_on};
15use super::throw_projectile::{ThrowParams, throw_item_projectile};
16use crate::behavior::context::{InteractionResult, UseItemContext, UseOnContext};
17use crate::behavior::item::ItemBehavior;
18use crate::entity::entities::{LingeringPotionEntity, SplashPotionEntity};
19use crate::entity::next_entity_id;
20
21const SPLASH_THROW: ThrowParams = ThrowParams {
22    sound: &sound_events::ENTITY_SPLASH_POTION_THROW,
23    sound_source: SoundSource::Players,
24    sound_volume: 0.5,
25    y_offset: -20.0,
26    power: 0.5,
27    uncertainty: 1.0,
28};
29
30const LINGERING_THROW: ThrowParams = ThrowParams {
31    sound: &sound_events::ENTITY_LINGERING_POTION_THROW,
32    sound_source: SoundSource::Neutral,
33    ..SPLASH_THROW
34};
35
36/// Splash-potion behavior providing Vanilla's potion-content-dependent name
37/// and the water default instance inherited from `PotionItem`.
38// TODO: Implement the `ProjectileItem` dispenser dispatch.
39#[item_behavior]
40pub struct SplashPotionItem;
41
42impl ItemBehavior for SplashPotionItem {
43    fn get_name<'a>(&self, stack: &'a ItemStack) -> Cow<'a, TextComponent> {
44        potion_name(stack)
45    }
46
47    fn get_default_instance(&self, item: ItemRef) -> ItemStack {
48        potion_default_instance(item)
49    }
50
51    fn use_on(&self, context: &mut UseOnContext) -> InteractionResult {
52        potion_use_on(context)
53    }
54
55    fn use_item(&self, context: &mut UseItemContext) -> InteractionResult {
56        let world = context.world;
57        throw_item_projectile(context, &SPLASH_THROW, |spawn_pos| {
58            SplashPotionEntity::new(
59                &vanilla_entities::SPLASH_POTION,
60                next_entity_id(),
61                spawn_pos,
62                Arc::downgrade(world),
63            )
64        });
65        InteractionResult::Success
66    }
67}
68
69/// Lingering-potion behavior providing Vanilla's potion-content-dependent name
70/// and the water default instance inherited from `PotionItem`.
71// TODO: Implement the `ProjectileItem` dispenser dispatch.
72#[item_behavior]
73pub struct LingeringPotionItem;
74
75impl ItemBehavior for LingeringPotionItem {
76    fn get_name<'a>(&self, stack: &'a ItemStack) -> Cow<'a, TextComponent> {
77        potion_name(stack)
78    }
79
80    fn get_default_instance(&self, item: ItemRef) -> ItemStack {
81        potion_default_instance(item)
82    }
83
84    fn use_on(&self, context: &mut UseOnContext) -> InteractionResult {
85        potion_use_on(context)
86    }
87
88    fn use_item(&self, context: &mut UseItemContext) -> InteractionResult {
89        let world = context.world;
90        throw_item_projectile(context, &LINGERING_THROW, |spawn_pos| {
91            LingeringPotionEntity::new(
92                &vanilla_entities::LINGERING_POTION,
93                next_entity_id(),
94                spawn_pos,
95                Arc::downgrade(world),
96            )
97        });
98        InteractionResult::Success
99    }
100}