Skip to main content

steel_core/behavior/
item_utils.rs

1//! Helpers shared by item behavior implementations.
2
3use steel_registry::item_stack::ItemStack;
4use steel_registry::items::item::BlockHitResult;
5
6use crate::behavior::UseItemContext;
7use crate::inventory::lock::ContainerId;
8use crate::player::Player;
9use crate::player::player_inventory::PlayerInventory;
10use crate::world::{ClipBlockShape, ClipFluid, World};
11
12/// Vanilla `Item.getPlayerPOVHitResult`.
13#[must_use]
14pub(crate) fn get_player_pov_hit_result(
15    world: &World,
16    player: &Player,
17    fluid: ClipFluid,
18) -> BlockHitResult {
19    let (from, to) = player.get_ray_endpoints();
20    let hit = world.clip(from, to, ClipBlockShape::Outline, fluid);
21    BlockHitResult {
22        location: hit.location,
23        direction: hit.direction,
24        block_pos: hit.block_pos,
25        miss: hit.miss,
26        inside: hit.inside,
27        world_border_hit: hit.world_border_hit,
28    }
29}
30
31/// Applies vanilla `ItemUtils.createFilledResult`.
32pub(crate) fn create_filled_result(
33    context: &UseItemContext,
34    result_stack: ItemStack,
35    limit_creative_stack_size: bool,
36) {
37    let player = context.player;
38    let overflow = context.inv.with_guard(|guard| {
39        let inv_id = ContainerId::from_arc(&player.inventory);
40        let Some(inv) = guard.get_typed_mut::<PlayerInventory>(inv_id) else {
41            return result_stack;
42        };
43
44        inv.apply_filled_result(
45            context.hand,
46            result_stack,
47            player.has_infinite_materials(),
48            limit_creative_stack_size,
49        )
50    });
51
52    if !overflow.is_empty() {
53        let _ = player.drop_item(overflow, false, false);
54    }
55}