aboutsummaryrefslogtreecommitdiff
path: root/azalea-chat/src
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-chat/src')
-rwxr-xr-xazalea-chat/src/base_component.rs5
-rwxr-xr-xazalea-chat/src/component.rs14
-rwxr-xr-xazalea-chat/src/style.rs68
-rwxr-xr-xazalea-chat/src/text_component.rs19
-rwxr-xr-xazalea-chat/src/translatable_component.rs17
5 files changed, 110 insertions, 13 deletions
diff --git a/azalea-chat/src/base_component.rs b/azalea-chat/src/base_component.rs
index e532de11..ab4f5e5d 100755
--- a/azalea-chat/src/base_component.rs
+++ b/azalea-chat/src/base_component.rs
@@ -1,9 +1,12 @@
use crate::{style::Style, Component};
+use serde::Serialize;
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct BaseComponent {
// implements mutablecomponent
+ #[serde(skip_serializing_if = "Vec::is_empty")]
pub siblings: Vec<Component>,
+ #[serde(flatten)]
pub style: Style,
}
diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs
index 9362a66b..95387248 100755
--- a/azalea-chat/src/component.rs
+++ b/azalea-chat/src/component.rs
@@ -6,14 +6,15 @@ use crate::{
};
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use once_cell::sync::Lazy;
-use serde::{de, Deserialize, Deserializer};
+use serde::{de, Deserialize, Deserializer, Serialize};
use std::{
fmt::Display,
io::{Cursor, Write},
};
/// A chat component, basically anything you can see in chat.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+#[serde(untagged)]
pub enum Component {
Text(TextComponent),
Translatable(TranslatableComponent),
@@ -262,11 +263,10 @@ impl McBufReadable for Component {
}
impl McBufWritable for Component {
- fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> {
- // let json = serde_json::to_string(self).unwrap();
- // json.write_into(_buf);
- // Ok(())
- todo!()
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ let json = serde_json::to_string(self).unwrap();
+ json.write_into(buf)?;
+ Ok(())
}
}
diff --git a/azalea-chat/src/style.rs b/azalea-chat/src/style.rs
index cdf8f86f..cb708982 100755
--- a/azalea-chat/src/style.rs
+++ b/azalea-chat/src/style.rs
@@ -2,6 +2,7 @@ use std::{collections::HashMap, fmt};
use azalea_buf::McBuf;
use once_cell::sync::Lazy;
+use serde::{ser::SerializeStruct, Serialize, Serializer};
use serde_json::Value;
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -10,6 +11,19 @@ pub struct TextColor {
pub name: Option<String>,
}
+impl Serialize for TextColor {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ if self.name.is_some() {
+ serializer.serialize_str(&self.name.as_ref().unwrap().to_ascii_lowercase())
+ } else {
+ serializer.serialize_str(&self.format())
+ }
+ }
+}
+
impl TextColor {
pub fn parse(value: String) -> Option<TextColor> {
if value.starts_with('#') {
@@ -276,17 +290,67 @@ impl TryFrom<ChatFormatting> for TextColor {
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Style {
- // these are options instead of just bools because None is different than false in this case
+ // These are options instead of just bools because None is different than false in this case
pub color: Option<TextColor>,
pub bold: Option<bool>,
pub italic: Option<bool>,
pub underlined: Option<bool>,
pub strikethrough: Option<bool>,
pub obfuscated: Option<bool>,
- /// Whether it should reset the formatting before applying these styles
+ /// Whether formatting should be reset before applying these styles
pub reset: bool,
}
+impl Serialize for Style {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ let len = if self.reset {
+ 6
+ } else {
+ usize::from(self.color.is_some())
+ + usize::from(self.bold.is_some())
+ + usize::from(self.italic.is_some())
+ + usize::from(self.underlined.is_some())
+ + usize::from(self.strikethrough.is_some())
+ + usize::from(self.obfuscated.is_some())
+ };
+ let mut state = serializer.serialize_struct("Style", len)?;
+ if let Some(color) = &self.color {
+ state.serialize_field("color", color)?;
+ } else if self.reset {
+ state.serialize_field("color", "white")?;
+ }
+ if let Some(bold) = &self.bold {
+ state.serialize_field("bold", bold)?;
+ } else if self.reset {
+ state.serialize_field("bold", &false)?;
+ }
+ if let Some(italic) = &self.italic {
+ state.serialize_field("italic", italic)?;
+ } else if self.reset {
+ state.serialize_field("italic", &false)?;
+ }
+ if let Some(underlined) = &self.underlined {
+ state.serialize_field("underlined", underlined)?;
+ } else if self.reset {
+ state.serialize_field("underlined", &false)?;
+ }
+ if let Some(strikethrough) = &self.strikethrough {
+ state.serialize_field("strikethrough", strikethrough)?;
+ } else if self.reset {
+ state.serialize_field("strikethrough", &false)?;
+ }
+ if let Some(obfuscated) = &self.obfuscated {
+ state.serialize_field("obfuscated", obfuscated)?;
+ } else if self.reset {
+ state.serialize_field("obfuscated", &false)?;
+ }
+ state.end()
+ }
+}
+
impl Style {
pub fn empty() -> Self {
Self::default()
diff --git a/azalea-chat/src/text_component.rs b/azalea-chat/src/text_component.rs
index 0d88ca05..6715c93e 100755
--- a/azalea-chat/src/text_component.rs
+++ b/azalea-chat/src/text_component.rs
@@ -1,6 +1,6 @@
-use std::fmt::Display;
-
use crate::{base_component::BaseComponent, style::ChatFormatting, Component};
+use serde::{ser::SerializeMap, Serialize, Serializer, __private::ser::FlatMapSerializer};
+use std::fmt::Display;
/// A component that contains text that's the same in all locales.
#[derive(Clone, Debug, Default, PartialEq)]
@@ -9,6 +9,21 @@ pub struct TextComponent {
pub text: String,
}
+impl Serialize for TextComponent {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ let mut state = serializer.serialize_map(None)?;
+ state.serialize_entry("text", &self.text)?;
+ Serialize::serialize(&self.base, FlatMapSerializer(&mut state))?;
+ if !self.base.siblings.is_empty() {
+ state.serialize_entry("extra", &self.base.siblings)?;
+ }
+ state.end()
+ }
+}
+
const LEGACY_FORMATTING_CODE_SYMBOL: char = 'ยง';
/// Convert a legacy color code string into a Component
diff --git a/azalea-chat/src/translatable_component.rs b/azalea-chat/src/translatable_component.rs
index 28725c44..7819d5ff 100755
--- a/azalea-chat/src/translatable_component.rs
+++ b/azalea-chat/src/translatable_component.rs
@@ -3,8 +3,10 @@ use std::fmt::{self, Display, Formatter};
use crate::{
base_component::BaseComponent, style::Style, text_component::TextComponent, Component,
};
+use serde::{ser::SerializeMap, Serialize, Serializer, __private::ser::FlatMapSerializer};
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+#[serde(untagged)]
pub enum StringOrComponent {
String(String),
Component(Component),
@@ -18,6 +20,19 @@ pub struct TranslatableComponent {
pub args: Vec<StringOrComponent>,
}
+impl Serialize for TranslatableComponent {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ let mut state = serializer.serialize_map(None)?;
+ state.serialize_entry("translate", &self.key)?;
+ Serialize::serialize(&self.base, FlatMapSerializer(&mut state))?;
+ state.serialize_entry("with", &self.args)?;
+ state.end()
+ }
+}
+
impl TranslatableComponent {
pub fn new(key: String, args: Vec<StringOrComponent>) -> Self {
Self {