Pumpkin/crates/pumpkin/src/item/items/potions.rs
Alexander Medvedev 6eb02f65b9 chore: more fixes
2026-08-28 13:31:28 +02:00

152 lines
4.9 KiB
Rust

use std::sync::Arc;
use crate::entity::Entity;
use crate::entity::EntityBase;
use crate::entity::player::Player;
use crate::entity::projectile::{
lingering_potion::LingeringPotionEntity, splash_potion::SplashPotionEntity,
};
use crate::item::{ItemBehaviour, ItemMetadata};
use pumpkin_data::entity::EntityType;
use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
pub struct PotionItem;
pub struct SplashPotionItem;
pub struct LingeringPotionItem;
impl ItemMetadata for PotionItem {
fn ids() -> Box<[u16]> {
[Item::POTION.id].into()
}
}
impl ItemMetadata for SplashPotionItem {
fn ids() -> Box<[u16]> {
[Item::SPLASH_POTION.id].into()
}
}
impl ItemMetadata for LingeringPotionItem {
fn ids() -> Box<[u16]> {
[Item::LINGERING_POTION.id].into()
}
}
const POWER: f32 = 0.5;
impl ItemBehaviour for PotionItem {
fn normal_use(&self, _item: &Item, _player: &Player) {
// Drinking is handled by the consumable flow in the server (active hand + consumption tick).
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl ItemBehaviour for SplashPotionItem {
fn normal_use(&self, _item: &Item, player: &Player) {
let position = player.position();
let world = player.world();
world.play_sound(
Sound::EntityWitchThrow,
pumpkin_data::sound::SoundCategory::Neutral,
&position,
);
let entity = Entity::new(world.clone(), position, &EntityType::SPLASH_POTION);
let splash = SplashPotionEntity::new_shot(entity, player.get_entity());
// Copy the held item stack data into the projectile
let main_s = player.inventory.held_item();
let mut used_main = true;
let mut stack = (!main_s.is_empty()
&& main_s.item.id == pumpkin_data::item::Item::SPLASH_POTION.id)
.then_some(main_s);
if stack.is_none() {
let off_s = player.inventory.off_hand_item();
if !off_s.is_empty() && off_s.item.id == pumpkin_data::item::Item::SPLASH_POTION.id {
stack = Some(off_s);
used_main = false;
}
}
let stack = stack.unwrap_or_else(|| ItemStack::EMPTY.clone());
splash.set_item_stack(stack);
let (yaw, pitch) = player.rotation();
splash.thrown.set_velocity_from(pitch, yaw, 0.0, POWER, 1.0);
world.spawn_entity(Arc::new(splash));
// Decrement the used stack (clear)
if used_main {
let mut s = player.inventory.held_item();
s.decrement_unless_creative(player.gamemode.load(), 1);
player.inventory.set_held_item(s);
} else {
let mut s = player.inventory.off_hand_item();
s.decrement_unless_creative(player.gamemode.load(), 1);
player
.inventory
.set_stack_in_hand(pumpkin_util::Hand::Left, s);
}
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl ItemBehaviour for LingeringPotionItem {
fn normal_use(&self, _item: &Item, player: &Player) {
let position = player.position();
let world = player.world();
world.play_sound(
Sound::EntityWitchThrow,
pumpkin_data::sound::SoundCategory::Neutral,
&position,
);
let entity = Entity::new(world.clone(), position, &EntityType::LINGERING_POTION);
let ling = LingeringPotionEntity::new_shot(entity, player.get_entity());
// Copy the held item stack data into the projectile
let main_s = player.inventory.held_item();
let mut used_main = true;
let mut stack = (!main_s.is_empty()
&& main_s.item.id == pumpkin_data::item::Item::LINGERING_POTION.id)
.then_some(main_s);
if stack.is_none() {
let off_s = player.inventory.off_hand_item();
if !off_s.is_empty() && off_s.item.id == pumpkin_data::item::Item::LINGERING_POTION.id {
stack = Some(off_s);
used_main = false;
}
}
let stack = stack.unwrap_or_else(|| ItemStack::EMPTY.clone());
ling.set_item_stack(stack);
let (yaw, pitch) = player.rotation();
ling.thrown.set_velocity_from(pitch, yaw, 0.0, POWER, 1.0);
world.spawn_entity(Arc::new(ling));
// Decrement the used stack (clear)
if used_main {
let mut s = player.inventory.held_item();
s.decrement_unless_creative(player.gamemode.load(), 1);
player.inventory.set_held_item(s);
} else {
let mut s = player.inventory.off_hand_item();
s.decrement_unless_creative(player.gamemode.load(), 1);
player
.inventory
.set_stack_in_hand(pumpkin_util::Hand::Left, s);
}
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}