use crate::text::color::{ARGBColor, hsv_to_rgb}; use crate::translation::{ Locale, get_translation, get_translation_text, reorder_substitutions, translation_to_pretty, }; use click::ClickEvent; use color::Color; use colored::Colorize; use core::str; use hover::HoverEvent; use pumpkin_nbt::serializer::{NbtWriteHelperJava, Serializer}; use serde::de::{Error, MapAccess, SeqAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; use std::borrow::Cow; use std::fmt::Formatter; use std::fmt::Write; use std::sync::LazyLock; use style::Style; pub mod click; pub mod color; pub mod hover; pub mod style; /// Represents a Minecraft chat component. /// /// Text components are the building blocks of Minecraft's chat system, allowing for /// rich formatted text with colors, styles, click events, hover tooltips, and /// translations. They can be nested and combined to create complex messages. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TextComponent(pub TextComponentBase); impl<'de> Deserialize<'de> for TextComponent { fn deserialize>(deserializer: D) -> Result { struct TextComponentVisitor; impl<'de> Visitor<'de> for TextComponentVisitor { type Value = TextComponentBase; fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("a TextComponentBase or a sequence of TextComponentBase") } fn visit_str(self, v: &str) -> Result { Ok(TextComponentBase { content: Box::new(TextContent::Text { text: Cow::from(v.to_string()), }), style: Box::default(), extra: vec![], }) } fn visit_seq>(self, mut seq: A) -> Result { let mut bases = Vec::new(); while let Some(element) = seq.next_element::()? { bases.push(element.0); } Ok(TextComponentBase { content: Box::new(TextContent::Text { text: "".into() }), style: Box::default(), extra: bases, }) } fn visit_map>(self, map: A) -> Result { TextComponentBase::deserialize(serde::de::value::MapAccessDeserializer::new(map)) } } deserializer .deserialize_any(TextComponentVisitor) .map(TextComponent) } } impl Serialize for TextComponent { fn serialize(&self, serializer: S) -> Result { serializer.serialize_newtype_struct("TextComponent", &self.0.clone().to_translated()) } } /// The base structure for a text component containing content, style, and children. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "camelCase")] pub struct TextComponentBase { /// The actual content of this component (text, translation, etc.). #[serde(flatten)] pub content: Box, /// The styling applied to this component (color, bold, click events, etc.). #[serde(flatten)] pub style: Box