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.
47    pub fn as_block_hit_result_if_not_miss(&self) -> Option<&BlockHitResult> {
48        if let HitResult::Block(r) = self
49            && !r.miss
50        {
51            Some(r)
52        } else {
53            None
54        }
55    }
56
57    /// Returns the [`EntityHitResult`], if we were looking at an entity and it
58    /// wasn't a miss.
59    pub fn as_entity_hit_result(&self) -> Option<&EntityHitResult> {
60        if let HitResult::Entity(r) = self {
61            Some(r)
62        } else {
63            None
64        }
65    }
66}
67
68#[derive(Debug, Clone, PartialEq)]
69pub struct BlockHitResult {
70    pub location: Vec3,
71    pub miss: bool,
72
73    pub direction: Direction,
74    pub block_pos: BlockPos,
75    pub inside: bool,
76    pub world_border: bool,
77}
78impl BlockHitResult {
79    pub fn miss(location: Vec3, direction: Direction, block_pos: BlockPos) -> Self {
80        Self {
81            location,
82            miss: true,
83
84            direction,
85            block_pos,
86            inside: false,
87            world_border: false,
88        }
89    }
90
91    pub fn with_direction(&self, direction: Direction) -> Self {
92        Self { direction, ..*self }
93    }
94    pub fn with_position(&self, block_pos: BlockPos) -> Self {
95        Self { block_pos, ..*self }
96    }
97}
98#[cfg(feature = "bevy_ecs")]
99impl From<BlockHitResult> for HitResult {
100    fn from(value: BlockHitResult) -> Self {
101        HitResult::Block(value)
102    }
103}
104
105#[cfg(feature = "bevy_ecs")]
106#[derive(Debug, Clone, PartialEq)]
107pub struct EntityHitResult {
108    pub location: Vec3,
109    pub entity: bevy_ecs::entity::Entity,
110}
111
112#[cfg(feature = "bevy_ecs")]
113impl From<EntityHitResult> for HitResult {
114    fn from(value: EntityHitResult) -> Self {
115        HitResult::Entity(value)
116    }
117}