1use serde::Deserialize;
5use serde_json::json;
6use yog_ids::client_op as op;
7
8use super::op::ask;
9
10#[derive(Deserialize, Debug, Clone, PartialEq)]
12pub struct Found {
13 pub x: i32,
14 pub y: i32,
15 pub z: i32,
16 pub id: String,
17}
18
19pub fn scan(min: [i32; 3], max: [i32; 3], ids: &[&str]) -> Vec<Found> {
21 ask(op::SCAN, json!({ "min": min, "max": max, "ids": ids })).unwrap_or_default()
22}
23
24#[derive(Deserialize, Debug, Clone, PartialEq)]
26pub struct Kind {
27 pub id: String,
28 pub solid: bool,
30 pub liquid: bool,
31 pub climbable: bool,
33 pub harmful: bool,
35}
36
37#[derive(Deserialize, Debug, Clone, PartialEq)]
39pub struct Area {
40 pub min: [i32; 3],
41 pub max: [i32; 3],
42 pub palette: Vec<Kind>,
43 pub blocks: Vec<u16>,
44}
45
46impl Area {
47 pub fn at(&self, pos: [i32; 3]) -> Option<&Kind> {
49 let [w, _, d] = [self.max[0] - self.min[0] + 1, 0, self.max[2] - self.min[2] + 1];
50 let [x, y, z] = [pos[0] - self.min[0], pos[1] - self.min[1], pos[2] - self.min[2]];
51 let inside = (0..w).contains(&x) && (0..d).contains(&z) && (0..=self.max[1] - self.min[1]).contains(&y);
52 inside.then(|| self.blocks.get(((y * d + z) * w + x) as usize)).flatten().and_then(|i| self.palette.get(*i as usize))
53 }
54}
55
56pub fn area(min: [i32; 3], max: [i32; 3]) -> Option<Area> {
58 ask(op::AREA, json!({ "min": min, "max": max }))
59}
60
61#[derive(Deserialize, Debug, Clone, PartialEq)]
63pub struct Entity {
64 pub uuid: String,
65 #[serde(rename = "type")]
66 pub kind: String,
67 pub x: f64,
68 pub y: f64,
69 pub z: f64,
70 pub eye_height: f64,
71 #[serde(default)]
73 pub vx: f64,
74 #[serde(default)]
75 pub vy: f64,
76 #[serde(default)]
77 pub vz: f64,
78 pub health: Option<f32>,
79 pub name: Option<String>,
81 pub hostile: bool,
83}
84
85pub fn entities(radius: f64) -> Vec<Entity> {
87 ask(op::ENTITIES, json!({ "radius": radius })).unwrap_or_default()
88}
89