Mirror von
https://github.com/Chaoscaot/schemsearch
synchronisiert 2024-11-16 17:00:14 +01:00
Commits vergleichen
3 Commits
246927d840
...
5cff84538d
Autor | SHA1 | Datum | |
---|---|---|---|
|
5cff84538d | ||
|
9a0b0535c6 | ||
|
a47c2f44bd |
@ -7,7 +7,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flate2 = "1.0.25"
|
flate2 = "1.0.25"
|
||||||
fastnbt = "2.4.3"
|
named-binary-tag = "0.6"
|
||||||
serde = "1.0.152"
|
|
||||||
serde_json = "1.0.84"
|
|
||||||
|
|
||||||
|
@ -15,25 +15,12 @@
|
|||||||
* 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 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 fastnbt::error::Error;
|
use nbt::{CompoundTag, Tag};
|
||||||
use fastnbt::Value;
|
|
||||||
use flate2::read::GzDecoder;
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
|
||||||
use serde::de::value::MapDeserializer;
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
struct SchematicRaw {
|
|
||||||
version: i32,
|
|
||||||
#[serde(flatten)]
|
|
||||||
data: HashMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
#[serde(untagged, rename_all = "PascalCase")]
|
|
||||||
pub enum SchematicVersioned {
|
pub enum SchematicVersioned {
|
||||||
V1(SpongeV1Schematic),
|
V1(SpongeV1Schematic),
|
||||||
V2(SpongeV2Schematic),
|
V2(SpongeV2Schematic),
|
||||||
@ -105,65 +92,38 @@ impl SchematicVersioned {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<SchematicRaw> for SchematicVersioned {
|
#[derive(Clone, Debug)]
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn try_from(value: SchematicRaw) -> Result<Self, Self::Error> {
|
|
||||||
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")]
|
|
||||||
pub struct SpongeV1Schematic {
|
pub struct SpongeV1Schematic {
|
||||||
pub metadata: HashMap<String, Value>,
|
pub metadata: CompoundTag,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
pub offset: [i32; 3],
|
pub offset: [i32; 3],
|
||||||
pub palette_max: i32,
|
pub palette_max: i32,
|
||||||
pub palette: HashMap<String, i32>,
|
pub palette: HashMap<String, i32>,
|
||||||
#[serde(deserialize_with = "read_blockdata")]
|
|
||||||
pub block_data: Vec<i32>,
|
pub block_data: Vec<i32>,
|
||||||
pub tile_entities: Vec<BlockEntity>,
|
pub tile_entities: Vec<BlockEntity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct SpongeV2Schematic {
|
pub struct SpongeV2Schematic {
|
||||||
pub data_version: i32,
|
pub data_version: i32,
|
||||||
pub metadata: HashMap<String, Value>,
|
pub metadata: CompoundTag,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
pub offset: [i32; 3],
|
pub offset: [i32; 3],
|
||||||
pub palette_max: i32,
|
pub palette_max: i32,
|
||||||
pub palette: HashMap<String, i32>,
|
pub palette: HashMap<String, i32>,
|
||||||
#[serde(deserialize_with = "read_blockdata")]
|
|
||||||
pub block_data: Vec<i32>,
|
pub block_data: Vec<i32>,
|
||||||
pub block_entities: Vec<BlockEntity>,
|
pub block_entities: Vec<BlockEntity>,
|
||||||
pub entities: Option<Vec<Entity>>,
|
pub entities: Option<Vec<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct SpongeV3Schematic {
|
pub struct SpongeV3Schematic {
|
||||||
pub data_version: i32,
|
pub data_version: i32,
|
||||||
pub metadata: HashMap<String, Value>,
|
pub metadata: CompoundTag,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
@ -172,57 +132,142 @@ pub struct SpongeV3Schematic {
|
|||||||
pub entities: Option<Vec<Entity>>,
|
pub entities: Option<Vec<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct BlockContainer {
|
pub struct BlockContainer {
|
||||||
pub palette: HashMap<String, i32>,
|
pub palette: HashMap<String, i32>,
|
||||||
#[serde(deserialize_with = "read_blockdata")]
|
|
||||||
pub block_data: Vec<i32>,
|
pub block_data: Vec<i32>,
|
||||||
pub block_entities: Vec<BlockEntity>,
|
pub block_entities: Vec<BlockEntity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_blockdata<'de, D>(deserializer: D) -> Result<Vec<i32>, D::Error>
|
#[derive(Debug, Clone)]
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let s: Vec<i8> = Deserialize::deserialize(deserializer)?;
|
|
||||||
Ok(read_varint_array(&s))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct BlockEntity {
|
pub struct BlockEntity {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub pos: [i32; 3],
|
pub pos: [i32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct BlockEntityV3 {
|
pub struct BlockEntityV3 {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub pos: [i32; 3],
|
pub pos: [i32; 3],
|
||||||
pub data: HashMap<String, Value>,
|
pub data: HashMap<String, Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub pos: [i32; 3],
|
pub pos: [i32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SchematicVersioned {
|
impl SchematicVersioned {
|
||||||
pub fn load_data<R>(data: R) -> Result<SchematicVersioned, Error> where R: Read {
|
pub fn load_data<R>(data: &mut R) -> Result<SchematicVersioned, String> where R: Read {
|
||||||
let raw: SchematicRaw = fastnbt::from_reader(GzDecoder::new(data))?;
|
let nbt: CompoundTag = nbt::decode::read_gzip_compound_tag(data).map_err(|e| e.to_string())?;
|
||||||
SchematicVersioned::try_from(raw)
|
let version = nbt.get_i32("Version").map_err(|e| e.to_string())?;
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load(path: &PathBuf) -> Result<SchematicVersioned, Error> {
|
match version {
|
||||||
let file = std::fs::File::open(path)?;
|
1 => Ok(SchematicVersioned::V1(SpongeV1Schematic::from_nbt(nbt)?)),
|
||||||
Self::load_data(file)
|
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<SchematicVersioned, String> {
|
||||||
|
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: CompoundTag) -> Result<Self, String> {
|
||||||
|
Ok(Self {
|
||||||
|
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: CompoundTag) -> Result<Self, String> {
|
||||||
|
Ok(Self{
|
||||||
|
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: CompoundTag) -> Result<Self, String> {
|
||||||
|
let blocks = nbt.get_compound_tag("Blocks").map_err(|e| e.to_string())?;
|
||||||
|
Ok(Self{
|
||||||
|
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: Vec<&CompoundTag>) -> Result<Vec<BlockEntity>, 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<i32>) -> 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_palette(p: &CompoundTag) -> HashMap<String, i32> {
|
||||||
|
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_blocks(blockdata: &Vec<i8>) -> Vec<i32> {
|
||||||
|
read_varint_array(blockdata)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn read_varint_array(read: &Vec<i8>) -> Vec<i32> {
|
pub fn read_varint_array(read: &Vec<i8>) -> Vec<i32> {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
let mut value: i32 = 0;
|
let mut value: i32 = 0;
|
||||||
|
@ -7,6 +7,6 @@ license = "AGPL-3.0-or-later"
|
|||||||
# 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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hematite-nbt = "0.5.2"
|
serde = { version = "1.0.160", features = ["derive"] }
|
||||||
serde = "1.0.152"
|
|
||||||
schemsearch-files = { path = "../schemsearch-files" }
|
schemsearch-files = { path = "../schemsearch-files" }
|
||||||
|
named-binary-tag = "0.6"
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
pub mod pattern_mapper;
|
pub mod pattern_mapper;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use pattern_mapper::match_palette;
|
use pattern_mapper::match_palette;
|
||||||
use schemsearch_files::SchematicVersioned;
|
use schemsearch_files::SchematicVersioned;
|
||||||
use crate::pattern_mapper::match_palette_adapt;
|
use crate::pattern_mapper::match_palette_adapt;
|
||||||
@ -136,7 +136,7 @@ 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 serde::de::Unexpected::Map;
|
use schemsearch_files::SchematicVersioned::V2;
|
||||||
use schemsearch_files::SpongeV2Schematic;
|
use schemsearch_files::SpongeV2Schematic;
|
||||||
use crate::pattern_mapper::strip_data;
|
use crate::pattern_mapper::strip_data;
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -245,26 +245,4 @@ mod tests {
|
|||||||
println!("{:?}", matches);
|
println!("{:?}", matches);
|
||||||
assert_eq!(matches.len(), 1);
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* 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::Map;
|
use std::collections::HashMap;
|
||||||
|
use nbt::CompoundTag;
|
||||||
use schemsearch_files::{SchematicVersioned, SpongeV2Schematic};
|
use schemsearch_files::{SchematicVersioned, SpongeV2Schematic};
|
||||||
use crate::normalize_data;
|
use crate::normalize_data;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ fn create_reverse_palette(schem: &SchematicVersioned) -> Vec<&str> {
|
|||||||
pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned {
|
pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned {
|
||||||
let mut data: Vec<i32> = Vec::new();
|
let mut data: Vec<i32> = Vec::new();
|
||||||
|
|
||||||
let mut palette: Map<String, i32> = Map::new();
|
let mut palette: HashMap<String, i32> = HashMap::new();
|
||||||
let mut palette_max: i32 = 0;
|
let mut palette_max: i32 = 0;
|
||||||
let reverse_palette = create_reverse_palette(schem);
|
let reverse_palette = create_reverse_palette(schem);
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned {
|
|||||||
height: schem.get_height(),
|
height: schem.get_height(),
|
||||||
length: schem.get_length(),
|
length: schem.get_length(),
|
||||||
width: schem.get_width(),
|
width: schem.get_width(),
|
||||||
metadata: Map::new(),
|
metadata: CompoundTag::new(),
|
||||||
offset: [0; 3],
|
offset: [0; 3],
|
||||||
entities: None,
|
entities: None,
|
||||||
},)
|
},)
|
||||||
@ -64,7 +65,7 @@ pub fn strip_data(schem: &SchematicVersioned) -> SchematicVersioned {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &Map<String, i32>, ignore_data: bool) -> Vec<i32> {
|
pub fn match_palette_adapt(schem: &SchematicVersioned, matching_palette: &HashMap<String, i32>, ignore_data: bool) -> Vec<i32> {
|
||||||
let mut data: Vec<i32> = Vec::new();
|
let mut data: Vec<i32> = Vec::new();
|
||||||
let reverse_palette = create_reverse_palette(schem);
|
let reverse_palette = create_reverse_palette(schem);
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ fn match_palette_internal(
|
|||||||
height: pattern.get_height(),
|
height: pattern.get_height(),
|
||||||
length: pattern.get_length(),
|
length: pattern.get_length(),
|
||||||
width: pattern.get_width(),
|
width: pattern.get_width(),
|
||||||
metadata: Map::new(),
|
metadata: CompoundTag::new(),
|
||||||
offset: [0; 3],
|
offset: [0; 3],
|
||||||
entities: None,
|
entities: None,
|
||||||
})
|
})
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren