mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Implement more stuff with chat
Still need to parse styling from json
This commit is contained in:
parent
bda5362bdf
commit
221e54c7a6
7 changed files with 212 additions and 60 deletions
|
@ -1,15 +1,14 @@
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
base_component::BaseComponent,
|
base_component::BaseComponent,
|
||||||
|
style::Style,
|
||||||
text_component::TextComponent,
|
text_component::TextComponent,
|
||||||
translatable_component::{StringOrComponent, TranslatableComponent},
|
translatable_component::{StringOrComponent, TranslatableComponent},
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct Component {
|
|
||||||
// base: BaseComponent,
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Component {
|
pub enum Component {
|
||||||
TextComponent(TextComponent),
|
TextComponent(TextComponent),
|
||||||
|
@ -149,12 +148,16 @@ impl Component {
|
||||||
Ok(component)
|
Ok(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_base(&mut self) -> &mut BaseComponent {
|
||||||
|
match self {
|
||||||
|
Self::TextComponent(c) => &mut c.base,
|
||||||
|
Self::TranslatableComponent(c) => &mut c.base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a component as a sibling of this one
|
/// Add a component as a sibling of this one
|
||||||
fn append(&mut self, sibling: Component) {
|
fn append(&mut self, sibling: Component) {
|
||||||
match self {
|
self.get_base().siblings.push(sibling);
|
||||||
Self::TextComponent(c) => c.base.siblings.push(sibling),
|
|
||||||
Self::TranslatableComponent(c) => c.base.siblings.push(sibling),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the "separator" component from the json
|
/// Get the "separator" component from the json
|
||||||
|
@ -165,5 +168,38 @@ impl Component {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_ansi(&self) {}
|
/// Convert this component into an ansi string, using parent_style as the running style.
|
||||||
|
pub fn to_ansi(&self, parent_style: Option<&mut Style>) -> String {
|
||||||
|
// the siblings of this component
|
||||||
|
let base;
|
||||||
|
let mut text;
|
||||||
|
match self {
|
||||||
|
Self::TextComponent(c) => {
|
||||||
|
base = &c.base;
|
||||||
|
text = c.text.clone();
|
||||||
|
}
|
||||||
|
Self::TranslatableComponent(c) => {
|
||||||
|
base = &c.base;
|
||||||
|
text = c.key.clone();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// we'll fall back to this if there's no parent style
|
||||||
|
let default_style = &mut Style::new();
|
||||||
|
|
||||||
|
// apply the style of this component to the current style
|
||||||
|
let current_style: &mut Style = parent_style.unwrap_or(default_style);
|
||||||
|
let new_style = &base.style;
|
||||||
|
current_style.apply(new_style);
|
||||||
|
|
||||||
|
let ansi_text = base.style.compare_ansi(&new_style);
|
||||||
|
|
||||||
|
text.push_str(&ansi_text);
|
||||||
|
|
||||||
|
for sibling in &base.siblings {
|
||||||
|
text.push_str(&sibling.to_ansi(Some(current_style)));
|
||||||
|
}
|
||||||
|
|
||||||
|
text.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,6 @@
|
||||||
|
|
||||||
pub mod base_component;
|
pub mod base_component;
|
||||||
pub mod component;
|
pub mod component;
|
||||||
pub mod mutable_component;
|
|
||||||
pub mod style;
|
pub mod style;
|
||||||
pub mod text_component;
|
pub mod text_component;
|
||||||
pub mod translatable_component;
|
pub mod translatable_component;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
assert_eq!(2 + 2, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
use crate::{base_component::BaseComponent, component::Component};
|
|
||||||
|
|
||||||
pub trait MutableComponent {
|
|
||||||
/// Add a component as a sibling of this one
|
|
||||||
fn append(&self, component: Component);
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
struct TextColor {
|
struct TextColor {
|
||||||
value: u32,
|
value: u32,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
@ -15,6 +15,57 @@ struct ChatFormatting<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ChatFormatting<'a> {
|
impl<'a> ChatFormatting<'a> {
|
||||||
|
const BLACK: ChatFormatting<'a> = ChatFormatting::new("BLACK", '0', false, 0, Some(0));
|
||||||
|
const DARK_BLUE: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_BLUE", '1', false, 1, Some(170));
|
||||||
|
const DARK_GREEN: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_GREEN", '2', false, 2, Some(43520));
|
||||||
|
const DARK_AQUA: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_AQUA", '3', false, 3, Some(43690));
|
||||||
|
const DARK_RED: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_RED", '4', false, 4, Some(1114112));
|
||||||
|
const DARK_PURPLE: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_PURPLE", '5', false, 5, Some(11141290));
|
||||||
|
const GOLD: ChatFormatting<'a> = ChatFormatting::new("GOLD", '6', false, 6, Some(16755200));
|
||||||
|
const GRAY: ChatFormatting<'a> = ChatFormatting::new("GRAY", '7', false, 7, Some(11184810));
|
||||||
|
const DARK_GRAY: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("DARK_GRAY", '8', false, 8, Some(5592405));
|
||||||
|
const BLUE: ChatFormatting<'a> = ChatFormatting::new("BLUE", '9', false, 9, Some(5592575));
|
||||||
|
const GREEN: ChatFormatting<'a> = ChatFormatting::new("GREEN", 'a', false, 10, Some(5635925));
|
||||||
|
const AQUA: ChatFormatting<'a> = ChatFormatting::new("AQUA", 'b', false, 11, Some(5636095));
|
||||||
|
const RED: ChatFormatting<'a> = ChatFormatting::new("RED", 'c', false, 12, Some(16733525));
|
||||||
|
const LIGHT_PURPLE: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("LIGHT_PURPLE", 'd', false, 13, Some(16733695));
|
||||||
|
const YELLOW: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("YELLOW", 'e', false, 14, Some(16777045));
|
||||||
|
const WHITE: ChatFormatting<'a> = ChatFormatting::new("WHITE", 'f', false, 15, Some(16777215));
|
||||||
|
const OBFUSCATED: ChatFormatting<'a> = ChatFormatting::new("OBFUSCATED", 'k', true, -1, None);
|
||||||
|
const STRIKETHROUGH: ChatFormatting<'a> =
|
||||||
|
ChatFormatting::new("STRIKETHROUGH", 'm', true, -1, None);
|
||||||
|
const BOLD: ChatFormatting<'a> = ChatFormatting::new("BOLD", 'l', true, -1, None);
|
||||||
|
const UNDERLINE: ChatFormatting<'a> = ChatFormatting::new("UNDERLINE", 'n', true, -1, None);
|
||||||
|
const ITALIC: ChatFormatting<'a> = ChatFormatting::new("ITALIC", 'o', true, -1, None);
|
||||||
|
const RESET: ChatFormatting<'a> = ChatFormatting::new("RESET", 'r', true, -1, None);
|
||||||
|
|
||||||
|
pub const FORMATTERS: [ChatFormatting<'a>; 16] = [
|
||||||
|
ChatFormatting::BLACK,
|
||||||
|
ChatFormatting::DARK_BLUE,
|
||||||
|
ChatFormatting::DARK_GREEN,
|
||||||
|
ChatFormatting::DARK_AQUA,
|
||||||
|
ChatFormatting::DARK_RED,
|
||||||
|
ChatFormatting::DARK_PURPLE,
|
||||||
|
ChatFormatting::GOLD,
|
||||||
|
ChatFormatting::GRAY,
|
||||||
|
ChatFormatting::DARK_GRAY,
|
||||||
|
ChatFormatting::BLUE,
|
||||||
|
ChatFormatting::GREEN,
|
||||||
|
ChatFormatting::AQUA,
|
||||||
|
ChatFormatting::RED,
|
||||||
|
ChatFormatting::LIGHT_PURPLE,
|
||||||
|
ChatFormatting::YELLOW,
|
||||||
|
ChatFormatting::WHITE,
|
||||||
|
];
|
||||||
|
|
||||||
const fn new(
|
const fn new(
|
||||||
name: &str,
|
name: &str,
|
||||||
code: char,
|
code: char,
|
||||||
|
@ -32,33 +83,6 @@ impl<'a> ChatFormatting<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub const BLACK: ChatFormatting = ChatFormatting::new("BLACK", '0', false, 0, Some(0));
|
|
||||||
// pub const DARK_BLUE: ChatFormatting = ChatFormatting::new("DARK_BLUE", '1', false, 1, Some(170));
|
|
||||||
// pub const DARK_GREEN: ChatFormatting =
|
|
||||||
// ChatFormatting::new("DARK_GREEN", '2', false, 2, Some(43520));
|
|
||||||
// pub const DARK_AQUA: ChatFormatting = ChatFormatting::new("DARK_AQUA", '3', false, 3, Some(43690));
|
|
||||||
// pub const DARK_RED: ChatFormatting = ChatFormatting::new("DARK_RED", '4', false, 4, Some(1114112));
|
|
||||||
// pub const DARK_PURPLE: ChatFormatting =
|
|
||||||
// ChatFormatting::new("DARK_PURPLE", '5', false, 5, Some(11141290));
|
|
||||||
// pub const GOLD: ChatFormatting = ChatFormatting::new("GOLD", '6', false, 6, Some(16755200));
|
|
||||||
// pub const GRAY: ChatFormatting = ChatFormatting::new("GRAY", '7', false, 7, Some(11184810));
|
|
||||||
// pub const DARK_GRAY: ChatFormatting =
|
|
||||||
// ChatFormatting::new("DARK_GRAY", '8', false, 8, Some(5592405));
|
|
||||||
// pub const BLUE: ChatFormatting = ChatFormatting::new("BLUE", '9', false, 9, Some(5592575));
|
|
||||||
// pub const GREEN: ChatFormatting = ChatFormatting::new("GREEN", 'a', false, 10, Some(5635925));
|
|
||||||
// pub const AQUA: ChatFormatting = ChatFormatting::new("AQUA", 'b', false, 11, Some(5636095));
|
|
||||||
// pub const RED: ChatFormatting = ChatFormatting::new("RED", 'c', false, 12, Some(16733525));
|
|
||||||
// pub const LIGHT_PURPLE: ChatFormatting =
|
|
||||||
// ChatFormatting::new("LIGHT_PURPLE", 'd', false, 13, Some(16733695));
|
|
||||||
// pub const YELLOW: ChatFormatting = ChatFormatting::new("YELLOW", 'e', false, 14, Some(16777045));
|
|
||||||
// pub const WHITE: ChatFormatting = ChatFormatting::new("WHITE", 'f', false, 15, Some(16777215));
|
|
||||||
// pub const OBFUSCATED: ChatFormatting = ChatFormatting::new("OBFUSCATED", 'k', true, -1, None);
|
|
||||||
// pub const STRIKETHROUGH: ChatFormatting = ChatFormatting::new("STRIKETHROUGH", 'm', true, -1, None);
|
|
||||||
// pub const BOLD: ChatFormatting = ChatFormatting::new("BOLD", 'l', true, -1, None);
|
|
||||||
// pub const UNDERLINE: ChatFormatting = ChatFormatting::new("UNDERLINE", 'n', true, -1, None);
|
|
||||||
// pub const ITALIC: ChatFormatting = ChatFormatting::new("ITALIC", 'o', true, -1, None);
|
|
||||||
// pub const RESET: ChatFormatting = ChatFormatting::new("RESET", 'r', true, -1, None);
|
|
||||||
|
|
||||||
impl TextColor {
|
impl TextColor {
|
||||||
fn new(value: u32, name: Option<String>) -> Self {
|
fn new(value: u32, name: Option<String>) -> Self {
|
||||||
Self { value, name }
|
Self { value, name }
|
||||||
|
@ -113,11 +137,11 @@ impl Style {
|
||||||
pub fn new() -> Style {
|
pub fn new() -> Style {
|
||||||
Style {
|
Style {
|
||||||
color: None,
|
color: None,
|
||||||
bold: Some(false),
|
bold: None,
|
||||||
italic: Some(false),
|
italic: None,
|
||||||
underlined: Some(false),
|
underlined: None,
|
||||||
strikethrough: Some(false),
|
strikethrough: None,
|
||||||
obfuscated: Some(false),
|
obfuscated: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,4 +154,110 @@ impl Style {
|
||||||
&& self.strikethrough.is_none()
|
&& self.strikethrough.is_none()
|
||||||
&& self.obfuscated.is_none()
|
&& self.obfuscated.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// find the necessary ansi code to get from this style to another
|
||||||
|
pub fn compare_ansi(&self, after: &Style) -> String {
|
||||||
|
let should_reset = {
|
||||||
|
// if it used to be bold and now it's not, reset
|
||||||
|
if self.bold.unwrap_or(false) && !after.bold.unwrap_or(false) {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// if it used to be italic and now it's not, reset
|
||||||
|
else if self.italic.unwrap_or(false) && !after.italic.unwrap_or(false) {
|
||||||
|
true
|
||||||
|
// if it used to be underlined and now it's not, reset
|
||||||
|
} else if self.underlined.unwrap_or(false) && !after.underlined.unwrap_or(false) {
|
||||||
|
true
|
||||||
|
// if it used to be strikethrough and now it's not, reset
|
||||||
|
} else if self.strikethrough.unwrap_or(false) && !after.strikethrough.unwrap_or(false) {
|
||||||
|
true
|
||||||
|
// if it used to be obfuscated and now it's not, reset
|
||||||
|
} else if self.obfuscated.unwrap_or(false) && !after.obfuscated.unwrap_or(false) {
|
||||||
|
true
|
||||||
|
// if it used to have a color and now it doesn't, reset
|
||||||
|
} else if self.color.is_some() && after.color.is_none() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut ansi_codes = String::new();
|
||||||
|
|
||||||
|
let before = if should_reset {
|
||||||
|
ansi_codes.push_str("\x1b[0m");
|
||||||
|
Style::new()
|
||||||
|
} else {
|
||||||
|
self.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
// if bold used to be false/default and now it's true, set bold
|
||||||
|
if before.bold.unwrap_or(false) && !after.bold.unwrap_or(false) {
|
||||||
|
ansi_codes.push_str("\x1b[1m");
|
||||||
|
}
|
||||||
|
// if italic used to be false/default and now it's true, set italic
|
||||||
|
if before.italic.unwrap_or(false) && !after.italic.unwrap_or(false) {
|
||||||
|
ansi_codes.push_str("\x1b[3m");
|
||||||
|
}
|
||||||
|
// if underlined used to be false/default and now it's true, set underlined
|
||||||
|
if before.underlined.unwrap_or(false) && !after.underlined.unwrap_or(false) {
|
||||||
|
ansi_codes.push_str("\x1b[4m");
|
||||||
|
}
|
||||||
|
// if strikethrough used to be false/default and now it's true, set strikethrough
|
||||||
|
if before.strikethrough.unwrap_or(false) && !after.strikethrough.unwrap_or(false) {
|
||||||
|
ansi_codes.push_str("\x1b[9m");
|
||||||
|
}
|
||||||
|
// if obfuscated used to be false/default and now it's true, set obfuscated
|
||||||
|
if before.obfuscated.unwrap_or(false) && !after.obfuscated.unwrap_or(false) {
|
||||||
|
ansi_codes.push_str("\x1b[8m");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the new color is different and not none, set color
|
||||||
|
let color_changed = {
|
||||||
|
if before.color.is_none() && after.color.is_some() {
|
||||||
|
true
|
||||||
|
} else if before.color.is_some() && after.color.is_some() {
|
||||||
|
before.color.unwrap().value != after.color.as_ref().unwrap().value
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if color_changed {
|
||||||
|
let after_color = after.color.as_ref().unwrap();
|
||||||
|
ansi_codes.push_str(&format!(
|
||||||
|
"\x1b[38;2;{};{};{}m",
|
||||||
|
// r
|
||||||
|
(after_color.value >> 16) & 0xFF,
|
||||||
|
// g
|
||||||
|
(after_color.value >> 8) & 0xFF,
|
||||||
|
// b
|
||||||
|
after_color.value & 0xFF
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return "".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply another style to this one
|
||||||
|
pub fn apply(&mut self, style: &Style) {
|
||||||
|
if let Some(color) = &style.color {
|
||||||
|
self.color = Some(color.clone());
|
||||||
|
}
|
||||||
|
if let Some(bold) = &style.bold {
|
||||||
|
self.bold = Some(*bold);
|
||||||
|
}
|
||||||
|
if let Some(italic) = &style.italic {
|
||||||
|
self.italic = Some(*italic);
|
||||||
|
}
|
||||||
|
if let Some(underlined) = &style.underlined {
|
||||||
|
self.underlined = Some(*underlined);
|
||||||
|
}
|
||||||
|
if let Some(strikethrough) = &style.strikethrough {
|
||||||
|
self.strikethrough = Some(*strikethrough);
|
||||||
|
}
|
||||||
|
if let Some(obfuscated) = &style.obfuscated {
|
||||||
|
self.obfuscated = Some(*obfuscated);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{base_component::BaseComponent, mutable_component::MutableComponent};
|
use crate::{base_component::BaseComponent, component::Component};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TextComponent {
|
pub struct TextComponent {
|
||||||
|
|
|
@ -6,7 +6,6 @@ pub enum StringOrComponent {
|
||||||
Component(Component),
|
Component(Component),
|
||||||
}
|
}
|
||||||
|
|
||||||
// extends BaseComponent implements ContextAwareComponent
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TranslatableComponent {
|
pub struct TranslatableComponent {
|
||||||
pub base: BaseComponent,
|
pub base: BaseComponent,
|
||||||
|
|
|
@ -5,9 +5,11 @@ use serde_json::{Result, Value};
|
||||||
fn test() {
|
fn test() {
|
||||||
let j: Value = serde_json::from_str(
|
let j: Value = serde_json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"text":"hello"
|
"text": "hello",
|
||||||
|
"color": "red"
|
||||||
}"#,
|
}"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let component = Component::new(&j).unwrap();
|
let component = Component::new(&j).unwrap();
|
||||||
|
println!("println: {}", component.to_ansi(None));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue