1use yog_data::{Atom, Schema};
5
6use crate::{BlockPos, Point};
7
8#[derive(Debug, Clone, PartialEq, Schema)]
10#[data(view)]
11pub struct LocalState {
12 pub pos: Point,
13 pub yaw: f32,
15 pub pitch: f32,
16 pub velocity: Point,
18 pub on_ground: bool,
19 pub in_water: bool,
20 pub eye_height: f64,
21 pub health: f32,
22 pub food: i32,
23 pub dimension: Atom,
24 pub slot: u32,
26 pub attack_strength: f32,
28}
29
30impl LocalState {
31 pub fn eye_pos(&self) -> Point {
33 Point {
34 y: self.pos.y + self.eye_height,
35 ..self.pos
36 }
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Schema)]
42#[data(view)]
43pub struct BlockKind {
44 pub id: Atom,
45 pub solid: bool,
47 pub liquid: bool,
48 pub climbable: bool,
50 pub harmful: bool,
52}
53
54#[derive(Debug, Clone, PartialEq, Schema)]
58#[data(view)]
59pub struct BlockArea {
60 pub min: BlockPos,
61 pub max: BlockPos,
62 pub palette: Vec<BlockKind>,
63 pub blocks: Vec<u16>,
64}
65
66impl BlockArea {
67 pub fn at(&self, pos: BlockPos) -> Option<&BlockKind> {
69 let (w, d) = (self.max.x - self.min.x + 1, self.max.z - self.min.z + 1);
70 let (x, y, z) = (pos.x - self.min.x, pos.y - self.min.y, pos.z - self.min.z);
71 let inside = (0..w).contains(&x)
72 && (0..d).contains(&z)
73 && (0..=self.max.y - self.min.y).contains(&y);
74 let index = inside
75 .then(|| self.blocks.get(((y * d + z) * w + x) as usize))
76 .flatten()?;
77 self.palette.get(usize::from(*index))
78 }
79}
80
81#[derive(Debug, Clone, PartialEq, Schema)]
83#[data(view)]
84pub struct NearbyEntity {
85 pub uuid: String,
86 pub entity_type: Atom,
87 pub pos: Point,
88 pub eye_height: f64,
89 pub velocity: Point,
91 pub health: Option<f32>,
92 pub name: Option<String>,
94 pub hostile: bool,
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Schema)]
100pub enum ClickMode {
101 Pickup,
102 QuickMove,
103 Swap,
104 Clone,
105 Throw,
106 QuickCraft,
107 PickupAll,
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn an_area_finds_its_blocks() {
116 let kind = |id: &str| BlockKind {
117 id: id.into(),
118 solid: true,
119 liquid: false,
120 climbable: false,
121 harmful: false,
122 };
123 let area = BlockArea {
124 min: BlockPos::new(0, 0, 0),
125 max: BlockPos::new(1, 1, 0),
126 palette: vec![kind("a"), kind("b")],
127 blocks: vec![0, 1, 1, 0],
128 };
129 assert_eq!(
130 area.at(BlockPos::new(1, 0, 0)).map(|k| k.id.as_str()),
131 Some("b")
132 );
133 assert_eq!(
134 area.at(BlockPos::new(0, 1, 0)).map(|k| k.id.as_str()),
135 Some("b")
136 );
137 assert_eq!(area.at(BlockPos::new(2, 0, 0)), None);
138 }
139}