Pumpkin/pumpkin/src/item/items/hoe.rs
2025-06-22 21:28:14 +02:00

102 lines
3.6 KiB
Rust

use crate::entity::item::ItemEntity;
use crate::entity::player::Player;
use crate::item::pumpkin_item::{ItemMetadata, PumpkinItem};
use crate::server::Server;
use async_trait::async_trait;
use pumpkin_data::Block;
use pumpkin_data::BlockDirection;
use pumpkin_data::entity::EntityType;
use pumpkin_data::item::Item;
use pumpkin_data::tag::Tagable;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::item::ItemStack;
use pumpkin_world::world::BlockFlags;
use std::sync::Arc;
pub struct HoeItem;
impl ItemMetadata for HoeItem {
fn ids() -> Box<[u16]> {
Item::get_tag_values("#minecraft:hoes")
.expect("This is a valid vanilla tag")
.iter()
.map(|key| {
Item::from_registry_key(key)
.expect("We just got this key from the registry")
.id
})
.collect::<Vec<_>>()
.into_boxed_slice()
}
}
#[async_trait]
impl PumpkinItem for HoeItem {
async fn use_on_block(
&self,
_item: &Item,
player: &Player,
location: BlockPos,
face: BlockDirection,
block: &Block,
_server: &Server,
) {
// Yes, Minecraft does hardcode these
if block == &Block::GRASS_BLOCK
|| block == &Block::DIRT_PATH
|| block == &Block::DIRT
|| block == &Block::COARSE_DIRT
|| block == &Block::ROOTED_DIRT
{
let mut future_block = block;
let world = player.world().await;
//Only rooted can be right-clicked on the bottom of the block
if face == BlockDirection::Down {
if block == &Block::ROOTED_DIRT {
future_block = &Block::DIRT;
}
} else {
// grass, dirt && dirt path become farmland
if (block == &Block::GRASS_BLOCK
|| block == &Block::DIRT_PATH
|| block == &Block::DIRT)
&& world.get_block_state(&location.up()).await.is_air()
{
future_block = &Block::FARMLAND;
}
//Coarse dirt and rooted dirt become dirt
else if block == &Block::COARSE_DIRT || block == &Block::ROOTED_DIRT {
future_block = &Block::DIRT;
}
}
world
.set_block_state(
&location,
future_block.default_state.id,
BlockFlags::NOTIFY_ALL,
)
.await;
//Also rooted_dirt drop a hanging_root
if block == &Block::ROOTED_DIRT {
let location = match face {
BlockDirection::Up => location.up().to_f64(),
BlockDirection::Down => location.down().to_f64(),
BlockDirection::North => location.up().to_f64().add_raw(0.0, -0.4, -1.0),
BlockDirection::South => location.up().to_f64().add_raw(0.0, -0.4, 1.0),
BlockDirection::West => location.up().to_f64().add_raw(-1.0, -0.4, 0.0),
BlockDirection::East => location.up().to_f64().add_raw(1.0, -0.4, 0.0),
};
let entity = world.create_entity(location, EntityType::ITEM);
// TODO: Merge stacks together
let item_entity = Arc::new(
ItemEntity::new(entity, ItemStack::new(1, &Item::HANGING_ROOTS)).await,
);
world.spawn_entity(item_entity).await;
}
}
}
}