use std::convert::Infallible;
use ndarray::{Array, Ix3};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{
client::{DeviceBase, HlapiClient, HlapiClientError},
devices::robot::RobotSide,
messages::BlobMarker,
};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct InspectResult {
pub block: Option<String>,
pub fluid: Option<String>,
pub entities: Vec<String>,
}
#[derive(Deserialize, Debug, Clone)]
struct ScanResultRaw {
hardness: BlobMarker,
entities: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct ScanResult {
pub hardness: Array<u8, Ix3>,
pub entities: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct Scanner {
client: HlapiClient,
uuid: Uuid,
}
impl Scanner {
pub fn can_see_sky(&self) -> Result<bool, HlapiClientError> {
Ok(self.call("canSeeSky", &[], &[])?.0)
}
pub fn inspect(&self, side: RobotSide) -> Result<InspectResult, HlapiClientError> {
Ok(self.call("inspect", &[&side as _], &[])?.0)
}
pub fn scan(&self) -> Result<ScanResult, HlapiClientError> {
let (raw_result, blobs): (ScanResultRaw, _) = self.call("scan", &[], &[])?;
let hardness_bytes = blobs
.get(raw_result.hardness.blob_idx as usize)
.ok_or(HlapiClientError::UnexpectedResponseType)?;
if hardness_bytes.len() != 7 * 7 * 7 {
return Err(HlapiClientError::UnexpectedResponseType);
}
let hardness =
Array::from_shape_fn((7, 7, 7), |(y, z, x)| hardness_bytes[y * 7 * 7 + z * 7 + x]);
Ok(ScanResult {
hardness,
entities: raw_result.entities,
})
}
}
impl DeviceBase for Scanner {
const TYPE: &'static str = "scanner";
type Event = Infallible;
fn new(client: HlapiClient, uuid: Uuid) -> Result<Self, HlapiClientError> {
Ok(Self { client, uuid })
}
fn uuid_base(&self) -> Uuid {
self.uuid
}
fn client(&self) -> &HlapiClient {
&self.client
}
}