From a1b5449f06908a26b7d2a67cbbeda843194c845e Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 4 Apr 2023 12:07:33 +0200 Subject: [PATCH 1/9] Some basic tests and basic impls --- schemsearch-cli/src/main.rs | 8 +- schemsearch-cli/src/types.rs | 6 +- schemsearch-faster/src/lib.rs | 16 ++-- schemsearch-files/Cargo.toml | 2 + schemsearch-files/src/lib.rs | 64 ++++++++------- schemsearch-java/src/lib.rs | 6 +- schemsearch-lib/Cargo.toml | 5 +- schemsearch-lib/src/lib.rs | 111 +++++++++++++++++++------- schemsearch-lib/src/pattern_mapper.rs | 24 +++--- 9 files changed, 156 insertions(+), 86 deletions(-) diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index f17f263..fad1b4c 100644 --- a/schemsearch-cli/src/main.rs +++ b/schemsearch-cli/src/main.rs @@ -38,7 +38,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}; fn main() { @@ -186,7 +186,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(); @@ -303,8 +303,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/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 395f9fe..7f53e6d 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -6,5 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +flate2 = "1.0.25" hematite-nbt = "0.5.2" serde = "1.0.152" +serde-this-or-that = "0.4.2" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index b900f74..83c5dc1 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -17,34 +17,50 @@ use std::io::Read; use std::path::PathBuf; -use nbt::{Map, Value}; -use serde::{Deserialize, Deserializer, Serialize}; +use nbt::{Error, from_gzip_reader, Map, Value}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_this_or_that::as_i64; #[derive(Serialize, Deserialize, Debug)] -pub struct Schematic { - #[serde(rename = "Version")] +#[serde(untagged)] +pub enum SchematicVersioned { + V1, + V2(SpongeV2Schematic), + V3(SpongeV3Schematic), +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct SpongeV2Schematic { pub version: i32, - #[serde(rename = "DataVersion")] pub data_version: i32, - #[serde(rename = "Metadata")] pub metadata: Map, - #[serde(rename = "Width")] 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")] + #[serde(deserialize_with = "read_blockdata")] + pub block_data: Vec, + pub block_entities: Vec, + pub entities: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct SpongeV3Schematic { + pub data_version: i32, + pub metadata: Map, + pub width: u16, + pub height: u16, + pub length: u16, + pub offset: [i32; 3], + pub palette_max: i32, + pub palette: Map, + #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, - #[serde(rename = "BlockEntities")] pub block_entities: Vec, - #[serde(rename = "Entities")] pub entities: Option>, } @@ -72,21 +88,15 @@ pub struct Entity { 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)) - }; +impl SchematicVersioned { + pub fn load_data(data: R) -> Result where R: Read { + let schematic: SchematicVersioned = from_gzip_reader(data)?; Ok(schematic) } - 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 file = std::fs::File::open(path)?; + Self::load_data(file) } } 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 1c340ef..1a7f041 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -9,4 +9,7 @@ license = "AGPL-3.0-or-later" [dependencies] hematite-nbt = "0.5.2" serde = "1.0.152" -schemsearch-files = { path = "../schemsearch-files" } \ No newline at end of file +schemsearch-files = { path = "../schemsearch-files" } + +[dev-dependencies] +serde_json = "1.0.95" diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index c140532..58f1d6f 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -19,7 +19,8 @@ pub mod pattern_mapper; use serde::{Deserialize, Serialize}; use pattern_mapper::match_palette; -use schemsearch_files::Schematic; +use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; +use schemsearch_files::SchematicVersioned::V2; use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] @@ -33,10 +34,18 @@ pub struct SearchBehavior { } pub fn search( - schem: Schematic, - pattern_schem: &Schematic, + schem: SchematicVersioned, + pattern_schem: &SchematicVersioned, search_behavior: SearchBehavior, ) -> Vec { + let schem = match schem { + V2(x) => x, + _ => return vec![], + }; + let pattern_schem = match pattern_schem { + V2(schem) => schem, + _ => return vec![], + }; if schem.width < pattern_schem.width || schem.height < pattern_schem.height || schem.length < pattern_schem.length { return vec![]; } @@ -132,42 +141,47 @@ 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::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(schem) => schem, + _ => 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(schem) => schem, + _ => 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 schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; let stripped = strip_data(&schematic); assert_eq!(stripped.palette.keys().any(|k| k.contains('[')), false); @@ -175,24 +189,44 @@ mod tests { #[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 schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + + let endstone = match endstone { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; 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 schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + + let endstone = match endstone { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; 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 +240,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 +262,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, @@ -243,4 +277,25 @@ mod tests { println!("{:?}", matches); assert_eq!(matches.len(), 1); } + + #[test] + pub fn sezitest() { + let schem = V2(SpongeV2Schematic { + version: 2, + data_version: 0, + metadata: Default::default(), + width: 0, + height: 0, + length: 0, + offset: [1, 2, 3], + palette_max: 0, + palette: Default::default(), + block_data: vec![], + block_entities: vec![], + entities: None, + }); + + println!("{:?}", schem); + println!("{}", serde_json::to_string_pretty(&schem).unwrap()); + } } diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index edc9632..e56881f 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -16,10 +16,10 @@ */ use nbt::Map; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; use crate::normalize_data; -fn create_reverse_palette(schem: &Schematic) -> Vec<&str> { +fn create_reverse_palette(schem: &SpongeV2Schematic) -> 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() { @@ -28,7 +28,7 @@ fn create_reverse_palette(schem: &Schematic) -> Vec<&str> { reverse_palette } -pub fn strip_data(schem: &Schematic) -> Schematic { +pub fn strip_data(schem: &SpongeV2Schematic) -> SpongeV2Schematic { let mut data: Vec = Vec::new(); let mut palette: Map = Map::new(); @@ -47,7 +47,7 @@ pub fn strip_data(schem: &Schematic) -> Schematic { data.push(*entry); } - Schematic { + SpongeV2Schematic { version: schem.version, data_version: schem.data_version, palette, @@ -63,7 +63,7 @@ pub fn strip_data(schem: &Schematic) -> Schematic { } } -pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { +pub fn match_palette_adapt(schem: &SpongeV2Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { let mut data: Vec = Vec::new(); let reverse_palette = create_reverse_palette(schem); @@ -81,10 +81,10 @@ pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map Schematic { +) -> SpongeV2Schematic { if ignore_data { match_palette_internal(&strip_data(schem), &strip_data(pattern), ignore_data) } else { @@ -93,13 +93,13 @@ pub fn match_palette( } fn match_palette_internal( - schem: &Schematic, - pattern: &Schematic, + schem: &SpongeV2Schematic, + pattern: &SpongeV2Schematic, ignore_data: bool, -) -> Schematic { +) -> SpongeV2Schematic { let data_pattern: Vec = match_palette_adapt(&pattern, &schem.palette, ignore_data); - Schematic { + SpongeV2Schematic { version: pattern.version.clone(), data_version: pattern.data_version.clone(), palette: schem.palette.clone(), From 9cca860db36603c25d8854b9146f70ba996c0fcd Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 13 Apr 2023 16:16:02 +0200 Subject: [PATCH 2/9] Some new Ideas --- schemsearch-files/Cargo.toml | 2 + schemsearch-files/src/lib.rs | 116 +++++++++++++++++++++++--- schemsearch-lib/src/lib.rs | 89 +++++++------------- schemsearch-lib/src/pattern_mapper.rs | 76 ++++++++--------- 4 files changed, 173 insertions(+), 110 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 78756df..b954fe4 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -10,3 +10,5 @@ flate2 = "1.0.25" hematite-nbt = "0.5.2" serde = "1.0.152" serde-this-or-that = "0.4.2" +serde_repr = "0.1.12" + diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 83c5dc1..3c18428 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -21,18 +21,97 @@ use nbt::{Error, from_gzip_reader, Map, Value}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_this_or_that::as_i64; -#[derive(Serialize, Deserialize, Debug)] -#[serde(untagged)] +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(untagged, rename_all = "PascalCase")] pub enum SchematicVersioned { - V1, + V1(SpongeV1Schematic), V2(SpongeV2Schematic), V3(SpongeV3Schematic), } -#[derive(Serialize, Deserialize, Debug)] +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) -> &Map { + 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, Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct SpongeV1Schematic { + pub metadata: Map, + pub width: u16, + pub height: u16, + pub length: u16, + pub offset: [i32; 3], + pub palette_max: i32, + pub palette: Map, + #[serde(deserialize_with = "read_blockdata")] + pub block_data: Vec, + pub tile_entities: Vec, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] pub struct SpongeV2Schematic { - pub version: i32, pub data_version: i32, pub metadata: Map, pub width: u16, @@ -47,7 +126,7 @@ pub struct SpongeV2Schematic { pub entities: Option>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] pub struct SpongeV3Schematic { pub data_version: i32, @@ -56,12 +135,17 @@ pub struct SpongeV3Schematic { pub height: u16, pub length: u16, pub offset: [i32; 3], - pub palette_max: i32, + pub blocks: BlockContainer, + pub entities: Option>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct BlockContainer { pub palette: Map, #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub block_entities: Vec, - pub entities: Option>, } fn read_blockdata<'de, D>(deserializer: D) -> Result, D::Error> @@ -73,18 +157,24 @@ fn read_blockdata<'de, D>(deserializer: D) -> Result, D::Error> } #[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "PascalCase")] pub struct BlockEntity { - #[serde(rename = "Id")] pub id: String, - #[serde(rename = "Pos")] pub pos: [i32; 3], } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Entity { - #[serde(rename = "Id")] +#[serde(rename_all = "PascalCase")] +pub struct BlockEntityV3 { + pub id: String, + pub pos: [i32; 3], + pub data: Map, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "PascalCase")] +pub struct Entity { pub id: String, - #[serde(rename = "Pos")] pub pos: [i32; 3], } diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index 44af89e..dae1716 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -18,6 +18,7 @@ pub mod pattern_mapper; use serde::{Deserialize, Serialize}; +use nbt::Map; use pattern_mapper::match_palette; use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; use schemsearch_files::SchematicVersioned::V2; @@ -38,19 +39,11 @@ pub fn search( pattern_schem: &SchematicVersioned, search_behavior: SearchBehavior, ) -> Vec { - let schem = match schem { - V2(x) => x, - _ => return vec![], - }; - let pattern_schem = match pattern_schem { - V2(schem) => schem, - _ => return 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![]; } @@ -58,27 +51,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 { @@ -145,6 +138,7 @@ pub fn normalize_data(data: &str, ignore_data: bool) -> &str { #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; + use serde::de::Unexpected::Map; use schemsearch_files::SpongeV2Schematic; use crate::pattern_mapper::strip_data; use super::*; @@ -154,7 +148,7 @@ mod tests { let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let schematic = match schematic { - V2(schem) => schem, + V2 (schematic) => schematic, _ => panic!("Invalid schematic version"), }; @@ -167,7 +161,7 @@ mod tests { let schematic: SchematicVersioned = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let schematic = match schematic { - V2(schem) => schem, + V2 (schematic) => schematic, _ => panic!("Invalid schematic version"), }; @@ -178,13 +172,9 @@ mod tests { #[test] fn test_strip_schem() { let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let schematic = match schematic { - V2(schem) => schem, - _ => panic!("Invalid schematic version"), - }; 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] @@ -192,16 +182,6 @@ mod tests { let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); - let schematic = match schematic { - V2(schem) => schem, - _ => panic!("Invalid schematic version"), - }; - - let endstone = match endstone { - V2(schem) => schem, - _ => panic!("Invalid schematic version"), - }; - let _ = match_palette(&schematic, &endstone, true); } @@ -210,16 +190,6 @@ mod tests { let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); - let schematic = match schematic { - V2(schem) => schem, - _ => panic!("Invalid schematic version"), - }; - - let endstone = match endstone { - V2(schem) => schem, - _ => panic!("Invalid schematic version"), - }; - let _ = match_palette(&schematic, &endstone, false); } @@ -278,24 +248,25 @@ mod tests { assert_eq!(matches.len(), 1); } + #[test] - pub fn sezitest() { - let schem = V2(SpongeV2Schematic { - version: 2, + pub fn testsezi() { + let schematic = SchematicVersioned::V2(SpongeV2Schematic { data_version: 0, - metadata: Default::default(), - width: 0, - height: 0, - length: 0, - offset: [1, 2, 3], + metadata: nbt::Map::new(), + width: 16, + height: 16, + length: 16, + offset: [0; 3], palette_max: 0, - palette: Default::default(), + palette: nbt::Map::new(), block_data: vec![], + entities: Some(vec![]), block_entities: vec![], - entities: None, }); - println!("{:?}", schem); - println!("{}", serde_json::to_string_pretty(&schem).unwrap()); + println!("{:?}", schematic); + println!("{}", serde_json::to_string_pretty(&schematic).unwrap()); } + } diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index e56881f..8f3ddea 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -16,26 +16,26 @@ */ use nbt::Map; -use schemsearch_files::SpongeV2Schematic; +use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; use crate::normalize_data; -fn create_reverse_palette(schem: &SpongeV2Schematic) -> 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: &SpongeV2Schematic) -> SpongeV2Schematic { +pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { let mut data: Vec = Vec::new(); let mut palette: Map = Map::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 +47,28 @@ pub fn strip_data(schem: &SpongeV2Schematic) -> SpongeV2Schematic { data.push(*entry); } - SpongeV2Schematic { - 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: Map::new(), + offset: [0; 3], entities: None, - } + },) + + } -pub fn match_palette_adapt(schem: &SpongeV2Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { +pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &Map, 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 +82,10 @@ pub fn match_palette_adapt(schem: &SpongeV2Schematic, matching_palette: &Map SpongeV2Schematic { +) -> SchematicVersioned { if ignore_data { match_palette_internal(&strip_data(schem), &strip_data(pattern), ignore_data) } else { @@ -93,24 +94,23 @@ pub fn match_palette( } fn match_palette_internal( - schem: &SpongeV2Schematic, - pattern: &SpongeV2Schematic, + schem: &SchematicVersioned, + pattern: &SchematicVersioned, ignore_data: bool, -) -> SpongeV2Schematic { - 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); - SpongeV2Schematic { - 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: Map::new(), + offset: [0; 3], entities: None, - } + }) } \ No newline at end of file From e03a805bdbe4b89c2b357f8587aca927b5bd6c69 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 13 Apr 2023 23:16:12 +0200 Subject: [PATCH 3/9] Something Working :D --- schemsearch-files/Cargo.toml | 3 +-- schemsearch-files/src/lib.rs | 35 +++++++++++++++++++++++++++++++---- schemsearch-lib/Cargo.toml | 3 --- schemsearch-lib/src/lib.rs | 4 +--- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index b954fe4..76d6ddf 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -9,6 +9,5 @@ edition = "2021" flate2 = "1.0.25" hematite-nbt = "0.5.2" serde = "1.0.152" -serde-this-or-that = "0.4.2" -serde_repr = "0.1.12" +serde_json = "1.0.84" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 3c18428..cd1efe3 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -18,8 +18,15 @@ use std::io::Read; use std::path::PathBuf; use nbt::{Error, from_gzip_reader, Map, Value}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_this_or_that::as_i64; +use serde::{Deserialize, Deserializer, Serialize}; + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct SchematicRaw { + version: i32, + #[serde(flatten)] + data: Map, +} #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(untagged, rename_all = "PascalCase")] @@ -94,6 +101,26 @@ impl SchematicVersioned { } } +impl From for SchematicVersioned { + fn from(value: SchematicRaw) -> Self { + match value.version { + 1 => { + let schematic: SpongeV1Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + return SchematicVersioned::V1(schematic); + }, + 2 => { + let schematic: SpongeV2Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + return SchematicVersioned::V2(schematic); + }, + 3 => { + let schematic: SpongeV3Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + return SchematicVersioned::V3(schematic); + } + _ => panic!("Unknown Schematic Version: {}", value.version), + } + } +} + #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] pub struct SpongeV1Schematic { @@ -180,8 +207,8 @@ pub struct Entity { impl SchematicVersioned { pub fn load_data(data: R) -> Result where R: Read { - let schematic: SchematicVersioned = from_gzip_reader(data)?; - Ok(schematic) + let raw: SchematicRaw = from_gzip_reader(data)?; + Ok(SchematicVersioned::from(raw)) } pub fn load(path: &PathBuf) -> Result { diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index 1e3a0d0..d8e737f 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -10,6 +10,3 @@ license = "AGPL-3.0-or-later" hematite-nbt = "0.5.2" serde = "1.0.152" schemsearch-files = { path = "../schemsearch-files" } - -[dev-dependencies] -serde_json = "1.0.95" diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index dae1716..1c6d1b4 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -18,10 +18,8 @@ pub mod pattern_mapper; use serde::{Deserialize, Serialize}; -use nbt::Map; use pattern_mapper::match_palette; -use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; -use schemsearch_files::SchematicVersioned::V2; +use schemsearch_files::SchematicVersioned; use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] From d1a01dc0c1f511f569e2ef0038307d76ffdb1642 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 13 Apr 2023 23:49:39 +0200 Subject: [PATCH 4/9] Faster but not working --- schemsearch-files/Cargo.toml | 2 +- schemsearch-files/src/lib.rs | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 76d6ddf..cfaaff8 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] flate2 = "1.0.25" -hematite-nbt = "0.5.2" +fastnbt = "2.4.3" serde = "1.0.152" serde_json = "1.0.84" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index cd1efe3..719d47f 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -15,17 +15,21 @@ * along with this program. If not, see . */ +use std::collections::HashMap; use std::io::Read; use std::path::PathBuf; -use nbt::{Error, from_gzip_reader, Map, Value}; +use fastnbt::error::Error; +use fastnbt::Value; +use flate2::read::GzDecoder; use serde::{Deserialize, Deserializer, Serialize}; +use serde::de::value::MapDeserializer; #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] struct SchematicRaw { version: i32, #[serde(flatten)] - data: Map, + data: HashMap, } #[derive(Clone, Serialize, Deserialize, Debug)] @@ -74,7 +78,7 @@ impl SchematicVersioned { } #[inline] - pub fn get_palette(&self) -> &Map { + pub fn get_palette(&self) -> &HashMap { return match self { SchematicVersioned::V1(schematic) => &schematic.palette, SchematicVersioned::V2(schematic) => &schematic.palette, @@ -105,15 +109,15 @@ impl From for SchematicVersioned { fn from(value: SchematicRaw) -> Self { match value.version { 1 => { - let schematic: SpongeV1Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + let schematic: SpongeV1Schematic = SpongeV1Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); return SchematicVersioned::V1(schematic); }, 2 => { - let schematic: SpongeV2Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + let schematic: SpongeV2Schematic = SpongeV2Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); return SchematicVersioned::V2(schematic); }, 3 => { - let schematic: SpongeV3Schematic = serde_json::from_value(serde_json::to_value(value.data).unwrap()).unwrap(); + let schematic: SpongeV3Schematic = SpongeV3Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); return SchematicVersioned::V3(schematic); } _ => panic!("Unknown Schematic Version: {}", value.version), @@ -124,13 +128,13 @@ impl From for SchematicVersioned { #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] pub struct SpongeV1Schematic { - pub metadata: Map, + pub metadata: HashMap, pub width: u16, pub height: u16, pub length: u16, pub offset: [i32; 3], pub palette_max: i32, - pub palette: Map, + pub palette: HashMap, #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub tile_entities: Vec, @@ -140,13 +144,13 @@ pub struct SpongeV1Schematic { #[serde(rename_all = "PascalCase")] pub struct SpongeV2Schematic { pub data_version: i32, - pub metadata: Map, + pub metadata: HashMap, pub width: u16, pub height: u16, pub length: u16, pub offset: [i32; 3], pub palette_max: i32, - pub palette: Map, + pub palette: HashMap, #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub block_entities: Vec, @@ -157,7 +161,7 @@ pub struct SpongeV2Schematic { #[serde(rename_all = "PascalCase")] pub struct SpongeV3Schematic { pub data_version: i32, - pub metadata: Map, + pub metadata: HashMap, pub width: u16, pub height: u16, pub length: u16, @@ -169,7 +173,7 @@ pub struct SpongeV3Schematic { #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] pub struct BlockContainer { - pub palette: Map, + pub palette: HashMap, #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub block_entities: Vec, @@ -195,7 +199,7 @@ pub struct BlockEntity { pub struct BlockEntityV3 { pub id: String, pub pos: [i32; 3], - pub data: Map, + pub data: HashMap, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -207,7 +211,7 @@ pub struct Entity { impl SchematicVersioned { pub fn load_data(data: R) -> Result where R: Read { - let raw: SchematicRaw = from_gzip_reader(data)?; + let raw: SchematicRaw = fastnbt::from_reader(GzDecoder::new(data))?; Ok(SchematicVersioned::from(raw)) } From 246927d8403a04a72ea71789c40bf97300081c86 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 14 Apr 2023 17:56:28 +0200 Subject: [PATCH 5/9] idk what im doing --- schemsearch-files/src/lib.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 719d47f..502a1e4 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -use std::collections::HashMap; +use std::collections::hash_map::{HashMap}; use std::io::Read; use std::path::PathBuf; use fastnbt::error::Error; @@ -105,20 +105,22 @@ impl SchematicVersioned { } } -impl From for SchematicVersioned { - fn from(value: SchematicRaw) -> Self { +impl TryFrom for SchematicVersioned { + type Error = Error; + + fn try_from(value: SchematicRaw) -> Result { match value.version { 1 => { - let schematic: SpongeV1Schematic = SpongeV1Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); - return SchematicVersioned::V1(schematic); + let schematic: SpongeV1Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; + return Ok(SchematicVersioned::V1(schematic)); }, 2 => { - let schematic: SpongeV2Schematic = SpongeV2Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); - return SchematicVersioned::V2(schematic); + let schematic: SpongeV2Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; + return Ok(SchematicVersioned::V2(schematic)); }, 3 => { - let schematic: SpongeV3Schematic = SpongeV3Schematic::deserialize(MapDeserializer::new(value.data.into_iter())).unwrap(); - return SchematicVersioned::V3(schematic); + let schematic: SpongeV3Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; + return Ok(SchematicVersioned::V3(schematic)); } _ => panic!("Unknown Schematic Version: {}", value.version), } @@ -212,7 +214,7 @@ pub struct Entity { impl SchematicVersioned { pub fn load_data(data: R) -> Result where R: Read { let raw: SchematicRaw = fastnbt::from_reader(GzDecoder::new(data))?; - Ok(SchematicVersioned::from(raw)) + SchematicVersioned::try_from(raw) } pub fn load(path: &PathBuf) -> Result { From a47c2f44bd68a028dc32399bac9e6e841d508e00 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 22 Apr 2023 16:39:21 +0200 Subject: [PATCH 6/9] Something:tm: --- schemsearch-files/Cargo.toml | 2 +- schemsearch-files/src/lib.rs | 302 +++++++++++++++++++++++++++-------- 2 files changed, 235 insertions(+), 69 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index cfaaff8..76d6ddf 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] flate2 = "1.0.25" -fastnbt = "2.4.3" +hematite-nbt = "0.5.2" serde = "1.0.152" serde_json = "1.0.84" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 502a1e4..0fe2838 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -15,25 +15,12 @@ * along with this program. If not, see . */ -use std::collections::hash_map::{HashMap}; +use std::collections::hash_map::HashMap; use std::io::Read; use std::path::PathBuf; -use fastnbt::error::Error; -use fastnbt::Value; -use flate2::read::GzDecoder; -use serde::{Deserialize, Deserializer, Serialize}; -use serde::de::value::MapDeserializer; +use nbt::Value; -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] -struct SchematicRaw { - version: i32, - #[serde(flatten)] - data: HashMap, -} - -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(untagged, rename_all = "PascalCase")] +#[derive(Clone, Debug)] pub enum SchematicVersioned { V1(SpongeV1Schematic), V2(SpongeV2Schematic), @@ -105,30 +92,7 @@ impl SchematicVersioned { } } -impl TryFrom for SchematicVersioned { - type Error = Error; - - fn try_from(value: SchematicRaw) -> Result { - match value.version { - 1 => { - let schematic: SpongeV1Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; - return Ok(SchematicVersioned::V1(schematic)); - }, - 2 => { - let schematic: SpongeV2Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; - return Ok(SchematicVersioned::V2(schematic)); - }, - 3 => { - let schematic: SpongeV3Schematic = fastnbt::from_value(&fastnbt::to_value(value.data)?)?; - return Ok(SchematicVersioned::V3(schematic)); - } - _ => panic!("Unknown Schematic Version: {}", value.version), - } - } -} - -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] +#[derive(Clone, Debug)] pub struct SpongeV1Schematic { pub metadata: HashMap, pub width: u16, @@ -137,13 +101,11 @@ pub struct SpongeV1Schematic { pub offset: [i32; 3], pub palette_max: i32, pub palette: HashMap, - #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub tile_entities: Vec, } -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] +#[derive(Clone, Debug)] pub struct SpongeV2Schematic { pub data_version: i32, pub metadata: HashMap, @@ -153,14 +115,12 @@ pub struct SpongeV2Schematic { pub offset: [i32; 3], pub palette_max: i32, pub palette: HashMap, - #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub block_entities: Vec, pub entities: Option>, } -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] +#[derive(Clone, Debug)] pub struct SpongeV3Schematic { pub data_version: i32, pub metadata: HashMap, @@ -172,57 +132,263 @@ pub struct SpongeV3Schematic { pub entities: Option>, } -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] +#[derive(Clone, Debug)] pub struct BlockContainer { pub palette: HashMap, - #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, pub block_entities: Vec, } -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(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all = "PascalCase")] +#[derive(Debug, Clone)] pub struct BlockEntity { pub id: String, pub pos: [i32; 3], } -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all = "PascalCase")] +#[derive(Debug, Clone)] pub struct BlockEntityV3 { pub id: String, pub pos: [i32; 3], pub data: HashMap, } -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all = "PascalCase")] +#[derive(Debug, Clone)] pub struct Entity { pub id: String, pub pos: [i32; 3], } impl SchematicVersioned { - pub fn load_data(data: R) -> Result where R: Read { - let raw: SchematicRaw = fastnbt::from_reader(GzDecoder::new(data))?; - SchematicVersioned::try_from(raw) + pub fn load_data(data: R) -> Result where R: Read { + let nbt: HashMap = nbt::de::from_gzip_reader(data).map_err(|e| e.to_string())?; + let version = match nbt.get("Version") { + Some(version) => match version { + Value::Short(n) => *n as i32, + Value::Byte(n) => *n as i32, + Value::Int(n) => *n, + _ => return Err("Invalid schematic: Wrong Version Type".to_string()), + }, + None => return Err("Invalid schematic: Version not Found".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 = std::fs::File::open(path)?; + pub fn load(path: &PathBuf) -> Result { + let file = std::fs::File::open(path).map_err(|e| e.to_string())?; Self::load_data(file) } } +impl SpongeV1Schematic { + pub fn from_nbt(nbt: HashMap) -> Result { + Ok(Self { + metadata: match nbt.get("Metadata").ok_or("Invalid schematic: Metadata not found".to_string())? { + Value::Compound(metadata) => metadata.clone(), + _ => return Err("Invalid schematic: Metadata Wrong Type".to_string()), + }, + width: match nbt.get("Width").ok_or("Invalid schematic: Width not found".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Width Wrong Type".to_string()), + }, + height: match nbt.get("Height").ok_or("Invalid schematic: Height not found".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Height Wrong Type".to_string()), + }, + length: match nbt.get("Length").ok_or("Invalid schematic: Length not found".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Length Wrong Type".to_string()), + }, + offset: read_offset(nbt.get("Offset"))?, + palette_max: match nbt.get("PaletteMax").ok_or("Invalid schematic: PaletteMax not found".to_string())? { + Value::Int(p) => *p, + _ => return Err("Invalid schematic: PaletteMax Wrong Type".to_string()), + }, + palette: read_palette(nbt.get("Palette"))?, + block_data: read_blocks(nbt.get("BlockData"))?, + tile_entities: read_tile_entities(nbt.get("TileEntities"))?, + }) + } +} + +impl SpongeV2Schematic { + pub fn from_nbt(nbt: HashMap) -> Result { + Ok(Self{ + data_version: match nbt.get("DataVersion").ok_or("Invalid schematic: DataVersion Missing".to_string())? { + Value::Short(n) => *n as i32, + Value::Byte(n) => *n as i32, + Value::Int(n) => *n, + _ => return Err("Invalid schematic: DataVersion Wrong Type".to_string()), + }, + metadata: match nbt.get("Metadata").ok_or("Invalid schematic".to_string())? { + Value::Compound(m) => m.clone(), + _ => return Err("Invalid schematic: Metadata Wrong Type".to_string()), + }, + width: match nbt.get("Width").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Width Wrong Type".to_string()), + }, + height: match nbt.get("Height").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Height Wrong Type".to_string()), + }, + length: match nbt.get("Length").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic: Length Wrong Type".to_string()), + }, + offset: read_offset(nbt.get("Offset"))?, + palette_max: match nbt.get("PaletteMax").ok_or("Invalid schematic: PaletteMax Missing".to_string())? { + Value::Short(n) => *n as i32, + Value::Byte(n) => *n as i32, + Value::Int(n) => *n, + _ => return Err("Invalid schematic: PaletteMax Invalid Type".to_string()), + }, + palette: read_palette(nbt.get("Palette"))?, + block_data: read_blocks(nbt.get("BlockData"))?, + block_entities: read_tile_entities(nbt.get("BlockEntities"))?, + entities: None, + }) + } +} + +impl SpongeV3Schematic { + pub fn from_nbt(nbt: HashMap) -> Result { + Ok(Self{ + data_version: match nbt.get("DataVersion").ok_or("Invalid schematic".to_string())? { + Value::Int(d) => *d, + _ => return Err("Invalid schematic".to_string()), + }, + metadata: match nbt.get("Metadata").ok_or("Invalid schematic".to_string())? { + Value::Compound(m) => m.clone(), + _ => return Err("Invalid schematic".to_string()), + }, + width: match nbt.get("Width").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic".to_string()), + }, + height: match nbt.get("Height").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic".to_string()), + }, + length: match nbt.get("Length").ok_or("Invalid schematic".to_string())? { + Value::Short(n) => *n as u16, + Value::Byte(n) => *n as u16, + _ => return Err("Invalid schematic".to_string()), + }, + offset: read_offset(nbt.get("Offset"))?, + blocks: match nbt.get("Blocks").ok_or("Invalid schematic".to_string())? { + Value::Compound(b) => { + BlockContainer { + palette: read_palette(b.get("Palette"))?, + block_data: read_blocks(b.get("BlockData"))?, + block_entities: read_tile_entities(b.get("BlockEntities"))?, + } + } + _ => return Err("Invalid schematic".to_string()), + }, + entities: None, + }) + } +} + +fn read_tile_entities(tag: Option<&Value>) -> Result, String> { + match tag.ok_or("Invalid schematic: read_tile_entities not found".to_string())? { + Value::List(t) => { + let mut tile_entities = Vec::new(); + for te in t.iter() { + match te { + Value::Compound(te) => { + let id = match te.get("Id") { + None => return Err("Invalid schematic: Id Not Found".to_string()), + Some(id) => match id { + Value::String(id) => id.clone(), + _ => return Err("Invalid schematic: Id Wrong Type".to_string()), + }, + }; + let pos = read_offset(te.get("Pos"))?; + tile_entities.push(BlockEntity { id, pos }); + }, + _ => return Err("Invalid schematic: te Wrong Type".to_string()), + }; + } + Ok(tile_entities) + }, + Value::ByteArray(_) => Ok(vec![]), + _ => return Err("Invalid schematic: te wrong type".to_string()), + } +} + +#[inline] +fn read_offset(offset: Option<&Value>) -> Result<[i32; 3], String> { + match offset.ok_or("Invalid schematic: read_offset missing".to_string())? { + Value::IntArray(o) => match o.len() { + 3 => Ok([o[0], o[1], o[2]]), + _ => Err("Invalid schematic: Invalid IntArray".to_string()), + }, + Value::ByteArray(o) => match o.len() { + 3 => Ok([o[0] as i32, o[1] as i32, o[2] as i32]), + _ => Err("Invalid schematic: Invalid byteArray".to_string()), + }, + Value::List(l) => match l.len() { + 3 => { + let mut offset = [0; 3]; + for (i, v) in l.iter().enumerate() { + match v { + Value::Int(n) => offset[i] = *n, + Value::Byte(n) => offset[i] = *n as i32, + Value::Short(n) => offset[i] = *n as i32, + _ => return Err("Invalid schematic: read_offset invalid Number".to_string()), + }; + } + Ok(offset) + }, + _ => Err("Invalid schematic: Invalid List".to_string()), + } + _ => Err("Invalid schematic: read_offset".to_string()), + } +} + +#[inline] +fn read_palette(palette: Option<&Value>) -> Result, String> { + match palette.ok_or("Invalid schematic: read_palette missing".to_string())? { + Value::Compound(p) => { + let mut palette = HashMap::new(); + for (k, v) in p.iter() { + match v { + Value::Int(v) => { palette.insert(k.clone(), *v); }, + Value::Byte(v) => { palette.insert(k.clone(), *v as i32); }, + Value::Short(v) => { palette.insert(k.clone(), *v as i32); }, + _ => return Err("Invalid schematic: read_palette invalid Number".to_string()), + }; + } + Ok(palette) + }, + _ => Err("Invalid schematic: read_palette invalid Type".to_string()), + } +} + +#[inline] +fn read_blocks(blockdata: Option<&Value>) -> Result, String> { + match blockdata.ok_or("Invalid schematic: BlockData not found".to_string())? { + Value::ByteArray(b) => Ok(read_varint_array(b)), + _ => Err("Invalid schematic: Invalid BlockData".to_string()), + } +} + +#[inline] pub fn read_varint_array(read: &Vec) -> Vec { let mut data = Vec::new(); let mut value: i32 = 0; From 9a0b0535c6b8715098400efda68344b5ad1aa6ca Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 22 Apr 2023 21:03:00 +0200 Subject: [PATCH 7/9] remove Serde --- schemsearch-files/Cargo.toml | 2 -- schemsearch-lib/Cargo.toml | 2 -- schemsearch-lib/src/lib.rs | 25 +------------------------ 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 76d6ddf..0a87157 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -8,6 +8,4 @@ edition = "2021" [dependencies] flate2 = "1.0.25" hematite-nbt = "0.5.2" -serde = "1.0.152" -serde_json = "1.0.84" diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index d8e737f..96602a9 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -7,6 +7,4 @@ 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" } diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index 1c6d1b4..3892e50 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -17,7 +17,6 @@ pub mod pattern_mapper; -use serde::{Deserialize, Serialize}; use pattern_mapper::match_palette; use schemsearch_files::SchematicVersioned; use crate::pattern_mapper::match_palette_adapt; @@ -136,7 +135,7 @@ pub fn normalize_data(data: &str, ignore_data: bool) -> &str { #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; - use serde::de::Unexpected::Map; + use schemsearch_files::SchematicVersioned::V2; use schemsearch_files::SpongeV2Schematic; use crate::pattern_mapper::strip_data; use super::*; @@ -245,26 +244,4 @@ mod tests { println!("{:?}", matches); assert_eq!(matches.len(), 1); } - - - #[test] - pub fn testsezi() { - let schematic = SchematicVersioned::V2(SpongeV2Schematic { - data_version: 0, - metadata: nbt::Map::new(), - width: 16, - height: 16, - length: 16, - offset: [0; 3], - palette_max: 0, - palette: nbt::Map::new(), - block_data: vec![], - entities: Some(vec![]), - block_entities: vec![], - }); - - println!("{:?}", schematic); - println!("{}", serde_json::to_string_pretty(&schematic).unwrap()); - } - } From 5cff84538df8e016e6a5fcd8e532f4890affad97 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 22 Apr 2023 21:29:18 +0200 Subject: [PATCH 8/9] Fix Performance --- schemsearch-files/Cargo.toml | 2 +- schemsearch-files/src/lib.rs | 259 +++++++------------------- schemsearch-lib/Cargo.toml | 2 + schemsearch-lib/src/lib.rs | 1 + schemsearch-lib/src/pattern_mapper.rs | 11 +- 5 files changed, 79 insertions(+), 196 deletions(-) diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 0a87157..8134d7e 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] flate2 = "1.0.25" -hematite-nbt = "0.5.2" +named-binary-tag = "0.6" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index 0fe2838..7ef964f 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -18,7 +18,7 @@ use std::collections::hash_map::HashMap; use std::io::Read; use std::path::PathBuf; -use nbt::Value; +use nbt::{CompoundTag, Tag}; #[derive(Clone, Debug)] pub enum SchematicVersioned { @@ -94,7 +94,7 @@ impl SchematicVersioned { #[derive(Clone, Debug)] pub struct SpongeV1Schematic { - pub metadata: HashMap, + pub metadata: CompoundTag, pub width: u16, pub height: u16, pub length: u16, @@ -108,7 +108,7 @@ pub struct SpongeV1Schematic { #[derive(Clone, Debug)] pub struct SpongeV2Schematic { pub data_version: i32, - pub metadata: HashMap, + pub metadata: CompoundTag, pub width: u16, pub height: u16, pub length: u16, @@ -123,7 +123,7 @@ pub struct SpongeV2Schematic { #[derive(Clone, Debug)] pub struct SpongeV3Schematic { pub data_version: i32, - pub metadata: HashMap, + pub metadata: CompoundTag, pub width: u16, pub height: u16, pub length: u16, @@ -149,7 +149,7 @@ pub struct BlockEntity { pub struct BlockEntityV3 { pub id: String, pub pos: [i32; 3], - pub data: HashMap, + pub data: HashMap, } #[derive(Debug, Clone)] @@ -159,17 +159,9 @@ pub struct Entity { } impl SchematicVersioned { - pub fn load_data(data: R) -> Result where R: Read { - let nbt: HashMap = nbt::de::from_gzip_reader(data).map_err(|e| e.to_string())?; - let version = match nbt.get("Version") { - Some(version) => match version { - Value::Short(n) => *n as i32, - Value::Byte(n) => *n as i32, - Value::Int(n) => *n, - _ => return Err("Invalid schematic: Wrong Version Type".to_string()), - }, - None => return Err("Invalid schematic: Version not Found".to_string()), - }; + 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)?)), @@ -180,212 +172,99 @@ impl SchematicVersioned { } pub fn load(path: &PathBuf) -> Result { - let file = std::fs::File::open(path).map_err(|e| e.to_string())?; - Self::load_data(file) + 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: HashMap) -> Result { + pub fn from_nbt(nbt: CompoundTag) -> Result { Ok(Self { - metadata: match nbt.get("Metadata").ok_or("Invalid schematic: Metadata not found".to_string())? { - Value::Compound(metadata) => metadata.clone(), - _ => return Err("Invalid schematic: Metadata Wrong Type".to_string()), - }, - width: match nbt.get("Width").ok_or("Invalid schematic: Width not found".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Width Wrong Type".to_string()), - }, - height: match nbt.get("Height").ok_or("Invalid schematic: Height not found".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Height Wrong Type".to_string()), - }, - length: match nbt.get("Length").ok_or("Invalid schematic: Length not found".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Length Wrong Type".to_string()), - }, - offset: read_offset(nbt.get("Offset"))?, - palette_max: match nbt.get("PaletteMax").ok_or("Invalid schematic: PaletteMax not found".to_string())? { - Value::Int(p) => *p, - _ => return Err("Invalid schematic: PaletteMax Wrong Type".to_string()), - }, - palette: read_palette(nbt.get("Palette"))?, - block_data: read_blocks(nbt.get("BlockData"))?, - tile_entities: read_tile_entities(nbt.get("TileEntities"))?, + 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: HashMap) -> Result { + pub fn from_nbt(nbt: CompoundTag) -> Result { Ok(Self{ - data_version: match nbt.get("DataVersion").ok_or("Invalid schematic: DataVersion Missing".to_string())? { - Value::Short(n) => *n as i32, - Value::Byte(n) => *n as i32, - Value::Int(n) => *n, - _ => return Err("Invalid schematic: DataVersion Wrong Type".to_string()), - }, - metadata: match nbt.get("Metadata").ok_or("Invalid schematic".to_string())? { - Value::Compound(m) => m.clone(), - _ => return Err("Invalid schematic: Metadata Wrong Type".to_string()), - }, - width: match nbt.get("Width").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Width Wrong Type".to_string()), - }, - height: match nbt.get("Height").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Height Wrong Type".to_string()), - }, - length: match nbt.get("Length").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic: Length Wrong Type".to_string()), - }, - offset: read_offset(nbt.get("Offset"))?, - palette_max: match nbt.get("PaletteMax").ok_or("Invalid schematic: PaletteMax Missing".to_string())? { - Value::Short(n) => *n as i32, - Value::Byte(n) => *n as i32, - Value::Int(n) => *n, - _ => return Err("Invalid schematic: PaletteMax Invalid Type".to_string()), - }, - palette: read_palette(nbt.get("Palette"))?, - block_data: read_blocks(nbt.get("BlockData"))?, - block_entities: read_tile_entities(nbt.get("BlockEntities"))?, + 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: HashMap) -> Result { + pub fn from_nbt(nbt: CompoundTag) -> Result { + let blocks = nbt.get_compound_tag("Blocks").map_err(|e| e.to_string())?; Ok(Self{ - data_version: match nbt.get("DataVersion").ok_or("Invalid schematic".to_string())? { - Value::Int(d) => *d, - _ => return Err("Invalid schematic".to_string()), - }, - metadata: match nbt.get("Metadata").ok_or("Invalid schematic".to_string())? { - Value::Compound(m) => m.clone(), - _ => return Err("Invalid schematic".to_string()), - }, - width: match nbt.get("Width").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic".to_string()), - }, - height: match nbt.get("Height").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic".to_string()), - }, - length: match nbt.get("Length").ok_or("Invalid schematic".to_string())? { - Value::Short(n) => *n as u16, - Value::Byte(n) => *n as u16, - _ => return Err("Invalid schematic".to_string()), - }, - offset: read_offset(nbt.get("Offset"))?, - blocks: match nbt.get("Blocks").ok_or("Invalid schematic".to_string())? { - Value::Compound(b) => { - BlockContainer { - palette: read_palette(b.get("Palette"))?, - block_data: read_blocks(b.get("BlockData"))?, - block_entities: read_tile_entities(b.get("BlockEntities"))?, - } - } - _ => return Err("Invalid schematic".to_string()), + 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: Option<&Value>) -> Result, String> { - match tag.ok_or("Invalid schematic: read_tile_entities not found".to_string())? { - Value::List(t) => { - let mut tile_entities = Vec::new(); - for te in t.iter() { - match te { - Value::Compound(te) => { - let id = match te.get("Id") { - None => return Err("Invalid schematic: Id Not Found".to_string()), - Some(id) => match id { - Value::String(id) => id.clone(), - _ => return Err("Invalid schematic: Id Wrong Type".to_string()), - }, - }; - let pos = read_offset(te.get("Pos"))?; - tile_entities.push(BlockEntity { id, pos }); - }, - _ => return Err("Invalid schematic: te Wrong Type".to_string()), - }; - } - Ok(tile_entities) - }, - Value::ByteArray(_) => Ok(vec![]), - _ => return Err("Invalid schematic: te wrong type".to_string()), +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_offset(offset: Option<&Value>) -> Result<[i32; 3], String> { - match offset.ok_or("Invalid schematic: read_offset missing".to_string())? { - Value::IntArray(o) => match o.len() { - 3 => Ok([o[0], o[1], o[2]]), - _ => Err("Invalid schematic: Invalid IntArray".to_string()), - }, - Value::ByteArray(o) => match o.len() { - 3 => Ok([o[0] as i32, o[1] as i32, o[2] as i32]), - _ => Err("Invalid schematic: Invalid byteArray".to_string()), - }, - Value::List(l) => match l.len() { - 3 => { - let mut offset = [0; 3]; - for (i, v) in l.iter().enumerate() { - match v { - Value::Int(n) => offset[i] = *n, - Value::Byte(n) => offset[i] = *n as i32, - Value::Short(n) => offset[i] = *n as i32, - _ => return Err("Invalid schematic: read_offset invalid Number".to_string()), - }; - } - Ok(offset) - }, - _ => Err("Invalid schematic: Invalid List".to_string()), - } - _ => Err("Invalid schematic: read_offset".to_string()), +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_palette(palette: Option<&Value>) -> Result, String> { - match palette.ok_or("Invalid schematic: read_palette missing".to_string())? { - Value::Compound(p) => { - let mut palette = HashMap::new(); - for (k, v) in p.iter() { - match v { - Value::Int(v) => { palette.insert(k.clone(), *v); }, - Value::Byte(v) => { palette.insert(k.clone(), *v as i32); }, - Value::Short(v) => { palette.insert(k.clone(), *v as i32); }, - _ => return Err("Invalid schematic: read_palette invalid Number".to_string()), - }; - } - Ok(palette) - }, - _ => Err("Invalid schematic: read_palette invalid Type".to_string()), - } -} - -#[inline] -fn read_blocks(blockdata: Option<&Value>) -> Result, String> { - match blockdata.ok_or("Invalid schematic: BlockData not found".to_string())? { - Value::ByteArray(b) => Ok(read_varint_array(b)), - _ => Err("Invalid schematic: Invalid BlockData".to_string()), - } +fn read_blocks(blockdata: &Vec) -> Vec { + read_varint_array(blockdata) } #[inline] diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index 96602a9..5c33e50 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -7,4 +7,6 @@ license = "AGPL-3.0-or-later" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +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 3892e50..ce5d599 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -17,6 +17,7 @@ pub mod pattern_mapper; +use serde::{Serialize, Deserialize}; use pattern_mapper::match_palette; use schemsearch_files::SchematicVersioned; use crate::pattern_mapper::match_palette_adapt; diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index 8f3ddea..a74dab5 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -15,7 +15,8 @@ * along with this program. If not, see . */ -use nbt::Map; +use std::collections::HashMap; +use nbt::CompoundTag; use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; use crate::normalize_data; @@ -31,7 +32,7 @@ fn create_reverse_palette(schem: &SchematicVersioned) -> Vec<&str> { 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); @@ -56,7 +57,7 @@ pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { height: schem.get_height(), length: schem.get_length(), width: schem.get_width(), - metadata: Map::new(), + metadata: CompoundTag::new(), offset: [0; 3], entities: None, },) @@ -64,7 +65,7 @@ pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned { } -pub fn match_palette_adapt(schem: &SchematicVersioned, 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); @@ -109,7 +110,7 @@ fn match_palette_internal( height: pattern.get_height(), length: pattern.get_length(), width: pattern.get_width(), - metadata: Map::new(), + metadata: CompoundTag::new(), offset: [0; 3], entities: None, }) From 4671f38591881b92036d293b372192b1ca39a375 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 22 Apr 2023 21:55:08 +0200 Subject: [PATCH 9/9] Bump Version --- README.md | 1 - schemsearch-cli/Cargo.toml | 2 +- schemsearch-faster/Cargo.toml | 2 +- schemsearch-files/Cargo.toml | 2 +- schemsearch-java/Cargo.toml | 2 +- schemsearch-lib/Cargo.toml | 2 +- schemsearch-sql/Cargo.toml | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) 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-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-files/Cargo.toml b/schemsearch-files/Cargo.toml index 8134d7e..0b65862 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -1,6 +1,6 @@ [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 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-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index 5c33e50..aa7c963 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "schemsearch-lib" -version = "0.1.2" +version = "0.1.3" edition = "2021" license = "AGPL-3.0-or-later" 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"