Files
Pumpkin/pumpkin/src/item/items/bucket.rs
4lve 9e36cdf683 Full inventory refactor + barrels (#691)
* replace slot with ItemStackSeralizer

* Dismantle current inv logic

* Disassemble even more, items need fixing markd with TODO: Inv

* Player inventory methods implmented

* make some fields private

* remove invalid comment

* Partial screen handler and slot

* Add armorslot

* prepare for crafting

* implement some more crafting traits

* Fix ItemStack

* Fix pickup and remove faulty crafting (getting reworked in inv revamp)

* fix

* fix error

* add readme

* move readme file

* asd

* remove readme

* add uppsercase readme

* Some more work

* merge

* Move from generics to dynamics

* fix

* move to same impl

* Some changes

* add player open logic

* Basic impl of sync and listeners

* Why did mojang complicate it so much

* bruh

* Simplify things with DefaultScreenHandlerBehaviour

* Implement partial slot clicks

* add

* itemhashes are broken

* Start implementing packets

* fix deadlock

* new vanilla update

* Use static item refs and use Arc Mutex on invs

* working normal click

* fix deadlock

* implement sync handler

* small patch

* Implement quick_move

* Implement Swap click type

* pickup, update bug

* start fixing updates

* fix pickup desync

* Make Inventories non mutexes

* Implement some finishing stuff

* close screen on player leave

* fix pick item

* Move to item hashes

* remove some logs

* begin implementing barrels

* Begin implementing barrel

* implement barrels

* fix clippy + typos

* Fix merge conflicts

* Fix lint error

* don't use unwrap when getting equipment slot

* Fix typo and single threaded

* Accidentally removed tokio completley

* Fix crash when opening barrel holding item

* Add support for marking block entities dirty

* Player Equipment changes

* Make ScreenHandlerFactory own inventory instead of passing in optional

* remove log

* replace todo's

* fix clippy

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
2025-05-09 16:28:15 +02:00

131 lines
4.2 KiB
Rust

use std::sync::Arc;
use crate::entity::player::Player;
use async_trait::async_trait;
use pumpkin_data::Block;
use pumpkin_data::fluid::Fluid;
use pumpkin_data::item::Item;
use pumpkin_util::GameMode;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use crate::item::pumpkin_item::{ItemMetadata, PumpkinItem};
use crate::world::{BlockFlags, World};
pub struct EmptyBucketItem;
pub struct FilledBucketItem;
impl ItemMetadata for EmptyBucketItem {
fn ids() -> Box<[u16]> {
[Item::BUCKET.id].into()
}
}
impl ItemMetadata for FilledBucketItem {
fn ids() -> Box<[u16]> {
[
Item::WATER_BUCKET.id,
Item::LAVA_BUCKET.id,
// TODO drink milk
// Item::MILK_BUCKET.id,
// TODO implement these buckets, and getting the item from the world
// Item::POWDER_SNOW_BUCKET.id,
// Item::AXOLOTL_BUCKET.id,
// Item::COD_BUCKET.id,
// Item::SALMON_BUCKET.id,
// Item::TROPICAL_FISH_BUCKET.id,
// Item::PUFFERFISH_BUCKET.id,
// Item::TADPOLE_BUCKET.id,
]
.into()
}
}
fn get_start_and_end_pos(player: &Player) -> (Vector3<f64>, Vector3<f64>) {
let start_pos = player.eye_position();
let (yaw, pitch) = player.rotation();
let (yaw_rad, pitch_rad) = (f64::from(yaw.to_radians()), f64::from(pitch.to_radians()));
let block_interaction_range = 4.5; // This is not the same as the block_interaction_range in the
// player entity.
let direction = Vector3::new(
-yaw_rad.sin() * pitch_rad.cos() * block_interaction_range,
-pitch_rad.sin() * block_interaction_range,
pitch_rad.cos() * yaw_rad.cos() * block_interaction_range,
);
let end_pos = start_pos.add(&direction);
(start_pos, end_pos)
}
#[async_trait]
impl PumpkinItem for EmptyBucketItem {
#[allow(clippy::too_many_lines)]
async fn normal_use(&self, _item: &Item, player: &Player) {
let world = player.world().await.clone();
let (start_pos, end_pos) = get_start_and_end_pos(player);
let checker = async |pos: &BlockPos, world_inner: &Arc<World>| {
let Ok(state_id) = world_inner.get_block_state_id(pos).await else {
return false;
};
state_id == Block::WATER.default_state_id || state_id == Block::LAVA.default_state_id
};
let (block_pos, _) = world.raytrace(start_pos, end_pos, checker).await;
if let Some(pos) = block_pos {
let Ok(_state_id) = world.get_block_state_id(&pos).await else {
return;
};
world
.set_block_state(&pos, Block::AIR.id, BlockFlags::NOTIFY_NEIGHBORS)
.await;
//TODO: Pickup in inv
}
}
}
#[async_trait]
impl PumpkinItem for FilledBucketItem {
async fn normal_use(&self, item: &Item, player: &Player) {
if item.id == Item::MILK_BUCKET.id {
// TODO implement milk bucket
return;
}
let world = player.world().await.clone();
let (start_pos, end_pos) = get_start_and_end_pos(player);
let checker = async |pos: &BlockPos, world_inner: &Arc<World>| {
let Ok(state_id) = world_inner.get_block_state_id(pos).await else {
return false;
};
if Fluid::from_state_id(state_id).is_some() {
return false;
}
state_id != Block::AIR.id
};
let (block_pos, block_direction) = world.raytrace(start_pos, end_pos, checker).await;
if let (Some(pos), Some(direction)) = (block_pos, block_direction) {
world
.set_block_state(
&pos.offset(direction.to_offset()),
// Block::WATER.default_state_id,
if item.id == Item::WATER_BUCKET.id {
Block::WATER.default_state_id
} else {
Block::LAVA.default_state_id
},
BlockFlags::NOTIFY_NEIGHBORS,
)
.await;
if player.gamemode.load() != GameMode::Creative {
//TODO: Pickup in inv
}
}
}
}