mirror of
https://github.com/Chaoscaot/schemsearch.git
synced 2025-11-10 15:47:05 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
582079c80d | ||
|
|
e25aeab065 | ||
|
|
aee3a80267 | ||
|
|
5107e04497 | ||
|
|
a357da2ce8 |
@@ -1,5 +1,5 @@
|
|||||||
# schemsearch
|
# schemsearch
|
||||||
### A *simple* CLI tool to search in Sponge V2 Schematic files
|
### A *simple* CLI tool to search in Sponge Schematic files
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "schemsearch-cli"
|
name = "schemsearch-cli"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "schemsearch-files"
|
name = "schemsearch-files"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -64,7 +64,17 @@ pub struct Entity {
|
|||||||
impl SpongeSchematic {
|
impl SpongeSchematic {
|
||||||
pub fn load_data<R>(data: &mut R) -> Result<SpongeSchematic, String> where R: Read {
|
pub fn load_data<R>(data: &mut R) -> Result<SpongeSchematic, String> where R: Read {
|
||||||
let nbt: CompoundTag = nbt::decode::read_gzip_compound_tag(data).map_err(|e| e.to_string())?;
|
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())?;
|
let version = nbt.get_i32("Version").unwrap_or_else(|_| {
|
||||||
|
return if nbt.contains_key("Blocks") {
|
||||||
|
3
|
||||||
|
} else if nbt.contains_key("BlockEntities") {
|
||||||
|
2
|
||||||
|
} else if nbt.contains_key("TileEntities") {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
match version {
|
match version {
|
||||||
1 => SpongeSchematic::from_nbt_1(nbt),
|
1 => SpongeSchematic::from_nbt_1(nbt),
|
||||||
@@ -90,7 +100,7 @@ impl SpongeSchematic {
|
|||||||
palette_max: nbt.get_i32("PaletteMax").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())?),
|
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_data: read_blocks(nbt.get_i8_vec("BlockData").map_err(|e| e.to_string())?),
|
||||||
block_entities: read_tile_entities(nbt.get_compound_tag_vec("TileEntities").map_err(|e| e.to_string())?)?,
|
block_entities: read_tile_entities(nbt.get_compound_tag_vec("TileEntities").unwrap_or_else(|_| vec![]))?,
|
||||||
entities: None,
|
entities: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -106,7 +116,7 @@ impl SpongeSchematic {
|
|||||||
palette_max: nbt.get_i32("PaletteMax").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())?),
|
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_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())?)?,
|
block_entities: read_tile_entities(nbt.get_compound_tag_vec("BlockEntities").unwrap_or_else(|_| vec![]))?,
|
||||||
entities: None,
|
entities: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -123,7 +133,7 @@ impl SpongeSchematic {
|
|||||||
palette_max: compute_palette_max(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?),
|
palette_max: compute_palette_max(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?),
|
||||||
palette: read_palette(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?),
|
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_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())?)?,
|
block_entities: read_tile_entities(blocks.get_compound_tag_vec("BlockEntities").unwrap_or_else(|_| vec![]))?,
|
||||||
entities: None,
|
entities: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "schemsearch-lib"
|
name = "schemsearch-lib"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ pub fn search(
|
|||||||
let schem_height = schem.height as usize;
|
let schem_height = schem.height as usize;
|
||||||
let schem_length = schem.length as usize;
|
let schem_length = schem.length as usize;
|
||||||
|
|
||||||
|
let matching_needed = (pattern_blocks * search_behavior.threshold) as i32;
|
||||||
|
|
||||||
for y in 0..=schem_height - pattern_height {
|
for y in 0..=schem_height - pattern_height {
|
||||||
for z in 0..=schem_length - pattern_length {
|
for z in 0..=schem_length - pattern_length {
|
||||||
for x in 0..=schem_width - pattern_width {
|
for x in 0..=schem_width - pattern_width {
|
||||||
@@ -88,13 +90,12 @@ pub fn search(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let matching_percent = matching as f32 / pattern_blocks;
|
if matching >= matching_needed {
|
||||||
if matching_percent >= search_behavior.threshold {
|
|
||||||
matches.push(Match {
|
matches.push(Match {
|
||||||
x: x as u16,
|
x: x as u16,
|
||||||
y: y as u16,
|
y: y as u16,
|
||||||
z: z as u16,
|
z: z as u16,
|
||||||
percent: matching_percent,
|
percent: matching as f32 / pattern_blocks,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,19 +137,12 @@ pub fn normalize_data(data: &str, ignore_data: bool) -> &str {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use schemsearch_files::SchematicVersioned::V2;
|
|
||||||
use schemsearch_files::SpongeV2Schematic;
|
|
||||||
use crate::pattern_mapper::strip_data;
|
use crate::pattern_mapper::strip_data;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_schematic() {
|
fn read_schematic() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
|
|
||||||
let schematic = match schematic {
|
|
||||||
V2 (schematic) => schematic,
|
|
||||||
_ => panic!("Invalid schematic version"),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len());
|
assert_eq!(schematic.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);
|
assert_eq!(schematic.palette_max, schematic.palette.len() as i32);
|
||||||
@@ -156,12 +150,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_function() {
|
fn test_parse_function() {
|
||||||
let schematic: SchematicVersioned = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
|
|
||||||
let schematic = match schematic {
|
|
||||||
V2 (schematic) => schematic,
|
|
||||||
_ => panic!("Invalid schematic version"),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len());
|
assert_eq!(schematic.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);
|
assert_eq!(schematic.palette_max, schematic.palette.len() as i32);
|
||||||
@@ -169,32 +158,32 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_strip_schem() {
|
fn test_strip_schem() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
let stripped = strip_data(&schematic);
|
let stripped = strip_data(&schematic);
|
||||||
|
|
||||||
assert_eq!(stripped.get_palette().keys().any(|k| k.contains('[')), false);
|
assert_eq!(stripped.palette.keys().any(|k| k.contains('[')), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_match_palette() {
|
fn test_match_palette() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
let endstone = SpongeSchematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
||||||
|
|
||||||
let _ = match_palette(&schematic, &endstone, true);
|
let _ = match_palette(&schematic, &endstone, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_match_palette_ignore_data() {
|
fn test_match_palette_ignore_data() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
let endstone = SpongeSchematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
||||||
|
|
||||||
let _ = match_palette(&schematic, &endstone, false);
|
let _ = match_palette(&schematic, &endstone, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_big_search() {
|
pub fn test_big_search() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/simple.schem")).unwrap();
|
||||||
let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
let endstone = SpongeSchematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap();
|
||||||
|
|
||||||
let _ = search(schematic, &endstone, SearchBehavior {
|
let _ = search(schematic, &endstone, SearchBehavior {
|
||||||
ignore_block_data: true,
|
ignore_block_data: true,
|
||||||
@@ -208,8 +197,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_search() {
|
pub fn test_search() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/Random.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/Random.schem")).unwrap();
|
||||||
let pattern = SchematicVersioned::load(&PathBuf::from("../tests/Pattern.schem")).unwrap();
|
let pattern = SpongeSchematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap();
|
||||||
|
|
||||||
let matches = search(schematic, &pattern, SearchBehavior {
|
let matches = search(schematic, &pattern, SearchBehavior {
|
||||||
ignore_block_data: true,
|
ignore_block_data: true,
|
||||||
@@ -230,8 +219,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_search_ws() {
|
pub fn test_search_ws() {
|
||||||
let schematic = SchematicVersioned::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap();
|
let schematic = SpongeSchematic::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap();
|
||||||
let pattern = SchematicVersioned::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap();
|
let pattern = SpongeSchematic::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap();
|
||||||
|
|
||||||
let matches = search(schematic, &pattern, SearchBehavior {
|
let matches = search(schematic, &pattern, SearchBehavior {
|
||||||
ignore_block_data: false,
|
ignore_block_data: false,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub fn strip_data(schem: &SpongeSchematic) -> SpongeSchematic {
|
|||||||
let reverse_palette = create_reverse_palette(schem);
|
let reverse_palette = create_reverse_palette(schem);
|
||||||
|
|
||||||
for block in schem.block_data.iter() {
|
for block in schem.block_data.iter() {
|
||||||
let block_name = reverse_palette[*block as usize].clone();
|
let block_name = reverse_palette[*block as usize];
|
||||||
let block_name = block_name.split('[').next().unwrap().to_string();
|
let block_name = block_name.split('[').next().unwrap().to_string();
|
||||||
|
|
||||||
let entry = palette.entry(block_name).or_insert_with(|| {
|
let entry = palette.entry(block_name).or_insert_with(|| {
|
||||||
@@ -61,8 +61,6 @@ pub fn strip_data(schem: &SpongeSchematic) -> SpongeSchematic {
|
|||||||
offset: [0; 3],
|
offset: [0; 3],
|
||||||
entities: None,
|
entities: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_palette_adapt(schem: &SpongeSchematic, matching_palette: &HashMap<String, i32>, ignore_data: bool) -> Vec<i32> {
|
pub fn match_palette_adapt(schem: &SpongeSchematic, matching_palette: &HashMap<String, i32>, ignore_data: bool) -> Vec<i32> {
|
||||||
|
|||||||
Reference in New Issue
Block a user