2 Commits

Author SHA1 Message Date
Chaoscaot d39e876885 Slower: 1000ms 2024-10-30 21:39:43 +00:00
Chaoscaot 1e8d5d6311 Experimental: Cosine-Distance Matcher 2024-10-30 21:10:41 +00:00
4 changed files with 42 additions and 79 deletions
+1 -1
View File
@@ -259,7 +259,7 @@ fn main() {
if let Some(x) = matches.get_many::<String>("sql-filter-name") { if let Some(x) = matches.get_many::<String>("sql-filter-name") {
filter = filter.name(x.collect()); filter = filter.name(x.collect());
} }
for schem in block_on(load_all_schematics(filter, *matches.get_one::<usize>("threads").expect("Could not get Threads") as u32)) { for schem in block_on(load_all_schematics(filter)) {
schematics.push(SchematicSupplierType::SQL(SqlSchematicSupplier { schematics.push(SchematicSupplierType::SQL(SqlSchematicSupplier {
node: schem node: schem
})) }))
+18 -49
View File
@@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
use nbt::{CompoundTag, Tag};
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use std::io::Read; use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use nbt::{CompoundTag, Tag};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SpongeSchematic { pub struct SpongeSchematic {
@@ -62,12 +62,8 @@ pub struct Entity {
} }
impl SpongeSchematic { impl SpongeSchematic {
pub fn load_data<R>(data: &mut R) -> Result<SpongeSchematic, String> pub fn load_data<R>(data: &mut R) -> Result<SpongeSchematic, String> where R: Read {
where let nbt: CompoundTag = nbt::decode::read_gzip_compound_tag(data).map_err(|e| e.to_string())?;
R: Read,
{
let nbt: CompoundTag =
nbt::decode::read_gzip_compound_tag(data).map_err(|e| e.to_string())?;
let version = nbt.get_i32("Version").unwrap_or_else(|_| { let version = nbt.get_i32("Version").unwrap_or_else(|_| {
return if nbt.contains_key("Blocks") { return if nbt.contains_key("Blocks") {
3 3
@@ -83,10 +79,7 @@ impl SpongeSchematic {
match version { match version {
1 => SpongeSchematic::from_nbt_1(nbt), 1 => SpongeSchematic::from_nbt_1(nbt),
2 => SpongeSchematic::from_nbt_2(nbt), 2 => SpongeSchematic::from_nbt_2(nbt),
3 => SpongeSchematic::from_nbt_3( 3 => SpongeSchematic::from_nbt_3(nbt),
nbt.get_compound_tag("Schematic")
.map_err(|e| e.to_string())?,
),
_ => Err("Invalid schematic: Unknown Version".to_string()), _ => Err("Invalid schematic: Unknown Version".to_string()),
} }
} }
@@ -99,10 +92,7 @@ impl SpongeSchematic {
pub fn from_nbt_1(nbt: CompoundTag) -> Result<Self, String> { pub fn from_nbt_1(nbt: CompoundTag) -> Result<Self, String> {
Ok(Self { Ok(Self {
data_version: 0, data_version: 0,
metadata: nbt metadata: nbt.get_compound_tag("Metadata").map_err(|e| e.to_string())?.clone(),
.get_compound_tag("Metadata")
.map(|v| v.clone())
.unwrap_or_else(|_| CompoundTag::new()),
width: nbt.get_i16("Width").map_err(|e| e.to_string())? as u16, 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, 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, length: nbt.get_i16("Length").map_err(|e| e.to_string())? as u16,
@@ -110,10 +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( block_entities: read_tile_entities(nbt.get_compound_tag_vec("TileEntities").unwrap_or_else(|_| vec![]))?,
nbt.get_compound_tag_vec("TileEntities")
.unwrap_or_else(|_| vec![]),
)?,
entities: None, entities: None,
}) })
} }
@@ -121,10 +108,7 @@ impl SpongeSchematic {
pub fn from_nbt_2(nbt: CompoundTag) -> Result<Self, String> { pub fn from_nbt_2(nbt: CompoundTag) -> Result<Self, String> {
Ok(Self{ Ok(Self{
data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?, data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?,
metadata: nbt metadata: nbt.get_compound_tag("Metadata").map_err(|e| e.to_string())?.clone(),
.get_compound_tag("Metadata")
.map(|v| v.clone())
.unwrap_or_else(|_| CompoundTag::new()),
width: nbt.get_i16("Width").map_err(|e| e.to_string())? as u16, 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, 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, length: nbt.get_i16("Length").map_err(|e| e.to_string())? as u16,
@@ -132,33 +116,28 @@ 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( block_entities: read_tile_entities(nbt.get_compound_tag_vec("BlockEntities").unwrap_or_else(|_| vec![]))?,
nbt.get_compound_tag_vec("BlockEntities")
.unwrap_or_else(|_| vec![]),
)?,
entities: None, entities: None,
}) })
} }
pub fn from_nbt_3(nbt: &CompoundTag) -> Result<Self, String> { pub fn from_nbt_3(nbt: CompoundTag) -> Result<Self, String> {
let blocks = nbt.get_compound_tag("Blocks").map_err(|e| e.to_string())?; let blocks = nbt.get_compound_tag("Blocks").map_err(|e| e.to_string())?;
Ok(Self{ Ok(Self{
data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?, data_version: nbt.get_i32("DataVersion").map_err(|e| e.to_string())?,
metadata: nbt metadata: nbt.get_compound_tag("Metadata").map_err(|e| e.to_string())?.clone(),
.get_compound_tag("Metadata")
.map(|v| v.clone())
.unwrap_or_else(|_| CompoundTag::new()),
width: nbt.get_i16("Width").map_err(|e| e.to_string())? as u16, 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, 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, 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())?)?, offset: read_offset(nbt.get_i32_vec("Offset").map_err(|e| e.to_string())?)?,
palette_max: compute_palette_max(blocks.get_compound_tag("Palette").map_err(|e| e.to_string())?) + 1, 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("Data").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").unwrap_or_else(|_| vec![]))?, block_entities: read_tile_entities(blocks.get_compound_tag_vec("BlockEntities").unwrap_or_else(|_| vec![]))?,
entities: None, entities: None,
}) })
} }
} }
fn read_tile_entities(tag: Vec<&CompoundTag>) -> Result<Vec<BlockEntity>, String> { fn read_tile_entities(tag: Vec<&CompoundTag>) -> Result<Vec<BlockEntity>, String> {
@@ -185,10 +164,8 @@ fn read_palette(p: &CompoundTag) -> HashMap<String, i32> {
let mut palette = HashMap::new(); let mut palette = HashMap::new();
for (key, value) in p.iter() { for (key, value) in p.iter() {
match value { match value {
Tag::Int(n) => { Tag::Int(n) => { palette.insert(key.clone(), *n); },
palette.insert(key.clone(), *n); _ => {},
}
_ => {}
}; };
} }
palette palette
@@ -196,15 +173,10 @@ fn read_palette(p: &CompoundTag) -> HashMap<String, i32> {
#[inline] #[inline]
fn compute_palette_max(palette: &CompoundTag) -> i32 { fn compute_palette_max(palette: &CompoundTag) -> i32 {
palette palette.iter().map(|(_, v)| v).filter_map(|v| match v {
.iter()
.map(|(_, v)| v)
.filter_map(|v| match v {
Tag::Int(n) => Some(*n), Tag::Int(n) => Some(*n),
_ => None, _ => None,
}) }).max().unwrap_or(0)
.max()
.unwrap_or(0)
} }
#[inline] #[inline]
@@ -221,10 +193,7 @@ pub fn read_varint_array(read: &Vec<i8>) -> Vec<i32> {
let mut cursor = 0; let mut cursor = 0;
loop { loop {
match read.get(cursor) { match read.get(cursor) {
Some(byte) => { Some(byte) => { current_byte = *byte as u8; cursor += 1; },
current_byte = *byte as u8;
cursor += 1;
}
None => break, None => break,
}; };
+11 -17
View File
@@ -43,40 +43,34 @@ 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 skip_amount = ceil((pattern_blocks * (1.0 - search_behavior.threshold)) as f64, 0) as i32; let pattern_vec_length = pattern_schem.block_data.iter().map(|x| x * x).sum::<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 {
let mut not_matching = 0; let mut dot_p: i32 = 0;
'outer: let mut schem_vec_length = 0;
for j in 0..pattern_height { for j in 0..pattern_height {
for k in 0..pattern_length { for k in 0..pattern_length {
'inner:
for i in 0..pattern_width { for i in 0..pattern_width {
let index = (x + i) + schem_width * ((z + k) + (y + j) * schem_length); let index = (x + i) + schem_width * ((z + k) + (y + j) * schem_length);
let pattern_index = i + pattern_width * (k + j * pattern_length); let pattern_index = i + pattern_width * (k + j * pattern_length);
let data = unsafe { *schem_data.add(index) };
let pattern_data = unsafe { *pattern_data.add(pattern_index) }; dot_p += unsafe { *pattern_data.add(pattern_index) * *schem_data.add(index) };
if (search_behavior.ignore_air && data != *air_id) || (search_behavior.air_as_any && pattern_data != *air_id) { schem_vec_length += unsafe { *schem_data.add(index) * *schem_data.add(index) };
continue 'inner;
}
if data != pattern_data {
not_matching += 1;
if not_matching >= skip_amount {
break 'outer;
}
}
} }
} }
} }
if not_matching < skip_amount { let sim = dot_p as f32 / ((pattern_vec_length as f32).sqrt() * (schem_vec_length as f32).sqrt());
if sim > 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: (i_pattern_blocks - not_matching) as f32 / pattern_blocks, percent: sim,
}); });
} }
} }
+6 -6
View File
@@ -30,12 +30,12 @@ pub struct SchematicNode {
pub name: String pub name: String
} }
pub async unsafe fn get_connection(connections: u32) { pub async unsafe fn get_connection() {
let mut conn = CONN.lock().unwrap(); let mut conn = CONN.lock().unwrap();
if conn.is_none() { if conn.is_none() {
let properties = properties::load_mysql_properties(); let properties = properties::load_mysql_properties();
let _ = conn.insert(MySqlPoolOptions::new() let _ = conn.insert(MySqlPoolOptions::new()
.max_connections(connections) .max_connections(5)
.connect_with(MySqlConnectOptions::new() .connect_with(MySqlConnectOptions::new()
.host(properties.host.as_str()) .host(properties.host.as_str())
.port(3306) .port(3306)
@@ -46,10 +46,10 @@ pub async unsafe fn get_connection(connections: u32) {
} }
} }
pub async fn load_all_schematics(filter: SchematicFilter, connections: u32) -> Vec<SchematicNode> { pub async fn load_all_schematics(filter: SchematicFilter) -> Vec<SchematicNode> {
unsafe { get_connection(connections).await; } unsafe { get_connection().await; }
let mut schematics = Vec::new(); let mut schematics = Vec::new();
let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_all(format!("SELECT SN.NodeId, SN.NodeName FROM NodeData ND INNER JOIN SchematicNode SN ON SN.NodeId = ND.NodeId WHERE NodeFormat >= 2 {}", filter.build()).as_str()).await.expect("Failed to fetch schematics"); let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_all(format!("SELECT SN.NodeId, SN.NodeName FROM NodeData ND INNER JOIN SchematicNode SN ON SN.NodeId = ND.NodeId WHERE NodeFormat = true {}", filter.build()).as_str()).await.expect("Failed to fetch schematics");
for row in rows { for row in rows {
schematics.push(SchematicNode { schematics.push(SchematicNode {
id: row.get(0), id: row.get(0),
@@ -60,7 +60,7 @@ pub async fn load_all_schematics(filter: SchematicFilter, connections: u32) -> V
} }
pub async fn load_schemdata(id: i32) -> Vec<u8> { pub async fn load_schemdata(id: i32) -> Vec<u8> {
unsafe { get_connection(5).await; } unsafe { get_connection().await; }
let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_one(format!("SELECT SchemData FROM NodeData WHERE NodeId = {}", id).as_str()).await.expect("Failed to fetch schematics"); let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_one(format!("SELECT SchemData FROM NodeData WHERE NodeId = {}", id).as_str()).await.expect("Failed to fetch schematics");
rows.get(0) rows.get(0)
} }