Potato/potato-data/src/text_component.rs
2025-04-05 00:06:22 +02:00

143 lines
4.1 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::{Either, identifier::Identifier, registry::item::component_map::ItemComponentMap};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TextComponent {
// Content
#[serde(flatten)]
pub content: TextComponentContent,
// Children
pub extra: Option<Vec<TextComponent>>,
// Formatting
#[serde(flatten)]
pub style: TextComponentStyle,
// Interactivity
pub insertion: Option<String>,
pub click_event: Option<ClickEvent>,
pub hover_event: Option<HoverEvent>,
}
impl TextComponent {
// This is not the same function
#[allow(clippy::should_implement_trait)]
pub fn from_str(str: &str) -> Self {
TextComponent {
content: TextComponentContent::Text(TextComponentText {
text: str.to_string(),
}),
extra: None,
style: Default::default(),
insertion: None,
click_event: None,
hover_event: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Default)]
pub struct TextComponentStyle {
pub color: Option<String>,
pub font: Option<Identifier>,
pub bold: Option<bool>,
pub italic: Option<bool>,
pub underlined: Option<bool>,
pub strikethrough: Option<bool>,
pub obfuscated: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
#[serde(tag = "action", content = "value", rename_all = "snake_case")]
pub enum ClickEvent {
OpenUrl(String),
OpenFile(String),
RunCommand(String),
SuggestCommand(String),
ChangePage(String),
CopyToClipboard(String),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "action", content = "contents", rename_all = "snake_case")]
pub enum HoverEvent {
ShowText(Box<TextComponent>),
ShowItem {
id: Identifier,
count: Option<i32>,
#[serde(default)]
components: ItemComponentMap,
},
ShowEntity {
// NOTE: Not sure if this is a TextComponent or just a string.
name: String,
#[serde(rename = "type")]
ty: Identifier,
id: Either<String, (u32, u32, u32, u32)>,
},
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum TextComponentContent {
Text(TextComponentText),
Translatable(TextComponentTranslatable),
Score(TextComponentScore),
Selector(TextComponentSelector),
Keybind(TextComponentKeybind),
Nbt(TextComponentNbt),
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
#[serde(tag = "type", rename = "text")]
pub struct TextComponentText {
pub text: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", rename = "translatable")]
pub struct TextComponentTranslatable {
pub translate: String,
pub fallback: Option<String>,
pub with: Option<Vec<TextComponent>>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
#[serde(tag = "type", rename = "score")]
pub struct TextComponentScore {
pub score: TextComponentScoreInner,
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct TextComponentScoreInner {
pub name: String,
pub objective: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", rename = "selector")]
pub struct TextComponentSelector {
pub selector: String,
// TODO: Instead of an option, make this default to the default value.
pub separator: Option<Box<TextComponent>>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
#[serde(tag = "type", rename = "keybind")]
pub struct TextComponentKeybind {
pub keybind: String, // TODO: Maybe restrict this to the allowed keybinds, or maybe leave that
// for the client.
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", rename = "nbt")]
pub struct TextComponentNbt {
pub source: String,
pub nbt: String,
#[serde(default)]
pub interpret: bool,
// TODO: Instead of an option, make this default to the default value.
pub separator: Option<Box<TextComponent>>,
pub block: Option<String>,
pub entity: Option<String>,
pub storage: Option<String>,
}