mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-04-20 19:35:08 +02:00
103 lines
2.8 KiB
Rust
103 lines
2.8 KiB
Rust
//! Processing of block entity data
|
|
|
|
use minedmap_resource::{BlockFlag, BlockType};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use super::{
|
|
de,
|
|
sign::{BlockEntitySignExt, SignText},
|
|
};
|
|
|
|
/// Kind of sign block
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum SignKind {
|
|
/// Standing sign
|
|
Sign,
|
|
/// Sign attached to wall
|
|
WallSign,
|
|
/// Hanging sign
|
|
HangingSign,
|
|
/// Hanging sign attached to wall
|
|
HangingWallSign,
|
|
}
|
|
|
|
/// Processed sign data
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct Sign {
|
|
/// The kind of the sign
|
|
pub kind: SignKind,
|
|
/// The material of the sign
|
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
|
pub material: Option<String>,
|
|
/// The sign's front text
|
|
#[serde(skip_serializing_if = "SignText::is_empty", default)]
|
|
pub front_text: SignText,
|
|
/// The sign's back text
|
|
#[serde(skip_serializing_if = "SignText::is_empty", default)]
|
|
pub back_text: SignText,
|
|
}
|
|
|
|
impl Sign {
|
|
/// Processes a [de::BlockEntitySign] into a [Sign]
|
|
fn new(sign: &de::BlockEntitySign, kind: SignKind, material: Option<String>) -> Sign {
|
|
let (front_text, back_text) = sign.text();
|
|
let front_text = front_text.decode();
|
|
let back_text = back_text.decode();
|
|
Sign {
|
|
kind,
|
|
material,
|
|
front_text,
|
|
back_text,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Data for different kinds of [BlockEntity]
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum BlockEntityData {
|
|
/// A sign block
|
|
Sign(Sign),
|
|
}
|
|
|
|
/// A processed block entity
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct BlockEntity {
|
|
/// Global X coordinate
|
|
pub x: i32,
|
|
/// Global Y coordinate
|
|
pub y: i32,
|
|
/// Global Z coordinate
|
|
pub z: i32,
|
|
/// Entity data
|
|
#[serde(flatten)]
|
|
pub data: BlockEntityData,
|
|
}
|
|
|
|
impl BlockEntity {
|
|
/// Processes a [de::BlockEntity] into a [BlockEntity]
|
|
pub fn new(entity: &de::BlockEntity, block_type: Option<&BlockType>) -> Option<Self> {
|
|
let wall_sign = block_type
|
|
.map(|block_type| block_type.block_color.is(BlockFlag::WallSign))
|
|
.unwrap_or_default();
|
|
let (kind, sign) = match (&entity.data, wall_sign) {
|
|
(de::BlockEntityData::Sign(sign), false) => (SignKind::Sign, sign),
|
|
(de::BlockEntityData::Sign(sign), true) => (SignKind::WallSign, sign),
|
|
(de::BlockEntityData::HangingSign(sign), false) => (SignKind::HangingSign, sign),
|
|
(de::BlockEntityData::HangingSign(sign), true) => (SignKind::HangingWallSign, sign),
|
|
(de::BlockEntityData::Other, _) => return None,
|
|
};
|
|
let material = block_type
|
|
.as_ref()
|
|
.and_then(|block_type| block_type.sign_material.as_ref());
|
|
let data = BlockEntityData::Sign(Sign::new(sign, kind, material.cloned()));
|
|
|
|
Some(BlockEntity {
|
|
x: entity.x,
|
|
y: entity.y,
|
|
z: entity.z,
|
|
data,
|
|
})
|
|
}
|
|
}
|