steel_core/behavior/items/
ender_pearl.rs1use std::sync::Arc;
8
9use steel_macros::item_behavior;
10use steel_protocol::packets::game::SoundSource;
11use steel_registry::stat::vanilla_stat_types;
12use steel_registry::{sound_events, vanilla_entities};
13
14use crate::behavior::context::{InteractionResult, UseItemContext};
15use crate::behavior::item::ItemBehavior;
16use crate::entity::entities::EnderPearlEntity;
17use crate::entity::{Entity, next_entity_id, spawn_throwable_item_projectile};
18
19const SHOOT_POWER: f32 = 1.5;
21const THROW_UNCERTAINTY: f32 = 1.0;
23
24#[item_behavior(class = "EnderpearlItem")]
26pub struct EnderPearlItem;
27
28impl ItemBehavior for EnderPearlItem {
29 fn use_item(&self, context: &mut UseItemContext) -> InteractionResult {
30 let player = context.player;
31 let world = context.world;
32
33 let pitch = 0.4 / rand::random_range(0.8..1.2);
34 world.play_sound_at(
35 &sound_events::ENTITY_ENDER_PEARL_THROW,
36 SoundSource::Neutral,
37 player.position(),
38 0.5,
39 pitch,
40 None,
41 );
42
43 let mut thrown_item = context.inv.with_item(|item| item.clone());
44 let Some(entity) = spawn_throwable_item_projectile(
45 world,
46 player,
47 &mut thrown_item,
48 SHOOT_POWER,
49 THROW_UNCERTAINTY,
50 |spawn_pos| {
51 EnderPearlEntity::new(
52 &vanilla_entities::ENDER_PEARL,
53 next_entity_id(),
54 spawn_pos,
55 Arc::downgrade(world),
56 )
57 },
58 ) else {
59 return InteractionResult::Fail;
60 };
61 player.register_ender_pearl(&entity);
62
63 player.award_stat(&vanilla_stat_types::ITEM_USED, thrown_item.item);
64 let has_infinite_materials = player.has_infinite_materials();
65 context
66 .inv
67 .with_item(|item| item.consume_one(has_infinite_materials));
68
69 InteractionResult::Success
70 }
71}