mod direction;
mod transform;
pub use direction::{Direction, Axis};
pub use transform::{BlockTransform, ElementRotation};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlockPosition {
pub x: i32,
pub y: i32,
pub z: i32,
}
impl BlockPosition {
pub fn new(x: i32, y: i32, z: i32) -> Self {
Self { x, y, z }
}
pub fn neighbor(&self, direction: Direction) -> Self {
let (dx, dy, dz) = direction.offset();
Self {
x: self.x + dx,
y: self.y + dy,
z: self.z + dz,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BoundingBox {
pub min: [f32; 3],
pub max: [f32; 3],
}
impl BoundingBox {
pub fn new(min: [f32; 3], max: [f32; 3]) -> Self {
Self { min, max }
}
pub fn from_points(points: impl Iterator<Item = [f32; 3]>) -> Option<Self> {
let mut min = [f32::MAX; 3];
let mut max = [f32::MIN; 3];
let mut has_points = false;
for p in points {
has_points = true;
for i in 0..3 {
min[i] = min[i].min(p[i]);
max[i] = max[i].max(p[i]);
}
}
if has_points {
Some(Self { min, max })
} else {
None
}
}
pub fn dimensions(&self) -> [f32; 3] {
[
self.max[0] - self.min[0],
self.max[1] - self.min[1],
self.max[2] - self.min[2],
]
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InputBlock {
pub name: String,
pub properties: HashMap<String, String>,
}
impl InputBlock {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
properties: HashMap::new(),
}
}
pub fn with_property(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.properties.insert(key.into(), value.into());
self
}
pub fn namespace(&self) -> &str {
self.name.split(':').next().unwrap_or("minecraft")
}
pub fn block_id(&self) -> &str {
self.name.split(':').nth(1).unwrap_or(&self.name)
}
pub fn is_air(&self) -> bool {
matches!(
self.name.as_str(),
"minecraft:air" | "minecraft:cave_air" | "minecraft:void_air" | "air"
)
}
}
pub trait BlockSource {
fn get_block(&self, pos: BlockPosition) -> Option<&InputBlock>;
fn iter_blocks(&self) -> Box<dyn Iterator<Item = (BlockPosition, &InputBlock)> + '_>;
fn bounds(&self) -> BoundingBox;
}