diff --git a/README.md b/README.md index 0f6141e..4987fb3 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ schemsearch-cli --help ## Roadmap A list of features that are planned to be implemented in the future. In order of priority. -- [ ] Full JSON output (Progressbar) - [ ] Use AVX2 for faster search - [ ] Tile entities data search - [ ] Entities search diff --git a/schemsearch-cli/Cargo.toml b/schemsearch-cli/Cargo.toml index 85a7786..45abc9f 100644 --- a/schemsearch-cli/Cargo.toml +++ b/schemsearch-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "schemsearch-cli" -version = "0.1.2" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later" diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index dc86ff5..697ddc6 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::Schematic; +use schemsearch_files::{SchematicVersioned}; 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 Schematic::load(&PathBuf::from(matches.get_one::("pattern").unwrap())) { + let pattern = match SchematicVersioned::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 Schematic::load(schem_path) { +fn load_schem(schem_path: &PathBuf) -> Option { + match SchematicVersioned::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 5dc7ca5..a6a1d37 100644 --- a/schemsearch-cli/src/types.rs +++ b/schemsearch-cli/src/types.rs @@ -19,7 +19,7 @@ use std::path::PathBuf; #[cfg(feature = "sql")] use futures::executor::block_on; #[allow(unused_imports)] -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; #[cfg(feature = "sql")] use schemsearch_sql::{load_schemdata, SchematicNode}; @@ -46,9 +46,9 @@ pub struct SqlSchematicSupplier { #[cfg(feature = "sql")] impl SqlSchematicSupplier { - pub fn get_schematic(&self) -> Result { + pub fn get_schematic(&self) -> Result { let schemdata = block_on(load_schemdata(self.node.id)); - Schematic::load_data(schemdata.as_slice()) + SchematicVersioned::load_data(schemdata.as_slice()) } pub fn get_name(&self) -> String { diff --git a/schemsearch-faster/Cargo.toml b/schemsearch-faster/Cargo.toml index f073e1c..4808577 100644 --- a/schemsearch-faster/Cargo.toml +++ b/schemsearch-faster/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "schemsearch_faster" -version = "0.1.1" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later" diff --git a/schemsearch-faster/src/lib.rs b/schemsearch-faster/src/lib.rs index bc386b0..a6ffa93 100644 --- a/schemsearch-faster/src/lib.rs +++ b/schemsearch-faster/src/lib.rs @@ -16,9 +16,9 @@ */ use nbt::Map; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; -pub fn convert_to_search_space(schem: &Schematic, palette: &Vec) -> Vec> { +pub fn convert_to_search_space(schem: &SpongeV2Schematic, palette: &Vec) -> Vec> { let mut data: Vec> = Vec::with_capacity(palette.len()); let block_data = &schem.block_data; for name in palette { @@ -48,26 +48,26 @@ pub fn unwrap_palette(palette: &Map) -> Vec { #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; - use schemsearch_files::Schematic; + use schemsearch_files::SpongeV2Schematic; use crate::{convert_to_search_space, unwrap_palette}; //#[test] pub fn test() { - let schematic = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); dbg!(convert_to_search_space(&schematic, &unwrap_palette(&schematic.palette))); } //#[test] pub fn test_2() { - let schematic = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); - let schematic2 = Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic2 = SpongeV2Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); println!("{:?}", convert_to_search_space(&schematic2, &unwrap_palette(&schematic.palette))); } //#[test] pub fn test_big() { - let schematic = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); - let schematic2 = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic2 = SpongeV2Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let _ = convert_to_search_space(&schematic2, &unwrap_palette(&schematic.palette)); } } \ No newline at end of file diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 368fc4f..0b65862 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "schemsearch-files" -version = "0.1.2" +version = "0.1.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hematite-nbt = "0.5.2" -serde = "1.0.152" +flate2 = "1.0.25" +named-binary-tag = "0.6" + diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index b900f74..7ef964f 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -15,81 +15,259 @@ * along with this program. If not, see . */ +use std::collections::hash_map::HashMap; use std::io::Read; use std::path::PathBuf; -use nbt::{Map, Value}; -use serde::{Deserialize, Deserializer, Serialize}; +use nbt::{CompoundTag, Tag}; -#[derive(Serialize, Deserialize, Debug)] -pub struct Schematic { - #[serde(rename = "Version")] - pub version: i32, - #[serde(rename = "DataVersion")] - pub data_version: i32, - #[serde(rename = "Metadata")] - pub metadata: Map, - #[serde(rename = "Width")] +#[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, - #[serde(rename = "Height")] pub height: u16, - #[serde(rename = "Length")] pub length: u16, - #[serde(rename = "Offset")] pub offset: [i32; 3], - #[serde(rename = "PaletteMax")] pub palette_max: i32, - #[serde(rename = "Palette")] - pub palette: Map, - #[serde(rename = "BlockData", deserialize_with = "read_blockdata")] + pub palette: HashMap, + pub block_data: Vec, + pub tile_entities: Vec, +} + +#[derive(Clone, Debug)] +pub struct SpongeV2Schematic { + pub data_version: i32, + 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, - #[serde(rename = "BlockEntities")] pub block_entities: Vec, - #[serde(rename = "Entities")] pub entities: Option>, } -fn read_blockdata<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, -{ - let s: Vec = Deserialize::deserialize(deserializer)?; - Ok(read_varint_array(&s)) +#[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(Serialize, Deserialize, Debug, Clone)] +#[derive(Clone, Debug)] +pub struct BlockContainer { + pub palette: HashMap, + pub block_data: Vec, + pub block_entities: Vec, +} + +#[derive(Debug, Clone)] pub struct BlockEntity { - #[serde(rename = "Id")] pub id: String, - #[serde(rename = "Pos")] pub pos: [i32; 3], } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Clone)] +pub struct BlockEntityV3 { + pub id: String, + pub pos: [i32; 3], + pub data: HashMap, +} + +#[derive(Debug, Clone)] pub struct Entity { - #[serde(rename = "Id")] pub id: String, - #[serde(rename = "Pos")] pub pos: [i32; 3], } -impl Schematic { - pub fn load_data(data: R) -> Result where R: Read { - let schematic: Schematic = match nbt::from_gzip_reader(data) { - Ok(schem) => schem, - Err(e) => return Err(format!("Failed to parse schematic: {}", e)) - }; - Ok(schematic) +impl SchematicVersioned { + 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)?)), + _ => Err("Invalid schematic: Unknown Version".to_string()), + } } - pub fn load(path: &PathBuf) -> Result { - let file = match std::fs::File::open(path) { - Ok(x) => x, - Err(_) => return Err(format!("Failed to open file: {}", path.to_str().unwrap())) - }; - Schematic::load_data(file) + 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 { + Ok(Self { + 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, + 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())?)?, + 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())?)?, + }) + } +} + +impl SpongeV2Schematic { + pub fn from_nbt(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(), + 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, + 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())?)?, + 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())?), + block_entities: read_tile_entities(nbt.get_compound_tag_vec("BlockEntities").map_err(|e| e.to_string())?)?, + entities: None, + }) + } +} + +impl SpongeV3Schematic { + pub fn from_nbt(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())?, + 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, + 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())?)?, + }, + entities: None, + }) + } +} + +fn read_tile_entities(tag: Vec<&CompoundTag>) -> Result, String> { +let mut tile_entities = Vec::new(); + for t in tag { + tile_entities.push(BlockEntity { + id: t.get_str("Id").map_err(|e| e.to_string())?.to_string(), + pos: read_offset(t.get("Pos").map_err(|e| e.to_string())?)?, + }); + } + Ok(tile_entities) +} + +#[inline] +fn read_offset(offset: &Vec) -> Result<[i32; 3], String> { + match offset.len() { + 3 => Ok([offset[0], offset[1], offset[2]]), + _ => Err("Invalid schematic: read_offset wrong length".to_string()), + } +} + +#[inline] +fn read_palette(p: &CompoundTag) -> HashMap { + let mut palette = HashMap::new(); + for (key, value) in p.iter() { + match value { + Tag::Int(n) => { palette.insert(key.clone(), *n); }, + _ => {}, + }; + } + palette +} + +#[inline] +fn read_blocks(blockdata: &Vec) -> Vec { + read_varint_array(blockdata) +} + +#[inline] pub fn read_varint_array(read: &Vec) -> Vec { let mut data = Vec::new(); let mut value: i32 = 0; diff --git a/schemsearch-java/Cargo.toml b/schemsearch-java/Cargo.toml index f8eb27c..bbfbd8e 100644 --- a/schemsearch-java/Cargo.toml +++ b/schemsearch-java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "schemsearch-java" -version = "0.1.1" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later" diff --git a/schemsearch-java/src/lib.rs b/schemsearch-java/src/lib.rs index e9a2d96..35c2b51 100644 --- a/schemsearch-java/src/lib.rs +++ b/schemsearch-java/src/lib.rs @@ -21,7 +21,7 @@ use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; use schemsearch_lib::{search, SearchBehavior}; #[no_mangle] @@ -32,8 +32,8 @@ pub extern "system" fn Java_SchemSearch_search<'local>(mut env: JNIEnv<'local>, pattern_path: JString<'local>) -> jstring { let schematic_path: String = env.get_string(&schematic_path).expect("Couldn't get java string!").into(); let pattern_path: String = env.get_string(&pattern_path).expect("Couldn't get java string!").into(); - let schematic = Schematic::load(&PathBuf::from(&schematic_path)).unwrap(); - let pattern = Schematic::load(&PathBuf::from(&pattern_path)).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from(&schematic_path)).unwrap(); + let pattern = SpongeV2Schematic::load(&PathBuf::from(&pattern_path)).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: true, diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index 559e62c..aa7c963 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "schemsearch-lib" -version = "0.1.2" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hematite-nbt = "0.5.2" -serde = "1.0.152" -schemsearch-files = { path = "../schemsearch-files" } \ No newline at end of file +serde = { version = "1.0.160", features = ["derive"] } +schemsearch-files = { path = "../schemsearch-files" } +named-binary-tag = "0.6" diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index 98a512e..ce5d599 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -17,9 +17,9 @@ pub mod pattern_mapper; -use serde::{Deserialize, Serialize}; +use serde::{Serialize, Deserialize}; use pattern_mapper::match_palette; -use schemsearch_files::Schematic; +use schemsearch_files::SchematicVersioned; use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] @@ -33,15 +33,15 @@ pub struct SearchBehavior { } pub fn search( - schem: Schematic, - pattern_schem: &Schematic, + schem: SchematicVersioned, + pattern_schem: &SchematicVersioned, search_behavior: SearchBehavior, ) -> Vec { - if schem.width < pattern_schem.width || schem.height < pattern_schem.height || schem.length < pattern_schem.length { + if schem.get_width() < pattern_schem.get_width() || schem.get_height() < pattern_schem.get_height() || schem.get_length() < pattern_schem.get_length() { return vec![]; } - if pattern_schem.palette.len() > schem.palette.len() { + if pattern_schem.get_palette().len() > schem.get_palette().len() { return vec![]; } @@ -49,27 +49,27 @@ pub fn search( let mut matches: Vec = Vec::new(); - let pattern_data = pattern_schem.block_data.as_slice(); + let pattern_data = pattern_schem.get_block_data().as_slice(); let schem_data = if search_behavior.ignore_block_data { - match_palette_adapt(&schem, &pattern_schem.palette, search_behavior.ignore_block_data) + match_palette_adapt(&schem, &pattern_schem.get_palette(), search_behavior.ignore_block_data) } else { - schem.block_data + schem.get_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.palette.get("minecraft:air").unwrap_or(&-1) } else { &-1}; + 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 pattern_blocks = pattern_data.len() as f32; - 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 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 schem_width = schem.width as usize; - let schem_height = schem.height as usize; - let schem_length = 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; for y in 0..=schem_height - pattern_height { for z in 0..=schem_length - pattern_length { @@ -132,67 +132,69 @@ pub fn normalize_data(data: &str, ignore_data: bool) -> &str { } } -pub fn parse_schematic(data: &Vec) -> Schematic { - if data[0] == 0x1f && data[1] == 0x8b { - // gzip - nbt::from_gzip_reader(data.as_slice()).unwrap() - } else { - // uncompressed - nbt::from_reader(data.as_slice()).unwrap() - } -} - #[allow(unused_imports)] #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; - use schemsearch_files::Schematic; + use schemsearch_files::SchematicVersioned::V2; + use schemsearch_files::SpongeV2Schematic; use crate::pattern_mapper::strip_data; use super::*; #[test] fn read_schematic() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + + let schematic = match schematic { + V2 (schematic) => schematic, + _ => panic!("Invalid schematic version"), + }; + assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len()); assert_eq!(schematic.palette_max, schematic.palette.len() as i32); } #[test] fn test_parse_function() { - let file = std::fs::File::open("../tests/simple.schem").expect("Failed to open file"); - let schematic: Schematic = parse_schematic(&std::io::Read::bytes(file).map(|b| b.unwrap()).collect()); + let schematic: SchematicVersioned = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + + let schematic = match schematic { + V2 (schematic) => schematic, + _ => panic!("Invalid schematic version"), + }; + assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len()); assert_eq!(schematic.palette_max, schematic.palette.len() as i32); } #[test] fn test_strip_schem() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let stripped = strip_data(&schematic); - assert_eq!(stripped.palette.keys().any(|k| k.contains('[')), false); + assert_eq!(stripped.get_palette().keys().any(|k| k.contains('[')), false); } #[test] fn test_match_palette() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); let _ = match_palette(&schematic, &endstone, true); } #[test] fn test_match_palette_ignore_data() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); let _ = match_palette(&schematic, &endstone, false); } #[test] pub fn test_big_search() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); let _ = search(schematic, &endstone, SearchBehavior { ignore_block_data: true, @@ -206,8 +208,8 @@ mod tests { #[test] pub fn test_search() { - let schematic = Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); - let pattern = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/Random.schem")).unwrap(); + let pattern = SchematicVersioned::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: true, @@ -228,8 +230,8 @@ mod tests { #[test] pub fn test_search_ws() { - let schematic = Schematic::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap(); - let pattern = Schematic::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap(); + let pattern = SchematicVersioned::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: false, diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index edc9632..a74dab5 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -15,27 +15,28 @@ * along with this program. If not, see . */ -use nbt::Map; -use schemsearch_files::Schematic; +use std::collections::HashMap; +use nbt::CompoundTag; +use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; use crate::normalize_data; -fn create_reverse_palette(schem: &Schematic) -> 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() { +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() { reverse_palette[*value as usize] = key; } reverse_palette } -pub fn strip_data(schem: &Schematic) -> Schematic { +pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { let mut data: Vec = Vec::new(); - let mut palette: Map = Map::new(); + let mut palette: HashMap = HashMap::new(); let mut palette_max: i32 = 0; let reverse_palette = create_reverse_palette(schem); - for block in schem.block_data.iter() { + for block in schem.get_block_data().iter() { let block_name = reverse_palette[*block as usize].clone(); let block_name = block_name.split('[').next().unwrap().to_string(); @@ -47,27 +48,28 @@ pub fn strip_data(schem: &Schematic) -> Schematic { data.push(*entry); } - Schematic { - version: schem.version, - data_version: schem.data_version, + SchematicVersioned::V2(SpongeV2Schematic { + data_version: 1, palette, palette_max, block_data: data, - block_entities: schem.block_entities.clone(), - height: schem.height, - length: schem.length, - width: schem.width, - metadata: schem.metadata.clone(), - offset: schem.offset.clone(), + block_entities: schem.get_block_entities().clone(), + height: schem.get_height(), + length: schem.get_length(), + width: schem.get_width(), + metadata: CompoundTag::new(), + offset: [0; 3], entities: None, - } + },) + + } -pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { +pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &HashMap, ignore_data: bool) -> Vec { let mut data: Vec = Vec::new(); let reverse_palette = create_reverse_palette(schem); - for x in &schem.block_data { + for x in schem.get_block_data() { 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) { @@ -81,10 +83,10 @@ pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map Schematic { +) -> SchematicVersioned { if ignore_data { match_palette_internal(&strip_data(schem), &strip_data(pattern), ignore_data) } else { @@ -93,24 +95,23 @@ pub fn match_palette( } fn match_palette_internal( - schem: &Schematic, - pattern: &Schematic, + schem: &SchematicVersioned, + pattern: &SchematicVersioned, ignore_data: bool, -) -> Schematic { - let data_pattern: Vec = match_palette_adapt(&pattern, &schem.palette, ignore_data); +) -> SchematicVersioned { + let data_pattern: Vec = match_palette_adapt(&pattern, schem.get_palette(), ignore_data); - Schematic { - version: pattern.version.clone(), - data_version: pattern.data_version.clone(), - palette: schem.palette.clone(), - palette_max: schem.palette_max, + SchematicVersioned::V2(SpongeV2Schematic { + data_version: 0, + palette: schem.get_palette().clone(), + palette_max: schem.get_palette_max(), block_data: data_pattern, - block_entities: pattern.block_entities.clone(), - height: pattern.height.clone(), - length: pattern.length.clone(), - width: pattern.width.clone(), - metadata: pattern.metadata.clone(), - offset: pattern.offset.clone(), + block_entities: pattern.get_block_entities().clone(), + height: pattern.get_height(), + length: pattern.get_length(), + width: pattern.get_width(), + metadata: CompoundTag::new(), + offset: [0; 3], entities: None, - } + }) } \ No newline at end of file diff --git a/schemsearch-sql/Cargo.toml b/schemsearch-sql/Cargo.toml index b4825df..39919c8 100644 --- a/schemsearch-sql/Cargo.toml +++ b/schemsearch-sql/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "schemsearch-sql" -version = "0.1.1" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later"