From 9cca860db36603c25d8854b9146f70ba996c0fcd Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 13 Apr 2023 16:16:02 +0200 Subject: [PATCH] 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