switched to SwarmBot's schematic parser
This commit is contained in:
parent
70c096b6c7
commit
c49f5735ec
4 changed files with 39 additions and 58 deletions
|
@ -1,41 +1,30 @@
|
|||
use std::{sync::{atomic::{AtomicBool, AtomicUsize, Ordering, AtomicI32}, Arc}, borrow::Cow};
|
||||
|
||||
use rustmatica::{Region, Litematic, BlockState, util::UVec3};
|
||||
use anyhow::{Context, Ok};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use swarmbot_interfaces::types::BlockState;
|
||||
use tokio::task::AbortHandle;
|
||||
use tracing::{error, info, trace};
|
||||
use typetag::serde;
|
||||
|
||||
use crate::{blocks::{Vec3, Position, World, Block, SharedWorld, Direction}, mine::{ChunkedTask, fill}, turtle::{TurtleCommander, TurtleCommandResponse, TurtleCommand}, tasks::{Task, TaskState}};
|
||||
use crate::{blocks::{Vec3, Position, World, Block, SharedWorld, Direction}, mine::{ChunkedTask, fill}, turtle::{TurtleCommander, TurtleCommandResponse, TurtleCommand}, tasks::{Task, TaskState}, vendored::schematic::Schematic};
|
||||
|
||||
fn region2world<'a>(region: &'a Region) -> World {
|
||||
fn schematic2world(region: &Schematic) -> anyhow::Result<World> {
|
||||
let mut world = World::new();
|
||||
let min = Vec3::new(
|
||||
region.min_x() as i32,
|
||||
region.min_y() as i32,
|
||||
region.min_z() as i32,
|
||||
);
|
||||
|
||||
let max = Vec3::new(
|
||||
region.max_x() as i32 + 1,
|
||||
region.max_y() as i32 + 1,
|
||||
region.max_z() as i32 + 1,
|
||||
let min = region.origin().context("bad schematic")?;
|
||||
let area = Vec3::new(
|
||||
region.width() as i32,
|
||||
region.height() as i32,
|
||||
region.length() as i32,
|
||||
);
|
||||
|
||||
let area = max - min;
|
||||
info!("area {}", area);
|
||||
|
||||
// region.blocks() is broken (or how I was using it), which cost me quite some time TODO: make a pr
|
||||
|
||||
for position in (0..area.product()).map(|n| fill(area, n)) {
|
||||
let block = UVec3::new(position.x as usize, position.y as usize, position.z as usize);
|
||||
let block = region.get_block(block);
|
||||
|
||||
for (position, block) in region.blocks() {
|
||||
println!("{:#?}, {}", block, position);
|
||||
|
||||
let name = match block {
|
||||
BlockState::Air => None,
|
||||
BlockState::Stone => Some("minecraft:stone"),
|
||||
BlockState::AIR => None,
|
||||
// who cares
|
||||
_ => Some("terrestria:hemlock_planks")
|
||||
}.map(|s| s.to_string());
|
||||
|
@ -50,7 +39,7 @@ fn region2world<'a>(region: &'a Region) -> World {
|
|||
}
|
||||
}
|
||||
|
||||
world
|
||||
Ok(world)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize,Clone)]
|
||||
|
@ -68,16 +57,16 @@ pub struct BuildSimple {
|
|||
}
|
||||
|
||||
impl BuildSimple {
|
||||
pub fn new<'a>(position: Vec3, schematic: &'a Region, input: Position) -> Self {
|
||||
pub fn new(position: Vec3, schematic: &Schematic, input: Position) -> Self {
|
||||
let size = Vec3::new(
|
||||
(1 + schematic.max_x() - schematic.min_x()) as i32,
|
||||
(1 + schematic.max_y() - schematic.min_y()) as i32,
|
||||
(1 + schematic.max_z() - schematic.min_z()) as i32,
|
||||
schematic.width() as i32,
|
||||
schematic.height() as i32,
|
||||
schematic.length() as i32,
|
||||
);
|
||||
Self {
|
||||
pos: position,
|
||||
size,
|
||||
region: Some(SharedWorld::from_world(region2world(schematic))),
|
||||
region: Some(SharedWorld::from_world(schematic2world(schematic).unwrap())),
|
||||
input,
|
||||
miners: Default::default(),
|
||||
progress: Default::default(),
|
||||
|
|
|
@ -2,12 +2,13 @@ use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
|
|||
|
||||
use anyhow::{Ok, Context, anyhow, Result};
|
||||
use axum::{Router, routing::post, extract::State, Json};
|
||||
use hyper::body::Buf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::task::AbortHandle;
|
||||
use tracing::{info, error};
|
||||
use typetag::serde;
|
||||
|
||||
use crate::{SharedControl, mine::{Remove, ChunkedTask, Quarry}, blocks::{Vec3, Direction, Position}, tasks::{TaskState, Task}, turtle::TurtleCommander, construct::BuildSimple};
|
||||
use crate::{SharedControl, mine::{Remove, ChunkedTask, Quarry}, blocks::{Vec3, Direction, Position}, tasks::{TaskState, Task}, turtle::TurtleCommander, construct::BuildSimple, vendored::schematic::Schematic};
|
||||
|
||||
pub fn forms_api() -> Router<SharedControl> {
|
||||
Router::new()
|
||||
|
@ -106,14 +107,7 @@ async fn omni_inner(state: SharedControl, req: GoogleOmniForm) -> anyhow::Result
|
|||
match req.operation {
|
||||
GoogleOmniFormMode::Schematic => {
|
||||
let schematic = req.schematic.context("no schematic uploaded")?.get(0).context("zero schematics")?.to_owned();
|
||||
let schematic = reqwest::get(format!("https://docs.google.com/uc?export=download&id={schematic}")).await?;
|
||||
|
||||
let schematic = rustmatica::Litematic::from_bytes(&schematic.bytes().await?)?;
|
||||
|
||||
|
||||
info!("schematic \"{}\" downloaded", &schematic.name);
|
||||
info!("{} blocks", schematic.total_blocks());
|
||||
info!("{} regions", schematic.regions.len());
|
||||
let schematic = reqwest::get(format!("https://docs.google.com/uc?export=download&id={schematic}")).await?.bytes().await?;
|
||||
|
||||
let input = Position::new(
|
||||
Vec3::new(53,73,77),
|
||||
|
@ -122,9 +116,9 @@ async fn omni_inner(state: SharedControl, req: GoogleOmniForm) -> anyhow::Result
|
|||
|
||||
// this converts to my memory representation so it can take a while
|
||||
let builder = tokio::task::spawn_blocking(move || {
|
||||
let region = schematic.regions.get(0).context("no regions");
|
||||
Ok(BuildSimple::new(position, region?, input))
|
||||
}).await??;
|
||||
let schematic = Schematic::load(&mut schematic.reader()).unwrap();
|
||||
BuildSimple::new(position, &schematic, input)
|
||||
}).await.unwrap();
|
||||
|
||||
schedule.add_task(Box::new(builder));
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::turtle::IDLE_TIME;
|
|||
use crate::turtle::TurtleCommandResponse;
|
||||
use crate::turtle::TurtleCommander;
|
||||
use crate::turtle::TurtleInfo;
|
||||
use crate::vendored::schematic::Schematic;
|
||||
use axum::extract::Path;
|
||||
use crate::turtle::TurtleCommand;
|
||||
use crate::names::Name;
|
||||
|
@ -295,12 +296,7 @@ pub(crate) async fn build(
|
|||
) -> &'static str {
|
||||
let state = state.read().await;
|
||||
let mut schedule = state.tasks.lock().await;
|
||||
let schematic = rustmatica::Litematic::read_file("Tree.litematic").unwrap();
|
||||
|
||||
|
||||
info!("schematic \"{}\" downloaded", &schematic.name);
|
||||
info!("{} blocks", schematic.total_blocks());
|
||||
info!("{} regions", schematic.regions.len());
|
||||
let schematic = Schematic::load(&mut fs::File::open("thethinkman.schematic").await.unwrap().into_std().await).unwrap();
|
||||
|
||||
let input = Position::new(
|
||||
Vec3::new(53,73,77),
|
||||
|
@ -309,8 +305,7 @@ pub(crate) async fn build(
|
|||
|
||||
// this converts to my memory representation so it can take a while
|
||||
let builder = tokio::task::spawn_blocking(move || {
|
||||
let region = schematic.regions.get(0);
|
||||
BuildSimple::new(req, region.unwrap(), input)
|
||||
BuildSimple::new(req, &schematic, input)
|
||||
}).await.unwrap();
|
||||
|
||||
schedule.add_task(Box::new(builder));
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use std::io::Read;
|
||||
|
||||
use anyhow::Context;
|
||||
use swarmbot_interfaces::types::{BlockLocation, BlockState};
|
||||
use swarmbot_interfaces::types::BlockState;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::blocks::Vec3;
|
||||
|
||||
/// The `WorldEdit` schematic format
|
||||
/// <https://minecraft.fandom.com/wiki/Schematic_file_format>
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -45,17 +47,17 @@ impl Schematic {
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn origin(&self) -> Option<BlockLocation> {
|
||||
pub fn origin(&self) -> Option<Vec3> {
|
||||
match (self.w_e_origin_x, self.w_e_origin_y, self.w_e_origin_z) {
|
||||
(Some(x), Some(y), Some(z)) => Some(BlockLocation::new(x, y as i16, z)),
|
||||
(Some(x), Some(y), Some(z)) => Some(Vec3::new(x, y, z)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn offset(&self) -> Option<BlockLocation> {
|
||||
pub fn offset(&self) -> Option<Vec3> {
|
||||
match (self.w_e_offset_x, self.w_e_offset_y, self.w_e_offset_z) {
|
||||
(Some(x), Some(y), Some(z)) => Some(BlockLocation::new(x, y as i16, z)),
|
||||
(Some(x), Some(y), Some(z)) => Some(Vec3::new(x, y, z)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +78,7 @@ impl Schematic {
|
|||
}
|
||||
|
||||
#[allow(unused, clippy::unwrap_used, clippy::indexing_slicing)]
|
||||
pub fn blocks(&self) -> impl Iterator<Item = (BlockLocation, BlockState)> + '_ {
|
||||
pub fn blocks(&self) -> impl Iterator<Item = (Vec3, BlockState)> + '_ {
|
||||
let origin = self.origin().unwrap_or_default();
|
||||
|
||||
(0..self.volume()).map(move |idx| {
|
||||
|
@ -87,7 +89,7 @@ impl Schematic {
|
|||
|
||||
let y = leftover / self.length();
|
||||
|
||||
let location = BlockLocation::new(x as i32, y as i16, z as i32) + origin;
|
||||
let location = Vec3::new(x as i32, y as i32, z as i32) + origin;
|
||||
|
||||
let id = self.blocks[idx as usize].abs_diff(0);
|
||||
let data = self.data[idx as usize].abs_diff(0);
|
||||
|
@ -102,9 +104,10 @@ impl Schematic {
|
|||
mod tests {
|
||||
use std::{collections::HashMap, fs::OpenOptions};
|
||||
|
||||
use swarmbot_interfaces::types::BlockLocation;
|
||||
use more_asserts::*;
|
||||
|
||||
use crate::blocks::Vec3;
|
||||
|
||||
use super::Schematic;
|
||||
|
||||
#[test]
|
||||
|
@ -126,14 +129,14 @@ mod tests {
|
|||
assert_lt!(loc.x, origin.x + schematic.width as i32);
|
||||
|
||||
assert_ge!(loc.y, origin.y);
|
||||
assert_lt!(loc.y, origin.y + schematic.height);
|
||||
assert_lt!(loc.y, origin.y + schematic.height as i32);
|
||||
|
||||
assert_ge!(loc.z, origin.z);
|
||||
assert_lt!(loc.z, origin.z + schematic.length as i32);
|
||||
map.insert(loc, state);
|
||||
}
|
||||
|
||||
let stained_glass = map[&BlockLocation::new(-162, 81, -357)];
|
||||
let stained_glass = map[&Vec3::new(-162, 81, -357)];
|
||||
assert_eq!(stained_glass.id(), 95);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue