azalea_core/
hit_result.rs

1use crate::{
2    direction::Direction,
3    position::{BlockPos, Vec3},
4};
5
6/// The block or entity that our player is looking at and can interact with.
7///
8/// If there's nothing, it'll be a [`BlockHitResult`] with `miss` set to true.
9#[cfg(feature = "bevy_ecs")]
10#[derive(Debug, Clone, PartialEq)]
11pub enum HitResult {
12    Block(BlockHitResult),
13    Entity(EntityHitResult),
14}
15
16#[cfg(feature = "bevy_ecs")]
17impl HitResult {
18    pub fn miss(&self) -> bool {
19        match self {
20            HitResult::Block(r) => r.miss,
21            _ => false,
22        }
23    }
24    pub fn location(&self) -> Vec3 {
25        match self {
26            HitResult::Block(r) => r.location,
27            HitResult::Entity(r) => r.location,
28        }
29    }
30
31    pub fn new_miss(location: Vec3, direction: Direction, block_pos: BlockPos) -> Self {
32        HitResult::Block(BlockHitResult {
33            location,
34            miss: true,
35            direction,
36            block_pos,
37            inside: false,
38            world_border: false,
39        })
40    }
41
42    pub fn is_block_hit_and_not_miss(&self) -> bool {
43        matches!(self, HitResult::Block(r) if !r.miss)
44    }
45
46    /// Returns the [`BlockHitResult`], if we were looking at a block and it
47    /// wasn't a miss.
48    pub fn as_block_hit_result_if_not_miss(&self) -> Option<&BlockHitResult> {
49        if let HitResult::Block(r) = self
50            && !r.miss
51        {
52            Some(r)
53        } else {
54            None
55        }
56    }
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub struct BlockHitResult {
61    pub location: Vec3,
62    pub miss: bool,
63
64    pub direction: Direction,
65    pub block_pos: BlockPos,
66    pub inside: bool,
67    pub world_border: bool,
68}
69impl BlockHitResult {
70    pub fn miss(location: Vec3, direction: Direction, block_pos: BlockPos) -> Self {
71        Self {
72            location,
73            miss: true,
74
75            direction,
76            block_pos,
77            inside: false,
78            world_border: false,
79        }
80    }
81
82    pub fn with_direction(&self, direction: Direction) -> Self {
83        Self { direction, ..*self }
84    }
85    pub fn with_position(&self, block_pos: BlockPos) -> Self {
86        Self { block_pos, ..*self }
87    }
88}
89#[cfg(feature = "bevy_ecs")]
90impl From<BlockHitResult> for HitResult {
91    fn from(value: BlockHitResult) -> Self {
92        HitResult::Block(value)
93    }
94}
95
96#[cfg(feature = "bevy_ecs")]
97#[derive(Debug, Clone, PartialEq)]
98pub struct EntityHitResult {
99    pub location: Vec3,
100    pub entity: bevy_ecs::entity::Entity,
101}
102
103#[cfg(feature = "bevy_ecs")]
104impl From<EntityHitResult> for HitResult {
105    fn from(value: EntityHitResult) -> Self {
106        HitResult::Entity(value)
107    }
108}