#[cfg(feature = "custom")]
use crate::custom::CustomContent;
use crate::{
content::{Content, NbtSource, Object, ObjectPlayer, Resolvable},
format::{Color, Format},
interactivity::{ClickEvent, HoverEvent, Interactivity},
translation::TranslatedMessage,
};
use std::borrow::Cow;
#[cfg(feature = "build")]
pub mod build;
pub mod content;
#[cfg(feature = "custom")]
pub mod custom;
pub mod fmt;
pub mod format;
pub mod interactivity;
#[cfg(feature = "nbt")]
pub mod nbt;
pub mod parse;
pub mod resolving;
pub mod translation;
#[derive(Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
pub struct TextComponent {
#[cfg_attr(feature = "serde", serde(flatten))]
pub content: Content,
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Vec::is_empty", rename = "extra", default)
)]
pub children: Vec<TextComponent>,
#[cfg_attr(feature = "serde", serde(flatten))]
pub format: Format,
#[cfg_attr(feature = "serde", serde(flatten))]
pub interactions: Interactivity,
}
impl TextComponent {
pub const fn new() -> Self {
TextComponent {
content: Content::Text {
text: Cow::Borrowed(""),
},
children: vec![],
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub const fn const_plain(text: &'static str) -> Self {
TextComponent {
content: Content::Text {
text: Cow::Borrowed(text),
},
children: vec![],
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub fn plain<T: Into<Cow<'static, str>>>(text: T) -> Self {
TextComponent {
content: Content::Text { text: text.into() },
children: vec![],
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub const fn translated(message: TranslatedMessage) -> Self {
TextComponent {
content: Content::Translate(message),
children: vec![],
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub fn atlas<T: Into<Cow<'static, str>>, R: Into<Cow<'static, str>>>(
sprite: T,
atlas: Option<R>,
) -> Self {
TextComponent {
content: Content::Object(Object::Atlas {
atlas: atlas.map(Into::into),
sprite: sprite.into(),
}),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub const fn player_head(player: ObjectPlayer, hat: bool) -> Self {
TextComponent {
content: Content::Object(Object::Player { player, hat }),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub fn scoreboard<T: Into<Cow<'static, str>>, R: Into<Cow<'static, str>>>(
selector: T,
objective: R,
) -> Self {
TextComponent {
content: Content::Resolvable(Resolvable::Scoreboard {
selector: selector.into(),
objective: objective.into(),
}),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub fn entity<T: Into<Cow<'static, str>>>(selector: T, separator: Option<Self>) -> Self {
TextComponent {
content: Content::Resolvable(Resolvable::Entity {
selector: selector.into(),
separator: match separator {
Some(separator) => Box::new(separator),
None => Box::new(", ".color(Color::Gray)),
},
}),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
pub fn nbt<T: Into<Cow<'static, str>>>(
path: T,
source: NbtSource,
interpret: bool,
separator: Option<Self>,
) -> Self {
TextComponent {
content: Content::Resolvable(Resolvable::NBT {
path: path.into(),
interpret: if interpret { Some(true) } else { None },
separator: match separator {
Some(separator) => Box::new(separator),
None => Box::new(", ".into()),
},
source,
}),
children: Vec::new(),
format: Format::new(),
interactions: Interactivity::new(),
}
}
#[cfg(feature = "custom")]
pub fn custom<T: CustomContent>(content: T) -> TextComponent {
TextComponent {
content: Content::Custom(content.as_data()),
children: vec![],
format: Format::new(),
interactions: Interactivity::new(),
}
}
}
impl Default for TextComponent {
fn default() -> Self {
TextComponent::new()
}
}
impl From<&'static str> for TextComponent {
fn from(value: &'static str) -> Self {
TextComponent::const_plain(value)
}
}
impl From<String> for TextComponent {
fn from(value: String) -> Self {
TextComponent::plain(value)
}
}
pub trait Modifier {
type Output;
fn add_child<T: Into<TextComponent>>(self, child: T) -> Self::Output;
fn add_children<T: Into<TextComponent>>(self, children: Vec<T>) -> Self::Output;
fn insertion<T: Into<Cow<'static, str>>>(self, insertion: T) -> Self::Output;
fn click_event(self, click: ClickEvent) -> Self::Output;
fn hover_event(self, hover: HoverEvent) -> Self::Output;
fn color(self, color: Color) -> Self::Output;
fn color_hex(self, color: &str) -> Self::Output;
fn font<F: Into<Cow<'static, str>>>(self, font: F) -> Self::Output;
fn bold(self, value: bool) -> Self::Output;
fn italic(self, value: bool) -> Self::Output;
fn underlined(self, value: bool) -> Self::Output;
fn strikethrough(self, value: bool) -> Self::Output;
fn obfuscated(self, value: bool) -> Self::Output;
fn shadow_color(self, a: u8, r: u8, g: u8, b: u8) -> Self::Output;
fn reset(self) -> Self::Output;
}
impl<T: Into<TextComponent> + Sized> Modifier for T {
type Output = TextComponent;
fn add_child<F: Into<TextComponent>>(self, child: F) -> TextComponent {
let mut component = self.into();
component.children.push(child.into());
component
}
fn add_children<F: Into<TextComponent>>(self, children: Vec<F>) -> TextComponent {
let mut component = self.into();
for child in children {
component.children.push(child.into());
}
component
}
fn insertion<R: Into<Cow<'static, str>>>(self, insertion: R) -> TextComponent {
let mut component = self.into();
component.interactions.insertion = Some(insertion.into());
component
}
fn click_event(self, click: ClickEvent) -> TextComponent {
let mut component = self.into();
component.interactions.click = Some(click);
component
}
fn hover_event(self, hover: HoverEvent) -> TextComponent {
let mut component = self.into();
component.interactions.hover = Some(hover);
component
}
fn color(self, color: Color) -> TextComponent {
let mut component = self.into();
component.format = component.format.color(color);
component
}
fn color_hex(self, color: &str) -> TextComponent {
let mut component = self.into();
component.format = component.format.color_hex(color);
component
}
fn font<F: Into<Cow<'static, str>>>(self, font: F) -> TextComponent {
let mut component = self.into();
component.format = component.format.font(font);
component
}
fn bold(self, value: bool) -> TextComponent {
let mut component = self.into();
component.format = component.format.bold(value);
component
}
fn italic(self, value: bool) -> TextComponent {
let mut component = self.into();
component.format = component.format.italic(value);
component
}
fn underlined(self, value: bool) -> TextComponent {
let mut component = self.into();
component.format = component.format.underlined(value);
component
}
fn strikethrough(self, value: bool) -> TextComponent {
let mut component = self.into();
component.format = component.format.strikethrough(value);
component
}
fn obfuscated(self, value: bool) -> TextComponent {
let mut component = self.into();
component.format = component.format.obfuscated(value);
component
}
fn shadow_color(self, a: u8, r: u8, g: u8, b: u8) -> TextComponent {
let mut component = self.into();
component.format = component.format.shadow_color(a, r, g, b);
component
}
fn reset(self) -> TextComponent {
let mut component = self.into();
component.format = component.format.reset();
component
}
}
impl<'a> Modifier for &'a mut TextComponent {
type Output = &'a mut TextComponent;
fn add_child<T: Into<TextComponent>>(self, child: T) -> &'a mut TextComponent {
self.children.push(child.into());
self
}
fn add_children<T: Into<TextComponent>>(self, children: Vec<T>) -> &'a mut TextComponent {
for child in children {
self.children.push(child.into());
}
self
}
fn insertion<T: Into<Cow<'static, str>>>(self, insertion: T) -> &'a mut TextComponent {
self.interactions.insertion = Some(insertion.into());
self
}
fn click_event(self, click: ClickEvent) -> &'a mut TextComponent {
self.interactions.click = Some(click);
self
}
fn hover_event(self, hover: HoverEvent) -> &'a mut TextComponent {
self.interactions.hover = Some(hover);
self
}
fn color(self, color: Color) -> &'a mut TextComponent {
self.format.color = Some(color);
self
}
fn color_hex(self, color: &str) -> &'a mut TextComponent {
if let Some(color) = Color::from_hex(color) {
self.format.color = Some(color);
}
self
}
fn font<F: Into<Cow<'static, str>>>(self, font: F) -> &'a mut TextComponent {
self.format.font = Some(font.into());
self
}
fn bold(self, value: bool) -> &'a mut TextComponent {
self.format.bold = Some(value);
self
}
fn italic(self, value: bool) -> &'a mut TextComponent {
self.format.italic = Some(value);
self
}
fn underlined(self, value: bool) -> &'a mut TextComponent {
self.format.underlined = Some(value);
self
}
fn strikethrough(self, value: bool) -> &'a mut TextComponent {
self.format.strikethrough = Some(value);
self
}
fn obfuscated(self, value: bool) -> &'a mut TextComponent {
self.format.obfuscated = Some(value);
self
}
fn shadow_color(self, a: u8, r: u8, g: u8, b: u8) -> &'a mut TextComponent {
self.format.shadow_color = Some(Format::parse_shadow_color(a, r, g, b));
self
}
fn reset(self) -> &'a mut TextComponent {
self.format.color = Some(Color::White);
self.format.font = Some(Cow::Borrowed("minecraft:default"));
self.format.bold = Some(false);
self.format.italic = Some(false);
self.format.underlined = Some(false);
self.format.strikethrough = Some(false);
self.format.obfuscated = Some(false);
self.format.shadow_color = None;
self
}
}