From d48910ecb466bee6cb481abbde1e504fa1b5059a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 21 Mar 2023 14:21:30 +0100 Subject: [PATCH] A very rude implementation for Tile-Entity Search --- schemsearch-cli/src/main.rs | 16 ++++++--- schemsearch-cli/src/types.rs | 1 - schemsearch-files/src/lib.rs | 6 ++++ schemsearch-java/src/lib.rs | 9 +---- schemsearch-lib/src/lib.rs | 66 ++++++++++++++++++++++-------------- 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index 2faa752..0ac41c6 100644 --- a/schemsearch-cli/src/main.rs +++ b/schemsearch-cli/src/main.rs @@ -65,10 +65,17 @@ fn main() { .action(ArgAction::SetTrue), ) .arg( - Arg::new("ignore-block-entities") - .help("Ignores block entities when searching [Not Implemented]") + Arg::new("ignore-tile-entities") + .help("Ignores tile entities when searching [Not Implemented]") .short('b') - .long("ignore-block-entities") + .long("ignore-tile-entities") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("ignore-tile-entity-data") + .help("Ignores tile entity data when searching [Not Implemented]") + .short('B') + .long("ignore-tile-entity-data") .action(ArgAction::SetTrue), ) .arg( @@ -179,7 +186,8 @@ fn main() { let search_behavior = SearchBehavior { ignore_block_data: matches.get_flag("ignore-data"), - ignore_block_entities: matches.get_flag("ignore-block-entities"), + ignore_tile_entities: matches.get_flag("ignore-tile-entities"), + ignore_tile_entity_data: matches.get_flag("ignore-tile-entity-data"), ignore_air: matches.get_flag("ignore-air"), air_as_any: matches.get_flag("air-as-any"), ignore_entities: matches.get_flag("ignore-entities"), diff --git a/schemsearch-cli/src/types.rs b/schemsearch-cli/src/types.rs index c2127c7..ee0451f 100644 --- a/schemsearch-cli/src/types.rs +++ b/schemsearch-cli/src/types.rs @@ -18,7 +18,6 @@ use std::path::PathBuf; #[cfg(feature = "sql")] use futures::executor::block_on; -use schemsearch_files::Schematic; #[cfg(feature = "sql")] use schemsearch_sql::{load_schemdata, SchematicNode}; diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index b900f74..1efa58b 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -62,6 +62,9 @@ pub struct BlockEntity { pub id: String, #[serde(rename = "Pos")] pub pos: [i32; 3], + + #[serde(flatten)] + pub data: Map, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -70,6 +73,9 @@ pub struct Entity { pub id: String, #[serde(rename = "Pos")] pub pos: [i32; 3], + + #[serde(flatten)] + pub data: Map, } impl Schematic { diff --git a/schemsearch-java/src/lib.rs b/schemsearch-java/src/lib.rs index 4323c55..77b0c6a 100644 --- a/schemsearch-java/src/lib.rs +++ b/schemsearch-java/src/lib.rs @@ -35,14 +35,7 @@ pub extern "system" fn Java_SchemSearch_search<'local>(mut env: JNIEnv<'local>, let schematic = Schematic::load(&PathBuf::from(&schematic_path)).unwrap(); let pattern = Schematic::load(&PathBuf::from(&pattern_path)).unwrap(); - let matches = search(schematic, &pattern, SearchBehavior { - ignore_block_data: true, - ignore_block_entities: true, - ignore_entities: true, - ignore_air: false, - air_as_any: false, - threshold: 0.0, - }); + let matches = search(schematic, &pattern, SearchBehavior::default()); let mut result = String::new(); for (x, y, z, p) in matches { diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index 68b5c6c..47c191e 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -25,13 +25,28 @@ use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] pub struct SearchBehavior { pub ignore_block_data: bool, - pub ignore_block_entities: bool, + pub ignore_tile_entities: bool, + pub ignore_tile_entity_data: bool, pub ignore_air: bool, pub air_as_any: bool, pub ignore_entities: bool, pub threshold: f32, } +impl Default for SearchBehavior { + fn default() -> Self { + SearchBehavior { + ignore_block_data: true, + ignore_tile_entities: true, + ignore_tile_entity_data: false, + ignore_entities: true, + ignore_air: false, + air_as_any: false, + threshold: 90.0, + } + } +} + pub fn search( schem: Schematic, pattern_schem: &Schematic, @@ -61,7 +76,7 @@ pub fn search( let air_id = if search_behavior.ignore_air || search_behavior.air_as_any { pattern_schem.palette.get("minecraft:air").unwrap_or(&-1) } else { &-1}; - let pattern_blocks = (pattern_schem.width * pattern_schem.height * pattern_schem.length) as f32; + let pattern_blocks = (pattern_schem.width * pattern_schem.height * pattern_schem.length) as f32 + if search_behavior.ignore_tile_entities { 0.0 } else { pattern_schem.block_entities.len() as f32 }; let pattern_width = pattern_schem.width as usize; let pattern_height = pattern_schem.height as usize; @@ -88,6 +103,26 @@ pub fn search( } } } + if !search_behavior.ignore_tile_entities { + for tile_entity in &pattern_schem.block_entities { + for entry in &schem.block_entities { + if tile_entity.id.as_str() == entry.id.as_str() { + let pos = tile_entity.pos; + let schem_pos = [pos[0] + x as i32, pos[1] + y as i32, pos[2] + z as i32]; + if schem_pos == entry.pos { + if search_behavior.ignore_tile_entity_data { + matching += 1; + } else { + if tile_entity.data == entry.data { + matching += 1; + } + } + } + } + } + } + } + let matching_percent = matching as f32 / pattern_blocks; if matching_percent >= search_behavior.threshold { matches.push((x as u16, y as u16, z as u16, matching_percent)); @@ -170,14 +205,7 @@ mod tests { let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); - let _ = search(schematic, &endstone, SearchBehavior { - ignore_block_data: true, - ignore_block_entities: true, - ignore_entities: true, - ignore_air: false, - air_as_any: false, - threshold: 0.9 - }); + let _ = search(schematic, &endstone, SearchBehavior::default()); } #[test] @@ -185,14 +213,7 @@ mod tests { let schematic = Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); let pattern = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); - let matches = search(schematic, &pattern, SearchBehavior { - ignore_block_data: true, - ignore_block_entities: true, - ignore_entities: true, - ignore_air: false, - air_as_any: false, - threshold: 0.9 - }); + let matches = search(schematic, &pattern, SearchBehavior::default()); println!("{:?}", matches); assert_eq!(matches.len(), 1); @@ -204,14 +225,7 @@ mod tests { 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 matches = search(schematic, &pattern, SearchBehavior { - ignore_block_data: false, - ignore_block_entities: false, - ignore_entities: false, - ignore_air: false, - air_as_any: false, - threshold: 0.9 - }); + let matches = search(schematic, &pattern, SearchBehavior::default()); println!("{:?}", matches); assert_eq!(matches.len(), 1);