#[cfg(feature = "custom")]
use crate::custom::CustomData;
use crate::{
TextComponent, format::Format, interactivity::Interactivity, translation::TranslatedMessage,
};
use std::borrow::Cow;
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Content {
Text(Cow<'static, str>),
Keybind(Cow<'static, str>),
#[cfg(feature = "custom")]
Custom(CustomData),
#[cfg_attr(feature = "serde", serde(untagged))]
Translate(TranslatedMessage),
#[cfg_attr(feature = "serde", serde(untagged))]
Object(Object),
#[cfg_attr(feature = "serde", serde(untagged))]
Resolvable(Resolvable),
}
impl From<String> for Content {
fn from(value: String) -> Self {
Content::Text(Cow::Owned(value))
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub enum Object {
Atlas {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
atlas: Option<Cow<'static, str>>,
sprite: Cow<'static, str>,
},
Player {
player: ObjectPlayer,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Clone::clone"))]
hat: bool,
},
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct ObjectPlayer {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<Cow<'static, str>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub id: Option<[i32; 4]>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub texture: Option<Cow<'static, str>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
pub properties: Vec<PlayerProperties>,
}
impl ObjectPlayer {
pub fn name<T: Into<Cow<'static, str>>>(name: T) -> Self {
ObjectPlayer {
name: Some(name.into()),
id: None,
texture: None,
properties: vec![],
}
}
pub fn id(id: [i32; 4]) -> Self {
ObjectPlayer {
name: None,
id: Some(id),
texture: None,
properties: vec![],
}
}
pub fn texture<T: Into<Cow<'static, str>>>(path: T) -> Self {
ObjectPlayer {
name: None,
id: None,
texture: Some(path.into()),
properties: vec![],
}
}
pub fn property<T: Into<Cow<'static, str>>, R: Into<Cow<'static, str>>>(
value: T,
signature: Option<R>,
) -> Self {
ObjectPlayer {
name: None,
id: None,
texture: None,
properties: vec![PlayerProperties {
name: Cow::Borrowed("textures"),
value: value.into(),
signature: signature.map(Into::into),
}],
}
}
pub fn is_empty(&self) -> bool {
self.name.is_none()
&& self.id.is_none()
&& self.texture.is_none()
&& self.properties.is_empty()
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct PlayerProperties {
pub name: Cow<'static, str>,
pub value: Cow<'static, str>,
pub signature: Option<Cow<'static, str>>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub enum Resolvable {
#[cfg_attr(feature = "serde", serde(rename = "score"))]
Scoreboard {
#[cfg_attr(feature = "serde", serde(rename = "name"))]
selector: Cow<'static, str>,
objective: Cow<'static, str>,
},
#[cfg_attr(feature = "serde", serde(untagged))]
Entity {
selector: Cow<'static, str>,
separator: Box<TextComponent>,
},
#[cfg_attr(feature = "serde", serde(untagged))]
NBT {
#[cfg_attr(feature = "serde", serde(rename = "nbt"))]
path: Cow<'static, str>,
interpret: Option<bool>,
separator: Box<TextComponent>,
#[cfg_attr(feature = "serde", serde(flatten))]
source: NbtSource,
},
}
impl Resolvable {
pub fn entity_separator() -> Box<TextComponent> {
Box::new(TextComponent {
content: Content::Text(Cow::Borrowed(", ")),
format: Format {
color: Some(crate::format::Color::Gray),
..Default::default()
},
..Default::default()
})
}
pub fn nbt_separator() -> Box<TextComponent> {
Box::new(TextComponent {
content: Content::Text(Cow::Borrowed(", ")),
..Default::default()
})
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum NbtSource {
Entity(Cow<'static, str>),
Block(Cow<'static, str>),
Storage(Cow<'static, str>),
}
impl NbtSource {
pub fn entity<T: Into<Cow<'static, str>>>(selector: T) -> Self {
NbtSource::Entity(selector.into())
}
pub fn block(x: i32, y: i32, z: i32) -> Self {
NbtSource::Block(Cow::Owned(format!("{x} {y} {z}")))
}
pub fn storage<T: Into<Cow<'static, str>>>(identifier: T) -> Self {
NbtSource::Storage(identifier.into())
}
}
impl From<Object> for TextComponent {
fn from(value: Object) -> Self {
TextComponent {
content: Content::Object(value),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
}
impl From<ObjectPlayer> for TextComponent {
fn from(value: ObjectPlayer) -> Self {
TextComponent {
content: Content::Object(Object::Player {
player: value,
hat: true,
}),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
}
impl From<Resolvable> for TextComponent {
fn from(value: Resolvable) -> Self {
TextComponent {
content: Content::Resolvable(value),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
}