use serde::Deserialize;
use serde_json::json;
use yog_ids::client_op as op;
use super::op::ask;
#[derive(Deserialize, Debug, Clone, PartialEq)]
pub struct Found {
pub x: i32,
pub y: i32,
pub z: i32,
pub id: String,
}
pub fn scan(min: [i32; 3], max: [i32; 3], ids: &[&str]) -> Vec<Found> {
ask(op::SCAN, json!({ "min": min, "max": max, "ids": ids })).unwrap_or_default()
}
#[derive(Deserialize, Debug, Clone, PartialEq)]
pub struct Kind {
pub id: String,
pub solid: bool,
pub liquid: bool,
pub climbable: bool,
pub harmful: bool,
}
#[derive(Deserialize, Debug, Clone, PartialEq)]
pub struct Area {
pub min: [i32; 3],
pub max: [i32; 3],
pub palette: Vec<Kind>,
pub blocks: Vec<u16>,
}
impl Area {
pub fn at(&self, pos: [i32; 3]) -> Option<&Kind> {
let [w, _, d] = [self.max[0] - self.min[0] + 1, 0, self.max[2] - self.min[2] + 1];
let [x, y, z] = [pos[0] - self.min[0], pos[1] - self.min[1], pos[2] - self.min[2]];
let inside = (0..w).contains(&x) && (0..d).contains(&z) && (0..=self.max[1] - self.min[1]).contains(&y);
inside.then(|| self.blocks.get(((y * d + z) * w + x) as usize)).flatten().and_then(|i| self.palette.get(*i as usize))
}
}
pub fn area(min: [i32; 3], max: [i32; 3]) -> Option<Area> {
ask(op::AREA, json!({ "min": min, "max": max }))
}
#[derive(Deserialize, Debug, Clone, PartialEq)]
pub struct Entity {
pub uuid: String,
#[serde(rename = "type")]
pub kind: String,
pub x: f64,
pub y: f64,
pub z: f64,
pub eye_height: f64,
#[serde(default)]
pub vx: f64,
#[serde(default)]
pub vy: f64,
#[serde(default)]
pub vz: f64,
pub health: Option<f32>,
pub name: Option<String>,
pub hostile: bool,
}
pub fn entities(radius: f64) -> Vec<Entity> {
ask(op::ENTITIES, json!({ "radius": radius })).unwrap_or_default()
}