vintage_schematics/formats/
mod.rs1use std::io::BufReader;
19
20use color_eyre::{eyre, eyre::Context};
21use flate2::read::GzDecoder;
22use serde::Deserialize;
23use strum::IntoEnumIterator;
24
25use crate::{
26 Set,
27 convert::mods::Mod,
28 formats::internal::{Internal, MinecraftBlockCode},
29};
30
31pub mod common;
32pub mod internal;
33pub mod litematic;
34pub mod schematic;
35pub mod sponge;
36pub mod vanilla;
37pub mod world_edit;
38
39#[derive(Debug, Clone)]
41pub struct Settings {
42 pub replace_missing: bool,
44
45 pub mods: Set<Mod>,
47}
48
49impl Default for Settings {
50 fn default() -> Self {
51 Self {
52 replace_missing: true,
53 mods: Set::new(),
54 }
55 }
56}
57
58impl Settings {
59 #[must_use]
60 pub fn all() -> Self {
61 Self {
62 replace_missing: true,
63 mods: Mod::iter().collect(),
64 }
65 }
66}
67
68fn read<'a, T: Deserialize<'a>>(reader: impl std::io::Read, compressed: bool) -> eyre::Result<T> {
69 let schematic = if compressed {
70 mininbt::from_reader(GzDecoder::new(reader))
71 } else {
72 mininbt::from_reader(BufReader::new(reader))
73 };
74
75 schematic.context("failed to parse NBT")
76}
77
78pub trait Loadable {
79 fn load(reader: impl std::io::Read, compressed: bool) -> eyre::Result<Self>
89 where
90 Self: Sized;
91
92 fn modernise(&mut self);
94}
95
96pub trait Saveable {
97 fn save(internal: &mut Internal, settings: &Settings) -> Self
99 where
100 Self: Sized;
101
102 #[allow(dead_code)]
103 fn is_vintage_story(&self) -> bool;
104}
105
106pub trait ToInternal {
107 fn to_internal(self) -> eyre::Result<Internal>;
114}
115
116fn should_reject(block: &MinecraftBlockCode) -> bool {
118 matches!(block.name.as_str(), "minecraft:air" | "minecraft:cave_air" | "minecraft:void_air")
119 || block.name.ends_with("_door") && block.properties.get("half").is_some_and(|h| h == "upper")
123 || (block.name == "minecraft:chest" || block.name == "minecraft:trapped_chest") && block.properties.get("type").is_some_and(|t| t == "left")
124}