diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index 697ddc6..313ea22 100644 --- a/schemsearch-cli/src/main.rs +++ b/schemsearch-cli/src/main.rs @@ -39,7 +39,7 @@ use schemsearch_sql::load_all_schematics; #[cfg(feature = "sql")] use crate::types::SqlSchematicSupplier; use indicatif::*; -use schemsearch_files::{SchematicVersioned}; +use schemsearch_files::SpongeSchematic; use crate::sinks::{OutputFormat, OutputSink}; use crate::stderr::MaschineStdErr; @@ -206,7 +206,7 @@ fn main() { threshold: *matches.get_one::("threshold").expect("Couldn't get threshold"), }; - let pattern = match SchematicVersioned::load(&PathBuf::from(matches.get_one::("pattern").unwrap())) { + let pattern = match SpongeSchematic::load(&PathBuf::from(matches.get_one::("pattern").unwrap())) { Ok(x) => x, Err(e) => { cmd.error(ErrorKind::Io, format!("Error while loading Pattern: {}", e.to_string())).exit(); @@ -334,8 +334,8 @@ fn main() { } } -fn load_schem(schem_path: &PathBuf) -> Option { - match SchematicVersioned::load(schem_path) { +fn load_schem(schem_path: &PathBuf) -> Option { + match SpongeSchematic::load(schem_path) { Ok(x) => Some(x), Err(e) => { println!("Error while loading schematic ({}): {}", schem_path.to_str().unwrap(), e.to_string()); diff --git a/schemsearch-cli/src/types.rs b/schemsearch-cli/src/types.rs index e0b6129..ba9a93e 100644 --- a/schemsearch-cli/src/types.rs +++ b/schemsearch-cli/src/types.rs @@ -15,11 +15,13 @@ * along with this program. If not, see . */ +#[cfg(feature = "sql")] use std::io::Cursor; use std::path::PathBuf; #[cfg(feature = "sql")] use futures::executor::block_on; -use schemsearch_files::SchematicVersioned; +#[cfg(feature = "sql")] +use schemsearch_files::SpongeSchematic; #[cfg(feature = "sql")] use schemsearch_sql::{load_schemdata, SchematicNode}; @@ -46,9 +48,9 @@ pub struct SqlSchematicSupplier { #[cfg(feature = "sql")] impl SqlSchematicSupplier { - pub fn get_schematic(&self) -> Result { + pub fn get_schematic(&self) -> Result { let mut schemdata = block_on(load_schemdata(self.node.id)); - SchematicVersioned::load_data(&mut Cursor::new(schemdata.as_mut_slice())) + SpongeSchematic::load_data(&mut Cursor::new(schemdata.as_mut_slice())) } pub fn get_name(&self) -> String { diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 7ef964f..16fdcb3 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -21,92 +21,7 @@ use std::path::PathBuf; use nbt::{CompoundTag, Tag}; #[derive(Clone, Debug)] -pub enum SchematicVersioned { - V1(SpongeV1Schematic), - V2(SpongeV2Schematic), - V3(SpongeV3Schematic), -} - -impl SchematicVersioned { - #[inline] - pub fn get_width(&self) -> u16 { - return match self { - SchematicVersioned::V1(schematic) => schematic.width, - SchematicVersioned::V2(schematic) => schematic.width, - SchematicVersioned::V3(schematic) => schematic.width, - }; - } - - #[inline] - pub fn get_height(&self) -> u16 { - return match self { - SchematicVersioned::V1(schematic) => schematic.height, - SchematicVersioned::V2(schematic) => schematic.height, - SchematicVersioned::V3(schematic) => schematic.height, - }; - } - - #[inline] - pub fn get_length(&self) -> u16 { - return match self { - SchematicVersioned::V1(schematic) => schematic.length, - SchematicVersioned::V2(schematic) => schematic.length, - SchematicVersioned::V3(schematic) => schematic.length, - }; - } - - #[inline] - pub fn get_palette_max(&self) -> i32 { - return match self { - SchematicVersioned::V1(schematic) => schematic.palette_max, - SchematicVersioned::V2(schematic) => schematic.palette_max, - SchematicVersioned::V3(schematic) => schematic.blocks.palette.len() as i32, - }; - } - - #[inline] - pub fn get_palette(&self) -> &HashMap { - return match self { - SchematicVersioned::V1(schematic) => &schematic.palette, - SchematicVersioned::V2(schematic) => &schematic.palette, - SchematicVersioned::V3(schematic) => &schematic.blocks.palette, - }; - } - - #[inline] - pub fn get_block_data(&self) -> &Vec { - return match self { - SchematicVersioned::V1(schematic) => &schematic.block_data, - SchematicVersioned::V2(schematic) => &schematic.block_data, - SchematicVersioned::V3(schematic) => &schematic.blocks.block_data, - }; - } - - #[inline] - pub fn get_block_entities(&self) -> &Vec { - return match self { - SchematicVersioned::V1(schematic) => &schematic.tile_entities, - SchematicVersioned::V2(schematic) => &schematic.block_entities, - SchematicVersioned::V3(schematic) => &schematic.blocks.block_entities, - }; - } -} - -#[derive(Clone, Debug)] -pub struct SpongeV1Schematic { - pub metadata: CompoundTag, - pub width: u16, - pub height: u16, - pub length: u16, - pub offset: [i32; 3], - pub palette_max: i32, - pub palette: HashMap, - pub block_data: Vec, - pub tile_entities: Vec, -} - -#[derive(Clone, Debug)] -pub struct SpongeV2Schematic { +pub struct SpongeSchematic { pub data_version: i32, pub metadata: CompoundTag, pub width: u16, @@ -120,18 +35,6 @@ pub struct SpongeV2Schematic { pub entities: Option>, } -#[derive(Clone, Debug)] -pub struct SpongeV3Schematic { - pub data_version: i32, - pub metadata: CompoundTag, - pub width: u16, - pub height: u16, - pub length: u16, - pub offset: [i32; 3], - pub blocks: BlockContainer, - pub entities: Option>, -} - #[derive(Clone, Debug)] pub struct BlockContainer { pub palette: HashMap, @@ -158,28 +61,27 @@ pub struct Entity { pub pos: [i32; 3], } -impl SchematicVersioned { - pub fn load_data(data: &mut R) -> Result where R: Read { +impl SpongeSchematic { + pub fn load_data(data: &mut R) -> Result where R: Read { let nbt: CompoundTag = nbt::decode::read_gzip_compound_tag(data).map_err(|e| e.to_string())?; let version = nbt.get_i32("Version").map_err(|e| e.to_string())?; match version { - 1 => Ok(SchematicVersioned::V1(SpongeV1Schematic::from_nbt(nbt)?)), - 2 => Ok(SchematicVersioned::V2(SpongeV2Schematic::from_nbt(nbt)?)), - 3 => Ok(SchematicVersioned::V3(SpongeV3Schematic::from_nbt(nbt)?)), + 1 => SpongeSchematic::from_nbt_1(nbt), + 2 => SpongeSchematic::from_nbt_2(nbt), + 3 => SpongeSchematic::from_nbt_3(nbt), _ => Err("Invalid schematic: Unknown Version".to_string()), } } - pub fn load(path: &PathBuf) -> Result { + pub fn load(path: &PathBuf) -> Result { let mut file = std::fs::File::open(path).map_err(|e| e.to_string())?; Self::load_data(&mut file) } -} -impl SpongeV1Schematic { - pub fn from_nbt(nbt: CompoundTag) -> Result { + pub fn from_nbt_1(nbt: CompoundTag) -> Result { Ok(Self { + data_version: 0, metadata: nbt.get_compound_tag("Metadata").map_err(|e| e.to_string())?.clone(), width: nbt.get_i16("Width").map_err(|e| e.to_string())? as u16, height: nbt.get_i16("Height").map_err(|e| e.to_string())? as u16, @@ -188,13 +90,12 @@ impl SpongeV1Schematic { palette_max: nbt.get_i32("PaletteMax").map_err(|e| e.to_string())?, palette: read_palette(nbt.get_compound_tag("Palette").map_err(|e| e.to_string())?), block_data: read_blocks(nbt.get_i8_vec("BlockData").map_err(|e| e.to_string())?), - tile_entities: read_tile_entities(nbt.get_compound_tag_vec("TileEntities").map_err(|e| e.to_string())?)?, + block_entities: read_tile_entities(nbt.get_compound_tag_vec("TileEntities").map_err(|e| e.to_string())?)?, + entities: None, }) } -} -impl SpongeV2Schematic { - pub fn from_nbt(nbt: CompoundTag) -> Result { + pub fn from_nbt_2(nbt: CompoundTag) -> Result { Ok(Self{ data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?, metadata: nbt.get_compound_tag("Metadata").map_err(|e| e.to_string())?.clone(), @@ -209,10 +110,8 @@ impl SpongeV2Schematic { entities: None, }) } -} -impl SpongeV3Schematic { - pub fn from_nbt(nbt: CompoundTag) -> Result { + pub fn from_nbt_3(nbt: CompoundTag) -> Result { let blocks = nbt.get_compound_tag("Blocks").map_err(|e| e.to_string())?; Ok(Self{ data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?, @@ -221,14 +120,14 @@ impl SpongeV3Schematic { height: nbt.get_i16("Height").map_err(|e| e.to_string())? as u16, length: nbt.get_i16("Length").map_err(|e| e.to_string())? as u16, offset: read_offset(nbt.get_i32_vec("Offset").map_err(|e| e.to_string())?)?, - blocks: BlockContainer { - palette: read_palette(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?), - block_data: read_blocks(blocks.get_i8_vec("BlockData").map_err(|e| e.to_string())?), - block_entities: read_tile_entities(blocks.get_compound_tag_vec("BlockEntities").map_err(|e| e.to_string())?)?, - }, + palette_max: compute_palette_max(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?), + palette: read_palette(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?), + block_data: read_blocks(blocks.get_i8_vec("BlockData").map_err(|e| e.to_string())?), + block_entities: read_tile_entities(blocks.get_compound_tag_vec("BlockEntities").map_err(|e| e.to_string())?)?, entities: None, }) } + } fn read_tile_entities(tag: Vec<&CompoundTag>) -> Result, String> { @@ -262,6 +161,14 @@ fn read_palette(p: &CompoundTag) -> HashMap { palette } +#[inline] +fn compute_palette_max(palette: &CompoundTag) -> i32 { + palette.iter().map(|(_, v)| v).filter_map(|v| match v { + Tag::Int(n) => Some(*n), + _ => None, + }).max().unwrap_or(0) +} + #[inline] fn read_blocks(blockdata: &Vec) -> Vec { read_varint_array(blockdata) diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index ce5d599..660e54c 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -19,7 +19,7 @@ pub mod pattern_mapper; use serde::{Serialize, Deserialize}; use pattern_mapper::match_palette; -use schemsearch_files::SchematicVersioned; +use schemsearch_files::SpongeSchematic; use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] @@ -33,15 +33,15 @@ pub struct SearchBehavior { } pub fn search( - schem: SchematicVersioned, - pattern_schem: &SchematicVersioned, + schem: SpongeSchematic, + pattern_schem: &SpongeSchematic, search_behavior: SearchBehavior, ) -> Vec { - if schem.get_width() < pattern_schem.get_width() || schem.get_height() < pattern_schem.get_height() || schem.get_length() < pattern_schem.get_length() { + if schem.width < pattern_schem.width || schem.height < pattern_schem.height || schem.length < pattern_schem.length { return vec![]; } - if pattern_schem.get_palette().len() > schem.get_palette().len() { + if pattern_schem.palette.len() > schem.palette.len() { return vec![]; } @@ -49,27 +49,27 @@ pub fn search( let mut matches: Vec = Vec::new(); - let pattern_data = pattern_schem.get_block_data().as_slice(); + let pattern_data = pattern_schem.block_data.as_slice(); let schem_data = if search_behavior.ignore_block_data { - match_palette_adapt(&schem, &pattern_schem.get_palette(), search_behavior.ignore_block_data) + match_palette_adapt(&schem, &pattern_schem.palette, search_behavior.ignore_block_data) } else { - schem.get_block_data().clone() + schem.block_data.clone() }; let schem_data = schem_data.as_slice(); - let air_id = if search_behavior.ignore_air || search_behavior.air_as_any { pattern_schem.get_palette().get("minecraft:air").unwrap_or(&-1) } else { &-1}; + let air_id = if search_behavior.ignore_air || search_behavior.air_as_any { pattern_schem.palette.get("minecraft:air").unwrap_or(&-1) } else { &-1}; let pattern_blocks = pattern_data.len() as f32; - let pattern_width = pattern_schem.get_width() as usize; - let pattern_height = pattern_schem.get_height() as usize; - let pattern_length = pattern_schem.get_length() as usize; + let pattern_width = pattern_schem.width as usize; + let pattern_height = pattern_schem.height as usize; + let pattern_length = pattern_schem.length as usize; - let schem_width = schem.get_width() as usize; - let schem_height = schem.get_height() as usize; - let schem_length = schem.get_length() as usize; + let schem_width = schem.width as usize; + let schem_height = schem.height as usize; + let schem_length = schem.length as usize; for y in 0..=schem_height - pattern_height { for z in 0..=schem_length - pattern_length { diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index a74dab5..2950b10 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -17,26 +17,26 @@ use std::collections::HashMap; use nbt::CompoundTag; -use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; +use schemsearch_files::SpongeSchematic; use crate::normalize_data; -fn create_reverse_palette(schem: &SchematicVersioned) -> Vec<&str> { - let mut reverse_palette = Vec::with_capacity(schem.get_palette_max() as usize); - (0..schem.get_palette_max()).for_each(|_| reverse_palette.push("")); - for (key, value) in schem.get_palette().iter() { +fn create_reverse_palette(schem: &SpongeSchematic) -> Vec<&str> { + let mut reverse_palette = Vec::with_capacity(schem.palette_max as usize); + (0..schem.palette_max).for_each(|_| reverse_palette.push("")); + for (key, value) in schem.palette.iter() { reverse_palette[*value as usize] = key; } reverse_palette } -pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { +pub fn strip_data(schem: &SpongeSchematic) -> SpongeSchematic { let mut data: Vec = Vec::new(); let mut palette: HashMap = HashMap::new(); let mut palette_max: i32 = 0; let reverse_palette = create_reverse_palette(schem); - for block in schem.get_block_data().iter() { + for block in schem.block_data.iter() { let block_name = reverse_palette[*block as usize].clone(); let block_name = block_name.split('[').next().unwrap().to_string(); @@ -48,28 +48,28 @@ pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { data.push(*entry); } - SchematicVersioned::V2(SpongeV2Schematic { + SpongeSchematic { data_version: 1, palette, palette_max, block_data: data, - block_entities: schem.get_block_entities().clone(), - height: schem.get_height(), - length: schem.get_length(), - width: schem.get_width(), + block_entities: schem.block_entities.clone(), + height: schem.height, + length: schem.length, + width: schem.width, metadata: CompoundTag::new(), offset: [0; 3], entities: None, - },) + } } -pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &HashMap, ignore_data: bool) -> Vec { +pub fn match_palette_adapt(schem: &SpongeSchematic, matching_palette: &HashMap, ignore_data: bool) -> Vec { let mut data: Vec = Vec::new(); let reverse_palette = create_reverse_palette(schem); - for x in schem.get_block_data() { + for x in schem.block_data.iter() { let blockname = reverse_palette[*x as usize]; let blockname = if ignore_data { normalize_data(blockname, ignore_data) } else { blockname }; let block_id = match matching_palette.get(&*blockname) { @@ -83,10 +83,10 @@ pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &HashMa } pub fn match_palette( - schem: &SchematicVersioned, - pattern: &SchematicVersioned, + schem: &SpongeSchematic, + pattern: &SpongeSchematic, ignore_data: bool, -) -> SchematicVersioned { +) -> SpongeSchematic { if ignore_data { match_palette_internal(&strip_data(schem), &strip_data(pattern), ignore_data) } else { @@ -95,23 +95,23 @@ pub fn match_palette( } fn match_palette_internal( - schem: &SchematicVersioned, - pattern: &SchematicVersioned, + schem: &SpongeSchematic, + pattern: &SpongeSchematic, ignore_data: bool, -) -> SchematicVersioned { - let data_pattern: Vec = match_palette_adapt(&pattern, schem.get_palette(), ignore_data); +) -> SpongeSchematic { + let data_pattern: Vec = match_palette_adapt(&pattern, &schem.palette, ignore_data); - SchematicVersioned::V2(SpongeV2Schematic { + SpongeSchematic { data_version: 0, - palette: schem.get_palette().clone(), - palette_max: schem.get_palette_max(), + palette: schem.palette.clone(), + palette_max: schem.palette_max, block_data: data_pattern, - block_entities: pattern.get_block_entities().clone(), - height: pattern.get_height(), - length: pattern.get_length(), - width: pattern.get_width(), + block_entities: pattern.block_entities.clone(), + height: pattern.height, + length: pattern.length, + width: pattern.width, metadata: CompoundTag::new(), offset: [0; 3], entities: None, - }) + } } \ No newline at end of file