use crate::building::{palette_by_name, BuildingTool, Cuboid, SolidBrush, Sphere};
use crate::formats::manager::get_manager;
use crate::BlockState;
use crate::UniversalSchematic;
pub fn palette_gradient_ids(
name: &str,
start: (u8, u8, u8),
end: (u8, u8, u8),
steps: usize,
) -> Result<Vec<String>, String> {
let palette = palette_by_name(name)?;
if palette.is_empty() {
return Err(format!("Palette '{name}' is empty"));
}
Ok(palette.gradient_ids(start, end, steps))
}
pub fn palette_block_ids(name: &str) -> Result<Vec<String>, String> {
Ok(palette_by_name(name)?
.sorted_by_lightness()
.block_ids()
.map(str::to_string)
.collect())
}
pub fn palette_closest_block(name: &str, r: u8, g: u8, b: u8) -> Result<String, String> {
palette_by_name(name)?
.find_closest(&crate::blockpedia::ExtendedColorData::from_rgb(r, g, b))
.ok_or_else(|| format!("Palette '{name}' is empty"))
}
#[derive(Debug)]
pub struct ScriptingSchematic {
pub inner: UniversalSchematic,
}
impl ScriptingSchematic {
pub fn new(name: Option<String>) -> Self {
Self {
inner: UniversalSchematic::new(name.unwrap_or_else(|| "Unnamed".to_string())),
}
}
pub fn from_file(path: &str) -> Result<Self, String> {
let data = std::fs::read(path).map_err(|e| format!("Failed to read file: {}", e))?;
let manager = get_manager();
let manager = manager.lock().map_err(|e| format!("Lock error: {}", e))?;
let schematic = manager
.read(&data)
.map_err(|e| format!("Failed to parse schematic: {}", e))?;
Ok(Self { inner: schematic })
}
pub fn get_name(&self) -> String {
self.inner
.metadata
.name
.clone()
.unwrap_or_else(|| "Unnamed".to_string())
}
pub fn set_name(&mut self, name: &str) {
self.inner.metadata.name = Some(name.to_string());
}
pub fn get_author(&self) -> String {
self.inner.metadata.author.clone().unwrap_or_default()
}
pub fn set_author(&mut self, author: &str) {
self.inner.metadata.author = Some(author.to_string());
}
pub fn get_description(&self) -> String {
self.inner.metadata.description.clone().unwrap_or_default()
}
pub fn set_description(&mut self, desc: &str) {
self.inner.metadata.description = Some(desc.to_string());
}
pub fn set_block(&mut self, x: i32, y: i32, z: i32, name: &str) {
self.inner.set_block_str(x, y, z, name);
}
pub fn get_block(&self, x: i32, y: i32, z: i32) -> Option<String> {
self.inner.get_block(x, y, z).map(|b| b.to_string())
}
pub fn fill_cuboid(&mut self, min: (i32, i32, i32), max: (i32, i32, i32), block_name: &str) {
let shape = Cuboid::new(min, max);
let brush = SolidBrush::new(BlockState::new(block_name.to_string()));
let mut tool = BuildingTool::new(&mut self.inner);
tool.fill(&shape, &brush);
}
pub fn fill_sphere(&mut self, center: (i32, i32, i32), radius: f64, block_name: &str) {
let shape = Sphere::new(center, radius);
let brush = SolidBrush::new(BlockState::new(block_name.to_string()));
let mut tool = BuildingTool::new(&mut self.inner);
tool.fill(&shape, &brush);
}
pub fn get_dimensions(&self) -> (i32, i32, i32) {
self.inner.get_dimensions()
}
pub fn get_block_count(&self) -> i32 {
self.inner.total_blocks()
}
pub fn get_volume(&self) -> i32 {
self.inner.total_volume()
}
pub fn flip_x(&mut self) {
self.inner.flip_x();
}
pub fn flip_y(&mut self) {
self.inner.flip_y();
}
pub fn flip_z(&mut self) {
self.inner.flip_z();
}
pub fn rotate_x(&mut self, degrees: i32) -> Result<(), String> {
self.inner.rotate_x(degrees)
}
pub fn rotate_y(&mut self, degrees: i32) -> Result<(), String> {
self.inner.rotate_y(degrees)
}
pub fn rotate_z(&mut self, degrees: i32) -> Result<(), String> {
self.inner.rotate_z(degrees)
}
pub fn to_schematic(&self) -> Result<Vec<u8>, String> {
let manager = get_manager();
let manager = manager.lock().map_err(|e| format!("Lock error: {}", e))?;
manager
.write("schematic", &self.inner, None)
.map_err(|e| format!("Export error: {}", e))
}
pub fn to_litematic(&self) -> Result<Vec<u8>, String> {
let manager = get_manager();
let manager = manager.lock().map_err(|e| format!("Lock error: {}", e))?;
manager
.write("litematic", &self.inner, None)
.map_err(|e| format!("Export error: {}", e))
}
pub fn save_as(&self, format: &str) -> Result<Vec<u8>, String> {
let manager = get_manager();
let manager = manager.lock().map_err(|e| format!("Lock error: {}", e))?;
manager
.write(format, &self.inner, None)
.map_err(|e| format!("Export error: {}", e))
}
pub fn save_to_file(&self, path: &str) -> Result<(), String> {
let manager = get_manager();
let manager = manager.lock().map_err(|e| format!("Lock error: {}", e))?;
let data = manager
.write_auto(path, &self.inner, None)
.map_err(|e| format!("Export error: {}", e))?;
std::fs::write(path, data).map_err(|e| format!("Failed to write file: {}", e))
}
pub fn get_all_blocks(&self) -> Vec<(i32, i32, i32, String)> {
self.inner
.iter_blocks()
.filter(|(_, bs)| !bs.name.contains("air"))
.map(|(pos, bs)| (pos.x, pos.y, pos.z, bs.to_string()))
.collect()
}
pub fn get_region_names(&self) -> Vec<String> {
self.inner.get_region_names()
}
}