Skip to main content

steel_core/behavior/items/
ender_pearl.rs

1//! Ender pearl item behavior (`EnderpearlItem`).
2//!
3//! Throwing an ender pearl spawns a [`EnderPearlEntity`] from the player's eye,
4//! shot along their look direction, and consumes one pearl unless the player
5//! has infinite materials. Mirrors vanilla `EnderpearlItem.use`.
6
7use std::sync::Arc;
8
9use steel_macros::item_behavior;
10use steel_protocol::packets::game::SoundSource;
11use steel_registry::{sound_events, vanilla_entities};
12
13use super::throw_projectile::{ThrowParams, throw_item_projectile};
14use crate::behavior::context::{InteractionResult, UseItemContext};
15use crate::behavior::item::ItemBehavior;
16use crate::entity::entities::EnderPearlEntity;
17use crate::entity::next_entity_id;
18
19/// Sound, shoot power and spread used when throwing an ender pearl.
20const THROW: ThrowParams = ThrowParams {
21    sound: &sound_events::ENTITY_ENDER_PEARL_THROW,
22    sound_source: SoundSource::Neutral,
23    sound_volume: 0.5,
24    y_offset: 0.0,
25    power: 1.5,
26    uncertainty: 1.0,
27};
28
29/// Behavior for the ender pearl item.
30#[item_behavior(class = "EnderpearlItem")]
31pub struct EnderPearlItem;
32
33impl ItemBehavior for EnderPearlItem {
34    fn use_item(&self, context: &mut UseItemContext) -> InteractionResult {
35        let world = context.world;
36        let pearl = throw_item_projectile(context, &THROW, |spawn_pos| {
37            EnderPearlEntity::new(
38                &vanilla_entities::ENDER_PEARL,
39                next_entity_id(),
40                spawn_pos,
41                Arc::downgrade(world),
42            )
43        });
44        if let Some(pearl) = pearl {
45            context.player.register_ender_pearl(&pearl);
46        }
47        InteractionResult::Success
48    }
49}